options_dsp.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. /** (c) Nullsoft, Inc. C O N F I D E N T I A L
  2. ** Filename:
  3. ** Project:
  4. ** Description:
  5. ** Author:
  6. ** Created:
  7. **/
  8. #include "Main.h"
  9. #include "resource.h"
  10. #include "Options.h"
  11. #include "dsp.h"
  12. #include "main.hpp"
  13. #include "../nu/AutoChar.h"
  14. #include "../nu/AutoWide.h"
  15. static bool pluginsLoaded;
  16. static void DSPUpdateSel( HWND hwndDlg, HWND listWindow, INT iItem )
  17. {
  18. wchar_t fn[ MAX_PATH * 2 ] = { 0 }, *libname = fn;
  19. int skip = 0;
  20. if ( ListView_GetNextItem( listWindow, -1, LVIS_SELECTED ) != -1 )
  21. {
  22. ListView_GetItemTextW( listWindow, iItem, 1, fn, ARRAYSIZE( fn ) );
  23. SendDlgItemMessageA( hwndDlg, IDC_DSPMOD, CB_RESETCONTENT, 0, 0 );
  24. int root = lstrcmpW( fn, getStringW( IDS_NOT_LOADED, NULL, 0 ) );
  25. if ( fn[ 0 ] && root )
  26. {
  27. if ( lstrcmpW( config_dspplugin_name, libname ) )
  28. config_dspplugin_num = 0;
  29. }
  30. else
  31. {
  32. if ( fn[ 0 ] )
  33. skip = 1;
  34. config_dspplugin_num = 0;
  35. }
  36. StringCchCopyW( config_dspplugin_name, MAX_PATH, libname );
  37. if ( *libname && !skip )
  38. {
  39. wchar_t b[ 1024 ] = { 0 };
  40. PathCombineW( b, DSPDIR, libname );
  41. HINSTANCE hLib = LoadLibraryW( b );
  42. if ( hLib )
  43. {
  44. winampDSPGetHeaderType pr = (winampDSPGetHeaderType) GetProcAddress( hLib, "winampDSPGetHeader2" );
  45. if ( pr )
  46. {
  47. int i = 0;
  48. for ( ;;)
  49. {
  50. winampDSPModule *module = pr( hMainWindow )->getModule( i++ );
  51. if ( !module )
  52. break;
  53. SendDlgItemMessageA( hwndDlg, IDC_DSPMOD, CB_ADDSTRING, 0, (LPARAM) (LPCSTR)module->description );
  54. // The description must be send in ASCII
  55. }
  56. }
  57. FreeModule( hLib );
  58. }
  59. SendDlgItemMessageA( hwndDlg, IDC_DSPMOD, CB_SETCURSEL, config_dspplugin_num, 0 );
  60. }
  61. }
  62. config_dspplugin_num = (unsigned char) SendDlgItemMessageA( hwndDlg, IDC_DSPMOD, CB_GETCURSEL, 0, 0 );
  63. if ( config_dspplugin_num == CB_ERR )
  64. config_dspplugin_num = 0;
  65. if ( pluginsLoaded )
  66. {
  67. dsp_quit();
  68. dsp_init();
  69. }
  70. if ( skip )
  71. fn[ 0 ] = 0;
  72. EnableWindow( GetDlgItem( hwndDlg, IDC_DSPCONF ), libname && !!*libname );
  73. EnableWindow( GetDlgItem( hwndDlg, IDC_UNINSTDSP ), libname && !!*libname || skip );
  74. EnableWindow( GetDlgItem( hwndDlg, IDC_DSPMOD ), libname && !!*libname );
  75. EnableWindow( GetDlgItem( hwndDlg, IDC_PLUGINLABEL ), libname && !!*libname );
  76. }
  77. // dsp tab procedure
  78. INT_PTR CALLBACK DspProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  79. {
  80. hi helpinfo[] = {
  81. {IDC_DSPLIB,IDS_P_DSP_LIB},
  82. {IDC_DSPMOD,IDS_P_DSP_MOD},
  83. {IDC_DSPCONF,IDS_P_DSP_CONF},
  84. };
  85. DO_HELP();
  86. if ( uMsg == WM_INITDIALOG )
  87. {
  88. pluginsLoaded = false;
  89. link_startsubclass( hwndDlg, IDC_PLUGINVERS );
  90. HWND listWindow = GetDlgItem( hwndDlg, IDC_DSPLIB );
  91. if ( IsWindow( listWindow ) )
  92. {
  93. RECT r = { 0 };
  94. GetWindowRect( listWindow, &r );
  95. GetClientRect( listWindow, &r );
  96. MapWindowPoints( listWindow, hwndDlg, (LPPOINT) &r, 2 );
  97. InflateRect( &r, 2, 2 );
  98. DestroyWindow( listWindow );
  99. listWindow = CreateWindowExW( WS_EX_NOPARENTNOTIFY | WS_EX_CLIENTEDGE, WC_LISTVIEWW, L"",
  100. WS_CHILD | WS_VISIBLE | WS_TABSTOP | LVS_REPORT | LVS_SINGLESEL |
  101. LVS_SHOWSELALWAYS | LVS_SORTASCENDING | LVS_NOCOLUMNHEADER | LVS_NOSORTHEADER,
  102. r.left, r.top, r.right - r.left, r.bottom - r.top,
  103. hwndDlg, (HMENU) IDC_DSPLIB, NULL, NULL );
  104. SetWindowPos( listWindow, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSENDCHANGING );
  105. ListView_SetExtendedListViewStyleEx( listWindow, LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP, LVS_EX_FULLROWSELECT | LVS_EX_INFOTIP );
  106. SendMessageW( listWindow, WM_SETFONT, SendMessageW( hwndDlg, WM_GETFONT, 0, 0 ), FALSE );
  107. LVCOLUMNW lvc = { 0 };
  108. ListView_InsertColumnW( listWindow, 0, &lvc );
  109. ListView_InsertColumnW( listWindow, 1, &lvc );
  110. if ( !g_safeMode )
  111. {
  112. SendMessageW( listWindow, LB_SETITEMDATA,
  113. SendMessageW( listWindow, LB_ADDSTRING, 0, (LPARAM) getStringW( IDS_DSP_NONE, NULL, 0 ) ),
  114. (LPARAM) 0 );
  115. SendMessageW( listWindow, LB_SETCURSEL, 0, 0 );
  116. LVITEMW lvi = { LVIF_TEXT | LVIF_STATE, 0, 0 };
  117. lvi.pszText = getStringW( IDS_DSP_NONE, NULL, 0 );
  118. lvi.state = LVIS_SELECTED | LVIS_FOCUSED;
  119. ListView_InsertItemW( listWindow, &lvi );
  120. }
  121. WIN32_FIND_DATAW d = { 0 };
  122. wchar_t dirstr[ MAX_PATH ] = { 0 };
  123. PathCombineW( dirstr, DSPDIR, L"DSP_*.DLL" );
  124. HANDLE h = FindFirstFileW( dirstr, &d );
  125. if ( h != INVALID_HANDLE_VALUE )
  126. {
  127. do
  128. {
  129. if ( !g_safeMode )
  130. {
  131. wchar_t dsp_dir[ 1024 ] = { 0 }, namestr[ MAX_PATH + 256 ] = { 0 };
  132. PathCombineW( dsp_dir, DSPDIR, d.cFileName );
  133. HINSTANCE hLib = LoadLibraryW( dsp_dir );
  134. if ( hLib )
  135. {
  136. winampDSPGetHeaderType pr = (winampDSPGetHeaderType) GetProcAddress( hLib, "winampDSPGetHeader2" );
  137. if ( pr )
  138. {
  139. winampDSPHeader *header = pr( hMainWindow );
  140. if ( header && header->version >= DSP_HDRVER && header->version < DSP_HDRVER + 0x10 )
  141. StringCchCopyW( namestr, MAX_PATH + 256, AutoWide( header->description ) );
  142. else
  143. StringCchCopyW( namestr, MAX_PATH + 256, L"!" );
  144. }
  145. else
  146. {
  147. StringCchCopyW( namestr, MAX_PATH + 256, L"!" );
  148. }
  149. FreeModule( hLib );
  150. }
  151. else
  152. {
  153. StringCchCopyW( namestr, MAX_PATH + 256, L"!" );
  154. }
  155. if ( wcscmp( namestr, L"!" ) )
  156. {
  157. LVITEMW lvi = { LVIF_TEXT, 0, 0 };
  158. lvi.pszText = namestr;
  159. lvi.iItem = ListView_InsertItemW( listWindow, &lvi );
  160. lvi.mask = LVIF_TEXT;
  161. lvi.iSubItem = 1;
  162. lvi.pszText = d.cFileName;
  163. ListView_SetItemW( listWindow, &lvi );
  164. if ( !_wcsicmp( d.cFileName, config_dspplugin_name ) )
  165. {
  166. ListView_SetItemState( listWindow, lvi.iItem, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED );
  167. DSPUpdateSel( hwndDlg, listWindow, lvi.iItem );
  168. }
  169. }
  170. else
  171. {
  172. LVITEMW lvi = { LVIF_TEXT, 0, 0 };
  173. lvi.pszText = d.cFileName;
  174. lvi.iItem = ListView_InsertItemW( listWindow, &lvi );
  175. lvi.mask = LVIF_TEXT;
  176. lvi.iSubItem = 1;
  177. lvi.pszText = getStringW( IDS_NOT_LOADED, NULL, 0 );
  178. ListView_SetItemW( listWindow, &lvi );
  179. }
  180. }
  181. else
  182. {
  183. LVITEMW lvi = { LVIF_TEXT, 0, 0 };
  184. lvi.pszText = d.cFileName;
  185. lvi.iItem = ListView_InsertItemW( listWindow, &lvi );
  186. lvi.mask = LVIF_TEXT;
  187. lvi.iSubItem = 1;
  188. lvi.pszText = getStringW( IDS_NOT_LOADED, NULL, 0 );
  189. ListView_SetItemW( listWindow, &lvi );
  190. }
  191. } while ( FindNextFileW( h, &d ) );
  192. FindClose( h );
  193. }
  194. if ( g_safeMode && !ListView_GetItemCount( listWindow ) )
  195. {
  196. LVITEMW lvi = { LVIF_TEXT | LVIF_STATE, 0, 0 };
  197. lvi.pszText = getStringW( IDS_DSP_NONE, NULL, 0 );
  198. lvi.state = LVIS_SELECTED | LVIS_FOCUSED;
  199. ListView_InsertItemW( listWindow, &lvi );
  200. }
  201. GetClientRect( listWindow, &r );
  202. ListView_SetColumnWidth( listWindow, 1, LVSCW_AUTOSIZE );
  203. ListView_SetColumnWidth( listWindow, 0, ( r.right - r.left ) - ListView_GetColumnWidth( listWindow, 1 ) );
  204. DirectMouseWheel_EnableConvertToMouseWheel( listWindow, TRUE );
  205. pluginsLoaded = true;
  206. }
  207. }
  208. else if ( uMsg == WM_DESTROY )
  209. {
  210. HWND listWindow = GetDlgItem( hwndDlg, IDC_DSPLIB );
  211. if ( IsWindow( listWindow ) )
  212. DirectMouseWheel_EnableConvertToMouseWheel( listWindow, FALSE );
  213. }
  214. else if ( uMsg == WM_NOTIFY )
  215. {
  216. static int own_update;
  217. LPNMHDR p = (LPNMHDR) lParam;
  218. if ( p->idFrom == IDC_DSPLIB )
  219. {
  220. if ( p->code == LVN_ITEMCHANGED && pluginsLoaded && !own_update )
  221. {
  222. if ( !g_safeMode )
  223. {
  224. LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
  225. LVITEM lvi = { LVIF_PARAM, pnmv->iItem };
  226. if ( ListView_GetItem( p->hwndFrom, &lvi ) && ( pnmv->uNewState & LVIS_SELECTED ) )
  227. {
  228. own_update = 1;
  229. DSPUpdateSel( hwndDlg, p->hwndFrom, pnmv->iItem );
  230. own_update = 0;
  231. }
  232. }
  233. }
  234. else if ( p->code == NM_DBLCLK || p->code == NM_CLICK )
  235. {
  236. // helps to keep the selection on things...
  237. LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE) lParam;
  238. if ( lpnmitem->iItem == -1 )
  239. {
  240. int which = ListView_GetNextItem( p->hwndFrom, -1, LVIS_SELECTED );
  241. if ( which == -1 )
  242. {
  243. for ( int i = 0; i < ListView_GetItemCount( p->hwndFrom ); i++ )
  244. {
  245. wchar_t fn[ MAX_PATH * 2 ] = { 0 };
  246. ListView_GetItemTextW( p->hwndFrom, i, 1, fn, ARRAYSIZE( fn ) );
  247. if ( !_wcsicmp( fn, config_dspplugin_name ) )
  248. {
  249. own_update = 1;
  250. ListView_SetItemState( p->hwndFrom, i, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED );
  251. own_update = 0;
  252. break;
  253. }
  254. }
  255. }
  256. else
  257. ListView_SetItemState( p->hwndFrom, which, LVIS_SELECTED, LVIS_SELECTED );
  258. }
  259. if ( p->code == NM_DBLCLK )
  260. {
  261. PostMessageW( hwndDlg, WM_COMMAND, MAKEWPARAM( IDC_DSPCONF, 0 ), (LPARAM) GetDlgItem( hwndDlg, IDC_DSPCONF ) );
  262. }
  263. }
  264. }
  265. else if ( p->code == HDN_ITEMCHANGINGW )
  266. {
  267. if ( pluginsLoaded )
  268. {
  269. #ifdef WIN64
  270. SetWindowLongPtrW( hwndDlg, DWLP_MSGRESULT, TRUE );
  271. #else
  272. SetWindowLongW( hwndDlg, DWL_MSGRESULT, TRUE );
  273. #endif
  274. return TRUE;
  275. }
  276. }
  277. }
  278. else if ( uMsg == WM_COMMAND )
  279. {
  280. switch ( LOWORD( wParam ) )
  281. {
  282. case IDC_DSPMOD:
  283. if ( HIWORD( wParam ) == CBN_SELCHANGE )
  284. {
  285. config_dspplugin_num = (unsigned char) SendDlgItemMessageA( hwndDlg, IDC_DSPMOD, CB_GETCURSEL, 0, 0 );
  286. if ( config_dspplugin_num == CB_ERR )
  287. config_dspplugin_num = 0;
  288. if ( pluginsLoaded && config_dspplugin_name[ 0 ] )
  289. {
  290. dsp_quit();
  291. dsp_init();
  292. }
  293. return FALSE;
  294. }
  295. case IDC_DSPCONF:
  296. {
  297. if ( g_safeMode ) return FALSE;
  298. if ( IsWindowEnabled( GetDlgItem( hwndDlg, IDC_DSPCONF ) ) )
  299. {
  300. wchar_t b[ 1024 ] = { 0 };
  301. PathCombineW( b, DSPDIR, config_dspplugin_name );
  302. HINSTANCE hLib = LoadLibraryW( b );
  303. if ( hLib )
  304. {
  305. winampDSPGetHeaderType pr = (winampDSPGetHeaderType) GetProcAddress( hLib, "winampDSPGetHeader2" );
  306. winampDSPModule *module = pr( hMainWindow )->getModule( SendDlgItemMessageA( hwndDlg, IDC_DSPMOD, CB_GETCURSEL, 0, 0 ) );
  307. if ( module )
  308. {
  309. module->hDllInstance = hLib;
  310. module->hwndParent = hMainWindow;
  311. if ( !( config_no_visseh & 2 ) )
  312. {
  313. try
  314. {
  315. module->Config( module );
  316. }
  317. catch ( ... )
  318. {
  319. LPMessageBox( hwndDlg, IDS_PLUGINERROR, IDS_ERROR, MB_OK | MB_ICONEXCLAMATION );
  320. }
  321. }
  322. else
  323. {
  324. module->Config( module );
  325. }
  326. }
  327. else
  328. {
  329. LPMessageBox( hwndDlg, IDS_ERRORLOADINGPLUGIN, IDS_ERROR, MB_OK );
  330. }
  331. FreeLibrary( hLib );
  332. }
  333. else
  334. {
  335. LPMessageBox( hwndDlg, IDS_ERRORLOADINGPLUGIN, IDS_ERROR, MB_OK );
  336. }
  337. }
  338. return FALSE;
  339. }
  340. case IDC_UNINSTDSP:
  341. {
  342. if ( g_safeMode ) return FALSE;
  343. if ( IsWindowEnabled( GetDlgItem( hwndDlg, IDC_UNINSTDSP ) ) )
  344. {
  345. HWND listWindow = GetDlgItem( hwndDlg, IDC_DSPLIB );
  346. int which = ListView_GetNextItem( listWindow, -1, LVIS_SELECTED );
  347. wchar_t fn[ FILENAME_SIZE ] = { 0 };
  348. ListView_GetItemTextW( listWindow, which, 1, fn, ARRAYSIZE( fn ) );
  349. // copes with not-loaded plug-in dlls
  350. if ( !lstrcmpW( fn, getStringW( IDS_NOT_LOADED, NULL, 0 ) ) )
  351. {
  352. ListView_GetItemTextW( listWindow, which, 0, fn, ARRAYSIZE( fn ) );
  353. }
  354. if ( fn[ 0 ] && LPMessageBox( hwndDlg, IDS_P_PLUGIN_UNINSTALL, IDS_P_PLUGIN_UNINSTALL_CONFIRM, MB_YESNO | MB_ICONEXCLAMATION ) == IDYES )
  355. {
  356. wchar_t b[ MAX_PATH ] = { 0 };
  357. dsp_quit();
  358. PathCombineW( b, DSPDIR, fn );
  359. HINSTANCE hLib = LoadLibraryW( b );
  360. if ( hLib )
  361. {
  362. int ret = DSP_PLUGIN_UNINSTALL_NOW;
  363. int ( *pr )( HINSTANCE hDllInst, HWND hwndDlg, int param );
  364. *(void **) &pr = (void *) GetProcAddress( hLib, "winampUninstallPlugin" );
  365. if ( pr )
  366. ret = pr( hLib, hwndDlg, 0 );
  367. wchar_t buf[ MAX_PATH ] = { 0 };
  368. GetModuleFileNameW( hLib, buf, MAX_PATH );
  369. FreeLibrary( hLib );
  370. if ( ret == DSP_PLUGIN_UNINSTALL_NOW )
  371. {
  372. IFileTypeRegistrar *registrar = 0;
  373. if ( GetRegistrar( &registrar, true ) == 0 && registrar )
  374. {
  375. if ( registrar->DeleteItem( buf ) != S_OK )
  376. {
  377. _w_sW( "remove_genplug", buf );
  378. _w_i( "show_prefs", 34 );
  379. }
  380. else
  381. ListView_DeleteItem( listWindow, which );
  382. registrar->Release();
  383. }
  384. }
  385. else if ( ret == DSP_PLUGIN_UNINSTALL_REBOOT )
  386. {
  387. extern void _w_s( char *name, char *data );
  388. wchar_t buf[ 1024 ] = { 0 };
  389. GetModuleFileNameW( hLib, buf, MAX_PATH );
  390. _w_sW( "remove_genplug", buf );
  391. _w_i( "show_prefs", 34 );
  392. PostMessageW( hMainWindow, WM_USER, 0, IPC_RESTARTWINAMP );
  393. }
  394. }
  395. else
  396. {
  397. IFileTypeRegistrar *registrar = 0;
  398. if ( GetRegistrar( &registrar, true ) == 0 && registrar )
  399. {
  400. if ( registrar->DeleteItem( b ) != S_OK )
  401. {
  402. _w_sW( "remove_genplug", fn );
  403. _w_i( "show_prefs", 34 );
  404. }
  405. else
  406. ListView_DeleteItem( listWindow, which );
  407. registrar->Release();
  408. }
  409. }
  410. }
  411. }
  412. return FALSE;
  413. }
  414. case IDC_PLUGINVERS:
  415. myOpenURLWithFallback( hwndDlg, L"http://www.google.com/search?q=Winamp+DSP+Effect+Plugins", L"http://www.google.com/search?q=Winamp+DSP+Effect+Plugins" );
  416. return TRUE;
  417. }
  418. }
  419. link_handledraw( hwndDlg, uMsg, wParam, lParam );
  420. return FALSE;
  421. } //dsp