aboutsummaryrefslogtreecommitdiff
path: root/Src/Plugins/General/gen_hotkeys
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Plugins/General/gen_hotkeys')
-rw-r--r--Src/Plugins/General/gen_hotkeys/Configdlg.cpp471
-rw-r--r--Src/Plugins/General/gen_hotkeys/Configdlg.h9
-rw-r--r--Src/Plugins/General/gen_hotkeys/HOTKEY.CPP56
-rw-r--r--Src/Plugins/General/gen_hotkeys/HOTKEY.H32
-rw-r--r--Src/Plugins/General/gen_hotkeys/HotKeyCtl.cpp293
-rw-r--r--Src/Plugins/General/gen_hotkeys/HotKeyCtl.h13
-rw-r--r--Src/Plugins/General/gen_hotkeys/RESOURCE.H116
-rw-r--r--Src/Plugins/General/gen_hotkeys/WINAMP.H38
-rw-r--r--Src/Plugins/General/gen_hotkeys/Wacommands.cpp366
-rw-r--r--Src/Plugins/General/gen_hotkeys/Wacommands.h50
-rw-r--r--Src/Plugins/General/gen_hotkeys/accelBlock.cpp47
-rw-r--r--Src/Plugins/General/gen_hotkeys/accelBlock.h24
-rw-r--r--Src/Plugins/General/gen_hotkeys/api__gen_hotkeys.h10
-rw-r--r--Src/Plugins/General/gen_hotkeys/gen_hotkeys.cpp519
-rw-r--r--Src/Plugins/General/gen_hotkeys/gen_hotkeys.h56
-rw-r--r--Src/Plugins/General/gen_hotkeys/gen_hotkeys.rc217
-rw-r--r--Src/Plugins/General/gen_hotkeys/gen_hotkeys.sln29
-rw-r--r--Src/Plugins/General/gen_hotkeys/gen_hotkeys.vcxproj316
-rw-r--r--Src/Plugins/General/gen_hotkeys/gen_hotkeys.vcxproj.filters79
-rw-r--r--Src/Plugins/General/gen_hotkeys/version.rc239
-rw-r--r--Src/Plugins/General/gen_hotkeys/wa_hotkeys.h91
-rw-r--r--Src/Plugins/General/gen_hotkeys/x.bmpbin0 -> 670 bytes
22 files changed, 2871 insertions, 0 deletions
diff --git a/Src/Plugins/General/gen_hotkeys/Configdlg.cpp b/Src/Plugins/General/gen_hotkeys/Configdlg.cpp
new file mode 100644
index 00000000..d0572efe
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/Configdlg.cpp
@@ -0,0 +1,471 @@
+#include "ConfigDlg.h"
+#include "gen_hotkeys.h"
+#include "accelBlock.h"
+
+#define ListView_InsertColumnW(hwnd, iCol, pcol) \
+ (int)SNDMSG((hwnd), LVM_INSERTCOLUMNW, (WPARAM)(int)(iCol), (LPARAM)(const LV_COLUMNW *)(pcol))
+
+#define ListView_InsertItemW(hwnd, pitem) \
+ (int)SNDMSG((hwnd), LVM_INSERTITEMW, 0, (LPARAM)(const LV_ITEMW *)(pitem))
+
+#define ListView_SetItemTextW(hwndLV, i, iSubItem_, pszText_) \
+{ LV_ITEMW _macro_lvi;\
+ _macro_lvi.iSubItem = (iSubItem_);\
+ _macro_lvi.pszText = (pszText_);\
+ SNDMSG((hwndLV), LVM_SETITEMTEXTW, (WPARAM)(i), (LPARAM)(LV_ITEMW *)&_macro_lvi);\
+}
+
+#define ListView_SetItemW(hwnd, pitem) \
+ (BOOL)SNDMSG((hwnd), LVM_SETITEMW, 0, (LPARAM)(LV_ITEMW *)(pitem))
+
+void SetListItem(HWND hwHKList, HWND hwHK, HOTKEY_DATA *hk_data, int idx = -1, int failed = 0);
+
+static AcceleratorBlocker *pAccelBlock = NULL;
+static bool changed = false;
+
+static int setCheckedStuff(HWND hwndDlg)
+{
+ int checked = SendMessage(GetDlgItem(hwndDlg, IDC_ENABLED), BM_GETCHECK, 0, 0) == BST_CHECKED;
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HKLIST),checked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_COMBO),checked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_HOTKEY),checked);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_ADD),checked);
+ if (!checked)
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SAVE),0);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_REMOVE),0);
+ }
+ EnableWindow(GetDlgItem(hwndDlg,IDC_DEFAULT),checked);
+ return checked;
+}
+
+int ResizeComboBoxDropDown(HWND hwndDlg, UINT id, const char* str, int width){
+ SIZE size = {0};
+ HWND control = GetDlgItem(hwndDlg, id);
+ HDC hdc = GetDC(control);
+ // get and select parent dialog's font so that it'll calculate things correctly
+ HFONT font = (HFONT)SendMessage(hwndDlg,WM_GETFONT,0,0), oldfont = (HFONT)SelectObject(hdc,font);
+ GetTextExtentPoint32(hdc, str, lstrlen(str)+1, &size);
+
+ int ret = width;
+ if(size.cx > width)
+ {
+ SendDlgItemMessageW(hwndDlg, id, CB_SETDROPPEDWIDTH, size.cx, 0);
+ ret = size.cx;
+ }
+
+ SelectObject(hdc, oldfont);
+ ReleaseDC(control, hdc);
+ return ret;
+}
+
+int ResizeComboBoxDropDownW(HWND hwndDlg, UINT id, const wchar_t *str, int width){
+ SIZE size = {0};
+ HWND control = GetDlgItem(hwndDlg, id);
+ HDC hdc = GetDC(control);
+ // get and select parent dialog's font so that it'll calculate things correctly
+ HFONT font = (HFONT)SendMessage(hwndDlg,WM_GETFONT,0,0), oldfont = (HFONT)SelectObject(hdc,font);
+ GetTextExtentPoint32W(hdc, str, (int)wcslen(str)+1, &size);
+
+ int ret = width;
+ if(size.cx > width)
+ {
+ SendDlgItemMessageW(hwndDlg, id, CB_SETDROPPEDWIDTH, size.cx, 0);
+ ret = size.cx;
+ }
+
+ SelectObject(hdc, oldfont);
+ ReleaseDC(control, hdc);
+ return ret;
+}
+
+BOOL CALLBACK ConfigProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hwHKList = GetDlgItem(hwndDlg, IDC_HKLIST);
+ HWND hwCombo = GetDlgItem(hwndDlg, IDC_COMBO);
+ HWND hwHK = GetDlgItem(hwndDlg, IDC_HOTKEY);
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ int colwidth1 = -1, colwidth2 = -1;
+ if (hwHKList && hwHK)
+ {
+ RECT r;
+
+ SendMessage(hwHKList, WM_SETREDRAW, FALSE, 0);
+ ListView_SetExtendedListViewStyle(hwHKList, LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP);
+
+ GetClientRect(hwHKList, &r);
+
+ colwidth2 = GetPrivateProfileIntW(L"gen_hotkeys", L"col2", -1, g_iniFile);
+ LVCOLUMNW lc = {LVCF_TEXT | LVCF_WIDTH, 0,
+ (colwidth2==-1?((r.right / 2) - GetSystemMetrics(SM_CYHSCROLL)):colwidth2),
+ WASABI_API_LNGSTRINGW(IDS_GHK_HOTKEY_COLUMN), 0, 0
+ };
+
+ ListView_InsertColumnW(hwHKList, 0, &lc);
+
+ lc.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
+ colwidth1 = GetPrivateProfileIntW(L"gen_hotkeys", L"col1", -1, g_iniFile);
+ lc.cx = (colwidth1==-1?(r.right - lc.cx - GetSystemMetrics(SM_CYHSCROLL)):colwidth1);
+ lc.pszText = WASABI_API_LNGSTRINGW(IDS_GHK_ACTION_COLUMN);
+ lc.iSubItem = 1;
+
+ ListView_InsertColumnW(hwHKList, 0, &lc);
+ }
+
+ changed = false;
+ SubclassEditBox(hwHK);
+ if (NULL != hwHK && NULL == pAccelBlock)
+ pAccelBlock = new AcceleratorBlocker(hwHK);
+
+ HBITMAP hBitmap = LoadBitmap(psPlugin.hDllInstance, MAKEINTRESOURCE(IDB_LVSTATE));
+
+ HIMAGELIST hImageList = ImageList_Create(14, 14, ILC_COLOR8|ILC_MASK, 1, 0);
+ ImageList_AddMasked(hImageList, hBitmap, RGB(252, 254, 252));
+ ListView_SetImageList(hwHKList, hImageList, LVSIL_STATE);
+ DeleteObject(hBitmap);
+
+ ListView_SetItemCount(hwHKList, g_dwHotkeys);
+
+ // We don't want our hot keys while in the config
+ for (size_t i = 0; i < g_dwHotkeys; i++)
+ {
+ SetLastError(0);
+ UnregisterHotkey(g_hotkeys + i);
+ SetListItem(hwHKList, hwHK, &g_hotkeys[i].hkd, -1, g_hotkeys[i].failed);
+ }
+ hotkeysClear();
+
+ if(colwidth1==-1)
+ ListView_SetColumnWidth(hwHKList, 0, LVSCW_AUTOSIZE);
+ if(colwidth2==-1)
+ ListView_SetColumnWidth(hwHKList, 1, LVSCW_AUTOSIZE);
+
+ // clear
+ SendMessage(hwHK, wmHKCtlSet, 0, 0);
+
+ ListView_SetItemState(hwHKList, -1, 0, LVIS_SELECTED);
+
+ SendMessage(hwHKList, WM_SETREDRAW, TRUE, 0);
+
+ int width = 0;
+ for (size_t i = 0; i < GetCommandsNum(); i++)
+ {
+ bool unicode = 0;
+ char *cmdname = GetCommandName((unsigned int)i, &unicode);
+ if (*cmdname)
+ {
+ LRESULT pos;
+ if (unicode)
+ {
+ pos = SendMessageW(hwCombo, CB_ADDSTRING, 0, (LPARAM) cmdname);
+ width = ResizeComboBoxDropDownW(hwndDlg, IDC_COMBO, (wchar_t*)cmdname, width);
+ }
+ else
+ {
+ pos = SendMessageA(hwCombo, CB_ADDSTRING, 0, (LPARAM) cmdname);
+ width = ResizeComboBoxDropDown(hwndDlg, IDC_COMBO, cmdname, width);
+ }
+ SendMessage(hwCombo, CB_SETITEMDATA, pos, i);
+ }
+ }
+
+ // Set the enabled checkbox
+ CheckDlgButton(hwndDlg,IDC_ENABLED,GetPrivateProfileIntW(L"gen_hotkeys", L"enabled", 0, g_iniFile));
+ CheckDlgButton(hwndDlg,IDC_ENABLED_WM_APPCOMMAND,GetPrivateProfileIntW(L"gen_hotkeys", L"appcommand", 0, g_iniFile));
+ setCheckedStuff(hwndDlg);
+
+ if (NULL != WASABI_API_APP)
+ WASABI_API_APP->DirectMouseWheel_EnableConvertToMouseWheel(hwHKList, TRUE);
+
+ break;
+ }
+
+ case WM_COMMAND:
+ {
+ // we don't want accelerator keys working when the hotkey window is focused
+ // that could be a problem if someone wants to bind Alt+D for example...
+ if (GetFocus() == hwHK)
+ break;
+
+ switch (LOWORD(wParam))
+ {
+ case IDC_ADD:
+ {
+ HOTKEY_DATA hkd;
+ DWORD dwHotKey = (unsigned long)SendMessage(hwHK, wmHKCtlGet, 0, 0);
+ UINT iCommand = (unsigned int)SendMessage(hwCombo, CB_GETITEMDATA, SendMessage(hwCombo, CB_GETCURSEL, 0, 0), 0);
+
+ if (!dwHotKey || iCommand == CB_ERR)
+ break;
+
+ hkd.dwHotKey = dwHotKey;
+ hkd.iCommand = iCommand;
+
+ changed = true;
+ SetListItem(hwHKList, hwHK, &hkd);
+ break;
+ }
+
+ case IDC_REMOVE:
+ {
+ int i = ListView_GetNextItem(hwHKList, -1, LVNI_SELECTED);
+ while (i != -1)
+ {
+ LVITEM lvi = {LVIF_PARAM, i};
+ ListView_GetItem(hwHKList, &lvi);
+ HOTKEY_DATA *hkd = (HOTKEY_DATA *) lvi.lParam;
+ delete hkd;
+
+ changed = true;
+ ListView_DeleteItem(hwHKList, i);
+ i = ListView_GetNextItem(hwHKList, -1, LVNI_SELECTED);
+ }
+ EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE), 0);
+ break;
+ }
+
+ case IDC_SAVE:
+ {
+ if (ListView_GetSelectedCount(hwHKList) != 1)
+ break;
+
+ int iSel = ListView_GetNextItem(hwHKList, -1, LVNI_SELECTED);
+
+ LVITEMW lvi = {LVIF_PARAM, iSel};
+ ListView_GetItem(hwHKList, &lvi);
+ HOTKEY_DATA *hkd = (HOTKEY_DATA *) lvi.lParam;
+ if (hkd)
+ {
+ DWORD dwHotKey = (unsigned long)SendMessage(hwHK, wmHKCtlGet, 0, 0);
+ UINT iCommand = (unsigned int)SendMessage(hwCombo, CB_GETITEMDATA, SendMessage(hwCombo, CB_GETCURSEL, 0, 0), 0);
+
+ if (!dwHotKey || iCommand == CB_ERR)
+ break;
+
+ hkd->dwHotKey = dwHotKey;
+ hkd->iCommand = iCommand;
+
+ changed = true;
+ SetListItem(hwHKList, hwHK, hkd, iSel);
+ }
+ break;
+ }
+
+ case IDC_ENABLED:
+ if (setCheckedStuff(hwndDlg))
+ {
+ DWORD dwSelected = ListView_GetSelectedCount(hwHKList);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SAVE), dwSelected == 1);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE), dwSelected);
+ changed = true;
+ }
+ break;
+
+ case IDC_DEFAULT:
+ {
+ DWORD i;
+ SendMessage(hwndDlg, WM_SETREDRAW, FALSE, 0);
+
+ DWORD dwCount = (DWORD)ListView_GetItemCount(hwHKList);
+ if (dwCount)
+ {
+ for (i = 0; i < dwCount; i++)
+ {
+ LVITEM lvi = {LVIF_PARAM,(int)i};
+ ListView_GetItem(hwHKList, &lvi);
+ HOTKEY_DATA *hkd = (HOTKEY_DATA *) lvi.lParam;
+ delete hkd;
+ }
+ }
+
+ changed = true;
+ ListView_DeleteAllItems(hwHKList);
+
+ for (i = 0; i < DEFHKDS_NUM; i++)
+ {
+ SetListItem(hwHKList, hwHK, g_defhkds + i);
+ }
+
+ // restore the size of the columns on a reset as well
+ ListView_SetColumnWidth(hwHKList, 0, LVSCW_AUTOSIZE);
+ ListView_SetColumnWidth(hwHKList, 1, LVSCW_AUTOSIZE);
+
+ ListView_SetItemState(hwHKList, -1, 0, LVIS_SELECTED);
+ SendMessage(hwndDlg, WM_SETREDRAW, TRUE, 0);
+ InvalidateRect(hwndDlg, 0, 0);
+ break;
+ }
+ }
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR nmhdr = (LPNMHDR) lParam;
+ if (nmhdr && nmhdr->idFrom == IDC_HKLIST)
+ {
+ if (nmhdr->code == LVN_ITEMCHANGED)
+ {
+ LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
+ DWORD dwSelected = ListView_GetSelectedCount(hwHKList);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_SAVE), dwSelected == 1);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_REMOVE), dwSelected);
+
+ SendMessage(hwHK, wmHKCtlSet, 0, 0);
+ SendMessage(hwCombo, CB_SETCURSEL, -1, 0);
+
+ if (dwSelected == 1 && (pnmv->uNewState & LVIS_SELECTED))
+ {
+ HOTKEY_DATA *hkd = (HOTKEY_DATA *) pnmv->lParam;
+ if (hkd)
+ {
+ SendMessage(hwHK, wmHKCtlSet, hkd->dwHotKey, 0);
+ bool unicode = 0;
+ char *cmd = GetCommandName(hkd->iCommand, &unicode);
+ if (*cmd)
+ {
+ if(unicode) SendMessageW(hwCombo, CB_SELECTSTRING, -1, (LPARAM) cmd);
+ else SendMessageA(hwCombo, CB_SELECTSTRING, -1, (LPARAM) cmd);
+ }
+ }
+ }
+ }
+ else if(nmhdr->code == LVN_KEYDOWN)
+ {
+ LPNMLVKEYDOWN pnmv = (LPNMLVKEYDOWN) lParam;
+ if(pnmv->wVKey == VK_DELETE)
+ {
+ changed = true;
+ SendMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_REMOVE,0),0);
+ }
+ else if(pnmv->wVKey == 'A' && GetAsyncKeyState(VK_CONTROL))
+ {
+ for(int i = 0; i < ListView_GetItemCount(hwHKList); i++)
+ {
+ ListView_SetItemState(hwHKList,i,LVIS_SELECTED,LVIS_SELECTED);
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ int checked = (SendMessage(GetDlgItem(hwndDlg, IDC_ENABLED), BM_GETCHECK, 0, 0) == BST_CHECKED);
+ writePrivateProfileInt(L"enabled", checked);
+ writePrivateProfileInt(L"appcommand",
+ (SendMessage(GetDlgItem(hwndDlg, IDC_ENABLED_WM_APPCOMMAND), BM_GETCHECK, 0, 0) == BST_CHECKED));
+ hotkeysClear();
+
+ int iCount = ListView_GetItemCount(hwHKList);
+ HOTKEY_DATA *hkds = NULL;
+ if (iCount)
+ {
+ hkds = new HOTKEY_DATA[iCount]; // TODO: could alloca this
+ memset(hkds, 0, iCount * sizeof(HOTKEY_DATA));
+ }
+ if (hkds || !iCount)
+ {
+ for (size_t i = 0; i < (unsigned int)iCount; i++)
+ {
+ LVITEM lvi = {LVIF_PARAM, (int)i};
+ ListView_GetItem(hwHKList, &lvi);
+ HOTKEY_DATA *hkd = (HOTKEY_DATA *) lvi.lParam;
+ if (hkd)
+ {
+ hkds[i] = *hkd;
+ delete hkd;
+ }
+ }
+
+ hotkeysLoad(hkds, iCount, checked);
+ if (changed) hotkeysSave(hkds, iCount);
+ delete [] hkds;
+ }
+ writePrivateProfileInt(L"col1", ListView_GetColumnWidth(hwHKList,0));
+ writePrivateProfileInt(L"col2", ListView_GetColumnWidth(hwHKList,1));
+ RegisterShellHookWindow(psPlugin.hwndParent);
+ if (NULL != pAccelBlock && hwHK == pAccelBlock->GetHwnd())
+ {
+ delete(pAccelBlock);
+ pAccelBlock = NULL;
+ }
+
+ if (NULL != WASABI_API_APP)
+ WASABI_API_APP->DirectMouseWheel_EnableConvertToMouseWheel(hwHKList, FALSE);
+ }
+ break;
+ }
+ return FALSE;
+}
+
+// idx = -1 for insertion
+void SetListItem(HWND hwHKList, HWND hwHK, HOTKEY_DATA *hk_data, int idx, int failed)
+{
+ wchar_t szHK[1024] = {L""};
+
+ SendMessage(hwHK, wmHKCtlSet, hk_data->dwHotKey, 0);
+ GetWindowTextW(hwHK, szHK, sizeof(szHK));
+
+ HOTKEY_DATA *hk_data_allocated = 0;
+
+ if (idx < 0)
+ hk_data_allocated = new HOTKEY_DATA;
+
+ if (idx >= 0 || hk_data_allocated)
+ {
+ if (idx < 0)
+ *hk_data_allocated = *hk_data;
+
+ int pos = ListView_GetItemCount(hwHKList);
+
+ if (idx >= 0)
+ pos = idx;
+
+ // Add item to the list
+ bool unicode = 0;
+ LVITEM lvi = {
+ LVIF_PARAM | LVIF_TEXT | LVIF_STATE,
+ pos,
+ 0,
+ LVIS_SELECTED | INDEXTOSTATEIMAGEMASK(failed ? (UINT)1 : 0) | LVIS_FOCUSED,
+ LVIS_SELECTED | LVIS_STATEIMAGEMASK | LVIS_FOCUSED,
+ GetCommandName(hk_data->iCommand, &unicode),
+ 0,
+ 0,
+ (LPARAM) hk_data_allocated
+ };
+
+ char tmp[1024] = {0};
+
+ if (!lvi.pszText || !*lvi.pszText)
+ {
+ if (hk_data->szCommand)
+ {
+ StringCchPrintf(tmp, 1024, "[%s]", hk_data->szCommand);
+ lvi.pszText = tmp;
+ }
+ }
+ if (!lvi.pszText || !*lvi.pszText)
+ lvi.pszText = WASABI_API_LNGSTRING(IDS_GHK_ACTION_NOT_FOUND);
+
+ if (idx >= 0)
+ {
+ lvi.mask ^= LVIF_PARAM;
+ if(unicode) ListView_SetItemW(hwHKList, &lvi);
+ else ListView_SetItem(hwHKList, &lvi);
+ }
+ else
+ {
+ ListView_SetItemState(hwHKList, -1, 0, LVIS_SELECTED | LVIS_FOCUSED);
+ if(unicode) ListView_InsertItemW(hwHKList, &lvi);
+ else ListView_InsertItem(hwHKList, &lvi);
+ }
+ ListView_SetItemTextW(hwHKList, pos, 1, szHK);
+ }
+} \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/Configdlg.h b/Src/Plugins/General/gen_hotkeys/Configdlg.h
new file mode 100644
index 00000000..a6fc772a
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/Configdlg.h
@@ -0,0 +1,9 @@
+#ifndef __CONFIG_DIALOG_H__
+#define __CONFIG_DIALOG_H__
+
+#include <windows.h>
+#include "resource.h"
+
+BOOL CALLBACK ConfigProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam);
+
+#endif \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/HOTKEY.CPP b/Src/Plugins/General/gen_hotkeys/HOTKEY.CPP
new file mode 100644
index 00000000..ad6144dc
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/HOTKEY.CPP
@@ -0,0 +1,56 @@
+// HotKey.cpp: implementation of the CHotKey class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "gen_hotkeys.h"
+#include "HotKey.h"
+
+//////////////////////////////////////////////////////////////////////
+// Registration / Unregstration
+//////////////////////////////////////////////////////////////////////
+
+int RegisterHotkey(HOTKEY *hk)
+{
+ if (!hk) return 1;
+
+ wchar_t atomName[1024] = {0};
+ bool unicode = 0;
+ char* name = GetCommandName(hk->hkd.iCommand, &unicode);
+ StringCchPrintfW(atomName, 1024, (unicode?L"%s %X %X %X":L"%hs %X %X %X"), name, hk->hkd.dwHotKey, hk->hkd.iCommand, GetTickCount());
+ hk->atom = GlobalAddAtomW(atomName);
+ if (!hk->atom)
+ return 1;
+
+ return !RegisterHotKey(psPlugin.hwndParent, hk->atom, GetModKeys(hk->hkd.dwHotKey), LOBYTE(hk->hkd.dwHotKey));
+}
+
+void UnregisterHotkey(HOTKEY *hk)
+{
+ if (!hk || !hk->atom)
+ return;
+
+ UnregisterHotKey(psPlugin.hwndParent, hk->atom);
+ GlobalDeleteAtom(hk->atom);
+ hk->atom = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Set / Get
+//////////////////////////////////////////////////////////////////////
+
+UINT GetModKeys(DWORD dwHotKey)
+{
+ UINT result = 0;
+ WORD wHotKey = HIBYTE(dwHotKey);
+
+ if (wHotKey & HOTKEYF_ALT)
+ result |= MOD_ALT;
+ if (wHotKey & HOTKEYF_CONTROL)
+ result |= MOD_CONTROL;
+ if (wHotKey & HOTKEYF_WIN)
+ result |= MOD_WIN;
+ if (wHotKey & HOTKEYF_SHIFT)
+ result |= MOD_SHIFT;
+
+ return result;
+} \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/HOTKEY.H b/Src/Plugins/General/gen_hotkeys/HOTKEY.H
new file mode 100644
index 00000000..88919dae
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/HOTKEY.H
@@ -0,0 +1,32 @@
+// HotKey.h: interface for the CHotKey class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_HOTKEY_H__82523B98_0E49_4B2A_8206_A4262D29C3C8__INCLUDED_)
+#define AFX_HOTKEY_H__82523B98_0E49_4B2A_8206_A4262D29C3C8__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "gen_hotkeys.h"
+
+struct HOTKEY_DATA
+{
+ DWORD dwHotKey;
+ int iCommand;
+ wchar_t *szCommand;
+};
+
+struct HOTKEY
+{
+ HOTKEY_DATA hkd;
+ ATOM atom;
+ BOOL failed;
+};
+
+int RegisterHotkey(HOTKEY *hk);
+void UnregisterHotkey(HOTKEY *hk);
+UINT GetModKeys(DWORD dwHotKey);
+
+#endif // !defined(AFX_HOTKEY_H__82523B98_0E49_4B2A_8206_A4262D29C3C8__INCLUDED_) \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/HotKeyCtl.cpp b/Src/Plugins/General/gen_hotkeys/HotKeyCtl.cpp
new file mode 100644
index 00000000..61e1ea28
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/HotKeyCtl.cpp
@@ -0,0 +1,293 @@
+#include "HotKeyCtl.h"
+#include "gen_hotkeys.h"
+
+struct HKWND_DATA
+{
+ WNDPROC lpfnEditWndProc;
+ DWORD dwScanCode;
+ WORD wMod;
+ DWORD dwHotKey;
+};
+
+LRESULT CALLBACK HotKeyWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+#if(_WIN32_WINNT < 0x0500)
+#define VK_BROWSER_BACK 0xA6
+#define VK_BROWSER_FORWARD 0xA7
+#define VK_BROWSER_REFRESH 0xA8
+#define VK_BROWSER_STOP 0xA9
+#define VK_BROWSER_SEARCH 0xAA
+#define VK_BROWSER_FAVORITES 0xAB
+#define VK_BROWSER_HOME 0xAC
+
+#define VK_VOLUME_MUTE 0xAD
+#define VK_VOLUME_DOWN 0xAE
+#define VK_VOLUME_UP 0xAF
+#define VK_MEDIA_NEXT_TRACK 0xB0
+#define VK_MEDIA_PREV_TRACK 0xB1
+#define VK_MEDIA_STOP 0xB2
+#define VK_MEDIA_PLAY_PAUSE 0xB3
+#define VK_LAUNCH_MAIL 0xB4
+#define VK_LAUNCH_MEDIA_SELECT 0xB5
+#define VK_LAUNCH_APP1 0xB6
+#define VK_LAUNCH_APP2 0xB7
+#endif
+
+#ifndef VK_SLEEP
+#define VK_SLEEP 0x5F
+#endif
+
+UINT wmHKCtlSet;
+UINT wmHKCtlGet;
+
+int SubclassEditBox(HWND hwEdit)
+{
+ if (!IsWindow(hwEdit))
+ return 0;
+
+ if (!wmHKCtlSet)
+ wmHKCtlSet = RegisterWindowMessage("gen_hotkeys HotKeyCTL set");
+
+ if (!wmHKCtlGet)
+ wmHKCtlGet = RegisterWindowMessage("gen_hotkeys HotKeyCTL get");
+
+ HKWND_DATA *hkwnd_data = new HKWND_DATA;
+ if (!hkwnd_data)
+ return 0;
+
+ memset(hkwnd_data, 0, sizeof(HKWND_DATA));
+
+ hkwnd_data->lpfnEditWndProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(hwEdit, GWLP_WNDPROC, (LONGX86)(LONG_PTR)HotKeyWndProc);
+
+ SetWindowLongPtr(hwEdit, GWLP_USERDATA, (LONGX86)(LONG_PTR) hkwnd_data);
+
+ return 1;
+}
+
+void HotKeySetText(HWND hwHK, HKWND_DATA *hkwnd_data)
+{
+ if (!IsWindow(hwHK) || !hkwnd_data)
+ return;
+
+ wchar_t szKeyName[1024] = L"";
+ wchar_t *p = szKeyName;
+ DWORD dwSize = sizeof(szKeyName);
+ DWORD dwLen = 0;
+ WORD wMod;
+
+ if (hkwnd_data->dwHotKey)
+ wMod = HIBYTE(hkwnd_data->dwHotKey);
+ else
+ wMod = hkwnd_data->wMod;
+
+ if(wMod & HOTKEYF_WIN) {
+ // GetKeyNameText gives us Left/Right Windows but RegisterHotKey doesn't seperate the two
+ //GetKeyNameText(MAKELPARAM(0, MapVirtualKey(VK_LWIN, 0)) | (1 << 24), p, dwSize);
+ // so we use just "Winkey" to avoid confusion
+ WASABI_API_LNGSTRINGW_BUF(IDS_GHK_WINKEY_STR,p,dwSize);
+ dwLen = lstrlenW(szKeyName);
+ StringCchCatW(p, dwSize, L" + ");
+ dwSize -= dwLen + 3;
+ p = szKeyName + dwLen + 3;
+ }
+ if(wMod & HOTKEYF_CONTROL) {
+ GetKeyNameTextW(MAKELONG(0, MapVirtualKey(VK_CONTROL, 0)), p, dwSize);
+ dwLen = lstrlenW(szKeyName);
+ StringCchCatW(p, dwSize, L" + ");
+ dwSize -= dwLen + 3;
+ p = szKeyName + dwLen + 3;
+ }
+ if(wMod & HOTKEYF_SHIFT) {
+ GetKeyNameTextW(MAKELONG(0, MapVirtualKey(VK_SHIFT, 0)), p, dwSize);
+ dwLen = lstrlenW(szKeyName);
+ StringCchCatW(p, dwSize, L" + ");
+ dwSize -= dwLen + 3;
+ p = szKeyName + dwLen + 3;
+ }
+ if(wMod & HOTKEYF_ALT) {
+ GetKeyNameTextW(MAKELONG(0, MapVirtualKey(VK_MENU, 0)), p, dwSize);
+ dwLen = lstrlenW(szKeyName);
+ StringCchCatW(p, dwSize, L" + ");
+ dwSize -= dwLen + 3;
+ p = szKeyName + dwLen + 3;
+ }
+
+ if(hkwnd_data->dwHotKey)
+ {
+ switch (LOBYTE(hkwnd_data->dwHotKey))
+ {
+ case VK_BROWSER_BACK:
+ WASABI_API_LNGSTRINGW_BUF(IDS_BROWSER_BACK,p,dwSize);
+ break;
+ case VK_BROWSER_FORWARD:
+ WASABI_API_LNGSTRINGW_BUF(IDS_BROWSER_FORWARD,p,dwSize);
+ break;
+ case VK_BROWSER_REFRESH:
+ WASABI_API_LNGSTRINGW_BUF(IDS_BROWSER_REFRESH,p,dwSize);
+ break;
+ case VK_BROWSER_STOP:
+ WASABI_API_LNGSTRINGW_BUF(IDS_BROWSER_STOP,p,dwSize);
+ break;
+ case VK_BROWSER_SEARCH:
+ WASABI_API_LNGSTRINGW_BUF(IDS_BROWSER_SEARCH,p,dwSize);
+ break;
+ case VK_BROWSER_FAVORITES:
+ WASABI_API_LNGSTRINGW_BUF(IDS_BROWSER_FAVOURITES,p,dwSize);
+ break;
+ case VK_BROWSER_HOME:
+ WASABI_API_LNGSTRINGW_BUF(IDS_BROWSER_HOME,p,dwSize);
+ break;
+ case VK_VOLUME_MUTE:
+ WASABI_API_LNGSTRINGW_BUF(IDS_VOLUME_MUTE,p,dwSize);
+ break;
+ case VK_VOLUME_DOWN:
+ WASABI_API_LNGSTRINGW_BUF(IDS_VOLUME_DOWN,p,dwSize);
+ break;
+ case VK_VOLUME_UP:
+ WASABI_API_LNGSTRINGW_BUF(IDS_VOLUME_UP,p,dwSize);
+ break;
+ case VK_MEDIA_NEXT_TRACK:
+ WASABI_API_LNGSTRINGW_BUF(IDS_NEXT_TRACK,p,dwSize);
+ break;
+ case VK_MEDIA_PREV_TRACK:
+ WASABI_API_LNGSTRINGW_BUF(IDS_PREVIOUS_TRACK,p,dwSize);
+ break;
+ case VK_MEDIA_STOP:
+ WASABI_API_LNGSTRINGW_BUF(IDS_STOP,p,dwSize);
+ break;
+ case VK_MEDIA_PLAY_PAUSE:
+ WASABI_API_LNGSTRINGW_BUF(IDS_PLAY_PAUSE,p,dwSize);
+ break;
+ case VK_LAUNCH_MAIL:
+ WASABI_API_LNGSTRINGW_BUF(IDS_LAUNCH_MAIL,p,dwSize);
+ break;
+ case VK_LAUNCH_MEDIA_SELECT:
+ WASABI_API_LNGSTRINGW_BUF(IDS_LAUNCH_MEDIA_SELECT,p,dwSize);
+ break;
+ case VK_LAUNCH_APP1:
+ WASABI_API_LNGSTRINGW_BUF(IDS_LAUCH_APP1,p,dwSize);
+ break;
+ case VK_LAUNCH_APP2:
+ WASABI_API_LNGSTRINGW_BUF(IDS_LAUCH_APP2,p,dwSize);
+ break;
+ case VK_SLEEP:
+ WASABI_API_LNGSTRINGW_BUF(IDS_SLEEP,p,dwSize);
+ break;
+ case VK_PAUSE:
+ WASABI_API_LNGSTRINGW_BUF(IDS_PAUSE,p,dwSize);
+ break;
+ default:
+ GetKeyNameTextW(hkwnd_data->dwScanCode, p, dwSize);
+ if (!*p)
+ StringCchPrintfW(p, 1024, L"0x%X", hkwnd_data->dwScanCode);
+ break;
+ }
+ }
+ else
+ szKeyName[dwLen] = 0;
+
+ SetWindowTextW(hwHK, szKeyName);
+
+ SendMessageW(hwHK, EM_SETSEL, lstrlenW(szKeyName), lstrlenW(szKeyName));
+}
+
+LRESULT CALLBACK HotKeyWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ HKWND_DATA *hkwnd_data = (HKWND_DATA *)(LONG_PTR)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+ HKWND_DATA hkwnd_data_local;
+
+ if (uMsg == wmHKCtlSet)
+ {
+ int extflag = 0;
+ if (HIBYTE(wParam) & HOTKEYF_EXT)
+ extflag = (1 << 24);
+
+ hkwnd_data->dwHotKey = (unsigned long)wParam;
+ hkwnd_data->dwScanCode = MAKELPARAM(0, MapVirtualKey(LOBYTE(wParam), 0)) | extflag;
+ //hkwnd_data->wMod = HIBYTE(wParam);
+ HotKeySetText(hwnd, hkwnd_data);
+ return 0;
+ }
+ else if (uMsg == wmHKCtlGet)
+ {
+ return hkwnd_data->dwHotKey;
+ }
+
+ switch (uMsg)
+ {
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ {
+ hkwnd_data->dwHotKey = 0;
+
+ switch (wParam)
+ {
+ case VK_SHIFT:
+ hkwnd_data->wMod |= HOTKEYF_SHIFT;
+ break;
+ case VK_CONTROL:
+ hkwnd_data->wMod |= HOTKEYF_CONTROL;
+ break;
+ case VK_MENU:
+ hkwnd_data->wMod |= HOTKEYF_ALT;
+ break;
+ case VK_LWIN:
+ case VK_RWIN:
+ hkwnd_data->wMod |= HOTKEYF_WIN;
+ break;
+ default:
+ hkwnd_data->dwScanCode = (unsigned long)lParam;
+ if (lParam & (1 << 24)) // extended bit
+ hkwnd_data->wMod |= HOTKEYF_EXT;
+ else
+ hkwnd_data->wMod &= ~HOTKEYF_EXT;
+ hkwnd_data->dwHotKey = MAKEWORD(wParam, hkwnd_data->wMod);
+ break;
+ }
+
+ HotKeySetText(hwnd, hkwnd_data);
+ return 1;
+ }
+
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ {
+ switch (wParam)
+ {
+ case VK_SHIFT:
+ hkwnd_data->wMod &= ~HOTKEYF_SHIFT;
+ break;
+ case VK_CONTROL:
+ hkwnd_data->wMod &= ~HOTKEYF_CONTROL;
+ break;
+ case VK_MENU:
+ hkwnd_data->wMod &= ~HOTKEYF_ALT;
+ break;
+ case VK_LWIN:
+ case VK_RWIN:
+ hkwnd_data->wMod &= ~HOTKEYF_WIN;
+ break;
+ }
+
+ HotKeySetText(hwnd, hkwnd_data);
+ return 1;
+ }
+
+ case WM_CHAR:
+ case WM_PASTE:
+ return 0;
+
+ case WM_DESTROY:
+ if (hkwnd_data)
+ {
+ SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR) hkwnd_data->lpfnEditWndProc);
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
+ hkwnd_data_local = *hkwnd_data;
+ delete hkwnd_data;
+ hkwnd_data = &hkwnd_data_local;
+ }
+ break;
+ }
+
+ return CallWindowProc(hkwnd_data->lpfnEditWndProc, hwnd, uMsg, wParam, lParam);
+} \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/HotKeyCtl.h b/Src/Plugins/General/gen_hotkeys/HotKeyCtl.h
new file mode 100644
index 00000000..237aabba
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/HotKeyCtl.h
@@ -0,0 +1,13 @@
+#ifndef ____HOTKEY_CTL___H____
+#define ____HOTKEY_CTL___H____
+
+#include <windows.h>
+
+#define HOTKEYF_WIN 0x10
+
+int SubclassEditBox(HWND hwEdit);
+
+extern UINT wmHKCtlSet;
+extern UINT wmHKCtlGet;
+
+#endif//____HOTKEY_CTL___H____ \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/RESOURCE.H b/Src/Plugins/General/gen_hotkeys/RESOURCE.H
new file mode 100644
index 00000000..0cfe5975
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/RESOURCE.H
@@ -0,0 +1,116 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by gen_hotkeys.rc
+//
+#define IDS_GHK_TITLE_STR 0
+#define IDS_GHK_HOTKEY_REG_FAILED 1
+#define IDC_CANCEL 2
+#define IDS_GHK_HOTKEY_REG_FAILED_MORE 2
+#define IDS_GHK_ABOUT_TEXT 3
+#define IDS_GHK_HOTKEY_COLUMN 4
+#define IDS_GHK_ACTION_COLUMN 5
+#define IDS_GHK_ACTION_NOT_FOUND 6
+#define IDS_GHK_WINKEY_STR 7
+#define IDS_BROWSER_BACK 8
+#define IDS_BROWSER_FORWARD 9
+#define IDS_BROWSER_REFRESH 10
+#define IDS_BROWSER_STOP 11
+#define IDS_BROWSER_SEARCH 12
+#define IDS_BROWSER_FAVOURITES 13
+#define IDS_BROWSER_HOME 14
+#define IDS_VOLUME_MUTE 15
+#define IDS_VOLUME_DOWN 16
+#define IDS_VOLUME_UP 17
+#define IDS_NEXT_TRACK 18
+#define IDS_PREVIOUS_TRACK 19
+#define IDS_STOP 20
+#define IDS_PLAY_PAUSE 21
+#define IDS_LAUNCH_MAIL 22
+#define IDS_LAUNCH_MEDIA_SELECT 23
+#define IDS_LAUCH_APP1 24
+#define IDS_LAUCH_APP2 25
+#define IDS_SLEEP 26
+#define IDS_PLAYBACK__PLAY 32
+#define IDS_PLAYBACK__PAUSE 33
+#define IDS_PLAYBACK__STOP 34
+#define IDS_PLAYBACK__PREVIOUS_IN_PLAYLIST 35
+#define IDS_PLAYBACK__NEXT_IN_PLAYLIST 36
+#define IDS_PLAYBACK__VOLUME_UP 37
+#define IDS_PLAYBACK__VOLUME_DOWN 38
+#define IDS_PLAYBACK__FORWARD 39
+#define IDS_PLAYBACK__REWIND 40
+#define IDS_PLAYBACK__REPEAT_ON 41
+#define IDS_PLAYBACK__REPEAT_OFF 42
+#define IDS_UI__TOGGLE_EQ 43
+#define IDS_UI__TOGGLE_PLAYLIST 44
+#define IDS_UI__TOGGLE_AOT 45
+#define IDS_UI__ABOUT 46
+#define IDS_PLAYBACK__JUMP_TO_BOX 47
+#define IDS_PLAYBACK__OPEN_FILE_DIALOG 48
+#define IDS_PLAYBACK__OPEN_LOC_DIALOG 49
+#define IDS_PLAYBACK__OPEN_FOLDER_DIALOG 50
+#define IDS_GENERAL__QUIT 51
+#define IDS_UI__PREFERENCES 52
+#define IDS_GENERAL__COPY_TITLE 53
+#define IDS_GENERAL__COPY_FILE_PATH 54
+#define IDS_PLAYBACK__PLAY_PAUSE 55
+#define IDS_PLAYBACK__TOGGLE_REPEAT 56
+#define IDS_PLAYBACK__TOGGLE_SHUFFLE 57
+#define IDS_UI__TOGGLE_WINSHADE 58
+#define IDS_UI__TOGGLE_PLAYLIST_WINSHADE 59
+#define IDS_UI__TOGGLE_DOUBLESIZE 60
+#define IDS_UI__TOGGLE_MAIN_WINDOW 61
+#define IDS_UI__TOGGLE_MINIBROWSER 62
+#define IDS_VIS__PREFERENCES 63
+#define IDS_VIS__PLUGIN_PREFERENCES 64
+#define IDS_VIS_TOGGLE_VIS_ON_OFF 65
+#define IDS_UI__SELECT_SKIN 66
+#define IDS_PLAYBACK__STOP_WITH_FADEOUT 67
+#define IDS_PLAYBACK__STOP_AFTER_CURRENT 68
+#define IDS_PLAYBACK__START_OF_LIST 69
+#define IDS_PLAYBACK__END_OF_LIST 70
+#define IDS_UI__BRING_TO_FRONT_OR_HIDE 71
+#define IDS_RATING__5_STARS 72
+#define IDS_RATING__4_STARS 73
+#define IDS_RATING__3_STARS 74
+#define IDS_RATING__2_STARS 75
+#define IDS_RATING__1_STAR 76
+#define IDS_RATING__NO_RATING 77
+#define IDS_GENERAL__COPY_TITLEW 78
+#define IDS_GENERAL__COPY_FILE_PATHW 79
+#define IDS_RATING__INC 80
+#define IDS_RATING__DEC 81
+#define IDS_PAUSE 82
+#define IDS_VIS_NEXT_PRESET 83
+#define IDS_VIS_PREV_PRESET 84
+#define IDS_VIS_RAND_PRESET 85
+#define IDS_VIS_FULL_SCREEN 86
+#define IDS_VIS_CONFIG 87
+#define IDS_PLAYBACK__MANUAL_ADVANCE 87
+#define IDS_VIS_MENU 88
+#define IDS_GENERAL_FFOD 89
+#define IDS_PLAYBACK_EDIT_ID3 90
+#define IDD_CONFIG 101
+#define IDB_LOGO 103
+#define IDB_LVSTATE 104
+#define IDC_ENABLED 1006
+#define IDC_ENABLED_WM_APPCOMMAND 1007
+#define IDC_HOTKEY 1012
+#define IDC_HKLIST 1017
+#define IDC_COMBO 1018
+#define IDC_SAVE 1019
+#define IDC_ADD 1020
+#define IDC_REMOVE 1021
+#define IDC_DEFAULT 1022
+#define IDS_NULLSOFT_GLOBAL_HOTKEYS 65534
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 91
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1024
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Src/Plugins/General/gen_hotkeys/WINAMP.H b/Src/Plugins/General/gen_hotkeys/WINAMP.H
new file mode 100644
index 00000000..2ebafaf6
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/WINAMP.H
@@ -0,0 +1,38 @@
+#ifndef _WAFE_H_
+#define _WAFE_H_
+
+#define IPC_FF_FIRST 2000
+#define IPC_FF_NOTIFYHOTKEY IPC_FF_FIRST + 6 // data = const char * to hotkey description
+
+#define WINAMP_OPTIONS_EQ 40036 // toggles the EQ window
+#define WINAMP_OPTIONS_PLEDIT 40040 // toggles the playlist window
+#define WINAMP_VOLUMEUP 40058 // turns the volume up a little
+#define WINAMP_VOLUMEDOWN 40059 // turns the volume down a little
+#define WINAMP_FFWD5S 40060 // fast forwards 5 seconds
+#define WINAMP_REW5S 40061 // rewinds 5 seconds
+
+// the following are the five main control buttons, with optionally shift
+// or control pressed
+// (for the exact functions of each, just try it out)
+#define WINAMP_BUTTON1 40044
+#define WINAMP_BUTTON2 40045
+#define WINAMP_BUTTON3 40046
+#define WINAMP_BUTTON4 40047
+#define WINAMP_BUTTON5 40048
+#define WINAMP_BUTTON1_SHIFT 40144
+#define WINAMP_BUTTON2_SHIFT 40145
+#define WINAMP_BUTTON3_SHIFT 40146
+#define WINAMP_BUTTON4_SHIFT 40147
+#define WINAMP_BUTTON5_SHIFT 40148
+#define WINAMP_BUTTON1_CTRL 40154
+#define WINAMP_BUTTON2_CTRL 40155
+#define WINAMP_BUTTON3_CTRL 40156
+#define WINAMP_BUTTON4_CTRL 40157
+#define WINAMP_BUTTON5_CTRL 40158
+
+#define WINAMP_FILE_PLAY 40029 // pops up the load file(s) box
+#define WINAMP_OPTIONS_PREFS 40012 // pops up the preferences
+#define WINAMP_OPTIONS_AOT 40019 // toggles always on top
+#define WINAMP_HELP_ABOUT 40041 // pops up the about box :)
+
+#endif \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/Wacommands.cpp b/Src/Plugins/General/gen_hotkeys/Wacommands.cpp
new file mode 100644
index 00000000..7acc71fc
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/Wacommands.cpp
@@ -0,0 +1,366 @@
+#include "WACommands.h"
+#include "gen_hotkeys.h"
+#include "../nu/AutoWide.h"
+
+typedef struct {
+ UINT strId;
+ genHotkeysAddStruct ghk;
+} genHotkeysAddStructLocalised;
+
+genHotkeysAddStructLocalised WADefCommands[] = {
+ {IDS_PLAYBACK__PLAY,{0, 0, WM_COMMAND, WINAMP_BUTTON2, 0, "ghkdc play"}},
+ {IDS_PLAYBACK__PAUSE,{0, 0, WM_COMMAND, WINAMP_BUTTON3, 0, "ghkdc pause"}},
+ {IDS_PLAYBACK__STOP,{0, 0, WM_COMMAND, WINAMP_BUTTON4, 0, "ghkdc stop"}},
+ {IDS_PLAYBACK__PREVIOUS_IN_PLAYLIST,{0, 0, WM_COMMAND, WINAMP_BUTTON1, 0, "ghkdc prev"}},
+ {IDS_PLAYBACK__NEXT_IN_PLAYLIST,{0, 0, WM_COMMAND, WINAMP_BUTTON5, 0, "ghkdc next"}},
+ {IDS_PLAYBACK__VOLUME_UP,{0, 0, WM_COMMAND, WINAMP_VOLUMEUP, 0, "ghkdc vup"}},
+ {IDS_PLAYBACK__VOLUME_DOWN,{0, 0, WM_COMMAND, WINAMP_VOLUMEDOWN, 0, "ghkdc vdown"}},
+ {IDS_PLAYBACK__FORWARD,{0, 0, WM_COMMAND, WINAMP_FFWD5S, 0, "ghkdc forward"}},
+ {IDS_PLAYBACK__REWIND,{0, 0, WM_COMMAND, WINAMP_REW5S, 0, "ghkdc rewind"}},
+ {IDS_PLAYBACK__REPEAT_ON,{0, 0, WM_WA_IPC, 1, IPC_SET_REPEAT, "ghkdc repeat on"}},
+ {IDS_PLAYBACK__REPEAT_OFF,{0, 0, WM_WA_IPC, 0, IPC_SET_REPEAT, "ghkdc repeat off"}},
+ {IDS_UI__TOGGLE_EQ,{0, 0, WM_COMMAND, WINAMP_OPTIONS_EQ, 0, "ghkdc t eq"}},
+ {IDS_UI__TOGGLE_PLAYLIST,{0, 0, WM_COMMAND, WINAMP_OPTIONS_PLEDIT, 0, "ghkdc t pl"}},
+ {IDS_UI__TOGGLE_AOT,{0, 0, WM_COMMAND, WINAMP_OPTIONS_AOT, 0, "ghkdc t aot"}},
+ {IDS_UI__ABOUT,{0, HKF_BRING_TO_FRONT, WM_COMMAND, WINAMP_HELP_ABOUT, 0, "ghkdc about"}},
+ {IDS_PLAYBACK__JUMP_TO_BOX,{0, HKF_BRING_TO_FRONT, WM_COMMAND, 40194, 0, "ghkdc jump"}},
+ {IDS_PLAYBACK__OPEN_FILE_DIALOG,{0, HKF_BRING_TO_FRONT|HKF_WPARAM_HWND, WM_WA_IPC, 0, IPC_OPENFILEBOX, "ghkdc file"}},
+ {IDS_PLAYBACK__OPEN_LOC_DIALOG,{0, HKF_BRING_TO_FRONT, WM_COMMAND, WINAMP_BUTTON2_CTRL, 0, "ghkdc url"}},
+ {IDS_PLAYBACK__OPEN_FOLDER_DIALOG,{0, HKF_BRING_TO_FRONT|HKF_WPARAM_HWND, WM_WA_IPC, 0, IPC_OPENDIRBOX, "ghkdc dir"}},
+ {IDS_GENERAL__QUIT,{0, 0, WM_CLOSE, 0, 0, "ghkdc quit"}},
+ {IDS_UI__PREFERENCES,{0, HKF_BRING_TO_FRONT, WM_WA_IPC, (WPARAM)(-1), IPC_OPENPREFSTOPAGE, "ghkdc prefs"}},
+ {IDS_GENERAL__COPY_TITLE,{0, HKF_COPY_RET|HKF_PLPOS_WPARAM, WM_WA_IPC, 0, IPC_GETPLAYLISTTITLE, "ghkdc copy"}},
+ {IDS_GENERAL__COPY_FILE_PATH,{0, HKF_COPY_RET|HKF_WPARAM_PLPOS, WM_WA_IPC, 0, IPC_GETPLAYLISTFILE, "ghkdc copy path"}},
+ {IDS_PLAYBACK__PLAY_PAUSE,{0, HKF_ISPLAYING_WL, WM_COMMAND, WINAMP_BUTTON3, WINAMP_BUTTON2, "ghkdc play/pause"}},
+ {IDS_PLAYBACK__TOGGLE_REPEAT,{0, 0, WM_COMMAND, 40022, 0, "ghkdc t repeaat"}},
+ {IDS_PLAYBACK__TOGGLE_SHUFFLE,{0, 0, WM_COMMAND, 40023, 0, "ghkdc t shuffle"}},
+ {IDS_UI__TOGGLE_WINSHADE,{0, 0, WM_COMMAND, 40064, 0, "ghkdc ws"}},
+ {IDS_UI__TOGGLE_PLAYLIST_WINSHADE,{0, 0, WM_COMMAND, 40266, 0, "ghkdc pl ws"}},
+ {IDS_UI__TOGGLE_DOUBLESIZE,{0, 0, WM_COMMAND, 40165, 0, "ghkdc ds"}},
+ {IDS_UI__TOGGLE_MAIN_WINDOW,{0, 0, WM_COMMAND, 40258, 0, "ghkdc t main"}},
+ // removed due to it not being in current winamp builds now {IDS_UI__TOGGLE_MINIBROWSER,{0, 0, WM_COMMAND, 40298, 0, "ghkdc t mb"}},
+ {IDS_VIS__PREFERENCES,{0, HKF_BRING_TO_FRONT, WM_COMMAND, 40191, 0, "ghkdc vis prefs"}},
+ {IDS_VIS_TOGGLE_VIS_ON_OFF,{0, 0, WM_COMMAND, 40192, 0, "ghkdc t vis"}},
+ // added in 1.91 based on user feedback (ID_VIS_* options) and also from finding the correct menu id to use
+ {IDS_VIS__PLUGIN_PREFERENCES,{0, HKF_BRING_TO_FRONT, WM_COMMAND, 40221, 0, "ghkdc prefs vis"}},
+ {IDS_VIS_NEXT_PRESET,{0, 0, WM_COMMAND, ID_VIS_NEXT, 0, "ghkdc vis next"}},
+ {IDS_VIS_PREV_PRESET,{0, 0, WM_COMMAND, ID_VIS_PREV, 0, "ghkdc vis prev"}},
+ {IDS_VIS_RAND_PRESET,{0, 0, WM_COMMAND, ID_VIS_RANDOM, 0, "ghkdc vis rand"}},
+ {IDS_VIS_FULL_SCREEN,{0, 0, WM_COMMAND, ID_VIS_FS, 0, "ghkdc vis fs"}},
+ {IDS_UI__SELECT_SKIN,{0, HKF_BRING_TO_FRONT, WM_COMMAND, 40219, 0, "ghkdc skin"}},
+ {IDS_PLAYBACK__STOP_WITH_FADEOUT,{0, 0, WM_COMMAND, WINAMP_BUTTON4_SHIFT, 0, "ghkdc stop fade"}},
+ {IDS_PLAYBACK__STOP_AFTER_CURRENT,{0, 0, WM_COMMAND, WINAMP_BUTTON4_CTRL, 0, "ghkdc stop ac"}},
+ {IDS_PLAYBACK__START_OF_LIST,{0, 0, WM_COMMAND, WINAMP_BUTTON1_CTRL, 0, "ghkdc sol"}},
+ {IDS_PLAYBACK__END_OF_LIST,{0, 0, WM_COMMAND, WINAMP_BUTTON5_CTRL, 0, "ghkdc eol"}},
+ {IDS_UI__BRING_TO_FRONT_OR_HIDE,{0, HKF_SHOWHIDE, WM_SHOWWINDOW, 0, 0, "ghkdc show/hide"}},
+ {IDS_RATING__5_STARS,{0, 0, WM_WA_IPC, 5, IPC_SETRATING, "ghkdc rating 5"}},
+ {IDS_RATING__4_STARS,{0, 0, WM_WA_IPC, 4, IPC_SETRATING, "ghkdc rating 4"}},
+ {IDS_RATING__3_STARS,{0, 0, WM_WA_IPC, 3, IPC_SETRATING, "ghkdc rating 3"}},
+ {IDS_RATING__2_STARS,{0, 0, WM_WA_IPC, 2, IPC_SETRATING, "ghkdc rating 2"}},
+ {IDS_RATING__1_STAR,{0, 0, WM_WA_IPC, 1, IPC_SETRATING, "ghkdc rating 1"}},
+ {IDS_RATING__NO_RATING,{0, 0, WM_WA_IPC, 0, IPC_SETRATING, "ghkdc rating 0"}},
+ // added in 1.4+ so that we can deal with unicode strings on 5.3x+ Winamp versions
+ {IDS_GENERAL__COPY_TITLEW,{0, HKF_COPYW_RET|HKF_PLPOS_WPARAM, WM_WA_IPC, 0, IPC_GETPLAYLISTTITLEW, "ghkdc copyw"}},
+ {IDS_GENERAL__COPY_FILE_PATHW,{0, HKF_COPYW_RET|HKF_WPARAM_PLPOS, WM_WA_IPC, 0, IPC_GETPLAYLISTFILEW, "ghkdc copy pathw"}},
+ // added in 1.6+ for neorth
+ {IDS_RATING__INC,{0, 0, WM_WA_IPC, 6, IPC_SETRATING, "ghkdc inc rating"}},
+ {IDS_RATING__DEC,{0, 0, WM_WA_IPC, (WPARAM)(-1), IPC_SETRATING, "ghkdc dec rating"}},
+ // added in 1.91 for kzuse
+ {IDS_PLAYBACK__MANUAL_ADVANCE,{0, 0, WM_COMMAND, 40395, 0, "ghkdc man adv"}},
+ // added in 1.92 as killing of separate gen_find_on_disk.dll to be native
+ {IDS_GENERAL_FFOD,{0, 0, WM_COMMAND, 40468, 0, "FFOD_Cur"}},
+ {IDS_PLAYBACK_EDIT_ID3,{0, 0, WM_COMMAND, 40188, 0, "VCFI"}},
+};
+
+static unsigned int WACommandsNum;
+static unsigned int WACommandsAllocated;
+WACommand *WACommands=0;
+
+inline unsigned int GetCommandsNum()
+{
+ return WACommandsNum;
+}
+
+static bool ReallocateCommands()
+{
+ if (WACommandsNum < WACommandsAllocated)
+ return true;
+
+ WACommand *newCommands = new WACommand[ WACommandsNum * 2 + 16];
+ if (newCommands)
+ memcpy(newCommands, WACommands, WACommandsAllocated*sizeof(WACommand));
+
+ WACommandsAllocated = WACommandsNum * 2 + 16;
+ delete [] WACommands;
+ WACommands = newCommands;
+ if (!WACommands)
+ {
+ WACommandsAllocated = 0;
+ return false;
+ }
+ return true;
+}
+
+void InitCommands()
+{
+ int l = sizeof(WADefCommands) / sizeof(WADefCommands[0]);
+ while (l--)
+ {
+ wchar_t rateBuf[1024] = {0};
+ wchar_t* rateStr = rateBuf;
+ WADefCommands[l].ghk.name = (char*)WASABI_API_LNGSTRINGW_BUF(WADefCommands[l].strId, rateBuf, 1024);
+ switch(WADefCommands[l].strId)
+ {
+ // for the rating entries force any asterisks to a unicode star
+ case IDS_RATING__1_STAR:
+ case IDS_RATING__2_STARS:
+ case IDS_RATING__3_STARS:
+ case IDS_RATING__4_STARS:
+ case IDS_RATING__5_STARS:
+ while(rateStr && *rateStr)
+ {
+ if(*rateStr == L'*') *rateStr = L'\u2605';
+ rateStr=CharNextW(rateStr);
+ }
+ break;
+ }
+ WADefCommands[l].ghk.flags |= HKF_UNICODE_NAME;
+ AddCommand(&WADefCommands[l].ghk);
+ }
+}
+
+int AddCommand(genHotkeysAddStruct *ghas)
+{
+ unsigned int idx = WACommandsNum;
+ if (!ghas)
+ return -1;
+
+ // legacy support
+ if (!ghas->id)
+ ghas->id = ghas->name;
+
+ if (WACommands)
+ {
+ unsigned int l = WACommandsNum;
+ while (l--)
+ {
+ if (!lstrcmpiW(WACommands[l].id, AutoWide(ghas->id)))
+ {
+ WACommands[l].bEnabled = !(ghas->flags & HKF_DISABLED);
+ char *name = 0;
+ if(!(ghas->flags & HKF_UNICODE_NAME))
+ name = (char *) malloc(lstrlen(ghas->name) + 1);
+ else
+ name = (char *) malloc((lstrlenW((wchar_t*)ghas->name) + 1) * sizeof(wchar_t));
+ if (name)
+ {
+ free(WACommands[l].name);
+ WACommands[l].name = name;
+ }
+ WACommands[l].dwFlags = (ghas->flags & 0x7FFFFFFF);
+ WACommands[l].uMsg = ghas->uMsg;
+ WACommands[l].wParam = ghas->wParam;
+ WACommands[l].lParam = ghas->lParam;
+ WACommands[l].wnd = ghas->wnd;
+ return l;
+ }
+ }
+ }
+ WACommandsNum++;
+ if (!ReallocateCommands())
+ {
+ WACommandsNum--;
+ return -2;
+ }
+
+ if(!(ghas->flags & HKF_UNICODE_NAME))
+ WACommands[idx].name = _strdup(ghas->name);
+ else
+ WACommands[idx].name = (char*)_wcsdup((wchar_t*)ghas->name);
+
+ if (!WACommands[idx].name)
+ {
+ WACommandsNum--;
+ return -1;
+ }
+
+ WACommands[idx].id = AutoWideDup(ghas->id);
+ if (!WACommands[idx].id)
+ {
+ free(WACommands[idx].name);
+ WACommandsNum--;
+ return -1;
+ }
+ WACommands[idx].dwFlags = (ghas->flags & 0x7FFFFFFF);
+ WACommands[idx].uMsg = ghas->uMsg;
+ WACommands[idx].wParam = ghas->wParam;
+ WACommands[idx].lParam = ghas->lParam;
+ WACommands[idx].bEnabled = !(ghas->flags & HKF_DISABLED);
+ WACommands[idx].wnd = ghas->wnd;
+ return idx;
+}
+
+inline char *GetCommandName(unsigned int i, bool *unicode)
+{
+ if (i < WACommandsNum)
+ {
+ if(unicode) *unicode = !!(WACommands[i].dwFlags & HKF_UNICODE_NAME);
+ return WACommands[i].name;
+ }
+ return "";
+}
+
+inline wchar_t *GetCommandId(unsigned int i)
+{
+ if (i < WACommandsNum)
+ return WACommands[i].id;
+ return L"";
+}
+
+int GetCommandIdx(wchar_t *id)
+{
+ if (WACommands)
+ {
+ unsigned int l = WACommandsNum;
+ while (l--)
+ {
+ if (!lstrcmpiW(WACommands[l].id, id))
+ {
+ return l;
+ }
+ }
+ }
+ return -1;
+}
+
+int HandleByScript(unsigned int i)
+{
+ if (i >= WACommandsNum) return 0;
+ if (SendMessage(psPlugin.hwndParent, WM_WA_IPC, (WPARAM)WACommands[i].name, IPC_FF_NOTIFYHOTKEY)) return 0;
+ return 1;
+}
+
+int DoCommand(unsigned int i)
+{
+ if (i >= WACommandsNum)
+ return 0;
+
+ if (!WACommands[i].bEnabled)
+ return 0;
+
+ if (HandleByScript(i)) return 1;
+
+ WPARAM wParam = WACommands[i].wParam;
+ LPARAM lParam = WACommands[i].lParam;
+
+ /*if (WACommands[i].dwFlags & HKF_CUSTOM_FUNC)
+ {
+ if (WACommands[i].uMsg)
+ {
+ pfnWAC pfn = (pfnWAC) WACommands[i].uMsg;
+ pfn();
+ }
+
+ return 0;
+ }*/
+
+ if (WACommands[i].dwFlags & HKF_SHOWHIDE)
+ {
+ DWORD dwThisProcId, dwProcId;
+ GetWindowThreadProcessId(psPlugin.hwndParent, &dwThisProcId);
+ GetWindowThreadProcessId(GetForegroundWindow(), &dwProcId);
+ if (IsWindowVisible(psPlugin.hwndParent) && dwProcId == dwThisProcId)
+ ShowWindow(psPlugin.hwndParent, SW_MINIMIZE);
+ else
+ {
+ ShowWindow(psPlugin.hwndParent, SW_SHOWNORMAL);
+ SetForegroundWindow(psPlugin.hwndParent);
+ }
+ }
+
+ HWND hwnddest=WACommands[i].wnd ? WACommands[i].wnd : psPlugin.hwndParent;
+
+ if (WACommands[i].dwFlags & HKF_BRING_TO_FRONT)
+ {
+ SetForegroundWindow(psPlugin.hwndParent);
+ }
+ if (WACommands[i].dwFlags & HKF_WPARAM_HWND)
+ {
+ wParam = (WPARAM) psPlugin.hwndParent;
+ }
+ if (WACommands[i].dwFlags & HKF_WPARAM_PLPOS)
+ {
+ wParam = (WPARAM) SendMessage(psPlugin.hwndParent, WM_WA_IPC, 0, IPC_GETLISTPOS);
+ }
+ if (WACommands[i].dwFlags & HKF_WPARAM_ISPLAYING_WL)
+ {
+ if (SendMessage(psPlugin.hwndParent, WM_WA_IPC, 0, IPC_ISPLAYING))
+ wParam = WACommands[i].wParam; // Pause
+ else
+ wParam = WACommands[i].lParam; // Play
+
+ lParam = 0;
+ }
+
+ LRESULT lResult = SendMessage(hwnddest, WACommands[i].uMsg, wParam, lParam);
+
+ if (WACommands[i].dwFlags & HKF_COPY && lResult)
+ {
+ char *szTitle = (char *) lResult;
+
+ if (!OpenClipboard(psPlugin.hwndParent))
+ return 0;
+ EmptyClipboard();
+
+ int bufLen = lstrlen(szTitle) + 1;
+ HGLOBAL hglbCopy = GlobalAlloc(GMEM_MOVEABLE, bufLen);
+ if (!hglbCopy)
+ {
+ CloseClipboard();
+ return 0;
+ }
+
+ char *szClipboardTitle = (char *) GlobalLock(hglbCopy);
+ if (!szClipboardTitle)
+ {
+ CloseClipboard();
+ return 0;
+ }
+ lstrcpyn(szClipboardTitle, szTitle, bufLen);
+ GlobalUnlock(hglbCopy);
+
+ SetClipboardData(CF_TEXT, hglbCopy);
+
+ CloseClipboard();
+ }
+
+ if (WACommands[i].dwFlags & HKF_COPYW && lResult)
+ {
+ wchar_t *szTitle = (wchar_t *) lResult;
+
+ if (!OpenClipboard(psPlugin.hwndParent))
+ return 0;
+ EmptyClipboard();
+
+ int bufLen = (lstrlenW(szTitle) + 1) * sizeof(wchar_t);
+ HGLOBAL hglbCopy = GlobalAlloc(GMEM_MOVEABLE, bufLen);
+ if (!hglbCopy)
+ {
+ CloseClipboard();
+ return 0;
+ }
+
+ wchar_t *szClipboardTitle = (wchar_t *) GlobalLock(hglbCopy);
+ if (!szClipboardTitle)
+ {
+ CloseClipboard();
+ return 0;
+ }
+ lstrcpynW(szClipboardTitle, szTitle, bufLen);
+ GlobalUnlock(hglbCopy);
+
+ SetClipboardData(CF_UNICODETEXT, hglbCopy);
+ CloseClipboard();
+ }
+ return (int)lResult;
+} \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/Wacommands.h b/Src/Plugins/General/gen_hotkeys/Wacommands.h
new file mode 100644
index 00000000..0ae832ff
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/Wacommands.h
@@ -0,0 +1,50 @@
+#ifndef ___WINAMP_COMMANDS___H___
+#define ___WINAMP_COMMANDS___H___
+
+#include "../winamp/wa_ipc.h"
+#include "wa_hotkeys.h"
+
+// calls SetForegroundWindow before sending the message
+#define HKF_BRING_TO_FRONT 0x1
+// sets wParam with Winamp's window handle
+#define HKF_WPARAM_HWND 0x2
+// copies returned text to the clipboard (CF_TEXT)
+#define HKF_COPY_RET 0x4
+// sets wParam with current pledit position
+#define HKF_WPARAM_PLPOS 0x8
+// sets wParam to genHotkeysAddStruct's wParam if playing, lParam if not
+// uses IPC_ISPLAYING to check if playing
+#define HKF_WPARAM_ISPLAYING_WL 0x10
+// brings Winamp to front or minimizes Winamp if already at front
+#define HKF_SHOWHIDE 0x20
+#define HKF_CUSTOM_FUNC 0x40
+// copies returned text to the clipboard (CF_UNICODETEXT)
+#define HKF_COPYW_RET 0x80
+#define HKF_UNICODE_NAME 0x100
+// set this when the 'name' is passed as a unicode string
+
+typedef void (*pfnWAC)();
+
+struct WACommand
+{
+ wchar_t *id;
+ char *name;
+ DWORD dwFlags;
+ UINT uMsg;
+ WPARAM wParam;
+ LPARAM lParam;
+ BOOL bEnabled;
+ HWND wnd;
+};
+
+extern WACommand *WACommands;
+
+extern inline unsigned int GetCommandsNum();
+void InitCommands();
+int AddCommand(genHotkeysAddStruct *ghas);
+extern inline char *GetCommandName(unsigned int i, bool *unicode);
+extern inline wchar_t *GetCommandId(unsigned int i);
+int GetCommandIdx(wchar_t *id);
+int DoCommand(unsigned int i);
+
+#endif \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/accelBlock.cpp b/Src/Plugins/General/gen_hotkeys/accelBlock.cpp
new file mode 100644
index 00000000..e98245d7
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/accelBlock.cpp
@@ -0,0 +1,47 @@
+#include "gen_hotkeys.h"
+#include "api__gen_hotkeys.h"
+#include "./accelBlock.h"
+
+static BOOL RegisterMessageProcessor(ifc_messageprocessor *processor, BOOL bRegister)
+{
+ if (NULL == WASABI_API_APP)
+ return FALSE;
+
+ if (bRegister)
+ WASABI_API_APP->app_addMessageProcessor(processor);
+ else
+ WASABI_API_APP->app_removeMessageProcessor(processor);
+
+ return TRUE;
+}
+
+AcceleratorBlocker::AcceleratorBlocker(HWND hwndToBlock) : hwnd(hwndToBlock)
+{
+ RegisterMessageProcessor(this, TRUE);
+}
+AcceleratorBlocker::~AcceleratorBlocker()
+{
+ RegisterMessageProcessor(this, FALSE);
+}
+
+bool AcceleratorBlocker::ProcessMessage(MSG *pMsg)
+{
+ if (pMsg->hwnd != hwnd)
+ return false;
+
+ switch(pMsg->message)
+ {
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ TranslateMessage(pMsg);
+ DispatchMessageW(pMsg);
+ return true;
+ }
+ return false;
+}
+
+
+#define CBCLASS AcceleratorBlocker
+START_DISPATCH;
+CB(IFC_MESSAGEPROCESSOR_PROCESS_MESSAGE, ProcessMessage)
+END_DISPATCH; \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/accelBlock.h b/Src/Plugins/General/gen_hotkeys/accelBlock.h
new file mode 100644
index 00000000..f0d5e792
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/accelBlock.h
@@ -0,0 +1,24 @@
+#ifndef NULLSOFT_WINAMP_ACCELERATOR_BLOCKER_HEADER
+#define NULLSOFT_WINAMP_ACCELERATOR_BLOCKER_HEADER
+
+#include <wtypes.h>
+#include <api\application\ifc_messageprocessor.h>
+
+class AcceleratorBlocker : public ifc_messageprocessor
+{
+public:
+ AcceleratorBlocker(HWND hwndToBlock);
+ ~AcceleratorBlocker();
+
+public:
+ bool ProcessMessage(MSG *pMsg);
+ HWND GetHwnd() { return hwnd; }
+protected:
+ RECVS_DISPATCH;
+
+protected:
+ HWND hwnd;
+
+};
+
+#endif// NULLSOFT_WINAMP_ACCELERATOR_BLOCKER_HEADER \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/api__gen_hotkeys.h b/Src/Plugins/General/gen_hotkeys/api__gen_hotkeys.h
new file mode 100644
index 00000000..823353fd
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/api__gen_hotkeys.h
@@ -0,0 +1,10 @@
+#ifndef NULLSOFT_GEN_HOTKEYS_API_H
+#define NULLSOFT_GEN_HOTKEYS_API_H
+
+#include "api/service/api_service.h"
+#include "../Agave/Language/api_language.h"
+
+#include <api/application/api_application.h>
+#define WASABI_API_APP applicationApi
+
+#endif // !NULLSOFT_GEN_HOTKEYS_API_H \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/gen_hotkeys.cpp b/Src/Plugins/General/gen_hotkeys/gen_hotkeys.cpp
new file mode 100644
index 00000000..f5e496ad
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/gen_hotkeys.cpp
@@ -0,0 +1,519 @@
+//#define PLUGIN_NAME //"Nullsoft Global Hotkeys"
+#define PLUGIN_VERSION L"1.97"
+
+// do this so we can get WM_APPCOMMAND support (needed in 1.6+)
+// (have to targetting xp sp1+ so we get the specific play & pause messages
+// though it'll work fine with win2k+ as those messages will never appear)
+//////#define _WIN32_WINNT 0x0501
+#include "gen_hotkeys.h"
+#include "ConfigDlg.h"
+#include "HotKey.h"
+#include "WACommands.h"
+#include <api/service/waServiceFactory.h>
+
+///////////////////////////////////////////////////////////
+// Globals
+///////////////////////////////////////////////////////////
+
+// The global plugin instance
+winampGeneralPurposePlugin psPlugin =
+{
+ GPPHDR_VER_U,
+ "nullsoft(gen_hotkeys.dll)",
+ pluginInit,
+ pluginConfig,
+ hotkeysClear
+};
+// Winamp's window procdure
+WNDPROC lpWndProcOld = NULL;
+static int winampIsUnicode=false;
+static int appcommand=false;
+// hotkeys
+HOTKEY *g_hotkeys = NULL;
+DWORD g_dwHotkeys = 0;
+// mutex to prevent two gen_hotkeys
+HANDLE g_hMutex = NULL;
+LPARAM uShellHook = NULL;
+
+// wasabi based services for localisation support
+api_service *WASABI_API_SVC = 0;
+api_application *WASABI_API_APP = NULL;
+api_language *WASABI_API_LNG = 0;
+HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
+
+static prefsDlgRecW g_prefsItem = {0};
+static wchar_t g_titlestr[128];
+wchar_t *g_iniFile = 0;
+
+// don't forget to set DEFHKDS_NUM if you change this
+HOTKEY_DATA g_defhkds[] = {
+ {MAKEWORD(VK_INSERT, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc play"},
+ {MAKEWORD(VK_HOME, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc pause"},
+ {MAKEWORD(VK_END, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc stop"},
+ {MAKEWORD(VK_PRIOR, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc prev"},
+ {MAKEWORD(VK_NEXT, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc next"},
+ {MAKEWORD(VK_UP, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc vup"},
+ {MAKEWORD(VK_DOWN, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc vdown"},
+ {MAKEWORD(VK_RIGHT, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc forward"},
+ {MAKEWORD(VK_LEFT, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc rewind"},
+ {MAKEWORD('J', HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc jump"},
+ {MAKEWORD('L', HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc file"},
+ //multimedia keyboard stuff
+ {2226, -1, L"ghkdc stop"},
+ {2227, -1, L"ghkdc play/pause"},
+ {2225, -1, L"ghkdc prev"},
+ {2224, -1, L"ghkdc next"},
+ };
+
+#define TIMER_ID 0x8855
+
+static int m_genhotkeys_add_ipc;
+
+///////////////////////////////////////////////////////////
+// DLL entry function
+///////////////////////////////////////////////////////////
+
+#ifndef _DEBUG
+BOOL WINAPI _DllMainCRTStartup(HINSTANCE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
+{
+ DisableThreadLibraryCalls(hInst);
+ return TRUE;
+}
+#endif
+
+///////////////////////////////////////////////////////////
+// Plugin functions
+///////////////////////////////////////////////////////////
+
+int pluginInit()
+{
+ RegisterShellHookWindow(psPlugin.hwndParent);
+ uShellHook = RegisterWindowMessage(TEXT("SHELLHOOK"));
+
+ g_iniFile = (wchar_t*)SendMessage(psPlugin.hwndParent, WM_WA_IPC, 0, IPC_GETINIFILEW);
+
+ // loader so that we can get the localisation service api for use
+ WASABI_API_SVC = (api_service*)SendMessage(psPlugin.hwndParent, WM_WA_IPC, 0, IPC_GET_API_SERVICE);
+ if (WASABI_API_SVC == (api_service*)1 ||
+ NULL == WASABI_API_SVC)
+ {
+ return 1;
+ }
+
+ waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(applicationApiServiceGuid);
+ if (sf) WASABI_API_APP = reinterpret_cast<api_application*>(sf->getInterface());
+
+ sf = WASABI_API_SVC->service_getServiceByGuid(languageApiGUID);
+ if (sf) WASABI_API_LNG = reinterpret_cast<api_language*>(sf->getInterface());
+
+ // need to have this initialised before we try to do anything with localisation features
+ WASABI_API_START_LANG(psPlugin.hDllInstance,GenHotkeysLangGUID);
+
+ m_genhotkeys_add_ipc = (int)SendMessage( psPlugin.hwndParent, WM_WA_IPC, (WPARAM) &"GenHotkeysAdd", IPC_REGISTER_WINAMP_IPCMESSAGE);
+
+ static wchar_t szDescription[256];
+ StringCchPrintfW(szDescription, ARRAYSIZE(szDescription),
+ WASABI_API_LNGSTRINGW(IDS_NULLSOFT_GLOBAL_HOTKEYS), PLUGIN_VERSION);
+ psPlugin.description = (char*)szDescription;
+
+ appcommand = GetPrivateProfileIntW(L"gen_hotkeys", L"appcommand", 0, g_iniFile);
+
+ // Save Winamp's window procedure
+ winampIsUnicode = IsWindowUnicode(psPlugin.hwndParent);
+ lpWndProcOld = (WNDPROC)(LONG_PTR)GetWindowLongPtr(psPlugin.hwndParent, GWLP_WNDPROC);
+ if (winampIsUnicode)
+ SetWindowLongPtrW(psPlugin.hwndParent, GWLP_WNDPROC, (LONGX86)(LONG_PTR)WndProc);
+ else
+ SetWindowLongPtrA(psPlugin.hwndParent, GWLP_WNDPROC, (LONGX86)(LONG_PTR)WndProc);
+
+ InitCommands();
+
+ SetTimer(psPlugin.hwndParent, TIMER_ID, 10, NULL); //call hotkeysInit() when all plugins are loaded
+
+ //register prefs screen
+ g_prefsItem.dlgID = IDD_CONFIG;
+ g_prefsItem.name = WASABI_API_LNGSTRINGW_BUF(IDS_GHK_TITLE_STR,g_titlestr,128);
+ g_prefsItem.proc = ConfigProc;
+ g_prefsItem.hInst = WASABI_API_LNG_HINST;
+ // delay the adding of this
+ // for some reason when changing a lang pack it can cause the WM_DESTROY of ConfigProc
+ // to be called which completely messes up the ghk list and so can wipe it :(
+ SendMessage(psPlugin.hwndParent, WM_WA_IPC, (WPARAM) &g_prefsItem, IPC_ADD_PREFS_DLGW);
+
+ return 0;
+}
+
+int hotkeysLoad(HOTKEY_DATA *hkds, DWORD num, int do_register, int verbose /*=1*/)
+{
+ unsigned int uFailed = 0;
+
+ delete [] g_hotkeys;
+ g_hotkeys = NULL;
+
+ if (num)
+ {
+ g_hotkeys = new HOTKEY[num];
+ memset(g_hotkeys, 0, num * sizeof(HOTKEY));
+ }
+ if (!g_hotkeys)
+ {
+ g_dwHotkeys = 0;
+ return 1;
+ }
+
+ g_dwHotkeys = num;
+
+ wchar_t moreStr[64] = {0};
+ WASABI_API_LNGSTRINGW_BUF(IDS_GHK_HOTKEY_REG_FAILED_MORE,moreStr,64);
+ size_t bufLen = 256 + wcslen(moreStr) + 1;
+ wchar_t* szFailed = (wchar_t*)malloc(bufLen*sizeof(wchar_t));
+ WASABI_API_LNGSTRINGW_BUF(IDS_GHK_HOTKEY_REG_FAILED,szFailed,bufLen);
+ DWORD dwLeft = 256 - lstrlenW(szFailed);
+ DWORD dwFailedWithNoMsg = 0;
+
+ for (DWORD i = 0; i < num; i++)
+ {
+ g_hotkeys[i].hkd = hkds[i];
+
+ if (g_hotkeys[i].hkd.iCommand < 0)
+ // action not loaded yet for this hotkey
+ continue;
+
+ if (do_register && RegisterHotkey(g_hotkeys + i))
+ {
+ if (verbose && dwLeft)
+ {
+ wchar_t szTemp[1024] = {0};
+ bool unicode = 0;
+ char* name = GetCommandName(g_hotkeys[i].hkd.iCommand, &unicode);
+ StringCchPrintfW(szTemp, 1024, (unicode?L"\n\t%s":L"\n\t%S"), name);
+ DWORD dwLen = lstrlenW(szTemp);
+ if (dwLen < dwLeft)
+ {
+ StringCchCatW(szFailed, bufLen, szTemp);
+ dwLeft -= dwLen;
+ }
+ else
+ dwFailedWithNoMsg++;
+ }
+
+ g_hotkeys[i].failed = TRUE;
+ uFailed++;
+ }
+ }
+
+ if (verbose && uFailed)
+ {
+ if (dwFailedWithNoMsg)
+ StringCchCatW(szFailed, bufLen, moreStr);
+ HWND parent = (HWND)SendMessage(psPlugin.hwndParent, WM_WA_IPC, 0, IPC_GETDIALOGBOXPARENT);
+ if (parent == 0 || parent == (HWND)1)
+ parent=psPlugin.hwndParent;
+
+ MessageBoxW(parent, szFailed, g_titlestr, MB_OK | MB_ICONSTOP | MB_TOPMOST);
+ }
+ free(szFailed);
+
+ return uFailed;
+}
+
+static volatile LONG initted=0;
+void hotkeysInit()
+{
+ if (initted)
+ return;
+ initted=1;
+
+ int enabled = GetPrivateProfileIntW(L"gen_hotkeys", L"enabled", 0, g_iniFile);
+
+ // base the mutex on the current winamp install
+ // (makes it work better with mutliple winamp installs otherwise the older
+ // "Winamp - gen_hotkeys.dll ^&*#@" mutex prevents different hotkeys from
+ // being initialised between the different installs without going to prefs)
+ char mutexStr[MAX_PATH] = {0}, ghkFilename[MAX_PATH] = {0};
+ GetModuleFileName(psPlugin.hDllInstance, ghkFilename, MAX_PATH);
+ StringCchPrintf(mutexStr, MAX_PATH, "Winamp - %s ^&*#@", ghkFilename);
+ g_hMutex = CreateMutex(0, TRUE, mutexStr);
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ enabled = 0;
+
+ int i;
+
+ for (i = 0; i < DEFHKDS_NUM; i++)
+ {
+ g_defhkds[i].iCommand = GetCommandIdx(g_defhkds[i].szCommand);
+ g_defhkds[i].szCommand = 0;
+ }
+
+ int l = GetPrivateProfileIntW(L"gen_hotkeys", L"nbkeys", -1, g_iniFile);
+ int ver = GetPrivateProfileIntW(L"gen_hotkeys", L"version", 1, g_iniFile);
+ if (l != -1)
+ {
+ if (ver == 2)
+ {
+ HOTKEY_DATA *hkds = new HOTKEY_DATA[l]; // TODO: could alloca this
+ if (hkds)
+ {
+ for (i = 0; i < l; i++)
+ {
+ wchar_t tmp[1024] = {0}, action[1024] = {0};
+ StringCchPrintfW(tmp, 1024, L"action%d", i);
+ GetPrivateProfileStringW(L"gen_hotkeys", tmp, L"", action, 1024, g_iniFile);
+ StringCchPrintfW(tmp, 1024, L"hotkey%d", i);
+ int hotkey = GetPrivateProfileIntW(L"gen_hotkeys", tmp, 0, g_iniFile);
+
+ hkds[i].dwHotKey = hotkey;
+
+ hkds[i].iCommand = GetCommandIdx(action);
+ if (hkds[i].iCommand >= 0)
+ hkds[i].szCommand = NULL;
+ else
+ hkds[i].szCommand = _wcsdup(action);
+ }
+
+ hotkeysLoad(hkds, l, enabled, 0);
+ delete [] hkds;
+ }
+ }
+ // legacy support
+ else if (ver == 1)
+ {
+ HOTKEY_DATA *hkds = new HOTKEY_DATA[l]; // TODO: could alloca this
+ if (hkds)
+ {
+ int nb = 0;
+ for (i = 0;i < l;i++)
+ {
+ wchar_t tmp[512] = {0};
+ StringCchPrintfW(tmp, 512, L"msg%d", i);
+ unsigned int msg = GetPrivateProfileIntW(L"gen_hotkeys", tmp, 0, g_iniFile);
+ if (msg)
+ {
+ StringCchPrintfW(tmp, 512, L"wparam%d", i);
+ WPARAM wparam = GetPrivateProfileIntW(L"gen_hotkeys", tmp, 0, g_iniFile);
+ StringCchPrintfW(tmp, 512, L"lparam%d", i);
+ LPARAM lparam = GetPrivateProfileIntW(L"gen_hotkeys", tmp, 0, g_iniFile);
+ for (int j = 0;WACommands[j].name;j++)
+ {
+ if (WACommands[j].uMsg == msg && WACommands[j].wParam == wparam && WACommands[j].lParam == lparam)
+ {
+ StringCchPrintfW(tmp, 512, L"hotkey%d", i);
+ int hotkey = GetPrivateProfileIntW(L"gen_hotkeys", tmp, 0, g_iniFile);
+ hkds[nb].dwHotKey = hotkey;
+ hkds[nb].iCommand = j;
+ hkds[nb].szCommand = NULL;
+ nb++;
+ break;
+ }
+ }
+ }
+ }
+ hotkeysLoad(hkds, nb, enabled, 0);
+ delete [] hkds;
+ }
+ }
+ }
+ else
+ {
+ // load defaults
+ hotkeysLoad(g_defhkds, DEFHKDS_NUM, enabled, 0);
+ }
+}
+
+void writePrivateProfileInt(wchar_t *section, int val)
+{
+ wchar_t s[32] = {0};
+ StringCchPrintfW(s, 32, L"%d", val);
+ WritePrivateProfileStringW(L"gen_hotkeys", section, s, g_iniFile);
+}
+
+void hotkeysSave(HOTKEY_DATA *hkds, DWORD num)
+{
+ int enabled = GetPrivateProfileIntW(L"gen_hotkeys", L"enabled", 0, g_iniFile);
+ appcommand = GetPrivateProfileIntW(L"gen_hotkeys", L"appcommand", 0, g_iniFile);
+ WritePrivateProfileStringW(L"gen_hotkeys", NULL, NULL, g_iniFile);
+ writePrivateProfileInt(L"nbkeys", num);
+ writePrivateProfileInt(L"version", 2);
+ writePrivateProfileInt(L"enabled", enabled);
+ writePrivateProfileInt(L"appcommand", appcommand);
+ if (!hkds || !num)
+ {
+ return ;
+ }
+ for (size_t i = 0; i < num; i++)
+ {
+ wchar_t tmp[1024] = {0};
+ StringCchPrintfW(tmp, 1024, L"action%d", i);
+ if (hkds[i].iCommand >= 0)
+ WritePrivateProfileStringW(L"gen_hotkeys", tmp, GetCommandId(hkds[i].iCommand), g_iniFile);
+ else if (hkds[i].szCommand)
+ WritePrivateProfileStringW(L"gen_hotkeys", tmp, hkds[i].szCommand, g_iniFile);
+ StringCchPrintfW(tmp, 1024, L"hotkey%d", i);
+ writePrivateProfileInt(tmp, hkds[i].dwHotKey);
+ }
+}
+
+void pluginConfig()
+{
+ SendMessage(psPlugin.hwndParent, WM_WA_IPC, (WPARAM) &g_prefsItem, IPC_OPENPREFSTOPAGE);
+}
+
+void hotkeysClear()
+{
+ DeregisterShellHookWindow(psPlugin.hwndParent);
+
+ if (!g_hotkeys)
+ return;
+
+ // Unregister all of the hot keys, and delete all of our unique hot key identifiers
+ for (DWORD i = 0; i < g_dwHotkeys; i++)
+ {
+ UnregisterHotkey(g_hotkeys + i);
+ }
+ delete [] g_hotkeys;
+ g_hotkeys = NULL;
+}
+
+///////////////////////////////////////////////////////////
+// Plugin export function
+///////////////////////////////////////////////////////////
+
+extern "C" __declspec(dllexport) winampGeneralPurposePlugin * winampGetGeneralPurposePlugin() { return &psPlugin; }
+
+///////////////////////////////////////////////////////////
+// DLL Windows message handling procedure
+///////////////////////////////////////////////////////////
+
+LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if(message == uShellHook && appcommand && wParam == HSHELL_APPCOMMAND)
+ {
+ // WM_APPCOMMAND info:: http://msdn2.microsoft.com/en-us/library/ms646275.aspx
+ int cmd = GET_APPCOMMAND_LPARAM(lParam);
+ switch (cmd)
+ {
+ case APPCOMMAND_MEDIA_PLAY_PAUSE:
+ {
+ int playing = (int)SendMessage(psPlugin.hwndParent, WM_WA_IPC, 0, IPC_ISPLAYING);
+ SendMessage(hwnd, WM_COMMAND, MAKEWPARAM((playing ? WINAMP_BUTTON3 : WINAMP_BUTTON2),0), 0);
+ }
+ break;
+ case APPCOMMAND_MEDIA_NEXTTRACK:
+ SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_BUTTON5,0), 0);
+ return TRUE;
+ case APPCOMMAND_MEDIA_PREVIOUSTRACK:
+ SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_BUTTON1,0), 0);
+ return TRUE;
+ case APPCOMMAND_MEDIA_STOP:
+ SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_BUTTON4,0), 0);
+ return TRUE;
+ case APPCOMMAND_VOLUME_DOWN:
+ SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_VOLUMEDOWN,0), 0);
+ return TRUE;
+ case APPCOMMAND_VOLUME_UP:
+ SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_VOLUMEUP,0), 0);
+ return TRUE;
+ /*case APPCOMMAND_VOLUME_MUTE:
+ return TRUE;*/
+
+ // info on play/pause (xp sp1+) commands:: http://msdn2.microsoft.com/en-us/library/bb417078.aspx
+ case APPCOMMAND_MEDIA_PLAY:
+ {
+ int playing = (int)SendMessage(psPlugin.hwndParent, WM_WA_IPC, 0, IPC_ISPLAYING);
+ // play if not currently playing/are stopped
+ if(!playing) SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_BUTTON2,0), 0);
+ // if paused then start playing again
+ else if(playing == 3) SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_BUTTON3,0), 0);
+ // otherwise do nothing if playing already (playing == 1)
+ }
+ return TRUE;
+ case APPCOMMAND_MEDIA_PAUSE:
+ {
+ int playing = (int)SendMessage(psPlugin.hwndParent, WM_WA_IPC, 0, IPC_ISPLAYING);
+ // if playing then we pause
+ if(playing == 1) SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_BUTTON3,0), 0);
+ // otherwise do nothing if already stopped or paused (playing == 0 || playing == 3)
+ }
+ return TRUE;
+ case APPCOMMAND_MEDIA_FAST_FORWARD:
+ SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_FFWD5S,0), 0);
+ return TRUE;
+ case APPCOMMAND_MEDIA_REWIND:
+ SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_REW5S,0), 0);
+ return TRUE;
+ }
+ }
+
+ switch (message)
+ {
+ case WM_TIMER:
+ if (wParam == TIMER_ID)
+ {
+ KillTimer(hwnd, TIMER_ID);
+ hotkeysInit();
+ return 0;
+ }
+ break;
+
+ case WM_HOTKEY:
+ if (g_hotkeys)
+ {
+ for (unsigned int i = 0; i < g_dwHotkeys; i++)
+ {
+ if (g_hotkeys[i].atom == wParam)
+ {
+ DoCommand(g_hotkeys[i].hkd.iCommand);
+ return 0;
+ }
+ }
+ }
+ break;
+
+ case WM_WA_IPC:
+ if (lParam == m_genhotkeys_add_ipc && m_genhotkeys_add_ipc > 65536)
+ {
+ int cmd = AddCommand((genHotkeysAddStruct *) wParam);
+ if (cmd > 0)
+ {
+ for (unsigned int i = 0; i < g_dwHotkeys; i++)
+ {
+ if (g_hotkeys[i].hkd.iCommand < 0
+ && g_hotkeys[i].hkd.szCommand
+ && !lstrcmpiW(g_hotkeys[i].hkd.szCommand, GetCommandId(cmd)))
+ {
+ g_hotkeys[i].hkd.iCommand = cmd;
+ free(g_hotkeys[i].hkd.szCommand);
+ g_hotkeys[i].hkd.szCommand = NULL;
+ int enabled = GetPrivateProfileIntW(L"gen_hotkeys", L"enabled", 0, g_iniFile);
+ if (enabled) RegisterHotkey(&g_hotkeys[i]);
+ }
+ }
+ }
+ return cmd;
+ }
+
+ // handles the weird inc/dec current rating (since it's locked to 0-5
+ // we can just wrap around and correct the real value passed on to the api)
+ else if(lParam == IPC_SETRATING && (wParam == -1 || wParam == 6))
+ {
+ LRESULT curRating = SendMessage(hwnd, WM_WA_IPC,
+ SendMessage(hwnd, WM_WA_IPC, 0, IPC_GETLISTPOS),
+ IPC_GETRATING);
+ if(wParam == 6) // increment
+ {
+ wParam = curRating+1;
+ }
+ else // decrement
+ {
+ wParam = curRating-1;
+ }
+ }
+ break;
+ }
+
+ // If we don't know how to handle this message, let WinAMP do it for us
+ if (winampIsUnicode)
+ return CallWindowProcW(lpWndProcOld, hwnd, message, wParam, lParam);
+ else
+ return CallWindowProcA(lpWndProcOld, hwnd, message, wParam, lParam);
+} \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/gen_hotkeys.h b/Src/Plugins/General/gen_hotkeys/gen_hotkeys.h
new file mode 100644
index 00000000..4cfb390c
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/gen_hotkeys.h
@@ -0,0 +1,56 @@
+#ifndef ___HOTAMP3_H___
+#define ___HOTAMP3_H___
+
+#include <windows.h>
+#include <commctrl.h>
+#include "winamp.h"
+#include "wa_hotkeys.h"
+#include "resource.h"
+#include "hotkey.h"
+#include "WACommands.h"
+#include "HotKeyCtl.h"
+#include "../winamp/gen.h"
+#include "api__gen_hotkeys.h"
+#include <strsafe.h>
+
+///////////////////////////////////////////////////////////
+// Hot keys initializer function
+///////////////////////////////////////////////////////////
+void hotkeysInit();
+int hotkeysLoad(HOTKEY_DATA *hkds, DWORD num, int do_register, int verbose=1);
+void hotkeysSave(HOTKEY_DATA *hkds, DWORD num);
+void hotkeysClear();
+
+///////////////////////////////////////////////////////////
+// Plugin function headers
+///////////////////////////////////////////////////////////
+int pluginInit();
+void pluginConfig();
+void pluginQuit();
+
+///////////////////////////////////////////////////////////
+// DLL Windows message handling procedure header
+///////////////////////////////////////////////////////////
+LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+///////////////////////////////////////////////////////////
+// Globals
+///////////////////////////////////////////////////////////
+extern winampGeneralPurposePlugin psPlugin;
+extern HOTKEY *g_hotkeys;
+extern DWORD g_dwHotkeys;
+extern wchar_t *g_iniFile;
+extern HOTKEY_DATA g_defhkds[];
+#define DEFHKDS_NUM 15
+
+void writePrivateProfileInt(wchar_t *section, int val);
+
+#ifndef LONGX86
+#ifdef _WIN64
+ #define LONGX86 LONG_PTR
+#else /*_WIN64*/
+ #define LONGX86 LONG
+#endif /*_WIN64*/
+#endif // LONGX86
+
+#endif \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/gen_hotkeys.rc b/Src/Plugins/General/gen_hotkeys/gen_hotkeys.rc
new file mode 100644
index 00000000..6187bdd1
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/gen_hotkeys.rc
@@ -0,0 +1,217 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_LVSTATE BITMAP "x.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_CONFIG DIALOGEX 0, 0, 273, 246
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ GROUPBOX "Global Hotkeys",IDC_STATIC,0,0,272,246
+ LTEXT "Global Hotkeys are keyboard shortcuts that you can use from within any running\napplication.",IDC_STATIC,6,11,260,17
+ CONTROL "Enable default &multimedia key support (you can customize them below)\n(Will process media related WM_APPCOMMAND messages - see MSDN)",IDC_ENABLED_WM_APPCOMMAND,
+ "Button",BS_AUTOCHECKBOX | BS_TOP | BS_MULTILINE | WS_TABSTOP,6,32,259,17
+ CONTROL "&Enabled",IDC_ENABLED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,54,42,10
+ PUSHBUTTON "Restore &defaults",IDC_DEFAULT,189,53,76,13
+ CONTROL "List1",IDC_HKLIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | WS_BORDER | WS_TABSTOP,6,70,259,137
+ LTEXT "Ac&tion",IDC_STATIC,6,213,24,9,SS_CENTERIMAGE
+ COMBOBOX IDC_COMBO,34,211,231,154,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "&Hotkey",IDC_STATIC,6,229,24,9
+ EDITTEXT IDC_HOTKEY,34,227,147,13,ES_AUTOHSCROLL
+ PUSHBUTTON "&Add",IDC_ADD,182,227,23,13
+ PUSHBUTTON "&Set",IDC_SAVE,208,227,20,13
+ PUSHBUTTON "&Remove",IDC_REMOVE,230,227,35,13
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "#include ""version.rc2""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_NULLSOFT_GLOBAL_HOTKEYS "Nullsoft Global Hotkeys v%s"
+ 65535 "{250FAA3C-20CD-49db-A932-67B1C0191B0E}"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_GHK_TITLE_STR "Global Hotkeys"
+ IDS_GHK_HOTKEY_REG_FAILED
+ "Hotkey registration failed as another program has already registered the following hotkey(s):\t\t\n"
+ IDS_GHK_HOTKEY_REG_FAILED_MORE "\n\tMore..."
+ IDS_GHK_HOTKEY_COLUMN "Hotkey"
+ IDS_GHK_ACTION_COLUMN "Action"
+ IDS_GHK_ACTION_NOT_FOUND "(action not found)"
+ IDS_GHK_WINKEY_STR "Winkey"
+ IDS_BROWSER_BACK "Browser Back"
+ IDS_BROWSER_FORWARD "Browser Forward"
+ IDS_BROWSER_REFRESH "Browser Refresh"
+ IDS_BROWSER_STOP "Browser Stop"
+ IDS_BROWSER_SEARCH "Browser Search"
+ IDS_BROWSER_FAVOURITES "Browser Favorites"
+ IDS_BROWSER_HOME "Browser Home"
+ IDS_VOLUME_MUTE "Volume Mute"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_VOLUME_DOWN "Volume Down"
+ IDS_VOLUME_UP "Volume Up"
+ IDS_NEXT_TRACK "Next Track"
+ IDS_PREVIOUS_TRACK "Previous Track"
+ IDS_STOP "Stop"
+ IDS_PLAY_PAUSE "Play/Pause"
+ IDS_LAUNCH_MAIL "Launch Mail"
+ IDS_LAUNCH_MEDIA_SELECT "Launch Media Select"
+ IDS_LAUCH_APP1 "Launch App1"
+ IDS_LAUCH_APP2 "Launch App2"
+ IDS_SLEEP "Sleep"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_PLAYBACK__PLAY "Playback: Play"
+ IDS_PLAYBACK__PAUSE "Playback: Pause"
+ IDS_PLAYBACK__STOP "Playback: Stop"
+ IDS_PLAYBACK__PREVIOUS_IN_PLAYLIST "Playback: Previous in playlist"
+ IDS_PLAYBACK__NEXT_IN_PLAYLIST "Playback: Next in playlist"
+ IDS_PLAYBACK__VOLUME_UP "Playback: Volume up"
+ IDS_PLAYBACK__VOLUME_DOWN "Playback: Volume down"
+ IDS_PLAYBACK__FORWARD "Playback: Forward"
+ IDS_PLAYBACK__REWIND "Playback: Rewind"
+ IDS_PLAYBACK__REPEAT_ON "Playback: Repeat on"
+ IDS_PLAYBACK__REPEAT_OFF "Playback: Repeat off"
+ IDS_UI__TOGGLE_EQ "UI: Toggle EQ"
+ IDS_UI__TOGGLE_PLAYLIST "UI: Toggle playlist"
+ IDS_UI__TOGGLE_AOT "UI: Toggle always on top"
+ IDS_UI__ABOUT "UI: About"
+ IDS_PLAYBACK__JUMP_TO_BOX "Playback: Jump to box"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_PLAYBACK__OPEN_FILE_DIALOG "Playback: Open file dialog"
+ IDS_PLAYBACK__OPEN_LOC_DIALOG "Playback: Open location dialog"
+ IDS_PLAYBACK__OPEN_FOLDER_DIALOG "Playback: Open folder dialog"
+ IDS_GENERAL__QUIT "General: Quit"
+ IDS_UI__PREFERENCES "UI: Preferences"
+ IDS_GENERAL__COPY_TITLE "General: Copy title"
+ IDS_GENERAL__COPY_FILE_PATH "General: Copy file path"
+ IDS_PLAYBACK__PLAY_PAUSE "Playback: Play/Pause"
+ IDS_PLAYBACK__TOGGLE_REPEAT "Playback: Toggle repeat"
+ IDS_PLAYBACK__TOGGLE_SHUFFLE "Playback: Toggle shuffle"
+ IDS_UI__TOGGLE_WINSHADE "UI: Toggle windowshade"
+ IDS_UI__TOGGLE_PLAYLIST_WINSHADE "UI: Toggle playlist windowshade"
+ IDS_UI__TOGGLE_DOUBLESIZE "UI: Toggle doublesize"
+ IDS_UI__TOGGLE_MAIN_WINDOW "UI: Toggle main window"
+ IDS_UI__TOGGLE_MINIBROWSER "UI: Toggle main minibrowser"
+ IDS_VIS__PREFERENCES "Visualization: Preferences"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_VIS__PLUGIN_PREFERENCES "Visualization: Plug-in preferences"
+ IDS_VIS_TOGGLE_VIS_ON_OFF "Visualization: Toggle on/off"
+ IDS_UI__SELECT_SKIN "UI: Select skin"
+ IDS_PLAYBACK__STOP_WITH_FADEOUT "Playback: Stop with fadeout"
+ IDS_PLAYBACK__STOP_AFTER_CURRENT "Playback: Stop after current"
+ IDS_PLAYBACK__START_OF_LIST "Playback: Start of list"
+ IDS_PLAYBACK__END_OF_LIST "Playback: End of list"
+ IDS_UI__BRING_TO_FRONT_OR_HIDE "UI: Bring to front/hide Winamp"
+ IDS_RATING__5_STARS "Rate current item: *****"
+ IDS_RATING__4_STARS "Rate current item: ****"
+ IDS_RATING__3_STARS "Rate current item: ***"
+ IDS_RATING__2_STARS "Rate current item: **"
+ IDS_RATING__1_STAR "Rate current item: *"
+ IDS_RATING__NO_RATING "Rate current item: No rating"
+ IDS_GENERAL__COPY_TITLEW "General: Copy title (Unicode)"
+ IDS_GENERAL__COPY_FILE_PATHW "General: Copy file path (Unicode)"
+END
+
+STRINGTABLE
+BEGIN
+ IDS_RATING__INC "Rating: Increase rating of current item"
+ IDS_RATING__DEC "Rating: Decrease rating of current item"
+ IDS_PAUSE "Pause"
+ IDS_VIS_NEXT_PRESET "Visualization: Next preset"
+ IDS_VIS_PREV_PRESET "Visualization: Previous preset"
+ IDS_VIS_RAND_PRESET "Visualization: Random preset"
+ IDS_VIS_FULL_SCREEN "Visualization: Toggle fullscreen"
+ IDS_PLAYBACK__MANUAL_ADVANCE "Playback: Toggle manual advance"
+ IDS_GENERAL_FFOD "General: Explore current item folder"
+ IDS_PLAYBACK_EDIT_ID3 "Playback: View current file information"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#include "version.rc2"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Src/Plugins/General/gen_hotkeys/gen_hotkeys.sln b/Src/Plugins/General/gen_hotkeys/gen_hotkeys.sln
new file mode 100644
index 00000000..25d787a7
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/gen_hotkeys.sln
@@ -0,0 +1,29 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29424.173
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_hotkeys", "gen_hotkeys.vcxproj", "{A0E56406-B1C9-4FC8-9589-A640D71A7364}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A0E56406-B1C9-4FC8-9589-A640D71A7364}.Debug|Win32.ActiveCfg = Debug|Win32
+ {A0E56406-B1C9-4FC8-9589-A640D71A7364}.Debug|Win32.Build.0 = Debug|Win32
+ {A0E56406-B1C9-4FC8-9589-A640D71A7364}.Debug|x64.ActiveCfg = Debug|x64
+ {A0E56406-B1C9-4FC8-9589-A640D71A7364}.Release|Win32.ActiveCfg = Release|Win32
+ {A0E56406-B1C9-4FC8-9589-A640D71A7364}.Release|Win32.Build.0 = Release|Win32
+ {A0E56406-B1C9-4FC8-9589-A640D71A7364}.Release|x64.ActiveCfg = Release|x64
+ {A0E56406-B1C9-4FC8-9589-A640D71A7364}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {AF3A8D23-4DD8-4A09-BD21-7A59EDA47D7C}
+ EndGlobalSection
+EndGlobal
diff --git a/Src/Plugins/General/gen_hotkeys/gen_hotkeys.vcxproj b/Src/Plugins/General/gen_hotkeys/gen_hotkeys.vcxproj
new file mode 100644
index 00000000..f8d7bc1c
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/gen_hotkeys.vcxproj
@@ -0,0 +1,316 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{A0E56406-B1C9-4FC8-9589-A640D71A7364}</ProjectGuid>
+ <RootNamespace>gen_hotkeys</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <LibraryPath>$(LibraryPath)</LibraryPath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <LibraryPath>$(LibraryPath)</LibraryPath>
+ <EmbedManifest>true</EmbedManifest>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg">
+ <VcpkgEnabled>false</VcpkgEnabled>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <VcpkgConfiguration>Debug</VcpkgConfiguration>
+ <VcpkgTriplet>
+ </VcpkgTriplet>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <VcpkgConfiguration>Debug</VcpkgConfiguration>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;_DEBUG;_WINDOWS;_USRDLL;HOTAMP3_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>odbc32.lib;odbccp32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ <MapFileName>$(IntDir)$(TargetName).map</MapFileName>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
+xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;_DEBUG;_WINDOWS;_USRDLL;HOTAMP3_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>odbc32.lib;odbccp32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ <MapFileName>$(IntDir)$(TargetName).map</MapFileName>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
+xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN32;NDEBUG;_WINDOWS;_USRDLL;HOTAMP3_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>None</DebugInformationFormat>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>odbc32.lib;odbccp32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <MapFileName>$(IntDir)$(TargetName).map</MapFileName>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <AdditionalIncludeDirectories>.;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;WIN64;NDEBUG;_WINDOWS;_USRDLL;HOTAMP3_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <BufferSecurityCheck>true</BufferSecurityCheck>
+ <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>None</DebugInformationFormat>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_WIN32_WINNT=0x0601;WINVER=0x0601;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Culture>0x0409</Culture>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>odbc32.lib;odbccp32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <MapFileName>$(IntDir)$(TargetName).map</MapFileName>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <SubSystem>Windows</SubSystem>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="accelBlock.cpp" />
+ <ClCompile Include="ConfigDlg.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">WIN64;_DEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">WIN64;NDEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="gen_hotkeys.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">WIN64;_DEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">WIN64;NDEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="HotKey.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">WIN64;_DEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">WIN64;NDEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="HotKeyCtl.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">WIN64;_DEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">WIN64;NDEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="WACommands.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">WIN64;_DEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">WIN64;NDEBUG;_WINDOWS;_MBCS;_USRDLL;HOTAMP3_EXPORTS</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="accelBlock.h" />
+ <ClInclude Include="api__gen_hotkeys.h" />
+ <ClInclude Include="ConfigDlg.h" />
+ <ClInclude Include="gen_hotkeys.h" />
+ <ClInclude Include="HotKey.h" />
+ <ClInclude Include="HotKeyCtl.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="WACommands.h" />
+ <ClInclude Include="wa_hotkeys.h" />
+ <ClInclude Include="winamp.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="gen_hotkeys.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <Image Include="x.bmp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\Wasabi\Wasabi.vcxproj">
+ <Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/gen_hotkeys.vcxproj.filters b/Src/Plugins/General/gen_hotkeys/gen_hotkeys.vcxproj.filters
new file mode 100644
index 00000000..515b3109
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/gen_hotkeys.vcxproj.filters
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="WACommands.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="HotKeyCtl.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="HotKey.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="gen_hotkeys.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="ConfigDlg.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="accelBlock.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="winamp.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="WACommands.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="wa_hotkeys.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="HotKey.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="gen_hotkeys.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="ConfigDlg.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="api__gen_hotkeys.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="accelBlock.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="HotKeyCtl.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{b429b35f-cbbb-427f-b618-1e7c2ef4fa72}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Ressource Files">
+ <UniqueIdentifier>{d06654b1-494e-468a-9e54-d70525ca2531}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{b03b7dae-2c85-4929-8e46-eb6b06b87635}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Image Files">
+ <UniqueIdentifier>{36cdd73d-755e-40a7-945a-f6cad3b9379c}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <Image Include="x.bmp">
+ <Filter>Image Files</Filter>
+ </Image>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="gen_hotkeys.rc">
+ <Filter>Ressource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/version.rc2 b/Src/Plugins/General/gen_hotkeys/version.rc2
new file mode 100644
index 00000000..f151f4be
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/version.rc2
@@ -0,0 +1,39 @@
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+#include "..\..\..\Winamp/buildType.h"
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,97,0,0
+ PRODUCTVERSION WINAMP_PRODUCTVER
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Winamp SA"
+ VALUE "FileDescription", "Winamp General Purpose Plug-in"
+ VALUE "FileVersion", "1,97,0,0"
+ VALUE "InternalName", "Nullsoft Global Hotkeys"
+ VALUE "LegalCopyright", "Copyright © 2003-2023 Winamp SA"
+ VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
+ VALUE "OriginalFilename", "gen_hotkeys.dll"
+ VALUE "ProductName", "Winamp"
+ VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/Src/Plugins/General/gen_hotkeys/wa_hotkeys.h b/Src/Plugins/General/gen_hotkeys/wa_hotkeys.h
new file mode 100644
index 00000000..2877c01d
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/wa_hotkeys.h
@@ -0,0 +1,91 @@
+#ifndef WA_HOTKEYS
+#define WA_HOTKEYS
+
+/*
+** #define IPC_GEN_HOTKEYS_ADD xxxx // pass a genHotkeysAddStruct * struct in data
+**
+** To get the IPC_GEN_HOTKEYS_ADD IPC number, you need to do this:
+**
+** genhotkeys_add_ipc=SendMessage(winampWindow,WM_WA_IPC,(WPARAM)&"GenHotkeysAdd",IPC_REGISTER_WINAMP_IPCMESSAGE);
+**
+** Then you can use:
+**
+** PostMessage(winampWindow,WM_WA_IPC,(WPARAM)&myGenHotkeysAddStruct,genhotkeys_add_ipc);
+*/
+
+//flags for the genHotkeysAddStruct struct
+#define HKF_BRING_TO_FRONT 0x1 // calls SetForegroundWindow before sending the message
+#define HKF_HWND_WPARAM 0x2 // sets wParam with Winamp's window handle
+#define HKF_COPY 0x4 // copies returned text to the clipboard (using CF_TEXT)
+#define HKF_PLPOS_WPARAM 0x8 // sets wParam with current pledit position
+#define HKF_ISPLAYING_WL 0x10 // sets wParam to genHotkeysAddStruct's wParam if playing, lParam if not
+ // uses IPC_ISPLAYING to check if playing
+#define HKF_SHOWHIDE 0x20 // brings Winamp to front or minimizes Winamp if already at front
+#define HKF_NOSENDMSG 0x40 // don't send any message to the winamp window
+
+#define HKF_COPYW 0x80 // copies returned text to the clipboard (using CF_UNICODETEXT)
+#define HKF_UNICODE_NAME 0x100 // set this when the 'name' is passed as a unicode string
+
+#define HKF_DISABLED 0x80000000
+
+#include "WinDef.h"
+
+typedef struct {
+ char *name; //name that will appear in the Global Hotkeys preferences panel
+ DWORD flags; //one or more flags from above
+ UINT uMsg; //message that will be sent to winamp's main window (must always be !=NULL)
+ WPARAM wParam; //wParam that will be sent to winamp's main window
+ LPARAM lParam; //lParam that will be sent to winamp's main window
+ char *id; //unique string to identify this command - case insensitive
+ HWND wnd; //set the HWND to send message (or 0 for main winamp window)
+
+ int extended[6]; //for future extension - always set to zero!
+} genHotkeysAddStruct;
+
+/*
+** Before calling this function you need to setup the genHotkeysAddStruct struct
+**
+** genHotkeysAddStruct test_key = {0}; // this will make the compiler zero the struct for you
+** // though you can do it manually if you want to as well
+**
+** UINT test_ipc = 0; // this will hold the uMsg value to look for in the assigned window proc
+**
+** // then call the function to register the hotkey
+** AddGlobalHotkey(&test_key,"Playback: Test key","Test_key",&test_ipc);
+**
+** void AddGlobalHotkey(genHotkeysAddStruct *hotkey, char* name, char* id, int* ipc){
+** UINT genhotkeys_add_ipc = 0;
+** hotkey->wnd = 0;
+** hotkey->flags = 0;
+** hotkey->name = name;
+** hotkey->id = id;
+** *ipc = hotkey->uMsg = SendMessage(winampWindow,WM_WA_IPC,(WPARAM)&hotkey->id,IPC_REGISTER_WINAMP_IPCMESSAGE);
+**
+** genhotkeys_add_ipc=SendMessage(winampWindow,WM_WA_IPC,(WPARAM)&"GenHotkeysAdd",IPC_REGISTER_WINAMP_IPCMESSAGE);
+** PostMessage(winampWindow,WM_WA_IPC,(WPARAM)hotkey,genhotkeys_add_ipc);
+** }
+*/
+
+/*
+** This shows how to detect the registered hotkey message
+** then it's upto you what you do
+**
+** LRESULT CALLBACK WinampWnd(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
+** int ret = 0;
+**
+** // handles the hotkey for the option :o)
+** if(uMsg == test_ipc){
+** // here you can do things needed for the hotkey you registered
+** }
+**
+** // do stuff before the winamp proc has been called
+**
+** ret = CallWindowProc(WinampProc,hwnd,uMsg,wParam,lParam);
+**
+** // do other stuff after the winamp proc has been called
+** // then return the value from CallWindowProc(..)
+** return ret;
+** }
+*/
+
+#endif \ No newline at end of file
diff --git a/Src/Plugins/General/gen_hotkeys/x.bmp b/Src/Plugins/General/gen_hotkeys/x.bmp
new file mode 100644
index 00000000..43ebcfc0
--- /dev/null
+++ b/Src/Plugins/General/gen_hotkeys/x.bmp
Binary files differ