gen_hotkeys.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. //#define PLUGIN_NAME //"Nullsoft Global Hotkeys"
  2. #define PLUGIN_VERSION L"1.97"
  3. // do this so we can get WM_APPCOMMAND support (needed in 1.6+)
  4. // (have to targetting xp sp1+ so we get the specific play & pause messages
  5. // though it'll work fine with win2k+ as those messages will never appear)
  6. //////#define _WIN32_WINNT 0x0501
  7. #include "gen_hotkeys.h"
  8. #include "ConfigDlg.h"
  9. #include "HotKey.h"
  10. #include "WACommands.h"
  11. #include <api/service/waServiceFactory.h>
  12. ///////////////////////////////////////////////////////////
  13. // Globals
  14. ///////////////////////////////////////////////////////////
  15. // The global plugin instance
  16. winampGeneralPurposePlugin psPlugin =
  17. {
  18. GPPHDR_VER_U,
  19. "nullsoft(gen_hotkeys.dll)",
  20. pluginInit,
  21. pluginConfig,
  22. hotkeysClear
  23. };
  24. // Winamp's window procdure
  25. WNDPROC lpWndProcOld = NULL;
  26. static int winampIsUnicode=false;
  27. static int appcommand=false;
  28. // hotkeys
  29. HOTKEY *g_hotkeys = NULL;
  30. DWORD g_dwHotkeys = 0;
  31. // mutex to prevent two gen_hotkeys
  32. HANDLE g_hMutex = NULL;
  33. LPARAM uShellHook = NULL;
  34. // wasabi based services for localisation support
  35. api_service *WASABI_API_SVC = 0;
  36. api_application *WASABI_API_APP = NULL;
  37. api_language *WASABI_API_LNG = 0;
  38. HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
  39. static prefsDlgRecW g_prefsItem = {0};
  40. static wchar_t g_titlestr[128];
  41. wchar_t *g_iniFile = 0;
  42. // don't forget to set DEFHKDS_NUM if you change this
  43. HOTKEY_DATA g_defhkds[] = {
  44. {MAKEWORD(VK_INSERT, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc play"},
  45. {MAKEWORD(VK_HOME, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc pause"},
  46. {MAKEWORD(VK_END, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc stop"},
  47. {MAKEWORD(VK_PRIOR, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc prev"},
  48. {MAKEWORD(VK_NEXT, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc next"},
  49. {MAKEWORD(VK_UP, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc vup"},
  50. {MAKEWORD(VK_DOWN, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc vdown"},
  51. {MAKEWORD(VK_RIGHT, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc forward"},
  52. {MAKEWORD(VK_LEFT, HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc rewind"},
  53. {MAKEWORD('J', HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc jump"},
  54. {MAKEWORD('L', HOTKEYF_ALT | HOTKEYF_CONTROL | HOTKEYF_EXT), -1, L"ghkdc file"},
  55. //multimedia keyboard stuff
  56. {2226, -1, L"ghkdc stop"},
  57. {2227, -1, L"ghkdc play/pause"},
  58. {2225, -1, L"ghkdc prev"},
  59. {2224, -1, L"ghkdc next"},
  60. };
  61. #define TIMER_ID 0x8855
  62. static int m_genhotkeys_add_ipc;
  63. ///////////////////////////////////////////////////////////
  64. // DLL entry function
  65. ///////////////////////////////////////////////////////////
  66. #ifndef _DEBUG
  67. BOOL WINAPI _DllMainCRTStartup(HINSTANCE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
  68. {
  69. DisableThreadLibraryCalls(hInst);
  70. return TRUE;
  71. }
  72. #endif
  73. ///////////////////////////////////////////////////////////
  74. // Plugin functions
  75. ///////////////////////////////////////////////////////////
  76. int pluginInit()
  77. {
  78. RegisterShellHookWindow(psPlugin.hwndParent);
  79. uShellHook = RegisterWindowMessage(TEXT("SHELLHOOK"));
  80. g_iniFile = (wchar_t*)SendMessage(psPlugin.hwndParent, WM_WA_IPC, 0, IPC_GETINIFILEW);
  81. // loader so that we can get the localisation service api for use
  82. WASABI_API_SVC = (api_service*)SendMessage(psPlugin.hwndParent, WM_WA_IPC, 0, IPC_GET_API_SERVICE);
  83. if (WASABI_API_SVC == (api_service*)1 ||
  84. NULL == WASABI_API_SVC)
  85. {
  86. return 1;
  87. }
  88. waServiceFactory *sf = WASABI_API_SVC->service_getServiceByGuid(applicationApiServiceGuid);
  89. if (sf) WASABI_API_APP = reinterpret_cast<api_application*>(sf->getInterface());
  90. sf = WASABI_API_SVC->service_getServiceByGuid(languageApiGUID);
  91. if (sf) WASABI_API_LNG = reinterpret_cast<api_language*>(sf->getInterface());
  92. // need to have this initialised before we try to do anything with localisation features
  93. WASABI_API_START_LANG(psPlugin.hDllInstance,GenHotkeysLangGUID);
  94. m_genhotkeys_add_ipc = (int)SendMessage( psPlugin.hwndParent, WM_WA_IPC, (WPARAM) &"GenHotkeysAdd", IPC_REGISTER_WINAMP_IPCMESSAGE);
  95. static wchar_t szDescription[256];
  96. StringCchPrintfW(szDescription, ARRAYSIZE(szDescription),
  97. WASABI_API_LNGSTRINGW(IDS_NULLSOFT_GLOBAL_HOTKEYS), PLUGIN_VERSION);
  98. psPlugin.description = (char*)szDescription;
  99. appcommand = GetPrivateProfileIntW(L"gen_hotkeys", L"appcommand", 0, g_iniFile);
  100. // Save Winamp's window procedure
  101. winampIsUnicode = IsWindowUnicode(psPlugin.hwndParent);
  102. lpWndProcOld = (WNDPROC)(LONG_PTR)GetWindowLongPtr(psPlugin.hwndParent, GWLP_WNDPROC);
  103. if (winampIsUnicode)
  104. SetWindowLongPtrW(psPlugin.hwndParent, GWLP_WNDPROC, (LONGX86)(LONG_PTR)WndProc);
  105. else
  106. SetWindowLongPtrA(psPlugin.hwndParent, GWLP_WNDPROC, (LONGX86)(LONG_PTR)WndProc);
  107. InitCommands();
  108. SetTimer(psPlugin.hwndParent, TIMER_ID, 10, NULL); //call hotkeysInit() when all plugins are loaded
  109. //register prefs screen
  110. g_prefsItem.dlgID = IDD_CONFIG;
  111. g_prefsItem.name = WASABI_API_LNGSTRINGW_BUF(IDS_GHK_TITLE_STR,g_titlestr,128);
  112. g_prefsItem.proc = ConfigProc;
  113. g_prefsItem.hInst = WASABI_API_LNG_HINST;
  114. // delay the adding of this
  115. // for some reason when changing a lang pack it can cause the WM_DESTROY of ConfigProc
  116. // to be called which completely messes up the ghk list and so can wipe it :(
  117. SendMessage(psPlugin.hwndParent, WM_WA_IPC, (WPARAM) &g_prefsItem, IPC_ADD_PREFS_DLGW);
  118. return 0;
  119. }
  120. int hotkeysLoad(HOTKEY_DATA *hkds, DWORD num, int do_register, int verbose /*=1*/)
  121. {
  122. unsigned int uFailed = 0;
  123. delete [] g_hotkeys;
  124. g_hotkeys = NULL;
  125. if (num)
  126. {
  127. g_hotkeys = new HOTKEY[num];
  128. memset(g_hotkeys, 0, num * sizeof(HOTKEY));
  129. }
  130. if (!g_hotkeys)
  131. {
  132. g_dwHotkeys = 0;
  133. return 1;
  134. }
  135. g_dwHotkeys = num;
  136. wchar_t moreStr[64] = {0};
  137. WASABI_API_LNGSTRINGW_BUF(IDS_GHK_HOTKEY_REG_FAILED_MORE,moreStr,64);
  138. size_t bufLen = 256 + wcslen(moreStr) + 1;
  139. wchar_t* szFailed = (wchar_t*)malloc(bufLen*sizeof(wchar_t));
  140. WASABI_API_LNGSTRINGW_BUF(IDS_GHK_HOTKEY_REG_FAILED,szFailed,bufLen);
  141. DWORD dwLeft = 256 - lstrlenW(szFailed);
  142. DWORD dwFailedWithNoMsg = 0;
  143. for (DWORD i = 0; i < num; i++)
  144. {
  145. g_hotkeys[i].hkd = hkds[i];
  146. if (g_hotkeys[i].hkd.iCommand < 0)
  147. // action not loaded yet for this hotkey
  148. continue;
  149. if (do_register && RegisterHotkey(g_hotkeys + i))
  150. {
  151. if (verbose && dwLeft)
  152. {
  153. wchar_t szTemp[1024] = {0};
  154. bool unicode = 0;
  155. char* name = GetCommandName(g_hotkeys[i].hkd.iCommand, &unicode);
  156. StringCchPrintfW(szTemp, 1024, (unicode?L"\n\t%s":L"\n\t%S"), name);
  157. DWORD dwLen = lstrlenW(szTemp);
  158. if (dwLen < dwLeft)
  159. {
  160. StringCchCatW(szFailed, bufLen, szTemp);
  161. dwLeft -= dwLen;
  162. }
  163. else
  164. dwFailedWithNoMsg++;
  165. }
  166. g_hotkeys[i].failed = TRUE;
  167. uFailed++;
  168. }
  169. }
  170. if (verbose && uFailed)
  171. {
  172. if (dwFailedWithNoMsg)
  173. StringCchCatW(szFailed, bufLen, moreStr);
  174. HWND parent = (HWND)SendMessage(psPlugin.hwndParent, WM_WA_IPC, 0, IPC_GETDIALOGBOXPARENT);
  175. if (parent == 0 || parent == (HWND)1)
  176. parent=psPlugin.hwndParent;
  177. MessageBoxW(parent, szFailed, g_titlestr, MB_OK | MB_ICONSTOP | MB_TOPMOST);
  178. }
  179. free(szFailed);
  180. return uFailed;
  181. }
  182. static volatile LONG initted=0;
  183. void hotkeysInit()
  184. {
  185. if (initted)
  186. return;
  187. initted=1;
  188. int enabled = GetPrivateProfileIntW(L"gen_hotkeys", L"enabled", 0, g_iniFile);
  189. // base the mutex on the current winamp install
  190. // (makes it work better with mutliple winamp installs otherwise the older
  191. // "Winamp - gen_hotkeys.dll ^&*#@" mutex prevents different hotkeys from
  192. // being initialised between the different installs without going to prefs)
  193. char mutexStr[MAX_PATH] = {0}, ghkFilename[MAX_PATH] = {0};
  194. GetModuleFileName(psPlugin.hDllInstance, ghkFilename, MAX_PATH);
  195. StringCchPrintf(mutexStr, MAX_PATH, "Winamp - %s ^&*#@", ghkFilename);
  196. g_hMutex = CreateMutex(0, TRUE, mutexStr);
  197. if (GetLastError() == ERROR_ALREADY_EXISTS)
  198. enabled = 0;
  199. int i;
  200. for (i = 0; i < DEFHKDS_NUM; i++)
  201. {
  202. g_defhkds[i].iCommand = GetCommandIdx(g_defhkds[i].szCommand);
  203. g_defhkds[i].szCommand = 0;
  204. }
  205. int l = GetPrivateProfileIntW(L"gen_hotkeys", L"nbkeys", -1, g_iniFile);
  206. int ver = GetPrivateProfileIntW(L"gen_hotkeys", L"version", 1, g_iniFile);
  207. if (l != -1)
  208. {
  209. if (ver == 2)
  210. {
  211. HOTKEY_DATA *hkds = new HOTKEY_DATA[l]; // TODO: could alloca this
  212. if (hkds)
  213. {
  214. for (i = 0; i < l; i++)
  215. {
  216. wchar_t tmp[1024] = {0}, action[1024] = {0};
  217. StringCchPrintfW(tmp, 1024, L"action%d", i);
  218. GetPrivateProfileStringW(L"gen_hotkeys", tmp, L"", action, 1024, g_iniFile);
  219. StringCchPrintfW(tmp, 1024, L"hotkey%d", i);
  220. int hotkey = GetPrivateProfileIntW(L"gen_hotkeys", tmp, 0, g_iniFile);
  221. hkds[i].dwHotKey = hotkey;
  222. hkds[i].iCommand = GetCommandIdx(action);
  223. if (hkds[i].iCommand >= 0)
  224. hkds[i].szCommand = NULL;
  225. else
  226. hkds[i].szCommand = _wcsdup(action);
  227. }
  228. hotkeysLoad(hkds, l, enabled, 0);
  229. delete [] hkds;
  230. }
  231. }
  232. // legacy support
  233. else if (ver == 1)
  234. {
  235. HOTKEY_DATA *hkds = new HOTKEY_DATA[l]; // TODO: could alloca this
  236. if (hkds)
  237. {
  238. int nb = 0;
  239. for (i = 0;i < l;i++)
  240. {
  241. wchar_t tmp[512] = {0};
  242. StringCchPrintfW(tmp, 512, L"msg%d", i);
  243. unsigned int msg = GetPrivateProfileIntW(L"gen_hotkeys", tmp, 0, g_iniFile);
  244. if (msg)
  245. {
  246. StringCchPrintfW(tmp, 512, L"wparam%d", i);
  247. WPARAM wparam = GetPrivateProfileIntW(L"gen_hotkeys", tmp, 0, g_iniFile);
  248. StringCchPrintfW(tmp, 512, L"lparam%d", i);
  249. LPARAM lparam = GetPrivateProfileIntW(L"gen_hotkeys", tmp, 0, g_iniFile);
  250. for (int j = 0;WACommands[j].name;j++)
  251. {
  252. if (WACommands[j].uMsg == msg && WACommands[j].wParam == wparam && WACommands[j].lParam == lparam)
  253. {
  254. StringCchPrintfW(tmp, 512, L"hotkey%d", i);
  255. int hotkey = GetPrivateProfileIntW(L"gen_hotkeys", tmp, 0, g_iniFile);
  256. hkds[nb].dwHotKey = hotkey;
  257. hkds[nb].iCommand = j;
  258. hkds[nb].szCommand = NULL;
  259. nb++;
  260. break;
  261. }
  262. }
  263. }
  264. }
  265. hotkeysLoad(hkds, nb, enabled, 0);
  266. delete [] hkds;
  267. }
  268. }
  269. }
  270. else
  271. {
  272. // load defaults
  273. hotkeysLoad(g_defhkds, DEFHKDS_NUM, enabled, 0);
  274. }
  275. }
  276. void writePrivateProfileInt(wchar_t *section, int val)
  277. {
  278. wchar_t s[32] = {0};
  279. StringCchPrintfW(s, 32, L"%d", val);
  280. WritePrivateProfileStringW(L"gen_hotkeys", section, s, g_iniFile);
  281. }
  282. void hotkeysSave(HOTKEY_DATA *hkds, DWORD num)
  283. {
  284. int enabled = GetPrivateProfileIntW(L"gen_hotkeys", L"enabled", 0, g_iniFile);
  285. appcommand = GetPrivateProfileIntW(L"gen_hotkeys", L"appcommand", 0, g_iniFile);
  286. WritePrivateProfileStringW(L"gen_hotkeys", NULL, NULL, g_iniFile);
  287. writePrivateProfileInt(L"nbkeys", num);
  288. writePrivateProfileInt(L"version", 2);
  289. writePrivateProfileInt(L"enabled", enabled);
  290. writePrivateProfileInt(L"appcommand", appcommand);
  291. if (!hkds || !num)
  292. {
  293. return ;
  294. }
  295. for (size_t i = 0; i < num; i++)
  296. {
  297. wchar_t tmp[1024] = {0};
  298. StringCchPrintfW(tmp, 1024, L"action%d", i);
  299. if (hkds[i].iCommand >= 0)
  300. WritePrivateProfileStringW(L"gen_hotkeys", tmp, GetCommandId(hkds[i].iCommand), g_iniFile);
  301. else if (hkds[i].szCommand)
  302. WritePrivateProfileStringW(L"gen_hotkeys", tmp, hkds[i].szCommand, g_iniFile);
  303. StringCchPrintfW(tmp, 1024, L"hotkey%d", i);
  304. writePrivateProfileInt(tmp, hkds[i].dwHotKey);
  305. }
  306. }
  307. void pluginConfig()
  308. {
  309. SendMessage(psPlugin.hwndParent, WM_WA_IPC, (WPARAM) &g_prefsItem, IPC_OPENPREFSTOPAGE);
  310. }
  311. void hotkeysClear()
  312. {
  313. DeregisterShellHookWindow(psPlugin.hwndParent);
  314. if (!g_hotkeys)
  315. return;
  316. // Unregister all of the hot keys, and delete all of our unique hot key identifiers
  317. for (DWORD i = 0; i < g_dwHotkeys; i++)
  318. {
  319. UnregisterHotkey(g_hotkeys + i);
  320. }
  321. delete [] g_hotkeys;
  322. g_hotkeys = NULL;
  323. }
  324. ///////////////////////////////////////////////////////////
  325. // Plugin export function
  326. ///////////////////////////////////////////////////////////
  327. extern "C" __declspec(dllexport) winampGeneralPurposePlugin * winampGetGeneralPurposePlugin() { return &psPlugin; }
  328. ///////////////////////////////////////////////////////////
  329. // DLL Windows message handling procedure
  330. ///////////////////////////////////////////////////////////
  331. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  332. {
  333. if(message == uShellHook && appcommand && wParam == HSHELL_APPCOMMAND)
  334. {
  335. // WM_APPCOMMAND info:: http://msdn2.microsoft.com/en-us/library/ms646275.aspx
  336. int cmd = GET_APPCOMMAND_LPARAM(lParam);
  337. switch (cmd)
  338. {
  339. case APPCOMMAND_MEDIA_PLAY_PAUSE:
  340. {
  341. int playing = (int)SendMessage(psPlugin.hwndParent, WM_WA_IPC, 0, IPC_ISPLAYING);
  342. SendMessage(hwnd, WM_COMMAND, MAKEWPARAM((playing ? WINAMP_BUTTON3 : WINAMP_BUTTON2),0), 0);
  343. }
  344. break;
  345. case APPCOMMAND_MEDIA_NEXTTRACK:
  346. SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_BUTTON5,0), 0);
  347. return TRUE;
  348. case APPCOMMAND_MEDIA_PREVIOUSTRACK:
  349. SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_BUTTON1,0), 0);
  350. return TRUE;
  351. case APPCOMMAND_MEDIA_STOP:
  352. SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_BUTTON4,0), 0);
  353. return TRUE;
  354. case APPCOMMAND_VOLUME_DOWN:
  355. SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_VOLUMEDOWN,0), 0);
  356. return TRUE;
  357. case APPCOMMAND_VOLUME_UP:
  358. SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_VOLUMEUP,0), 0);
  359. return TRUE;
  360. /*case APPCOMMAND_VOLUME_MUTE:
  361. return TRUE;*/
  362. // info on play/pause (xp sp1+) commands:: http://msdn2.microsoft.com/en-us/library/bb417078.aspx
  363. case APPCOMMAND_MEDIA_PLAY:
  364. {
  365. int playing = (int)SendMessage(psPlugin.hwndParent, WM_WA_IPC, 0, IPC_ISPLAYING);
  366. // play if not currently playing/are stopped
  367. if(!playing) SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_BUTTON2,0), 0);
  368. // if paused then start playing again
  369. else if(playing == 3) SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_BUTTON3,0), 0);
  370. // otherwise do nothing if playing already (playing == 1)
  371. }
  372. return TRUE;
  373. case APPCOMMAND_MEDIA_PAUSE:
  374. {
  375. int playing = (int)SendMessage(psPlugin.hwndParent, WM_WA_IPC, 0, IPC_ISPLAYING);
  376. // if playing then we pause
  377. if(playing == 1) SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_BUTTON3,0), 0);
  378. // otherwise do nothing if already stopped or paused (playing == 0 || playing == 3)
  379. }
  380. return TRUE;
  381. case APPCOMMAND_MEDIA_FAST_FORWARD:
  382. SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_FFWD5S,0), 0);
  383. return TRUE;
  384. case APPCOMMAND_MEDIA_REWIND:
  385. SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(WINAMP_REW5S,0), 0);
  386. return TRUE;
  387. }
  388. }
  389. switch (message)
  390. {
  391. case WM_TIMER:
  392. if (wParam == TIMER_ID)
  393. {
  394. KillTimer(hwnd, TIMER_ID);
  395. hotkeysInit();
  396. return 0;
  397. }
  398. break;
  399. case WM_HOTKEY:
  400. if (g_hotkeys)
  401. {
  402. for (unsigned int i = 0; i < g_dwHotkeys; i++)
  403. {
  404. if (g_hotkeys[i].atom == wParam)
  405. {
  406. DoCommand(g_hotkeys[i].hkd.iCommand);
  407. return 0;
  408. }
  409. }
  410. }
  411. break;
  412. case WM_WA_IPC:
  413. if (lParam == m_genhotkeys_add_ipc && m_genhotkeys_add_ipc > 65536)
  414. {
  415. int cmd = AddCommand((genHotkeysAddStruct *) wParam);
  416. if (cmd > 0)
  417. {
  418. for (unsigned int i = 0; i < g_dwHotkeys; i++)
  419. {
  420. if (g_hotkeys[i].hkd.iCommand < 0
  421. && g_hotkeys[i].hkd.szCommand
  422. && !lstrcmpiW(g_hotkeys[i].hkd.szCommand, GetCommandId(cmd)))
  423. {
  424. g_hotkeys[i].hkd.iCommand = cmd;
  425. free(g_hotkeys[i].hkd.szCommand);
  426. g_hotkeys[i].hkd.szCommand = NULL;
  427. int enabled = GetPrivateProfileIntW(L"gen_hotkeys", L"enabled", 0, g_iniFile);
  428. if (enabled) RegisterHotkey(&g_hotkeys[i]);
  429. }
  430. }
  431. }
  432. return cmd;
  433. }
  434. // handles the weird inc/dec current rating (since it's locked to 0-5
  435. // we can just wrap around and correct the real value passed on to the api)
  436. else if(lParam == IPC_SETRATING && (wParam == -1 || wParam == 6))
  437. {
  438. LRESULT curRating = SendMessage(hwnd, WM_WA_IPC,
  439. SendMessage(hwnd, WM_WA_IPC, 0, IPC_GETLISTPOS),
  440. IPC_GETRATING);
  441. if(wParam == 6) // increment
  442. {
  443. wParam = curRating+1;
  444. }
  445. else // decrement
  446. {
  447. wParam = curRating-1;
  448. }
  449. }
  450. break;
  451. }
  452. // If we don't know how to handle this message, let WinAMP do it for us
  453. if (winampIsUnicode)
  454. return CallWindowProcW(lpWndProcOld, hwnd, message, wParam, lParam);
  455. else
  456. return CallWindowProcA(lpWndProcOld, hwnd, message, wParam, lParam);
  457. }