From 7ebc990573da8a08c58c1092ed126357c44804f5 Mon Sep 17 00:00:00 2001
From: George Hazan <george.hazan@gmail.com>
Date: Tue, 6 Aug 2013 15:47:08 +0000
Subject: - added sounds for the protocols' state change; - visual code moved
 to the separate files; - version bump

git-svn-id: http://svn.miranda-ng.org/main/trunk@5603 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
---
 plugins/XSoundNotify/XSoundNotify_10.vcxproj       |   2 +
 .../XSoundNotify/XSoundNotify_10.vcxproj.filters   |   6 +
 plugins/XSoundNotify/XSoundNotify_11.vcxproj       |   2 +
 .../XSoundNotify/XSoundNotify_11.vcxproj.filters   |   6 +
 plugins/XSoundNotify/src/Common.h                  |  14 +-
 plugins/XSoundNotify/src/Version.h                 |   4 +-
 plugins/XSoundNotify/src/dialog.cpp                | 217 +++++++++
 plugins/XSoundNotify/src/options.cpp               | 243 ++++++++++
 plugins/XSoundNotify/src/xsn_main.cpp              | 528 +++------------------
 9 files changed, 558 insertions(+), 464 deletions(-)
 create mode 100644 plugins/XSoundNotify/src/dialog.cpp
 create mode 100644 plugins/XSoundNotify/src/options.cpp

diff --git a/plugins/XSoundNotify/XSoundNotify_10.vcxproj b/plugins/XSoundNotify/XSoundNotify_10.vcxproj
index 5f7e2d23a6..f2f706c2fe 100644
--- a/plugins/XSoundNotify/XSoundNotify_10.vcxproj
+++ b/plugins/XSoundNotify/XSoundNotify_10.vcxproj
@@ -191,6 +191,8 @@
     <ClInclude Include="src\Version.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="src\dialog.cpp" />
+    <ClCompile Include="src\options.cpp" />
     <ClCompile Include="src\stdafx.cpp">
       <PrecompiledHeader>Create</PrecompiledHeader>
     </ClCompile>
diff --git a/plugins/XSoundNotify/XSoundNotify_10.vcxproj.filters b/plugins/XSoundNotify/XSoundNotify_10.vcxproj.filters
index 1422243f31..1826cc9cf7 100644
--- a/plugins/XSoundNotify/XSoundNotify_10.vcxproj.filters
+++ b/plugins/XSoundNotify/XSoundNotify_10.vcxproj.filters
@@ -29,6 +29,12 @@
     <ClCompile Include="src\stdafx.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="src\dialog.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\options.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="res\XSoundNotify.rc">
diff --git a/plugins/XSoundNotify/XSoundNotify_11.vcxproj b/plugins/XSoundNotify/XSoundNotify_11.vcxproj
index 1d0768a8b8..6a31cce386 100644
--- a/plugins/XSoundNotify/XSoundNotify_11.vcxproj
+++ b/plugins/XSoundNotify/XSoundNotify_11.vcxproj
@@ -196,6 +196,8 @@
     <ClInclude Include="src\Version.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="src\dialog.cpp" />
+    <ClCompile Include="src\options.cpp" />
     <ClCompile Include="src\stdafx.cpp">
       <PrecompiledHeader>Create</PrecompiledHeader>
     </ClCompile>
diff --git a/plugins/XSoundNotify/XSoundNotify_11.vcxproj.filters b/plugins/XSoundNotify/XSoundNotify_11.vcxproj.filters
index 1422243f31..1826cc9cf7 100644
--- a/plugins/XSoundNotify/XSoundNotify_11.vcxproj.filters
+++ b/plugins/XSoundNotify/XSoundNotify_11.vcxproj.filters
@@ -29,6 +29,12 @@
     <ClCompile Include="src\stdafx.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="src\dialog.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\options.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="res\XSoundNotify.rc">
diff --git a/plugins/XSoundNotify/src/Common.h b/plugins/XSoundNotify/src/Common.h
index bec554f4aa..c71dd34a4a 100644
--- a/plugins/XSoundNotify/src/Common.h
+++ b/plugins/XSoundNotify/src/Common.h
@@ -33,4 +33,16 @@ struct XSN_Data
 		_tcsncpy(path, _path, SIZEOF(path));
 		ignore = _ignore;
 	}
-};
\ No newline at end of file
+};
+
+extern LIST<XSN_Data> XSN_Users;
+
+extern HINSTANCE hInst;
+extern HANDLE hChangeSoundDlgList;
+extern BYTE isIgnoreSound, isOwnSound;
+
+bool IsSuitableProto(PROTOACCOUNT* pa);
+
+INT OptInit(WPARAM wParam, LPARAM lParam);
+
+INT_PTR ShowDialog(WPARAM wParam, LPARAM lParam);
diff --git a/plugins/XSoundNotify/src/Version.h b/plugins/XSoundNotify/src/Version.h
index ee5380fd76..fe501309d9 100644
--- a/plugins/XSoundNotify/src/Version.h
+++ b/plugins/XSoundNotify/src/Version.h
@@ -1,7 +1,7 @@
 #define __MAJOR_VERSION				1
 #define __MINOR_VERSION				0
-#define __RELEASE_NUM				0
-#define __BUILD_NUM					1
+#define __RELEASE_NUM				1
+#define __BUILD_NUM					2
 
 #define __FILEVERSION_STRING		__MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
 
diff --git a/plugins/XSoundNotify/src/dialog.cpp b/plugins/XSoundNotify/src/dialog.cpp
new file mode 100644
index 0000000000..84b5602a20
--- /dev/null
+++ b/plugins/XSoundNotify/src/dialog.cpp
@@ -0,0 +1,217 @@
+/*
+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"
+
+static INT_PTR CALLBACK DlgProcContactsOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+	switch (msg) {
+	case WM_INITDIALOG:
+		{
+			TranslateDialogDefault(hwndDlg);
+			HANDLE hContact = (HANDLE)lParam;
+			SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
+			WindowList_Add(hChangeSoundDlgList, hwndDlg, hContact);
+			Utils_RestoreWindowPositionNoSize(hwndDlg, hContact, SETTINGSNAME, "ChangeSoundDlg");
+			char* szProto = GetContactProto(hContact);
+			PROTOACCOUNT *pa = ProtoGetAccount(szProto);
+			char* szUniqueId = (char*)CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0);
+			if ((INT_PTR) szUniqueId != CALLSERVICE_NOTFOUND && szUniqueId != NULL) {
+				DBVARIANT dbvuid = {0};
+				if ( !db_get(hContact, pa->szModuleName, szUniqueId, &dbvuid)) {
+					TCHAR uid[MAX_PATH];
+					switch(dbvuid.type) {
+					case DBVT_DWORD:
+						_itot(dbvuid.dVal, uid, 10);
+						break;
+
+					case DBVT_ASCIIZ:
+						_tcscpy(uid, _A2T(dbvuid.pszVal));
+						break;
+
+					case DBVT_UTF8:
+						_tcscpy(uid, ptrT( mir_utf8decodeT(dbvuid.pszVal)));
+						break;
+					}
+
+					TCHAR *nick = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR);
+					TCHAR value[100];
+					mir_sntprintf(value, SIZEOF(value), TranslateT("Custom sound for %s (%s)"), nick, uid);
+					SetWindowText(hwndDlg, value);
+					db_free(&dbvuid);
+				}
+			}
+			EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_CHOOSE_SOUND), TRUE);
+			DBVARIANT dbv = {0};
+			if ( !db_get_ts(hContact, SETTINGSNAME, SETTINGSKEY, &dbv)) {
+				EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_TEST_PLAY), TRUE);
+				EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_RESET_SOUND), TRUE);
+				SetDlgItemText(hwndDlg, IDC_CONT_LABEL_SOUND, PathFindFileName(dbv.ptszVal));
+				db_free(&dbv);
+			}
+			else {
+				EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_TEST_PLAY), FALSE);
+				EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_RESET_SOUND), FALSE);
+				SetDlgItemText(hwndDlg, IDC_CONT_LABEL_SOUND, TranslateT("Not set"));
+			}
+			EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_IGNORE_SOUND), TRUE);
+			CheckDlgButton(hwndDlg, IDC_CONT_IGNORE_SOUND, db_get_b(hContact, SETTINGSNAME, SETTINGSIGNOREKEY, 0));
+			XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
+			if (p == NULL) {
+				DBVARIANT dbv;
+				if ( !db_get_ts(hContact, SETTINGSNAME, SETTINGSKEY, &dbv)) {
+					XSN_Users.insert( new XSN_Data(hContact, dbv.ptszVal, IsDlgButtonChecked(hwndDlg, IDC_CONT_IGNORE_SOUND) ? 1 : 0));
+					db_free(&dbv);
+				}
+			}
+		}
+		return TRUE;
+
+	case WM_COMMAND:
+		switch (LOWORD(wParam)) {
+		case IDOK:
+			{
+				HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+				XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
+				if (p != NULL) {
+					if (lstrcmpi(p->path, _T(""))) {
+						TCHAR shortpath[MAX_PATH];
+						PathToRelativeT(p->path, shortpath);
+						db_set_ts(hContact, SETTINGSNAME, SETTINGSKEY, shortpath);
+					}
+					db_set_b(hContact, SETTINGSNAME, SETTINGSIGNOREKEY, p->ignore);
+				}
+			}
+
+		case IDCANCEL:
+			DestroyWindow(hwndDlg);
+			break;
+
+		case IDC_CONT_BUTTON_CHOOSE_SOUND:
+			{
+				TCHAR FileName[MAX_PATH];
+				TCHAR *tszMirDir = Utils_ReplaceVarsT(_T("%miranda_path%"));
+
+				OPENFILENAME ofn = {0};
+				ofn.lStructSize = sizeof(ofn);
+				TCHAR tmp[MAX_PATH];
+				if (GetModuleHandle(_T("bass_interface.dll")))
+					mir_sntprintf(tmp, SIZEOF(tmp), _T("%s (*.wav, *.mp3, *.ogg)%c*.wav;*.mp3;*.ogg%c%c"), TranslateT("Sound files"), 0, 0, 0);
+				else
+					mir_sntprintf(tmp, SIZEOF(tmp), _T("%s (*.wav)%c*.wav%c%c"), TranslateT("WAV files"), 0, 0, 0);
+				ofn.lpstrFilter = tmp;
+				ofn.hwndOwner = 0;
+				ofn.lpstrFile = FileName;
+				ofn.nMaxFile = MAX_PATH;
+				ofn.nMaxFileTitle = MAX_PATH;
+				ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
+				ofn.lpstrInitialDir = tszMirDir;
+				*FileName = '\0';
+				ofn.lpstrDefExt = _T("");
+
+				if (GetOpenFileName(&ofn)) {
+					HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+					SetDlgItemText(hwndDlg, IDC_CONT_LABEL_SOUND, PathFindFileName(FileName));
+					XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
+					if (p == NULL)
+						XSN_Users.insert( new XSN_Data(hContact, FileName, IsDlgButtonChecked(hwndDlg, IDC_CONT_IGNORE_SOUND) ? 1 : 0));
+					else {
+						_tcsncpy(p->path, FileName, SIZEOF(p->path));
+						p->ignore = IsDlgButtonChecked(hwndDlg, IDC_CONT_IGNORE_SOUND) ? 1 : 0;
+					}
+					EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_TEST_PLAY), TRUE);
+					EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_RESET_SOUND), TRUE);
+				}
+				mir_free(tszMirDir);
+			}
+			break;
+
+		case IDC_CONT_BUTTON_TEST_PLAY:
+			{
+				HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+				XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
+				isIgnoreSound = 0;
+				if (p == NULL) {
+					DBVARIANT dbv;
+					if ( !db_get_ts(hContact, SETTINGSNAME, SETTINGSKEY, &dbv)) {
+						TCHAR longpath[MAX_PATH] = {0};
+						PathToAbsoluteT(dbv.ptszVal, longpath);
+						SkinPlaySoundFile(longpath);
+						db_free(&dbv);
+					}
+				}
+				else {
+					TCHAR longpath[MAX_PATH] = {0};
+					PathToAbsoluteT(p->path, longpath);
+					SkinPlaySoundFile(longpath);
+				}
+			}
+			break;
+
+		case IDC_CONT_BUTTON_RESET_SOUND:
+			{
+				HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+				EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_TEST_PLAY), FALSE);
+				EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_RESET_SOUND), FALSE);
+				CheckDlgButton(hwndDlg, IDC_CONT_IGNORE_SOUND, BST_UNCHECKED);
+				SetDlgItemText(hwndDlg, IDC_CONT_LABEL_SOUND, TranslateT("Not set"));
+				XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
+				if (p != NULL) {
+					XSN_Users.remove(p);
+					delete p;
+				}
+				db_unset(hContact, SETTINGSNAME, SETTINGSKEY);
+				db_unset(hContact, SETTINGSNAME, SETTINGSIGNOREKEY);
+			}
+			break;
+
+		case IDC_CONT_IGNORE_SOUND:
+			{
+				HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+				XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
+				if (p == NULL) {
+					DBVARIANT dbv;
+					if ( !db_get_ts(hContact, SETTINGSNAME, SETTINGSKEY, &dbv)) {
+						TCHAR longpath[MAX_PATH];
+						PathToAbsoluteT(dbv.ptszVal, longpath);
+						XSN_Users.insert( new XSN_Data(hContact, longpath, IsDlgButtonChecked(hwndDlg, IDC_CONT_IGNORE_SOUND) ? 1 : 0));
+						db_free(&dbv);
+					}
+					else XSN_Users.insert( new XSN_Data(hContact, _T(""), IsDlgButtonChecked(hwndDlg, IDC_CONT_IGNORE_SOUND) ? 1 : 0));
+				}
+				else p->ignore = IsDlgButtonChecked(hwndDlg, IDC_CONT_IGNORE_SOUND) ? 1 : 0;
+			}
+		}
+		break;
+
+	case WM_CLOSE:
+		DestroyWindow(hwndDlg);
+		break;
+
+	case WM_DESTROY:
+		HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+		Utils_SaveWindowPosition(hwndDlg, hContact, SETTINGSNAME, "ChangeSoundDlg");
+		WindowList_Remove(hChangeSoundDlgList, hwndDlg);
+	}
+	return FALSE;
+}
+
+INT_PTR ShowDialog(WPARAM wParam, LPARAM lParam)
+{
+	HWND hChangeSoundDlg = WindowList_Find(hChangeSoundDlgList, (HANDLE)wParam);
+	if (!hChangeSoundDlg) {
+		hChangeSoundDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_CONTACTS), 0, DlgProcContactsOptions, (LPARAM)wParam);
+		ShowWindow(hChangeSoundDlg, SW_SHOW);
+	}
+	else {
+		SetForegroundWindow(hChangeSoundDlg);
+		SetFocus(hChangeSoundDlg);
+	}
+	return 0;
+}
diff --git a/plugins/XSoundNotify/src/options.cpp b/plugins/XSoundNotify/src/options.cpp
new file mode 100644
index 0000000000..339bb93342
--- /dev/null
+++ b/plugins/XSoundNotify/src/options.cpp
@@ -0,0 +1,243 @@
+/*
+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"
+
+bool IsSuitableProto(PROTOACCOUNT* pa)
+{
+	if (pa == NULL)
+		return false;
+
+	if (pa->bDynDisabled || !pa->bIsEnabled)
+		return false;
+
+	if (!(CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMRECV))
+		return false;
+
+	return true;
+}
+
+static INT_PTR CALLBACK OptsProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+	switch (msg) {
+	case WM_INITDIALOG:
+		TranslateDialogDefault(hwndDlg);
+		int count;
+		PROTOACCOUNT **protos;
+		ProtoEnumAccounts(&count, &protos);
+		for(int i = 0; i < count; i++)
+			if (IsSuitableProto(protos[i]))
+				SendMessage(GetDlgItem(hwndDlg, IDC_OPT_COMBO_PROTO), CB_SETITEMDATA, SendMessage(GetDlgItem(hwndDlg, IDC_OPT_COMBO_PROTO), CB_ADDSTRING, 0, (LPARAM)protos[i]->tszAccountName), (LPARAM)protos[i]);
+		return TRUE;
+
+	case WM_COMMAND:
+		switch (LOWORD(wParam)) {
+		case IDC_OPT_COMBO_PROTO:
+			if ((HIWORD(wParam) == CBN_SELCHANGE) || (HIWORD(wParam) == LBN_SELCHANGE)) {
+				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_COMBO_USERS), TRUE);
+				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_TEST_PLAY), FALSE);
+				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_RESET_SOUND), FALSE);
+				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_IGNORE_SOUND), FALSE);
+				CheckDlgButton(hwndDlg, IDC_OPT_IGNORE_SOUND, BST_UNCHECKED);
+				SetDlgItemText(hwndDlg, IDC_OPT_LABEL_SOUND, TranslateT("Not set"));
+				SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_RESETCONTENT, 0, 0);
+				int cursel = SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_PROTO, CB_GETCURSEL, 0, 0);
+				PROTOACCOUNT *pa = (PROTOACCOUNT *)SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_PROTO, CB_GETITEMDATA, cursel, 0);
+
+				for (HANDLE hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) {
+					char* szUniqueId = (char*)CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0);
+					if ((INT_PTR) szUniqueId != CALLSERVICE_NOTFOUND && szUniqueId != NULL) {
+						DBVARIANT dbvuid = {0};
+						if ( !db_get(hContact, pa->szModuleName, szUniqueId, &dbvuid)) {
+							TCHAR uid[MAX_PATH];
+							switch(dbvuid.type) {
+							case DBVT_DWORD:
+								_itot(dbvuid.dVal, uid, 10);
+								break;
+
+							case DBVT_ASCIIZ:
+								_tcscpy(uid, _A2T(dbvuid.pszVal));
+								break;
+
+							case DBVT_UTF8:
+								_tcscpy(uid, ptrT(mir_utf8decodeT(dbvuid.pszVal)));
+								break;
+							}
+
+							TCHAR *nick = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR);
+							TCHAR *value = (TCHAR *)mir_alloc(sizeof(TCHAR) * (_tcslen(uid) + _tcslen(nick) + 4));
+							mir_sntprintf(value, _tcslen(uid) + _tcslen(nick) + 4, _T("%s (%s)"), nick, uid);
+							SendMessage(GetDlgItem(hwndDlg, IDC_OPT_COMBO_USERS), CB_SETITEMDATA, SendMessage(GetDlgItem(hwndDlg, IDC_OPT_COMBO_USERS), CB_ADDSTRING, 0, (LPARAM)value), (LPARAM)hContact);
+							mir_free(value);
+							db_free(&dbvuid);
+						}
+					}
+				}
+			}
+			return 0;
+
+		case IDC_OPT_COMBO_USERS:
+			if ((HIWORD(wParam) == CBN_SELCHANGE) || (HIWORD(wParam) == LBN_SELCHANGE)) {
+				int cursel = SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETCURSEL, 0, 0);
+				HANDLE hContact = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETITEMDATA, cursel, 0);
+				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_CHOOSE_SOUND), TRUE);
+				DBVARIANT dbv = {0};
+				if ( !db_get_ts(hContact, SETTINGSNAME, SETTINGSKEY, &dbv))
+				{
+					EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_TEST_PLAY), TRUE);
+					EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_RESET_SOUND), TRUE);
+					SetDlgItemText(hwndDlg, IDC_OPT_LABEL_SOUND, PathFindFileName(dbv.ptszVal));
+					db_free(&dbv);
+				} else {
+					EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_TEST_PLAY), FALSE);
+					EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_RESET_SOUND), FALSE);
+					SetDlgItemText(hwndDlg, IDC_OPT_LABEL_SOUND, TranslateT("Not set"));
+				}
+				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_IGNORE_SOUND), TRUE);
+				CheckDlgButton(hwndDlg, IDC_OPT_IGNORE_SOUND, db_get_b(hContact, SETTINGSNAME, SETTINGSIGNOREKEY, 0));
+			}
+			return 0;
+
+		case IDC_OPT_BUTTON_CHOOSE_SOUND:
+			{
+				TCHAR FileName[MAX_PATH];
+				TCHAR *tszMirDir = Utils_ReplaceVarsT(_T("%miranda_path%"));
+
+				OPENFILENAME ofn = {0};
+				ofn.lStructSize = sizeof(ofn);
+				TCHAR tmp[MAX_PATH];
+				if (GetModuleHandle(_T("bass_interface.dll")))
+					mir_sntprintf(tmp, SIZEOF(tmp), _T("%s (*.wav, *.mp3, *.ogg)%c*.wav;*.mp3;*.ogg%c%c"), TranslateT("Sound files"), 0, 0, 0);
+				else
+					mir_sntprintf(tmp, SIZEOF(tmp), _T("%s (*.wav)%c*.wav%c%c"), TranslateT("WAV files"), 0, 0, 0);
+				ofn.lpstrFilter = tmp;
+				ofn.hwndOwner = 0;
+				ofn.lpstrFile = FileName;
+				ofn.nMaxFile = MAX_PATH;
+				ofn.nMaxFileTitle = MAX_PATH;
+				ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
+				ofn.lpstrInitialDir = tszMirDir;
+				*FileName = '\0';
+				ofn.lpstrDefExt = _T("");
+
+				if (GetOpenFileName(&ofn)) {
+					SetDlgItemText(hwndDlg, IDC_OPT_LABEL_SOUND, PathFindFileName(FileName));
+					int cursel = SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETCURSEL, 0, 0);
+					HANDLE hContact = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETITEMDATA, cursel, 0);
+					XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
+					if (p == NULL)
+						XSN_Users.insert( new XSN_Data(hContact, FileName, IsDlgButtonChecked(hwndDlg, IDC_OPT_IGNORE_SOUND) ? 1 : 0));
+					else
+					{
+						_tcsncpy(p->path, FileName, SIZEOF(p->path));
+						p->ignore = IsDlgButtonChecked(hwndDlg, IDC_OPT_IGNORE_SOUND) ? 1 : 0;
+					}
+					EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_TEST_PLAY), TRUE);
+					EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_RESET_SOUND), TRUE);
+					SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+				}
+				mir_free(tszMirDir);
+			}
+			return 0;
+
+		case IDC_OPT_BUTTON_TEST_PLAY:
+			{
+				int cursel = SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETCURSEL, 0, 0);
+				HANDLE hContact = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETITEMDATA, cursel, 0);
+				XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
+				isIgnoreSound = 0;
+				if (p == NULL) {
+					DBVARIANT dbv;
+					if ( !db_get_ts(hContact, SETTINGSNAME, SETTINGSKEY, &dbv)) {
+						TCHAR longpath[MAX_PATH];
+						PathToAbsoluteT(dbv.ptszVal, longpath);
+						SkinPlaySoundFile(longpath);
+						db_free(&dbv);
+					}
+				}
+				else {
+					TCHAR longpath[MAX_PATH] = {0};
+					PathToAbsoluteT(p->path, longpath);
+					SkinPlaySoundFile(longpath);
+				}
+			}
+			return 0;
+
+		case IDC_OPT_BUTTON_RESET_SOUND:
+			{
+				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_TEST_PLAY), FALSE);
+				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_RESET_SOUND), FALSE);
+				CheckDlgButton(hwndDlg, IDC_OPT_IGNORE_SOUND, BST_UNCHECKED);
+				SetDlgItemText(hwndDlg, IDC_OPT_LABEL_SOUND, TranslateT("Not set"));
+				int cursel = SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETCURSEL, 0, 0);
+				HANDLE hContact = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETITEMDATA, cursel, 0);
+				XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
+				if (p != NULL) {
+					XSN_Users.remove(p);
+					delete p;
+					SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+				}
+				db_unset(hContact, SETTINGSNAME, SETTINGSKEY);
+				db_unset(hContact, SETTINGSNAME, SETTINGSIGNOREKEY);
+			}
+			return 0;
+
+		case IDC_OPT_IGNORE_SOUND:
+			{
+				int cursel = SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETCURSEL, 0, 0);
+				HANDLE hContact = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETITEMDATA, cursel, 0);
+				XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
+				if (p == NULL) {
+					DBVARIANT dbv;
+					if ( !db_get_ts(hContact, SETTINGSNAME, SETTINGSKEY, &dbv)) {
+						TCHAR longpath[MAX_PATH];
+						PathToAbsoluteT(dbv.ptszVal, longpath);
+						XSN_Users.insert( new XSN_Data(hContact, longpath, IsDlgButtonChecked(hwndDlg, IDC_OPT_IGNORE_SOUND) ? 1 : 0));
+						db_free(&dbv);
+					}
+					else XSN_Users.insert( new XSN_Data(hContact, _T(""), IsDlgButtonChecked(hwndDlg, IDC_OPT_IGNORE_SOUND) ? 1 : 0));
+				}
+				else p->ignore = IsDlgButtonChecked(hwndDlg, IDC_OPT_IGNORE_SOUND) ? 1 : 0;
+				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+			}
+			return 0;
+		}
+		break;
+
+	case WM_NOTIFY:
+		NMHDR *hdr = (NMHDR *)lParam;
+		switch (hdr->code) {
+		case PSN_APPLY:
+			for (int i = 0; i < XSN_Users.getCount(); i++) {
+				if (lstrcmpi(XSN_Users[i]->path, _T(""))) {
+					TCHAR shortpath[MAX_PATH];
+					PathToRelativeT(XSN_Users[i]->path, shortpath);
+					db_set_ts(XSN_Users[i]->hContact, SETTINGSNAME, SETTINGSKEY, shortpath);
+				}
+				db_set_b(XSN_Users[i]->hContact, SETTINGSNAME, SETTINGSIGNOREKEY, XSN_Users[i]->ignore);
+			}
+			break;
+		}
+	}
+	return FALSE;
+}
+
+INT OptInit(WPARAM wParam, LPARAM lParam)
+{
+	OPTIONSDIALOGPAGE odp = { sizeof(odp) };
+	odp.position = 100000000;
+	odp.hInstance = hInst;
+	odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
+	odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS);
+	odp.ptszGroup = LPGENT("Sounds");
+	odp.ptszTitle = LPGENT("XSound Notify");
+	odp.pfnDlgProc = OptsProc;
+	Options_AddPage(wParam, &odp);
+	return 0;
+}
diff --git a/plugins/XSoundNotify/src/xsn_main.cpp b/plugins/XSoundNotify/src/xsn_main.cpp
index f70d61c3be..71178febd6 100644
--- a/plugins/XSoundNotify/src/xsn_main.cpp
+++ b/plugins/XSoundNotify/src/xsn_main.cpp
@@ -41,7 +41,65 @@ extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD miranda
 	return &pluginInfo;
 }
 
-bool isReceiveMessage(HANDLE hDbEvent)
+/////////////////////////////////////////////////////////////////////////////////////////
+
+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);
@@ -50,7 +108,7 @@ bool isReceiveMessage(HANDLE hDbEvent)
 	return !(((info.eventType != EVENTTYPE_MESSAGE) && !(info.flags & DBEF_READ)) || (info.flags & DBEF_SENT));
 }
 
-INT ProcessEvent(WPARAM wParam, LPARAM lParam)
+static int ProcessEvent(WPARAM wParam, LPARAM lParam)
 {
 	if (!isReceiveMessage(HANDLE(lParam)))
 		return 0;
@@ -68,7 +126,7 @@ INT ProcessEvent(WPARAM wParam, LPARAM lParam)
 	return 0;
 }
 
-int OnPlaySound(WPARAM wParam, LPARAM lParam)
+static int OnPlaySound(WPARAM wParam, LPARAM lParam)
 {
 	if (isIgnoreSound)
 		return 1;
@@ -80,462 +138,7 @@ int OnPlaySound(WPARAM wParam, LPARAM lParam)
 	return 0;
 }
 
-bool IsSuitableProto(PROTOACCOUNT* pa)
-{
-	if (pa == NULL)
-		return false;
-
-	if (pa->bDynDisabled || !pa->bIsEnabled)
-		return false;
-
-	if (!(CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IMRECV))
-		return false;
-
-	return true;
-}
-
-INT_PTR CALLBACK OptsProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
-	switch (msg) {
-	case WM_INITDIALOG:
-		TranslateDialogDefault(hwndDlg);
-		int count;
-		PROTOACCOUNT **protos;
-		ProtoEnumAccounts(&count, &protos);
-		for(int i = 0; i < count; i++)
-			if (IsSuitableProto(protos[i]))
-				SendMessage(GetDlgItem(hwndDlg, IDC_OPT_COMBO_PROTO), CB_SETITEMDATA, SendMessage(GetDlgItem(hwndDlg, IDC_OPT_COMBO_PROTO), CB_ADDSTRING, 0, (LPARAM)protos[i]->tszAccountName), (LPARAM)protos[i]);
-		return TRUE;
-
-	case WM_COMMAND:
-		switch (LOWORD(wParam)) {
-		case IDC_OPT_COMBO_PROTO:
-			if ((HIWORD(wParam) == CBN_SELCHANGE) || (HIWORD(wParam) == LBN_SELCHANGE)) {
-				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_COMBO_USERS), TRUE);
-				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_TEST_PLAY), FALSE);
-				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_RESET_SOUND), FALSE);
-				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_IGNORE_SOUND), FALSE);
-				CheckDlgButton(hwndDlg, IDC_OPT_IGNORE_SOUND, BST_UNCHECKED);
-				SetDlgItemText(hwndDlg, IDC_OPT_LABEL_SOUND, TranslateT("Not set"));
-				SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_RESETCONTENT, 0, 0);
-				int cursel = SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_PROTO, CB_GETCURSEL, 0, 0);
-				PROTOACCOUNT *pa = (PROTOACCOUNT *)SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_PROTO, CB_GETITEMDATA, cursel, 0);
-
-				for (HANDLE hContact = db_find_first(); hContact; hContact = db_find_next(hContact)) {
-					char* szUniqueId = (char*)CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0);
-					if ((INT_PTR) szUniqueId != CALLSERVICE_NOTFOUND && szUniqueId != NULL) {
-						DBVARIANT dbvuid = {0};
-						if ( !db_get(hContact, pa->szModuleName, szUniqueId, &dbvuid)) {
-							TCHAR uid[MAX_PATH];
-							switch(dbvuid.type) {
-							case DBVT_DWORD:
-								_itot(dbvuid.dVal, uid, 10);
-								break;
-
-							case DBVT_ASCIIZ:
-								_tcscpy(uid, _A2T(dbvuid.pszVal));
-								break;
-
-							case DBVT_UTF8:
-								_tcscpy(uid, ptrT(mir_utf8decodeT(dbvuid.pszVal)));
-								break;
-							}
-
-							TCHAR *nick = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR);
-							TCHAR *value = (TCHAR *)mir_alloc(sizeof(TCHAR) * (_tcslen(uid) + _tcslen(nick) + 4));
-							mir_sntprintf(value, _tcslen(uid) + _tcslen(nick) + 4, _T("%s (%s)"), nick, uid);
-							SendMessage(GetDlgItem(hwndDlg, IDC_OPT_COMBO_USERS), CB_SETITEMDATA, SendMessage(GetDlgItem(hwndDlg, IDC_OPT_COMBO_USERS), CB_ADDSTRING, 0, (LPARAM)value), (LPARAM)hContact);
-							mir_free(value);
-							db_free(&dbvuid);
-						}
-					}
-				}
-			}
-			return 0;
-
-		case IDC_OPT_COMBO_USERS:
-			if ((HIWORD(wParam) == CBN_SELCHANGE) || (HIWORD(wParam) == LBN_SELCHANGE)) {
-				int cursel = SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETCURSEL, 0, 0);
-				HANDLE hContact = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETITEMDATA, cursel, 0);
-				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_CHOOSE_SOUND), TRUE);
-				DBVARIANT dbv = {0};
-				if ( !db_get_ts(hContact, SETTINGSNAME, SETTINGSKEY, &dbv))
-				{
-					EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_TEST_PLAY), TRUE);
-					EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_RESET_SOUND), TRUE);
-					SetDlgItemText(hwndDlg, IDC_OPT_LABEL_SOUND, PathFindFileName(dbv.ptszVal));
-					db_free(&dbv);
-				} else {
-					EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_TEST_PLAY), FALSE);
-					EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_RESET_SOUND), FALSE);
-					SetDlgItemText(hwndDlg, IDC_OPT_LABEL_SOUND, TranslateT("Not set"));
-				}
-				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_IGNORE_SOUND), TRUE);
-				CheckDlgButton(hwndDlg, IDC_OPT_IGNORE_SOUND, db_get_b(hContact, SETTINGSNAME, SETTINGSIGNOREKEY, 0));
-			}
-			return 0;
-
-		case IDC_OPT_BUTTON_CHOOSE_SOUND:
-			{
-				TCHAR FileName[MAX_PATH];
-				TCHAR *tszMirDir = Utils_ReplaceVarsT(_T("%miranda_path%"));
-
-				OPENFILENAME ofn = {0};
-				ofn.lStructSize = sizeof(ofn);
-				TCHAR tmp[MAX_PATH];
-				if (GetModuleHandle(_T("bass_interface.dll")))
-					mir_sntprintf(tmp, SIZEOF(tmp), _T("%s (*.wav, *.mp3, *.ogg)%c*.wav;*.mp3;*.ogg%c%c"), TranslateT("Sound files"), 0, 0, 0);
-				else
-					mir_sntprintf(tmp, SIZEOF(tmp), _T("%s (*.wav)%c*.wav%c%c"), TranslateT("WAV files"), 0, 0, 0);
-				ofn.lpstrFilter = tmp;
-				ofn.hwndOwner = 0;
-				ofn.lpstrFile = FileName;
-				ofn.nMaxFile = MAX_PATH;
-				ofn.nMaxFileTitle = MAX_PATH;
-				ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
-				ofn.lpstrInitialDir = tszMirDir;
-				*FileName = '\0';
-				ofn.lpstrDefExt = _T("");
-
-				if (GetOpenFileName(&ofn)) {
-					SetDlgItemText(hwndDlg, IDC_OPT_LABEL_SOUND, PathFindFileName(FileName));
-					int cursel = SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETCURSEL, 0, 0);
-					HANDLE hContact = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETITEMDATA, cursel, 0);
-					XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
-					if (p == NULL)
-						XSN_Users.insert( new XSN_Data(hContact, FileName, IsDlgButtonChecked(hwndDlg, IDC_OPT_IGNORE_SOUND) ? 1 : 0));
-					else
-					{
-						_tcsncpy(p->path, FileName, SIZEOF(p->path));
-						p->ignore = IsDlgButtonChecked(hwndDlg, IDC_OPT_IGNORE_SOUND) ? 1 : 0;
-					}
-					EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_TEST_PLAY), TRUE);
-					EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_RESET_SOUND), TRUE);
-					SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
-				}
-				mir_free(tszMirDir);
-			}
-			return 0;
-
-		case IDC_OPT_BUTTON_TEST_PLAY:
-			{
-				int cursel = SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETCURSEL, 0, 0);
-				HANDLE hContact = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETITEMDATA, cursel, 0);
-				XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
-				isIgnoreSound = 0;
-				if (p == NULL) {
-					DBVARIANT dbv;
-					if ( !db_get_ts(hContact, SETTINGSNAME, SETTINGSKEY, &dbv)) {
-						TCHAR longpath[MAX_PATH];
-						PathToAbsoluteT(dbv.ptszVal, longpath);
-						SkinPlaySoundFile(longpath);
-						db_free(&dbv);
-					}
-				}
-				else {
-					TCHAR longpath[MAX_PATH] = {0};
-					PathToAbsoluteT(p->path, longpath);
-					SkinPlaySoundFile(longpath);
-				}
-			}
-			return 0;
-
-		case IDC_OPT_BUTTON_RESET_SOUND:
-			{
-				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_TEST_PLAY), FALSE);
-				EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_BUTTON_RESET_SOUND), FALSE);
-				CheckDlgButton(hwndDlg, IDC_OPT_IGNORE_SOUND, BST_UNCHECKED);
-				SetDlgItemText(hwndDlg, IDC_OPT_LABEL_SOUND, TranslateT("Not set"));
-				int cursel = SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETCURSEL, 0, 0);
-				HANDLE hContact = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETITEMDATA, cursel, 0);
-				XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
-				if (p != NULL) {
-					XSN_Users.remove(p);
-					delete p;
-					SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
-				}
-				db_unset(hContact, SETTINGSNAME, SETTINGSKEY);
-				db_unset(hContact, SETTINGSNAME, SETTINGSIGNOREKEY);
-			}
-			return 0;
-
-		case IDC_OPT_IGNORE_SOUND:
-			{
-				int cursel = SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETCURSEL, 0, 0);
-				HANDLE hContact = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_OPT_COMBO_USERS, CB_GETITEMDATA, cursel, 0);
-				XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
-				if (p == NULL)
-				{
-					DBVARIANT dbv;
-					if ( !db_get_ts(hContact, SETTINGSNAME, SETTINGSKEY, &dbv)) {
-						TCHAR longpath[MAX_PATH];
-						PathToAbsoluteT(dbv.ptszVal, longpath);
-						XSN_Users.insert( new XSN_Data(hContact, longpath, IsDlgButtonChecked(hwndDlg, IDC_OPT_IGNORE_SOUND) ? 1 : 0));
-						db_free(&dbv);
-					} else
-						XSN_Users.insert( new XSN_Data(hContact, _T(""), IsDlgButtonChecked(hwndDlg, IDC_OPT_IGNORE_SOUND) ? 1 : 0));
-				}
-				else
-					p->ignore = IsDlgButtonChecked(hwndDlg, IDC_OPT_IGNORE_SOUND) ? 1 : 0;
-				SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
-			}
-			return 0;
-		}
-		break;
-
-	case WM_NOTIFY:
-		{
-			NMHDR *hdr = (NMHDR *)lParam;
-			switch (hdr->code) {
-			case PSN_APPLY:
-				for (int i = 0; i < XSN_Users.getCount(); i++) {
-					if (lstrcmpi(XSN_Users[i]->path, _T(""))) {
-						TCHAR shortpath[MAX_PATH];
-						PathToRelativeT(XSN_Users[i]->path, shortpath);
-						db_set_ts(XSN_Users[i]->hContact, SETTINGSNAME, SETTINGSKEY, shortpath);
-					}
-					db_set_b(XSN_Users[i]->hContact, SETTINGSNAME, SETTINGSIGNOREKEY, XSN_Users[i]->ignore);
-				}
-				break;
-			}
-		}
-	}
-	return FALSE;
-}
-
-INT OptInit(WPARAM wParam, LPARAM lParam)
-{
-	OPTIONSDIALOGPAGE odp = { sizeof(odp) };
-	odp.position = 100000000;
-	odp.hInstance = hInst;
-	odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
-	odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS);
-	odp.ptszGroup = LPGENT("Sounds");
-	odp.ptszTitle = LPGENT("XSound Notify");
-	odp.pfnDlgProc = OptsProc;
-	Options_AddPage(wParam, &odp);
-	return 0;
-}
-
-INT_PTR CALLBACK DlgProcContactsOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
-{
-	switch (msg) {
-	case WM_INITDIALOG:
-		{
-			TranslateDialogDefault(hwndDlg);
-			HANDLE hContact = (HANDLE)lParam;
-			SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
-			WindowList_Add(hChangeSoundDlgList, hwndDlg, hContact);
-			Utils_RestoreWindowPositionNoSize(hwndDlg, hContact, SETTINGSNAME, "ChangeSoundDlg");
-			char* szProto = GetContactProto(hContact);
-			PROTOACCOUNT *pa = ProtoGetAccount(szProto);
-			char* szUniqueId = (char*)CallProtoService(pa->szModuleName, PS_GETCAPS, PFLAG_UNIQUEIDSETTING, 0);
-			if ((INT_PTR) szUniqueId != CALLSERVICE_NOTFOUND && szUniqueId != NULL) {
-				DBVARIANT dbvuid = {0};
-				if ( !db_get(hContact, pa->szModuleName, szUniqueId, &dbvuid)) {
-					TCHAR uid[MAX_PATH];
-					switch(dbvuid.type) {
-					case DBVT_DWORD:
-						_itot(dbvuid.dVal, uid, 10);
-						break;
-
-					case DBVT_ASCIIZ:
-						_tcscpy(uid, _A2T(dbvuid.pszVal));
-						break;
-
-					case DBVT_UTF8:
-						_tcscpy(uid, ptrT( mir_utf8decodeT(dbvuid.pszVal)));
-						break;
-					}
-
-					TCHAR *nick = (TCHAR *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, GCDNF_TCHAR);
-					TCHAR value[100];
-					mir_sntprintf(value, SIZEOF(value), TranslateT("Custom sound for %s (%s)"), nick, uid);
-					SetWindowText(hwndDlg, value);
-					db_free(&dbvuid);
-				}
-			}
-			EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_CHOOSE_SOUND), TRUE);
-			DBVARIANT dbv = {0};
-			if ( !db_get_ts(hContact, SETTINGSNAME, SETTINGSKEY, &dbv))
-			{
-				EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_TEST_PLAY), TRUE);
-				EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_RESET_SOUND), TRUE);
-				SetDlgItemText(hwndDlg, IDC_CONT_LABEL_SOUND, PathFindFileName(dbv.ptszVal));
-				db_free(&dbv);
-			} else {
-				EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_TEST_PLAY), FALSE);
-				EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_RESET_SOUND), FALSE);
-				SetDlgItemText(hwndDlg, IDC_CONT_LABEL_SOUND, TranslateT("Not set"));
-			}
-			EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_IGNORE_SOUND), TRUE);
-			CheckDlgButton(hwndDlg, IDC_CONT_IGNORE_SOUND, db_get_b(hContact, SETTINGSNAME, SETTINGSIGNOREKEY, 0));
-			XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
-			if (p == NULL)
-			{
-				DBVARIANT dbv;
-				if ( !db_get_ts(hContact, SETTINGSNAME, SETTINGSKEY, &dbv))
-				{
-					XSN_Users.insert( new XSN_Data(hContact, dbv.ptszVal, IsDlgButtonChecked(hwndDlg, IDC_CONT_IGNORE_SOUND) ? 1 : 0));
-					db_free(&dbv);
-				}
-			}
-		}
-		return TRUE;
-	
-	case WM_COMMAND:
-		switch (LOWORD(wParam)) {
-		case IDOK:
-			{
-				HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-				XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
-				if (p != NULL)
-				{
-					if (lstrcmpi(p->path, _T(""))) {
-						TCHAR shortpath[MAX_PATH];
-						PathToRelativeT(p->path, shortpath);
-						db_set_ts(hContact, SETTINGSNAME, SETTINGSKEY, shortpath);
-					}
-					db_set_b(hContact, SETTINGSNAME, SETTINGSIGNOREKEY, p->ignore);
-				}
-			}
-
-		case IDCANCEL:
-			DestroyWindow(hwndDlg);
-			break;
-
-		case IDC_CONT_BUTTON_CHOOSE_SOUND:
-			{
-				TCHAR FileName[MAX_PATH];
-				TCHAR *tszMirDir = Utils_ReplaceVarsT(_T("%miranda_path%"));
-
-				OPENFILENAME ofn = {0};
-				ofn.lStructSize = sizeof(ofn);
-				TCHAR tmp[MAX_PATH];
-				if (GetModuleHandle(_T("bass_interface.dll")))
-					mir_sntprintf(tmp, SIZEOF(tmp), _T("%s (*.wav, *.mp3, *.ogg)%c*.wav;*.mp3;*.ogg%c%c"), TranslateT("Sound files"), 0, 0, 0);
-				else
-					mir_sntprintf(tmp, SIZEOF(tmp), _T("%s (*.wav)%c*.wav%c%c"), TranslateT("WAV files"), 0, 0, 0);
-				ofn.lpstrFilter = tmp;
-				ofn.hwndOwner = 0;
-				ofn.lpstrFile = FileName;
-				ofn.nMaxFile = MAX_PATH;
-				ofn.nMaxFileTitle = MAX_PATH;
-				ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
-				ofn.lpstrInitialDir = tszMirDir;
-				*FileName = '\0';
-				ofn.lpstrDefExt = _T("");
-
-				if (GetOpenFileName(&ofn)) {
-					HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-					SetDlgItemText(hwndDlg, IDC_CONT_LABEL_SOUND, PathFindFileName(FileName));
-					XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
-					if (p == NULL)
-						XSN_Users.insert( new XSN_Data(hContact, FileName, IsDlgButtonChecked(hwndDlg, IDC_CONT_IGNORE_SOUND) ? 1 : 0));
-					else
-					{
-						_tcsncpy(p->path, FileName, SIZEOF(p->path));
-						p->ignore = IsDlgButtonChecked(hwndDlg, IDC_CONT_IGNORE_SOUND) ? 1 : 0;
-					}
-					EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_TEST_PLAY), TRUE);
-					EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_RESET_SOUND), TRUE);
-				}
-				mir_free(tszMirDir);
-			}
-			break;
-
-		case IDC_CONT_BUTTON_TEST_PLAY:
-			{
-				HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-				XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
-				isIgnoreSound = 0;
-				if (p == NULL)
-				{
-					DBVARIANT dbv;
-					if ( !db_get_ts(hContact, SETTINGSNAME, SETTINGSKEY, &dbv))
-					{
-						TCHAR longpath[MAX_PATH] = {0};
-						PathToAbsoluteT(dbv.ptszVal, longpath);
-						SkinPlaySoundFile(longpath);
-						db_free(&dbv);
-					}
-				}
-				else
-				{
-					TCHAR longpath[MAX_PATH] = {0};
-					PathToAbsoluteT(p->path, longpath);
-					SkinPlaySoundFile(longpath);
-				}
-			}
-			break;
-
-		case IDC_CONT_BUTTON_RESET_SOUND:
-			{
-				HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-				EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_TEST_PLAY), FALSE);
-				EnableWindow(GetDlgItem(hwndDlg, IDC_CONT_BUTTON_RESET_SOUND), FALSE);
-				CheckDlgButton(hwndDlg, IDC_CONT_IGNORE_SOUND, BST_UNCHECKED);
-				SetDlgItemText(hwndDlg, IDC_CONT_LABEL_SOUND, TranslateT("Not set"));
-				XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
-				if (p != NULL)
-				{
-					XSN_Users.remove(p);
-					delete p;
-				}
-				db_unset(hContact, SETTINGSNAME, SETTINGSKEY);
-				db_unset(hContact, SETTINGSNAME, SETTINGSIGNOREKEY);
-			}
-			break;
-
-		case IDC_CONT_IGNORE_SOUND:
-			{
-				HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-				XSN_Data *p = XSN_Users.find((XSN_Data *)&hContact);
-				if (p == NULL)
-				{
-					DBVARIANT dbv;
-					if ( !db_get_ts(hContact, SETTINGSNAME, SETTINGSKEY, &dbv)) {
-						TCHAR longpath[MAX_PATH];
-						PathToAbsoluteT(dbv.ptszVal, longpath);
-						XSN_Users.insert( new XSN_Data(hContact, longpath, IsDlgButtonChecked(hwndDlg, IDC_CONT_IGNORE_SOUND) ? 1 : 0));
-						db_free(&dbv);
-					} else
-						XSN_Users.insert( new XSN_Data(hContact, _T(""), IsDlgButtonChecked(hwndDlg, IDC_CONT_IGNORE_SOUND) ? 1 : 0));
-				}
-				else
-					p->ignore = IsDlgButtonChecked(hwndDlg, IDC_CONT_IGNORE_SOUND) ? 1 : 0;
-			}
-			break;
-		}
-		break;
-
-	case WM_CLOSE:
-		DestroyWindow(hwndDlg);
-		break;
-
-	case WM_DESTROY:
-		HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
-		Utils_SaveWindowPosition(hwndDlg, hContact, SETTINGSNAME, "ChangeSoundDlg");
-		WindowList_Remove(hChangeSoundDlgList, hwndDlg);
-	}
-	return FALSE;
-}
-
-INT_PTR ShowDialog(WPARAM wParam, LPARAM lParam)
-{
-	HWND hChangeSoundDlg = WindowList_Find(hChangeSoundDlgList, (HANDLE)wParam);
-	if (!hChangeSoundDlg) {
-		hChangeSoundDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_CONTACTS), 0, DlgProcContactsOptions, (LPARAM)wParam);
-		ShowWindow(hChangeSoundDlg, SW_SHOW);
-	}
-	else {
-		SetForegroundWindow(hChangeSoundDlg);
-		SetFocus(hChangeSoundDlg);
-	}
-	return 0;
-}
-
-int OnLoadInit(WPARAM wParam, LPARAM lParam)
+static int OnLoadInit(WPARAM wParam, LPARAM lParam)
 {
 	CLISTMENUITEM mi = { sizeof(mi) };
 	mi.position = -0x7FFFFFFF; 
@@ -544,10 +147,12 @@ int OnLoadInit(WPARAM wParam, LPARAM lParam)
 	mi.ptszName = LPGENT("Custom contact sound"); 
 	mi.pszService = "XSoundNotify/ContactMenuCommand"; 
 	hChangeSound = Menu_AddContactMenuItem(&mi); 
+
+	InitSelfSounds();
 	return 0;
 }
 
-int PrebuildContactMenu(WPARAM wParam, LPARAM lParam)
+static int PrebuildContactMenu(WPARAM wParam, LPARAM lParam)
 {
 	HANDLE hContact = (HANDLE)wParam;
 	if (hContact) {
@@ -558,7 +163,7 @@ int PrebuildContactMenu(WPARAM wParam, LPARAM lParam)
 	return 0;
 }
 
-int OnPreShutdown(WPARAM wParam, LPARAM lParam)
+static int OnPreShutdown(WPARAM wParam, LPARAM lParam)
 {
 	WindowList_Broadcast(hChangeSoundDlgList, WM_CLOSE, 0, 0);
 	return 0;
@@ -572,6 +177,7 @@ extern "C" int __declspec(dllexport) Load()
 
 	hChangeSoundDlgList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
 
+	HookEvent(ME_PROTO_ACK, ProtoAck);
 	HookEvent(ME_OPT_INITIALISE, OptInit);
 	HookEvent(ME_DB_EVENT_ADDED, ProcessEvent);
 	HookEvent(ME_SYSTEM_MODULESLOADED, OnLoadInit);
-- 
cgit v1.2.3