main.cpp 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892
  1. /** (c) Nullsoft, Inc. C O N F I D E N T I A L
  2. ** Filename: main.cpp
  3. ** Project: Winamp
  4. ** Description: Winamp initialization code
  5. ** Author: Justin Frankel
  6. ** Created: April 1997
  7. **/
  8. #include "main.h"
  9. #include <windowsx.h>
  10. #include "../Agave/Language/lang.h"
  11. #include <stdarg.h>
  12. #include "vis.h"
  13. #include "fft.h"
  14. #include "gen.h"
  15. #include "../nu/ns_wc.h"
  16. #include "../nu/AutoWide.h"
  17. #include "../nu/AutoChar.h"
  18. #include "menuv5.h"
  19. #include "../Plugins/General/gen_ml/ml.h"
  20. #include "wa_dlg.h"
  21. #include "strutil.h"
  22. #include "./setup/setupfactory.h"
  23. #include "./commandLink.h"
  24. #include "AppRefCount.h"
  25. #include <unknwn.h>
  26. #include <shlwapi.h>
  27. #include <shobjidl.h>
  28. #include "WAT/WAT.h"
  29. #ifndef WM_DWMSENDICONICTHUMBNAIL
  30. #define WM_DWMSENDICONICTHUMBNAIL 0x0323
  31. #endif
  32. #include "Agave/Language/api_language.h"
  33. #ifndef WM_DWMSENDICONICLIVEPREVIEWBITMAP
  34. #define WM_DWMSENDICONICLIVEPREVIEWBITMAP 0x0326
  35. #endif
  36. #ifndef THBN_CLICKED
  37. #define THBN_CLICKED 0x1800
  38. #endif
  39. typedef HRESULT( WINAPI *CHANGEWINDOWMESSAGEFILTER )( UINT message, DWORD dwFlag );
  40. static HMODULE user32Lib = 0;
  41. static CHANGEWINDOWMESSAGEFILTER changeWMFilter;
  42. static BOOL changeWMLoadTried = FALSE;
  43. //#define BENSKI_TEST_WM_PRINTCLIENT
  44. static UINT WM_TASKBARCREATED;
  45. static UINT WM_TASKBARBUTTONCREATED;
  46. LARGE_INTEGER freq;
  47. UINT g_scrollMsg;
  48. UINT songChangeBroadcastMessage = 0;
  49. int g_noreg;
  50. int disable_skin_borders = 0;
  51. int no_notify_play = 0;
  52. int last_no_notify_play = 0;
  53. int main_delta_carryover = 0;
  54. int g_restartonquit = 0;
  55. char g_audiocdletter[ 4 ] = { 0 };
  56. int g_audiocdletters = 0;
  57. const char app_name[] = "Winamp", app_version[] = APP_VERSION, app_version_string[] = APP_VERSION_STRING; // application name and version strings
  58. int g_fullstop;
  59. char *app_date = __DATE__;
  60. int g_stopaftercur;
  61. int is_install;
  62. HWND hTooltipWindow, hEQTooltipWindow, hVideoTooltipWindow, hPLTooltipWindow;
  63. HWND hMainWindow = NULL; // main window
  64. HWND hEQWindow, hPLWindow, /*hMBWindow, */hVideoWindow, hExternalVisWindow = NULL;
  65. HWND g_dialog_box_parent = NULL; // used by IPC_SETDIALOGBOXPARENT (FG, 5/19/03)
  66. HINSTANCE language_pack_instance;
  67. HINSTANCE hMainInstance; // program instance
  68. HANDLE hMainThread; // main thread handle
  69. DWORD mainThreadId; // main thread ID
  70. HMENU main_menu = 0, top_menu = 0, g_submenus_bookmarks1 = 0,
  71. g_submenus_bookmarks2 = 0, g_submenus_skins1 = 0,
  72. g_submenus_skins2 = 0, g_submenus_vis = 0,
  73. g_submenus_options = 0, g_submenus_lang = 0,
  74. g_submenus_play = 0;
  75. int g_submenus_lang_id = 0;
  76. int g_video_numaudiotracks = 1;
  77. int g_video_curaudiotrack = 0;
  78. int bStartPlaying = 0;
  79. int paused = 0;
  80. int playing = 0;
  81. wchar_t caption[ CAPTION_SIZE ] = { 0 }; // current program caption
  82. wchar_t FileName[ FILENAME_SIZE ] = { 0 }; // current file name
  83. wchar_t FileTitle[ FILETITLE_SIZE ] = { 0 }; // current file title
  84. wchar_t FileTitleNum[ FILETITLE_SIZE ] = { 0 }; // current file title + track position
  85. int eggstat = 0; // used for easter eggs
  86. int g_srate, g_brate, g_nch, g_srate_exact;
  87. int last_brate = -1;
  88. int g_need_titleupd = 0;
  89. int g_need_infoupd = 0;
  90. int g_SkinTop, g_BookmarkTop, g_LangTop;
  91. int g_mm_optionsbase_adj = 0; //used by IPC_ADJUST_OPTIONSMENUPOS
  92. int g_mm_ffwindowsbase_adj = 0; //used by IPC_ADJUST_FFWINDOWSMENUPOS
  93. int g_mm_ffoptionsbase_adj = 0; //used by IPC_ADJUST_FFOPTIONSMENUPOS
  94. int g_has_video_plugin = 0;
  95. int g_no_video_loaded = 0; //filled in by in_init
  96. char playlist_custom_font[ 128 ] = { 0 };
  97. wchar_t playlist_custom_fontW[ 128 ] = { 0 };
  98. int config_custom_plfont = 1;
  99. int disable_skin_cursors = 0;
  100. int vis_fullscreen = 0;
  101. struct ITaskbarList3 *pTaskbar3 = NULL;
  102. static LRESULT Main_OnSysCommand( HWND hwnd, UINT cmd, int x, int y );
  103. HWND find_otherwinamp( wchar_t * );
  104. #undef HANDLE_WM_NCACTIVATE
  105. #define HANDLE_WM_NCACTIVATE(hwnd, wParam, lParam, fn) \
  106. (LRESULT)(DWORD)(BOOL)(fn)((hwnd), (BOOL)(wParam), (HWND)(lParam), 0L)
  107. int stat_isit = 1; // used for faster version checkig
  108. wchar_t szAppName[ 64 ] = { 0 }; // window class name, generated on the fly.
  109. EXTERN_C BOOL eggTyping = FALSE;
  110. static char eggstr[] = "NULLSOFT";
  111. UINT USER_CONSENT_EVENT_ID = 123456;
  112. int g_exit_disabled = 0;
  113. int g_safeMode = 0;
  114. HANDLE g_hEventRunning;
  115. int bNoHwndOther = 0;
  116. static void CreateEQPresets()
  117. {
  118. if ( !PathFileExistsW( EQDIR1 ) )
  119. {
  120. int x;
  121. struct
  122. {
  123. char *s;
  124. unsigned char tab[ 10 ];
  125. }
  126. eqsets[] =
  127. {
  128. {"Classical", {31, 31, 31, 31, 31, 31, 44, 44, 44, 48}},
  129. {"Club", {31, 31, 26, 22, 22, 22, 26, 31, 31, 31}},
  130. {"Dance", {16, 20, 28, 32, 32, 42, 44, 44, 32, 32}},
  131. {"Flat", {31, 31, 31, 31, 31, 31, 31, 31, 31, 31}},
  132. {"Laptop speakers/headphones", {24, 14, 23, 38, 36, 29, 24, 16, 11, 8}},
  133. {"Large hall", {15, 15, 22, 22, 31, 40, 40, 40, 31, 31}},
  134. {"Party", {20, 20, 31, 31, 31, 31, 31, 31, 20, 20}},
  135. {"Pop", {35, 24, 20, 19, 23, 34, 36, 36, 35, 35}},
  136. {"Reggae", {31, 31, 33, 42, 31, 21, 21, 31, 31, 31}},
  137. {"Rock", {19, 24, 41, 45, 38, 25, 17, 14, 14, 14}},
  138. {"Soft", {24, 29, 34, 36, 34, 25, 18, 16, 14, 12}},
  139. {"Ska", {36, 40, 39, 33, 25, 22, 17, 16, 14, 16}},
  140. {"Full Bass", {16, 16, 16, 22, 29, 39, 46, 49, 50, 50}},
  141. {"Soft Rock", {25, 25, 28, 33, 39, 41, 38, 33, 27, 17}},
  142. {"Full Treble", {48, 48, 48, 39, 27, 14, 6, 6, 6, 4}},
  143. {"Full Bass & Treble", {20, 22, 31, 44, 40, 29, 18, 14, 12, 12}},
  144. {"Live", {40, 31, 25, 23, 22, 22, 25, 27, 27, 28}},
  145. {"Techno", {19, 22, 31, 41, 40, 31, 19, 16, 16, 17}},
  146. };
  147. for ( x = 0; x < sizeof( eqsets ) / sizeof( eqsets[ 0 ] ); x++ )
  148. writeEQfile_init( EQDIR1, eqsets[ x ].s, eqsets[ x ].tab );
  149. }
  150. }
  151. void BuildAppName()
  152. {
  153. StringCchCopyW( szAppName, 64, L"Winamp v1.x" );
  154. StringCchPrintfW( caption, CAPTION_SIZE, L"%S %S", app_name, app_version_string );
  155. }
  156. static void CALLBACK DisplayUserConsentMessageBox( HWND hwnd, UINT uMsg, UINT_PTR eventId, DWORD time )
  157. {
  158. KillTimer( hMainWindow, USER_CONSENT_EVENT_ID );
  159. if ( config_user_consent_join_channels != -1 )
  160. {
  161. return;
  162. }
  163. wchar_t titleStr[ 32 ] = { 0 };
  164. int msgboxID = MessageBoxW(
  165. NULL,
  166. WASABI_API_LNGSTRINGW( IDS_RC_CHANNEL_MESSAGE ),
  167. WASABI_API_LNGSTRINGW_BUF( IDS_RC_CHANNEL_TITLE, titleStr, 32 ),
  168. MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON1
  169. );
  170. switch ( msgboxID )
  171. {
  172. case IDYES:
  173. config_user_consent_join_channels = 1;
  174. config_newverchk_rc = 1;
  175. config_newverchk = 1;
  176. break;
  177. case IDNO:
  178. config_user_consent_join_channels = 0;
  179. config_newverchk_rc = 0;
  180. config_newverchk = 1;
  181. break;
  182. }
  183. }
  184. // creates (but does not show) main window
  185. int CreateMainWindow()
  186. {
  187. if ( !IsWindow( hMainWindow ) )
  188. {
  189. WNDCLASSW wcW = { 0 };
  190. wcW.style = CS_DBLCLKS;
  191. wcW.lpfnWndProc = Main_WndProc;
  192. wcW.hInstance = hMainInstance;
  193. wcW.hIcon = LoadIconW( hMainInstance, MAKEINTRESOURCE( ICON_XP ) );
  194. wcW.hCursor = NULL;
  195. wcW.lpszClassName = szAppName;
  196. if ( !RegisterClassW( &wcW ) )
  197. return 0;
  198. if ( !CreateWindowExW( WS_EX_ACCEPTFILES, szAppName, L"Winamp", WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_BORDER | WS_CAPTION,
  199. config_wx, config_wy, 0, 0, // WM_CREATE will size it
  200. NULL, NULL, hMainInstance, NULL ) )
  201. {
  202. return 0;
  203. }
  204. }
  205. return 1;
  206. }
  207. wchar_t *getGUIDstr( const GUID guid, wchar_t *target )
  208. {
  209. StringCchPrintfW( target, 40, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\0",
  210. (int)guid.Data1, (int)guid.Data2, (int)guid.Data3,
  211. (int)guid.Data4[ 0 ], (int)guid.Data4[ 1 ], (int)guid.Data4[ 2 ], (int)guid.Data4[ 3 ],
  212. (int)guid.Data4[ 4 ], (int)guid.Data4[ 5 ], (int)guid.Data4[ 6 ], (int)guid.Data4[ 7 ] );
  213. return target;
  214. }
  215. BOOL parseMessageCommands( HWND hwnd_other, int bCommand, int bCmdParam )
  216. {
  217. if ( LOWORD( bCommand ) ) // attempt to send the action to it
  218. {
  219. if ( HIWORD( bCommand ) == 1 )
  220. {
  221. SendMessageW( hwnd_other, WM_WA_IPC, bCmdParam, MAKELPARAM( LOWORD( bCommand ), 0 ) );
  222. return TRUE;
  223. }
  224. else if ( HIWORD( bCommand ) == 2 )
  225. {
  226. // these need some additional processing which is easier to do once we're loaded
  227. if ( LOWORD( bCommand ) == EQ_PANLEFT || LOWORD( bCommand ) == EQ_PANRIGHT ||
  228. LOWORD( bCommand ) == IPC_SETPANNING )
  229. {
  230. int pan = IPC_GETPANNING( hwnd_other );
  231. if ( LOWORD( bCommand ) == EQ_PANLEFT ) pan -= 12;
  232. else if ( LOWORD( bCommand ) == EQ_PANRIGHT ) pan += 12;
  233. else pan = bCmdParam;
  234. if ( pan < -127 ) pan = -127;
  235. if ( pan > 127 ) pan = 127;
  236. SendMessageW( hwnd_other, WM_WA_IPC, pan, IPC_SETPANNING );
  237. }
  238. else if ( LOWORD( bCommand ) == IPC_ISPLAYING )
  239. {
  240. int command = SendMessageW( hwnd_other, WM_WA_IPC, 0, IPC_ISPLAYING );
  241. switch ( command )
  242. {
  243. case 1: // playing so need to pause
  244. command = WINAMP_BUTTON3;
  245. break;
  246. default: // stopped so start playing
  247. command = WINAMP_BUTTON2;
  248. break;
  249. }
  250. SendMessageW( hwnd_other, WM_COMMAND, command, 0 );
  251. }
  252. return TRUE;
  253. }
  254. else
  255. {
  256. SendMessageW( hwnd_other, WM_COMMAND, bCommand, 0 );
  257. if ( LOWORD( bCommand ) == WINAMP_JUMPFILE )
  258. {
  259. // TODO need to make this locale independant...
  260. HWND jumpWnd = FindWindowW( NULL, L"Jump to file" );
  261. if ( IsWindow( jumpWnd ) )
  262. {
  263. SetForegroundWindow( jumpWnd );
  264. }
  265. }
  266. return TRUE;
  267. }
  268. }
  269. return FALSE;
  270. }
  271. static int PassToOtherWinamp( wchar_t *lpszCmdParam, HWND hwnd_other, int bAdd, int bBookmark, int bHandle, int bCommand, int bCmdParam )
  272. {
  273. // if we have command line params, pass to other winamp window
  274. if ( lpszCmdParam && *lpszCmdParam )
  275. {
  276. int skinExit = 0;
  277. int bC = 0;
  278. HANDLE hSem = NULL;
  279. HINSTANCE existingWLZ = 0, templng = 0;
  280. DWORD_PTR vn = 0;
  281. // check if we're using a language pack with the already open winamp process
  282. // and if so then we're going to use the winamp.lng from it on the messagebox
  283. // only if we had a success and the other winamp returned the correct value
  284. // within the timeout period (can't be having it lock up so revert if needed)
  285. if ( SendMessageTimeout( hwnd_other, WM_WA_IPC, 1, IPC_GETLANGUAGEPACKINSTANCE, SMTO_NORMAL, 5000, &vn ) && !vn )
  286. {
  287. DWORD processid = 0;
  288. HANDLE hwaProcess = NULL;
  289. SIZE_T bread = 0;
  290. wchar_t lng_path_copy[ MAX_PATH ] = { 0 }, dirmask[ MAX_PATH ] = { 0 }, gs[ 40 ] = { 0 };
  291. WIN32_FIND_DATAW d = { 0 };
  292. GetWindowThreadProcessId( hwnd_other, &processid );
  293. hwaProcess = OpenProcess( PROCESS_VM_READ, FALSE, processid );
  294. ReadProcessMemory( hwaProcess, (wchar_t *)SendMessageW( hwnd_other, WM_WA_IPC, 3, IPC_GETLANGUAGEPACKINSTANCE ), lng_path_copy, MAX_PATH, &bread );
  295. CloseHandle( hwaProcess );
  296. getGUIDstr( WinampLangGUID, gs );
  297. PathCombineW( dirmask, lng_path_copy, L"*.lng" );
  298. HANDLE h = FindFirstFileW( dirmask, &d );
  299. if ( h != INVALID_HANDLE_VALUE )
  300. {
  301. do
  302. {
  303. PathCombineW( dirmask, lng_path_copy, d.cFileName );
  304. templng = LoadLibraryExW( dirmask, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE );
  305. if ( !templng ) templng = LoadLibraryW( dirmask );
  306. if ( templng )
  307. {
  308. wchar_t s[ 39 ] = { 0 };
  309. if ( LoadStringW( templng, LANG_DLL_GUID_STRING_ID, s, 39 ) )
  310. {
  311. if ( !_wcsnicmp( gs, s, 38 ) )
  312. {
  313. existingWLZ = Lang_FakeWinampLangHInst( templng );
  314. }
  315. else
  316. FreeLibrary( templng );
  317. }
  318. else
  319. FreeLibrary( templng );
  320. }
  321. } while ( FindNextFileW( h, &d ) );
  322. FindClose( h );
  323. }
  324. }
  325. lpszCmdParam = CheckSkin( lpszCmdParam, hwnd_other, &skinExit );
  326. if ( skinExit )
  327. {
  328. // restore the language pack settings now that we've done the override and clean up as needed
  329. if ( existingWLZ )
  330. {
  331. Lang_FakeWinampLangHInst( existingWLZ );
  332. FreeLibrary( templng );
  333. }
  334. return TRUE;
  335. }
  336. skinExit = 0;
  337. lpszCmdParam = CheckLang( lpszCmdParam, hwnd_other, &skinExit );
  338. // restore the language pack settings now that we've done the override and clean up as needed
  339. if ( existingWLZ )
  340. {
  341. Lang_FakeWinampLangHInst( existingWLZ );
  342. FreeLibrary( templng );
  343. }
  344. if ( skinExit )
  345. return TRUE;
  346. hSem = CreateSemaphoreA( 0, 0, 65535, "WinampExplorerHack1" );
  347. if ( hSem && GetLastError() != ERROR_ALREADY_EXISTS )
  348. {
  349. bC = 1;
  350. if ( !bAdd && !bBookmark && !bHandle )
  351. {
  352. SendMessageW( hwnd_other, WM_WA_IPC, 0, IPC_DELETE_INT );
  353. }
  354. }
  355. if ( hSem )
  356. {
  357. ReleaseSemaphore( hSem, 1, NULL );
  358. if ( bBookmark )
  359. {
  360. static wchar_t tmp[ MAX_PATH ];
  361. StringCchPrintfW( tmp, MAX_PATH, L"/BOOKMARK %s", lpszCmdParam );
  362. lpszCmdParam = tmp;
  363. }
  364. else if ( bHandle )
  365. {
  366. static wchar_t tmp[ MAX_PATH ];
  367. StringCchPrintfW( tmp, MAX_PATH, L"/HANDLE %s", lpszCmdParam );
  368. lpszCmdParam = tmp;
  369. }
  370. parseCmdLine( lpszCmdParam, hwnd_other );
  371. WaitForSingleObject( hSem, 5000 );
  372. if ( bC )
  373. {
  374. int n = 500;
  375. if ( !bAdd && !bBookmark && !bHandle ) SendMessageW( hwnd_other, WM_WA_IPC, 0, IPC_STARTPLAY_INT );
  376. Sleep( 200 );
  377. for ( ;;)
  378. {
  379. if ( WaitForSingleObject( hSem, 100 ) == WAIT_TIMEOUT )
  380. {
  381. if ( WaitForSingleObject( hSem, 900 ) == WAIT_TIMEOUT )
  382. {
  383. break;
  384. }
  385. else
  386. {
  387. ReleaseSemaphore( hSem, 1, NULL );
  388. n--;
  389. }
  390. }
  391. else
  392. {
  393. ReleaseSemaphore( hSem, 1, NULL );
  394. Sleep( 100 );
  395. n--;
  396. }
  397. }
  398. }
  399. CloseHandle( hSem );
  400. }
  401. }
  402. else
  403. {
  404. if ( !parseMessageCommands( hwnd_other, bCommand, bCmdParam ) )
  405. {
  406. ShowWindow( hwnd_other, SW_RESTORE );
  407. SetForegroundWindow( hwnd_other );
  408. }
  409. }
  410. return TRUE;
  411. }
  412. DWORD CALLBACK MainThread( LPVOID param );
  413. extern wchar_t vidoutbuf_save[ 1024 ];
  414. static LPWSTR lpszCmdParam = 0;
  415. static int bAdd = 0, bBookmark = 0,
  416. bHandle = 0, bCommand = 0,
  417. bCmdParam = 0, bAllowCompat = 0;
  418. void ShowSafeModeMessage( int mode )
  419. {
  420. if ( g_safeMode && ( g_safeMode != 3 ) )
  421. {
  422. wchar_t title[ 256 ] = { 0 }, message[ 512 ] = { 0 };
  423. MSGBOXPARAMSW msgbx = { sizeof( MSGBOXPARAMSW ),0 };
  424. if ( !mode )
  425. {
  426. msgbx.lpszText = getStringW( ( g_safeMode == 2 ? IDS_SAFE_MODE_ALL : IDS_SAFE_MODE_NORMAL ), message, 512 );
  427. msgbx.lpszCaption = getStringW( IDS_START_SAFE_MODE, title, 256 );
  428. }
  429. else
  430. {
  431. msgbx.lpszText = getStringW( IDS_FAILED_SAFE_MODE_MSG, message, 512 );
  432. msgbx.lpszCaption = getStringW( IDS_FAILED_SAFE_MODE, title, 256 );
  433. }
  434. msgbx.lpszIcon = MAKEINTRESOURCEW( 102 );
  435. msgbx.hInstance = hMainInstance;
  436. msgbx.dwStyle = MB_USERICON;
  437. MessageBoxIndirectW( &msgbx );
  438. }
  439. }
  440. #ifdef BETA
  441. time_t inline get_compile_time( char const *time )
  442. {
  443. char s_month[ 5 ] = { 0 };
  444. int day = 0, year = 0;
  445. struct tm t = { 0 };
  446. static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
  447. sscanf( time, "%s %d %d", s_month, &day, &year );
  448. t.tm_mon = ( ( strstr( month_names, s_month ) - month_names ) / 3 );
  449. t.tm_mday = day;
  450. t.tm_year = year - 1900;
  451. t.tm_isdst = -1;
  452. return mktime( &t );
  453. }
  454. #endif
  455. int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR unused /*lpszCmdParam*/, int nCmdShow )
  456. {
  457. INITCOMMONCONTROLSEX icex = { sizeof( icex ), ICC_WIN95_CLASSES | ICC_DATE_CLASSES };
  458. InitCommonControlsEx( &icex );
  459. QueryPerformanceFrequency( &freq );
  460. #if 0
  461. #ifdef BETA
  462. // gives ~4 weeks from a build compile to when it'll show this (should be enough time)
  463. time_t now = time( 0 ), compile = get_compile_time( app_date );
  464. struct tm *tn = localtime( &now );
  465. tn->tm_sec = tn->tm_min = tn->tm_hour = 0;
  466. now = mktime( tn );
  467. if ( ( now - compile ) >= 2678400 )
  468. {
  469. /* Skip the executable name in the commandline */
  470. /* and check for /UNREG which we will allow so */
  471. /* an expired beta can be uninstalled properly */
  472. lpszCmdParam = GetCommandLineW();
  473. lpszCmdParam = FindNextCommand( lpszCmdParam );
  474. ParseParametersExpired( lpszCmdParam );
  475. MSGBOXPARAMSW msgbx = {
  476. sizeof( MSGBOXPARAMSW ),
  477. 0,
  478. GetModuleHandle( NULL ),
  479. L"This beta version of Winamp is now over 4 weeks old.\n\n"
  480. L"Please update to the latest Winamp version available.",
  481. L"Winamp Beta Expired",
  482. MB_USERICON,
  483. MAKEINTRESOURCEW( 102 ),
  484. 0, 0, 0
  485. };
  486. MessageBoxIndirectW( &msgbx );
  487. ShellExecuteW( NULL, L"open", L"http://www.winamp.com/media-player", NULL, NULL, SW_SHOWNORMAL );
  488. return 0;
  489. }
  490. #endif
  491. #endif
  492. DWORD threadId = 0, res = 0;
  493. HANDLE mainThread = nullptr;
  494. int cmdShow = nCmdShow;
  495. /*void *refCounter = */InitAppRefCounterObject( GetCurrentThreadId() );
  496. //SHSetInstanceExplorer((IUnknown *)refCounter);
  497. SetErrorMode( SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS );
  498. // don't load from working directory !!!!!
  499. // requires XP SP3+
  500. SetDllDirectoryW( L"" );
  501. GetModuleFileNameW( NULL, SHAREDDIR, MAX_PATH );
  502. PathRemoveFileSpecW( SHAREDDIR );
  503. PathAppendW( SHAREDDIR, L"Shared" );
  504. // load supporting dlls from the Winamp\Shared directory
  505. SetDllDirectoryW( SHAREDDIR );
  506. hMainInstance = hInstance;
  507. /* Skip the executable name in the commandline */
  508. lpszCmdParam = GetCommandLineW();
  509. lpszCmdParam = FindNextCommand( lpszCmdParam );
  510. BuildAppName();
  511. init_config();
  512. LoadPathsIni();
  513. lpszCmdParam = ParseParameters( lpszCmdParam, &bAdd, &bBookmark, &bHandle, &cmdShow, &bCommand, &bCmdParam, &bAllowCompat );
  514. setup_config();
  515. // ensure we've got things set up as needed for safe mode being always on so we
  516. // don't incorrectly prompt about entering it from using IPC_RESTARTSAFEWINAMP.
  517. int mode = _r_i( "allowcompat", 0 );
  518. if ( mode ) bAllowCompat = 1;
  519. if ( !bAllowCompat && read_compatmode() )
  520. {
  521. MSGBOXPARAMSW msgbx = {
  522. sizeof( MSGBOXPARAMSW ),
  523. 0,
  524. GetModuleHandle( NULL ),
  525. L"Winamp appears to have been started with Windows program compatibility mode enabled.\n\n"
  526. L"This is not a recommended way to run Winamp as it can often cause problems with how Winamp works e.g. causing it to randomly crash."
  527. L"\n\n\nAre you sure you want to continue to run Winamp like this?\n\n\n"
  528. L"If you choose 'No', you can disable this by right-clicking winamp.exe, choosing 'Properties' and selecting the 'Compatibility' tab, "
  529. L"followed by unchecking 'Run this program in compatibility mode for:' and run Winamp again.",
  530. L"Winamp",
  531. MB_USERICON | MB_YESNO | MB_DEFBUTTON2,
  532. MAKEINTRESOURCEW( 102 ),
  533. 0, 0, 0
  534. };
  535. if ( MessageBoxIndirectW( &msgbx ) == IDNO )
  536. {
  537. return 0;
  538. }
  539. }
  540. CoInitializeEx( 0, COINIT_MULTITHREADED );
  541. // ensure we've got things set up as needed for safe mode being always on so we
  542. // don't incorrectly prompt about entering it from using IPC_RESTARTSAFEWINAMP.
  543. mode = _r_i( "safemode", 0 );
  544. if ( mode ) g_safeMode = 3;
  545. if ( 0 == ( 128 & is_install ) )
  546. {
  547. HWND hwnd_other = find_otherwinamp( lpszCmdParam );
  548. if ( IsWindow( hwnd_other ) )
  549. {
  550. // unable to start safe mode so inform the user
  551. ShowSafeModeMessage( 1 );
  552. int x = PassToOtherWinamp( lpszCmdParam, hwnd_other, bAdd, bBookmark, bHandle, bCommand, bCmdParam );
  553. CoUninitialize();
  554. return x;
  555. }
  556. }
  557. // unable to start safe mode so inform the user
  558. ShowSafeModeMessage( 0 );
  559. mainThread = CreateThread( 0, 0, MainThread, (LPVOID)cmdShow, 0, &threadId );
  560. while ( !AppRefCount_CanQuit() )
  561. {
  562. DWORD dwStatus = MsgWaitForMultipleObjectsEx( 1, &mainThread, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE );
  563. if ( dwStatus == WAIT_OBJECT_0 + 1 )
  564. {
  565. MSG msg;
  566. while ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
  567. {
  568. if ( msg.message == WM_QUIT )
  569. return msg.wParam;
  570. DispatchMessage( &msg );
  571. }
  572. }
  573. else if ( dwStatus == WAIT_OBJECT_0 )
  574. {
  575. GetExitCodeThread( mainThread, &res );
  576. CloseHandle( mainThread );
  577. AppRefCount_Release();
  578. }
  579. }
  580. return 0;
  581. }
  582. static BOOL LoadWMFilter()
  583. {
  584. if ( !changeWMLoadTried )
  585. {
  586. user32Lib = LoadLibraryA( "user32.dll" );
  587. if ( user32Lib )
  588. changeWMFilter = (CHANGEWINDOWMESSAGEFILTER)GetProcAddress( user32Lib, "ChangeWindowMessageFilter" );
  589. changeWMLoadTried = TRUE;
  590. }
  591. return user32Lib && changeWMFilter;
  592. }
  593. VOID CALLBACK PrefsShowProc( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime )
  594. {
  595. KillTimer( hwnd, idEvent );
  596. if ( IsWindow( prefs_hwnd ) )
  597. SetForegroundWindow( prefs_hwnd );
  598. }
  599. void load_gen_crasher()
  600. {
  601. // this will load gen_crasher.dll as applicable (included in beta builds but not release mode by default)
  602. // with extra checks to ensure it's 'valid' (as can be) so we could drop it into release builds as needed
  603. wchar_t crasherDll[ MAX_PATH ] = { 0 };
  604. PathCombineW( crasherDll, PLUGINDIR, L"gen_crasher.dll" );
  605. HMODULE hm = LoadLibraryW( crasherDll );
  606. if ( hm )
  607. {
  608. int( __cdecl * StartHandler )( wchar_t *iniPath ) = NULL;
  609. *(FARPROC *)&StartHandler = GetProcAddress( hm, "StartHandler" );
  610. if ( StartHandler )
  611. {
  612. wchar_t iniPath[ MAX_PATH ] = { 0 };
  613. if ( SUCCEEDED( StringCchPrintfW( iniPath, MAX_PATH, L"%s\\Plugins", CONFIGDIR ) ) )
  614. {
  615. winampGeneralPurposePluginGetter pr = (winampGeneralPurposePluginGetter)GetProcAddress( hm, "winampGetGeneralPurposePlugin" );
  616. if ( pr )
  617. {
  618. winampGeneralPurposePlugin *plugin = pr();
  619. if ( plugin && plugin->version == GPPHDR_VER_U )
  620. {
  621. char desc[ 128 ] = { 0 };
  622. lstrcpynA( desc, plugin->description, sizeof( desc ) );
  623. if ( desc[ 0 ] && !memcmp( desc, "nullsoft(", 9 ) )
  624. {
  625. char *p = strrchr( desc, ')' );
  626. if ( p )
  627. {
  628. *p = 0;
  629. if ( !_wcsicmp( L"gen_crasher.dll", AutoWide( desc + 9 ) ) )
  630. {
  631. StartHandler( iniPath );
  632. }
  633. else
  634. FreeLibrary( hm );
  635. }
  636. else
  637. FreeLibrary( hm );
  638. }
  639. else
  640. FreeLibrary( hm );
  641. }
  642. else
  643. FreeLibrary( hm );
  644. }
  645. else
  646. FreeLibrary( hm );
  647. }
  648. else
  649. FreeLibrary( hm );
  650. }
  651. else
  652. FreeLibrary( hm );
  653. }
  654. }
  655. DWORD CALLBACK MainThread( LPVOID param )
  656. {
  657. language_pack_instance = hMainInstance;
  658. playlistStr[ 0 ] = 0;
  659. playlistStr[ 18 ] = 0; // keep the last byte null terminated (and don't overwrite) so we can be smoewhat thread-safe (may have junk data, but it won't read outside the array)
  660. vidoutbuf_save[ 0 ] = 0;
  661. vidoutbuf_save[ 1023 ] = 0; // keep the last byte null terminated (and don't overwrite) so we can be smoewhat thread-safe (may have junk data, but it won't read outside the array)
  662. mainThreadId = GetCurrentThreadId();
  663. DuplicateHandle( GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS );
  664. InitializeCriticalSection( &embedcs );
  665. CoInitialize( 0 );
  666. Wasabi_Load();
  667. plstring_init();
  668. /*Browser_Create();*/
  669. // check if it's gen_crasher.dll that's being removed and skip loading it so uninstall will work
  670. bool skip_crasher = false;
  671. wchar_t buf[ 1024 ] = { 0 };
  672. _r_sW( "remove_genplug", buf, 1024 );
  673. if ( buf[ 0 ] )
  674. skip_crasher = !wcsicmp( PathFindFileNameW( buf ), L"gen_crasher.dll" );
  675. if ( !skip_crasher )
  676. load_gen_crasher();
  677. if ( ( 128 & is_install ) || ( !g_noreg && GetPrivateProfileIntW( L"WinampReg", L"NeedReg", 1, INI_FILE ) ) )
  678. {
  679. is_install = 128; // nothing else
  680. Setup_RegisterService();
  681. }
  682. draw_firstinit();
  683. WM_TASKBARCREATED = RegisterWindowMessageA( "TaskbarCreated" );
  684. g_scrollMsg = RegisterWindowMessageA( "MSWHEEL_ROLLMSG" );
  685. WM_TASKBARBUTTONCREATED = RegisterWindowMessageW( L"TaskbarButtonCreated" );
  686. if ( LoadWMFilter() )
  687. {
  688. changeWMFilter( WM_TASKBARBUTTONCREATED, 1/*MSGFLT_ADD*/ );
  689. changeWMFilter( WM_DWMSENDICONICTHUMBNAIL, 1/*MSGFLT_ADD*/ );
  690. changeWMFilter( WM_DWMSENDICONICLIVEPREVIEWBITMAP, 1/*MSGFLT_ADD*/ );
  691. changeWMFilter( WM_COMMAND, 1/*MSGFLT_ADD*/ ); //for thumbnail toolbar buttons
  692. }
  693. CommandLink_RegisterClass( hMainInstance );
  694. Skin_CleanupAfterCrash();
  695. Lang_CleanupAfterCrash();
  696. {
  697. int langExit = 0;
  698. lpszCmdParam = CheckLang( lpszCmdParam, 0, &langExit );
  699. if ( langExit )
  700. {
  701. Lang_EndLangSupport();
  702. Lang_CleanupZip();
  703. return TRUE;
  704. }
  705. }
  706. if ( !g_safeMode )
  707. {
  708. language_pack_instance = Lang_InitLangSupport( hMainInstance, WinampLangGUID );
  709. Lang_FollowUserDecimalLocale();
  710. }
  711. if ( bBookmark )
  712. {
  713. w5s_init();
  714. if ( !in_init() )
  715. {
  716. w5s_deinit();
  717. Wasabi_Unload();
  718. RemoveRegistrar();
  719. CoUninitialize();
  720. ExitProcess( 0 );
  721. }
  722. Bookmark_AddCommandline( lpszCmdParam );
  723. in_deinit();
  724. w5s_deinit();
  725. Wasabi_Unload();
  726. RemoveRegistrar();
  727. CoUninitialize();
  728. ExitProcess( 0 );
  729. }
  730. {
  731. int skinExit = 0;
  732. lpszCmdParam = CheckSkin( lpszCmdParam, 0, &skinExit );
  733. if ( skinExit )
  734. {
  735. return TRUE;
  736. }
  737. }
  738. {
  739. // remove general purpose plug-in (if set)
  740. wchar_t buf[ 1024 ] = { 0 };
  741. _r_sW( "remove_genplug", buf, 1024 );
  742. if ( buf[ 0 ] )
  743. {
  744. IFileTypeRegistrar *registrar = 0;
  745. if ( GetRegistrar( &registrar, true ) == 0 && registrar )
  746. {
  747. registrar->DeleteItem( buf );
  748. // if gen_crasher is requested to remove, also remove reporter.exe
  749. if ( skip_crasher )
  750. {
  751. GetModuleFileNameW( NULL, buf, MAX_PATH );
  752. PathRemoveFileSpecW( buf );
  753. PathCombineW( buf, buf, L"reporter.exe" );
  754. registrar->DeleteItem( buf );
  755. }
  756. registrar->Release();
  757. }
  758. _w_s( "remove_genplug", 0 );
  759. }
  760. }
  761. fft_init();
  762. SpectralAnalyzer_Create();
  763. JSAPI1_Initialize();
  764. stats_init();
  765. w5s_init();
  766. if ( !in_init() )
  767. {
  768. w5s_deinit();
  769. Wasabi_Unload();
  770. RemoveRegistrar();
  771. CoUninitialize();
  772. ExitProcess( 0 );
  773. }
  774. out_init();
  775. vis_init();
  776. if ( lpszCmdParam && *lpszCmdParam && !bAdd && !bHandle )
  777. config_read( 1 );
  778. else
  779. config_read( 0 );
  780. CreateEQPresets();
  781. if ( is_install )
  782. DoInstall( is_install );
  783. reg_associated_filetypes( 0 );
  784. if ( config_splash ) splashDlg( SPLASH_DELAY ); // display splash screen if desired
  785. PlayList_getcurrent( FileName, FileTitle, FileTitleNum ); // update filename and filetitle if a list was loaded
  786. songChangeBroadcastMessage = RegisterWindowMessageW( L"WinampSongChange" );
  787. if ( !InitApplication( hMainInstance ) )
  788. {
  789. LPMessageBox( NULL, IDS_ERRORINIT, IDS_ERROR, MB_OK );
  790. return FALSE;
  791. }
  792. if ( !InitInstance( hMainInstance, (int)param ) )
  793. {
  794. LPMessageBox( NULL, IDS_ERRORINIT, IDS_ERROR, MB_OK );
  795. return FALSE;
  796. }
  797. if ( !bHandle )
  798. {
  799. if ( *lpszCmdParam ) // if command line parameters, parse them
  800. {
  801. parseCmdLine( lpszCmdParam, 0 );
  802. plEditRefresh();
  803. {
  804. if ( config_shuffle )
  805. PlayList_randpos( -BIGINT );
  806. if ( !bAdd )
  807. bStartPlaying = 1;
  808. }
  809. }
  810. else // otherwise, we're using our loaded playlist
  811. {
  812. if ( config_shuffle ) PlayList_randpos( -BIGINT );
  813. PlayList_getcurrent( FileName, FileTitle, FileTitleNum );
  814. }
  815. }
  816. //SetCurrentDirectoryW(config_cwd);
  817. plEditSelect( PlayList_getPosition() );
  818. Ole_initDragDrop();
  819. if ( !( GetAsyncKeyState( VK_RCONTROL ) & 0x8000 ) || !( GetAsyncKeyState( VK_LCONTROL ) & 0x8000 ) )
  820. {
  821. load_genplugins(); // load general purpose plugins
  822. if ( !Skin_Check_Modern_Support() )
  823. {
  824. wchar_t msg[ 512 ] = { 0 };
  825. StringCchPrintfW( msg, 512, getStringW( IDS_NO_MODERN_SKIN_SUPPORT, NULL, 0 ), config_skin );
  826. MessageBoxW( NULL, msg, getStringW( IDS_SKIN_LOAD_ERROR, NULL, 0 ), MB_ICONWARNING | MB_OK | MB_TOPMOST );
  827. }
  828. }
  829. //disable video menu if no video plugins are present or configured as disabled
  830. if ( !g_has_video_plugin )
  831. {
  832. RemoveMenu( main_menu, WINAMP_OPTIONS_VIDEO, MF_BYCOMMAND );
  833. RemoveMenu( GetSubMenu( v5_top_menu, 3 ), WINAMP_OPTIONS_VIDEO, MF_BYCOMMAND );
  834. g_mm_optionsbase_adj -= 1;
  835. }
  836. set_aot( 0 ); // in case our gen plugins did anything fun
  837. set_priority();
  838. {
  839. int v = _r_i( "show_prefs", 0 );
  840. if ( v != 0 )
  841. {
  842. if ( v > 0 ) prefs_last_page = v;
  843. _w_i( "show_prefs", 0 );
  844. PostMessageW( hMainWindow, WM_COMMAND, WINAMP_OPTIONS_PREFS, 0 );
  845. SetTimer( hMainWindow, 969, 1, PrefsShowProc );
  846. }
  847. }
  848. if ( bStartPlaying )
  849. {
  850. PlayList_getcurrent( FileName, FileTitle, FileTitleNum );
  851. SendMessageW( hMainWindow, WM_COMMAND, WINAMP_BUTTON2, 0 );
  852. //SendMessageW(hMainWindow,WM_WA_IPC,0,IPC_STARTPLAY);
  853. draw_paint( NULL );
  854. }
  855. WADlg_init( hMainWindow );
  856. SetTimer( hMainWindow, USER_CONSENT_EVENT_ID, 5000, DisplayUserConsentMessageBox );
  857. #ifdef BENSKI_TEST_WM_PRINTCLIENT
  858. SetTimer( hMainWindow, 9999, 10000, 0 );
  859. #endif
  860. if ( bHandle && *lpszCmdParam )
  861. PostMessageW( hMainWindow, WM_WA_IPC, (WPARAM)lpszCmdParam, IPC_HANDLE_URI );
  862. parseMessageCommands( hMainWindow, bCommand, bCmdParam );
  863. WPARAM exitParam = WinampMessageLoop();
  864. JSAPI1_Uninitialize();
  865. unload_genplugins();
  866. w5s_deinit();
  867. stats_save();
  868. SpectralAnalyzer_Destroy();
  869. /*Browser_Destroy();*/
  870. //RaiseException(0x0000DEAD,0,0,0);
  871. Ole_uninitDragDrop();
  872. if ( g_restartonquit )
  873. {
  874. char buf[ MAX_PATH ] = "\"";
  875. STARTUPINFO si = { sizeof( si ), };
  876. PROCESS_INFORMATION pi;
  877. GetModuleFileNameA( NULL, buf + 1, sizeof( buf ) - 1 );
  878. StringCchCatA( buf, MAX_PATH, "\"" );
  879. if ( g_restartonquit == 2 )
  880. StringCchCatA( buf, MAX_PATH, " /SAFE=1" );
  881. CreateProcessA( NULL, buf, NULL, NULL, FALSE, 0, NULL, NULL, (LPSTARTUPINFOA)&si, &pi );
  882. }
  883. RemoveRegistrar();
  884. Wasabi_Unload();
  885. CoUninitialize();
  886. return exitParam;
  887. } // WinMain
  888. void MoveOffscreen( HWND hwnd )
  889. {
  890. RECT r;
  891. GetWindowRect( hwnd, &r );
  892. SetWindowPos( hwnd, 0, r.left, OFFSCREEN_Y_POS, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER );
  893. }
  894. int g_showcode, deferring_show = 0;
  895. #include "../Plugins/General/gen_ml/ml_ipc.h"
  896. extern librarySendToMenuStruct mainSendTo = { 0 };
  897. // used to delay / filter out quick IPC_SETDIALOGBOXPARENT messages
  898. // to try to prevent the aero-peek buttons failing / part loading
  899. #define AEROPEEKLOAD 0xC0DE+5
  900. VOID CALLBACK TaskButtonCreated( HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime )
  901. {
  902. KillTimer( hwnd, idEvent );
  903. OnTaskbarButtonCreated( TRUE );
  904. }
  905. void UpdateAudioCDMenus( HMENU hmenu )
  906. {
  907. wchar_t buf[ 32 ] = { 0 };
  908. if ( IsMenu( hmenu ) && in_get_extended_fileinfoW( L"cda://", L"ext_cdda", buf, ARRAYSIZE( buf ) ) && buf[ 0 ] == L'1' )
  909. {
  910. for ( int i = 0; i < 5; i++ )
  911. {
  912. DeleteMenu( hmenu, ID_MAIN_PLAY_AUDIOCD + i, MF_BYCOMMAND );
  913. }
  914. MENUITEMINFOW i = { sizeof( i ), MIIM_TYPE | MIIM_DATA | MIIM_ID, MFT_STRING, };
  915. i.wID = ID_MAIN_PLAY_AUDIOCD;
  916. DWORD drives = GetLogicalDrives();
  917. g_audiocdletters = 0;
  918. int need_sep = 1;
  919. for ( int drivemask = 0; drivemask < 32; drivemask++ )
  920. {
  921. if ( drives & ( 1 << drivemask ) )
  922. {
  923. int old_error_mode = SetErrorMode( SEM_FAILCRITICALERRORS );
  924. wchar_t str[ 64 ] = { 0 }, tmp[ 64 ] = { 0 }, vol_buf[ 40 ] = { 0 }, empty[ 64 ] = { 0 };
  925. DWORD system_flags = 0, max_file_len = 0;
  926. char c = ( 'A' + drivemask );
  927. StringCchPrintfW( str, 64, L"%c:\\", c );
  928. if ( GetDriveTypeW( str ) == DRIVE_CDROM )
  929. {
  930. if ( need_sep )
  931. {
  932. MENUITEMINFO i2 = { sizeof( i2 ), MIIM_TYPE | MIIM_ID, MFT_SEPARATOR, };
  933. i2.wID = ID_MAIN_PLAY_AUDIOCD_SEP;
  934. InsertMenuItem( hmenu, 4, TRUE, &i2 );
  935. need_sep = 0;
  936. }
  937. GetVolumeInformationW( str, vol_buf, ARRAYSIZE( vol_buf ), 0, &max_file_len, &system_flags, 0, 0 );
  938. SetErrorMode( old_error_mode );
  939. StringCchPrintfW( str, 256, getStringW( IDS_AUDIO_CD, tmp, 64 ), c, ( vol_buf[ 0 ] ? vol_buf : getStringW( IDS_EMPTY, empty, 64 ) ) );
  940. g_audiocdletter[ g_audiocdletters ] = c;
  941. i.dwTypeData = str;
  942. i.cch = (UINT)wcslen( str );
  943. InsertMenuItemW( hmenu, 4 + g_audiocdletters, TRUE, &i );
  944. i.wID++;
  945. g_audiocdletters++;
  946. if ( g_audiocdletters == 4 )
  947. break;
  948. }
  949. }
  950. }
  951. }
  952. }
  953. // Main Winamp window procedure
  954. // we use message crackers when available, write our own for the ones that aren't
  955. LRESULT CALLBACK Main_WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  956. {
  957. if ( uMsg == g_scrollMsg )
  958. {
  959. wParam <<= 16;
  960. uMsg = WM_MOUSEWHEEL;
  961. }
  962. if ( uMsg == WM_TASKBARCREATED )
  963. {
  964. if ( systray_intray )
  965. {
  966. systray_restore();
  967. systray_minimize( caption );
  968. }
  969. return 0;
  970. }
  971. if ( uMsg == WM_TASKBARBUTTONCREATED )
  972. {
  973. OnTaskbarButtonCreated( TRUE );
  974. KillTimer( hMainWindow, AEROPEEKLOAD );
  975. SetTimer( hMainWindow, AEROPEEKLOAD, 250, TaskButtonCreated );
  976. return 0;
  977. }
  978. if ( IsDirectMouseWheelMessage( uMsg ) != FALSE )
  979. {
  980. SendMessageW( hwnd, WM_MOUSEWHEEL, wParam, lParam );
  981. return TRUE;
  982. }
  983. switch ( uMsg )
  984. {
  985. case WM_INITMENUPOPUP:
  986. {
  987. HMENU hMenu = (HMENU)wParam;
  988. if ( wParam && hMenu == mainSendTo.build_hMenu && mainSendTo.mode == 1 )
  989. {
  990. int IPC_LIBRARY_SENDTOMENU = wa_register_ipc( ( WPARAM ) & "LibrarySendToMenu" );
  991. if ( IPC_LIBRARY_SENDTOMENU > 65536 && SendMessageW( hMainWindow, WM_WA_IPC, (WPARAM)&mainSendTo, IPC_LIBRARY_SENDTOMENU ) == 0xffffffff )
  992. mainSendTo.mode = 2;
  993. }
  994. if ( config_usecursors && !disable_skin_cursors )
  995. {
  996. if ( Skin_Cursors[ 2 ] )
  997. SetCursor( Skin_Cursors[ 2 ] );
  998. else
  999. SetCursor( LoadCursorW( NULL, IDC_ARROW ) );
  1000. }
  1001. else
  1002. SetCursor( LoadCursorW( NULL, IDC_ARROW ) );
  1003. if ( hMenu == main_menu )
  1004. {
  1005. MENUITEMINFOW l_menu_info = { sizeof( l_menu_info ), };
  1006. l_menu_info.fMask = MIIM_TYPE;
  1007. l_menu_info.fType = MFT_STRING;
  1008. l_menu_info.dwTypeData = getStringW( IDS_WINAMP_MENUITEM, NULL, 0 );
  1009. l_menu_info.cch = (UINT)wcslen( l_menu_info.dwTypeData );
  1010. SetMenuItemInfoW( main_menu, 0, TRUE, &l_menu_info );
  1011. EnableMenuItem( main_menu, WINAMP_FILE_QUIT, MF_BYCOMMAND | ( g_exit_disabled ? MF_GRAYED : MF_ENABLED ) );
  1012. }
  1013. else if ( hMenu == g_submenus_play )
  1014. {
  1015. UpdateAudioCDMenus( g_submenus_play );
  1016. }
  1017. else if ( hMenu == g_submenus_bookmarks1 || hMenu == g_submenus_bookmarks2 )
  1018. {
  1019. MENUITEMINFOW l_menu_info = { sizeof( l_menu_info ), };
  1020. FILE *fp = 0;
  1021. int a = 34768;
  1022. int offs = 3;
  1023. int count = GetMenuItemCount( hMenu ) + 1;
  1024. if ( hMenu != g_submenus_bookmarks1 )
  1025. offs = 0;
  1026. l_menu_info.fMask = MIIM_TYPE | MIIM_DATA | MIIM_ID;
  1027. l_menu_info.fType = MFT_STRING;
  1028. l_menu_info.wID = 34768;
  1029. // this will remove the "(no bookmarks)" item from Main menu->Play->Bookmsrk
  1030. // if it still exists -> removed as of 5.55 since we handle the menu better.
  1031. if ( !offs ) RemoveMenu( hMenu, ID_MAIN_PLAY_BOOKMARK_NONE, MF_BYCOMMAND );
  1032. // remove all of the items we might have added - do by command for certainty
  1033. while ( count )
  1034. {
  1035. if ( !RemoveMenu( hMenu, a++, MF_BYCOMMAND ) ) break;
  1036. count--;
  1037. }
  1038. fp = _wfopen( BOOKMARKFILE8, L"rt" );
  1039. if ( fp )
  1040. {
  1041. while ( 1 )
  1042. {
  1043. char ft[ 4096 ] = { 0 }, fn[ MAX_PATH ] = { 0 };
  1044. fgets( fn, MAX_PATH, fp );
  1045. if ( feof( fp ) ) break;
  1046. fgets( ft, 4096, fp );
  1047. if ( feof( fp ) ) break;
  1048. if ( ft[ 0 ] && fn[ 0 ] )
  1049. {
  1050. if ( fn[ lstrlenA( fn ) - 1 ] == '\n' ) fn[ lstrlenA( fn ) - 1 ] = 0;
  1051. if ( ft[ lstrlenA( ft ) - 1 ] == '\n' ) ft[ lstrlenA( ft ) - 1 ] = 0;
  1052. if ( ft[ 0 ] && fn[ 0 ] )
  1053. {
  1054. l_menu_info.dwTypeData = AutoWideDup( ft, CP_UTF8 );
  1055. l_menu_info.cch = lstrlenW( l_menu_info.dwTypeData );
  1056. RemoveMenu( hMenu, l_menu_info.wID, MF_BYCOMMAND );
  1057. InsertMenuItemW( hMenu, l_menu_info.wID + offs - 34768, TRUE, &l_menu_info );
  1058. l_menu_info.wID++;
  1059. }
  1060. }
  1061. }
  1062. fclose( fp );
  1063. }
  1064. g_BookmarkTop = l_menu_info.wID;
  1065. // put in a place holder item if there were no read bookmarks
  1066. if ( g_BookmarkTop == 34768 )
  1067. {
  1068. l_menu_info.dwTypeData = getStringW( IDS_NO_BOOKMARKS, NULL, 0 );
  1069. l_menu_info.cch = lstrlenW( l_menu_info.dwTypeData );
  1070. InsertMenuItemW( hMenu, l_menu_info.wID + offs - 34768, TRUE, &l_menu_info );
  1071. EnableMenuItem( hMenu, l_menu_info.wID, MF_BYCOMMAND | MF_GRAYED );
  1072. }
  1073. }
  1074. else if ( hMenu == g_submenus_skins1 || hMenu == g_submenus_skins2 )
  1075. {
  1076. MENUITEMINFOW l_menu_info = { sizeof( l_menu_info ), };
  1077. HANDLE h;
  1078. WIN32_FIND_DATAW d = { 0 };
  1079. wchar_t dirmask[ MAX_PATH ] = { 0 };
  1080. l_menu_info.fMask = MIIM_TYPE | MIIM_DATA | MIIM_ID | MIIM_STATE;
  1081. l_menu_info.fType = MFT_STRING;
  1082. l_menu_info.wID = 32768;
  1083. PathCombineW( dirmask, SKINDIR, L"*" );
  1084. if ( !config_skin[ 0 ] )
  1085. CheckMenuItem( hMenu, 32767, MF_CHECKED );
  1086. else
  1087. CheckMenuItem( hMenu, 32767, MF_UNCHECKED );
  1088. h = FindFirstFileW( dirmask, &d );
  1089. if ( h != INVALID_HANDLE_VALUE )
  1090. {
  1091. int a = 0, mod_got = 0, bento_got = 0, checked = 0;
  1092. do
  1093. {
  1094. if ( !wcscmp( d.cFileName, L"." ) || !wcscmp( d.cFileName, L".." ) ) continue;
  1095. if ( ( d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ||
  1096. !_wcsicmp( extensionW( d.cFileName ), L"zip" ) ||
  1097. !_wcsicmp( extensionW( d.cFileName ), L"wal" ) ||
  1098. !_wcsicmp( extensionW( d.cFileName ), L"wsz" ) )
  1099. {
  1100. if ( !_wcsicmp( config_skin, d.cFileName ) )
  1101. {
  1102. l_menu_info.fState = MFS_CHECKED | MFS_ENABLED;
  1103. checked = 1;
  1104. }
  1105. else
  1106. {
  1107. l_menu_info.fState = MFS_UNCHECKED | MFS_ENABLED;
  1108. }
  1109. if ( d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  1110. l_menu_info.dwItemData = 0;
  1111. else
  1112. {
  1113. if ( !_wcsicmp( extensionW( d.cFileName ), L"zip" ) )
  1114. l_menu_info.dwItemData = 1;
  1115. else if ( !_wcsicmp( extensionW( d.cFileName ), L"wal" ) )
  1116. l_menu_info.dwItemData = 4;
  1117. else
  1118. l_menu_info.dwItemData = 2;
  1119. extensionW( d.cFileName )[ -1 ] = 0;
  1120. }
  1121. l_menu_info.dwTypeData = d.cFileName;
  1122. l_menu_info.cch = (UINT)wcslen( d.cFileName );
  1123. if ( !a )
  1124. if ( !RemoveMenu( hMenu, l_menu_info.wID + 4 - 32768, MF_BYPOSITION ) )
  1125. a = 1;
  1126. if ( !l_menu_info.dwItemData && !_wcsicmp( d.cFileName, MODERN_SKIN_NAME ) )
  1127. {
  1128. mod_got = 1;
  1129. InsertMenuItemW( hMenu, 4, TRUE, &l_menu_info );
  1130. }
  1131. else if ( !_wcsicmp( d.cFileName, BENTO_SKIN_NAME ) )
  1132. {
  1133. // place below classic + modern (if it exists)
  1134. bento_got = 1;
  1135. InsertMenuItemW( hMenu, 4 + mod_got, TRUE, &l_menu_info );
  1136. }
  1137. else if ( !_wcsicmp( d.cFileName, BIG_BENTO_SKIN_NAME ) )
  1138. {
  1139. // place below classic + modern + normal bento (if it exists)
  1140. InsertMenuItemW( hMenu, 4 + mod_got + bento_got, TRUE, &l_menu_info );
  1141. }
  1142. else
  1143. InsertMenuItemW( hMenu, l_menu_info.wID + 4 - 32768, TRUE, &l_menu_info );
  1144. l_menu_info.wID++;
  1145. }
  1146. } while ( l_menu_info.wID < 34700 && FindNextFileW( h, &d ) );
  1147. FindClose( h );
  1148. g_SkinTop = l_menu_info.wID;
  1149. while ( !a ) if ( !RemoveMenu( hMenu, l_menu_info.wID++ + 4 - 32768, MF_BYPOSITION ) ) a = 1;
  1150. if ( !checked ) CheckMenuItem( hMenu, 32767, MF_CHECKED );
  1151. }
  1152. }
  1153. else if ( ( hMenu == g_submenus_lang ) && config_wlz_menu )
  1154. {
  1155. MENUITEMINFOW l_menu_info = { sizeof( l_menu_info ), };
  1156. HANDLE h;
  1157. WIN32_FIND_DATAW d = { 0 };
  1158. wchar_t dirmask[ MAX_PATH ] = { 0 };
  1159. l_menu_info.fMask = MIIM_TYPE | MIIM_DATA | MIIM_ID | MIIM_STATE;
  1160. l_menu_info.fType = MFT_STRING;
  1161. l_menu_info.wID = 34700;
  1162. PathCombineW( dirmask, LANGDIR, L"*" );
  1163. l_menu_info.dwTypeData = L"English (US)";
  1164. l_menu_info.cch = (UINT)wcslen( l_menu_info.dwTypeData );
  1165. InsertMenuItemW( hMenu, l_menu_info.wID - 34700, TRUE, &l_menu_info );
  1166. l_menu_info.wID++;
  1167. CheckMenuItem( hMenu, 34700, ( !config_langpack[ 0 ] ? MF_CHECKED : MF_UNCHECKED ) );
  1168. h = FindFirstFileW( dirmask, &d );
  1169. if ( h != INVALID_HANDLE_VALUE )
  1170. {
  1171. int a = 0, checked = 0;
  1172. do
  1173. {
  1174. if ( !wcscmp( d.cFileName, L"." ) || !wcscmp( d.cFileName, L".." ) ) continue;
  1175. if ( ( d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) ||
  1176. !_wcsicmp( extensionW( d.cFileName ), L"zip" ) ||
  1177. !_wcsicmp( extensionW( d.cFileName ), L"wlz" ) )
  1178. {
  1179. if ( !_wcsicmp( config_langpack, d.cFileName ) )
  1180. {
  1181. l_menu_info.fState = MFS_CHECKED | MFS_ENABLED;
  1182. checked = 1;
  1183. }
  1184. else
  1185. {
  1186. l_menu_info.fState = MFS_UNCHECKED | MFS_ENABLED;
  1187. }
  1188. if ( d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  1189. {
  1190. wchar_t check[ MAX_PATH ] = { 0 };
  1191. PathCombineW( check, LANGDIR, d.cFileName );
  1192. PathCombineW( check, check, L"winamp.lng" );
  1193. if ( !PathFileExistsW( check ) )
  1194. continue;
  1195. l_menu_info.dwItemData = 0;
  1196. }
  1197. else
  1198. {
  1199. if ( !_wcsicmp( extensionW( d.cFileName ), L"zip" ) )
  1200. l_menu_info.dwItemData = 1;
  1201. else
  1202. l_menu_info.dwItemData = 2;
  1203. extensionW( d.cFileName )[ -1 ] = 0;
  1204. }
  1205. l_menu_info.dwTypeData = d.cFileName;
  1206. l_menu_info.cch = (UINT)wcslen( d.cFileName );
  1207. if ( !a )
  1208. if ( !RemoveMenu( hMenu, l_menu_info.wID - 34700, MF_BYPOSITION ) )
  1209. a = 1;
  1210. InsertMenuItemW( hMenu, l_menu_info.wID - 34700, TRUE, &l_menu_info );
  1211. l_menu_info.wID++;
  1212. }
  1213. } while ( l_menu_info.wID < 34800 && FindNextFileW( h, &d ) );
  1214. FindClose( h );
  1215. g_LangTop = l_menu_info.wID;
  1216. while ( !a )
  1217. if ( !RemoveMenu( hMenu, l_menu_info.wID++ - 34700, MF_BYPOSITION ) )
  1218. a = 1;
  1219. if ( !checked )
  1220. CheckMenuItem( hMenu, 34700, MF_CHECKED );
  1221. }
  1222. }
  1223. break;
  1224. }
  1225. case WM_DISPLAYCHANGE:
  1226. Main_OnDisplayChange( hwnd );
  1227. break;
  1228. case WM_WA_SYSTRAY:
  1229. return ( Main_OnWASystray( hwnd, (int)LOWORD( lParam ) ) ? 0 : -1L );
  1230. case WM_WA_MPEG_EOF:
  1231. return ( Main_OnWAMPEGEOF( hwnd ) ? 0 : -1L ); // sent by decode thread
  1232. case WM_WA_IPC:
  1233. return ( Main_OnIPC( hwnd, lParam, (int)(DWORD)wParam ) );
  1234. HANDLE_MSG( hwnd, WM_COMMAND, Main_OnCommand );
  1235. HANDLE_MSG( hwnd, WM_SYSCOMMAND, Main_OnSysCommand );
  1236. HANDLE_MSG( hwnd, WM_CREATE, Main_OnCreate );
  1237. HANDLE_MSG( hwnd, WM_QUERYNEWPALETTE, Main_OnQueryNewPalette );
  1238. HANDLE_MSG( hwnd, WM_PALETTECHANGED, Main_OnPaletteChanged );
  1239. HANDLE_MSG( hwnd, WM_SIZE, Main_OnSize );
  1240. HANDLE_MSG( hwnd, WM_DROPFILES, Main_OnDropFiles );
  1241. HANDLE_MSG( hwnd, WM_TIMER, Main_OnTimer );
  1242. HANDLE_MSG( hwnd, WM_PAINT, draw_paint );
  1243. case WM_PRINTCLIENT:
  1244. draw_printclient( (HDC)wParam, lParam );
  1245. return 0;
  1246. HANDLE_MSG( hwnd, WM_RBUTTONUP, Main_OnRButtonUp );
  1247. HANDLE_MSG( hwnd, WM_LBUTTONDBLCLK, Main_OnLButtonDblClk );
  1248. HANDLE_MSG( hwnd, WM_LBUTTONUP, Main_OnLButtonUp );
  1249. HANDLE_MSG( hwnd, WM_LBUTTONDOWN, Main_OnLButtonDown );
  1250. HANDLE_MSG( hwnd, WM_MOUSEMOVE, Main_OnMouseMove );
  1251. case WM_CONTEXTMENU:
  1252. SendMessageW( hwnd, WM_COMMAND, WINAMP_MAINMENU, 0 );
  1253. return 0;
  1254. case WM_CAPTURECHANGED:
  1255. return Main_OnCaptureChanged( (HWND)lParam );
  1256. HANDLE_MSG( hwnd, WM_DESTROY, Main_OnDestroy );
  1257. HANDLE_MSG( hwnd, WM_CLOSE, Main_OnClose );
  1258. case WM_NCACTIVATE:
  1259. {
  1260. LRESULT result = (LRESULT)(DWORD)(BOOL)(Main_OnNCActivate)( ( hwnd ), (BOOL)( wParam ), (HWND)( lParam ), 0L );
  1261. if ( IsIconic( hwnd ) )
  1262. break;
  1263. else
  1264. return result;
  1265. }
  1266. case WM_NCHITTEST:
  1267. if ( IsIconic( hwnd ) )
  1268. break;
  1269. return (LRESULT)(DWORD)(UINT)(Main_OnNCHitTest)( ( hwnd ), (int)(short)LOWORD( lParam ), (int)(short)HIWORD( lParam ) );
  1270. case WM_NCCALCSIZE:
  1271. if ( IsIconic( hwnd ) )
  1272. break;
  1273. return (LRESULT)(DWORD)(UINT)Main_OnNCCalcSize( hwnd, (BOOL)wParam, (NCCALCSIZE_PARAMS *)lParam );
  1274. HANDLE_MSG( hwnd, WM_ENDSESSION, Main_OnEndSession );
  1275. case WM_QUERYENDSESSION:
  1276. return !!SendMessageW( hwnd, WM_WA_IPC, 0, IPC_HOOK_OKTOQUIT );
  1277. case WM_KEYDOWN:
  1278. {
  1279. static int pos;
  1280. TCHAR buf[ 2 ] = { (TCHAR)wParam, 0 };
  1281. CharUpperBuff( buf, 1 );
  1282. if ( buf[ 0 ] == eggstr[ pos ] )
  1283. {
  1284. eggTyping = TRUE;
  1285. if ( !eggstr[ ++pos ] )
  1286. {
  1287. eggTyping = FALSE;
  1288. eggstat = !eggstat;
  1289. pos = 0;
  1290. draw_tbar( 1, config_windowshade, eggstat );
  1291. }
  1292. }
  1293. else
  1294. pos = 0;
  1295. break;
  1296. }
  1297. case WM_NCPAINT:
  1298. return 0;
  1299. case WM_COPYDATA:
  1300. return Main_OnCopyData( (HWND)wParam, (COPYDATASTRUCT *)lParam );
  1301. case WM_GETTEXT:
  1302. return Main_OnGetText( (wchar_t *)lParam, (int)wParam );
  1303. case WM_NOTIFY:
  1304. {
  1305. LPTOOLTIPTEXTW tt = (LPTOOLTIPTEXTW)lParam;
  1306. if ( tt->hdr.hwndFrom = hTooltipWindow )
  1307. {
  1308. switch ( tt->hdr.code )
  1309. {
  1310. case TTN_SHOW:
  1311. SetWindowPos( tt->hdr.hwndFrom, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE );
  1312. break;
  1313. case TTN_NEEDTEXTW:
  1314. {
  1315. LPTOOLTIPTEXTW tt = (LPTOOLTIPTEXTW)lParam;
  1316. wchar_t booga[ 81 ] = { 0 };
  1317. GetWindowTextW( hwnd, booga, 79 );
  1318. booga[ 79 ] = 0;
  1319. StringCchCopyW( tt->szText, 80, booga );
  1320. tt->lpszText = tt->szText;
  1321. return 0;
  1322. }
  1323. }
  1324. }
  1325. break;
  1326. }
  1327. case WM_SETFOCUS:
  1328. if ( !config_mw_open )
  1329. {
  1330. if ( config_pe_open )
  1331. SetForegroundWindow( hPLWindow );
  1332. else if ( config_eq_open )
  1333. SetForegroundWindow( hEQWindow );
  1334. // else if (config_mb_open) SetForegroundWindow(hMBWindow);
  1335. else if ( config_video_open )
  1336. SetForegroundWindow( hVideoWindow );
  1337. else
  1338. {
  1339. EnterCriticalSection( &embedcs );
  1340. {
  1341. embedWindowState *p = embedwndlist;
  1342. while ( p )
  1343. {
  1344. if ( IsWindowVisible( p->me ) )
  1345. {
  1346. SetForegroundWindow( p->me );
  1347. break;
  1348. }
  1349. p = p->link;
  1350. }
  1351. }
  1352. LeaveCriticalSection( &embedcs );
  1353. }
  1354. }
  1355. break;
  1356. case WM_KILLFOCUS:
  1357. {
  1358. if ( !config_mw_open )
  1359. {
  1360. if ( config_pe_open )
  1361. SetForegroundWindow( hPLWindow );
  1362. else if ( config_eq_open )
  1363. SetForegroundWindow( hEQWindow );
  1364. // else if (config_mb_open) SetForegroundWindow(hMBWindow);
  1365. else if ( config_video_open )
  1366. SetForegroundWindow( hVideoWindow );
  1367. else
  1368. {
  1369. EnterCriticalSection( &embedcs );
  1370. {
  1371. embedWindowState *p = embedwndlist;
  1372. while ( p )
  1373. {
  1374. if ( IsWindowVisible( p->me ) )
  1375. {
  1376. SetForegroundWindow( p->me );
  1377. break;
  1378. }
  1379. p = p->link;
  1380. }
  1381. }
  1382. LeaveCriticalSection( &embedcs );
  1383. }
  1384. }
  1385. break;
  1386. }
  1387. case WM_MOUSEWHEEL:
  1388. {
  1389. // because some people don't like it
  1390. if ( config_nomwheel )
  1391. break;
  1392. int zDelta = GET_WHEEL_DELTA_WPARAM( wParam ), dLines;
  1393. // if the delta changes then ignore prior carryover
  1394. // hopefully this will go with the expected action.
  1395. if ( zDelta < 0 && main_delta_carryover > 0 || zDelta > 0 && main_delta_carryover < 0 )
  1396. main_delta_carryover = 0;
  1397. // otherwise add on the carryover from the prior message
  1398. else
  1399. zDelta += main_delta_carryover;
  1400. if ( 0 == ( MK_MBUTTON & LOWORD( wParam ) ) )
  1401. zDelta *= 2;
  1402. dLines = zDelta / WHEEL_DELTA;
  1403. main_delta_carryover = zDelta - dLines * WHEEL_DELTA;
  1404. if ( 0 != dLines )
  1405. {
  1406. zDelta = ( dLines > 0 ) ? dLines : -dLines;
  1407. if ( 0 != ( MK_MBUTTON & LOWORD( wParam ) ) )
  1408. {
  1409. if ( dLines >= 0 )
  1410. dLines = WINAMP_FFWD5S;
  1411. else
  1412. dLines = WINAMP_REW5S;
  1413. }
  1414. else
  1415. {
  1416. if ( dLines >= 0 )
  1417. dLines = WINAMP_VOLUMEUP;
  1418. else
  1419. dLines = WINAMP_VOLUMEDOWN;
  1420. }
  1421. while ( zDelta-- )
  1422. {
  1423. SendMessageW( hwnd, WM_COMMAND, dLines, 0 );
  1424. }
  1425. }
  1426. break;
  1427. }
  1428. case WM_DWMSENDICONICTHUMBNAIL:
  1429. {
  1430. int x = HIWORD( lParam );
  1431. int y = LOWORD( lParam );
  1432. OnIconicThumbnail( x, y );
  1433. }
  1434. break;
  1435. #if 0
  1436. case WM_DWMSENDICONICLIVEPREVIEWBITMAP:
  1437. {
  1438. //MessageBoxA(NULL, "winamp/live", "winamp/live", MB_OK);
  1439. OnThumbnailPreview();
  1440. }
  1441. break;
  1442. #endif
  1443. case WM_MOVE:
  1444. #if 0
  1445. if ( (int)LOWORD( lParam ) < 32768 && (int)HIWORD( lParam ) < 32768 )
  1446. {
  1447. if (/*(int)LOWORD(lParam) != 3000 && */(int)HIWORD( lParam ) != OFFSCREEN_Y_POS )
  1448. {
  1449. if ( (int)LOWORD( lParam ) != config_wx ||
  1450. (int)HIWORD( lParam ) != config_wy )
  1451. if ( config_keeponscreen & 1 )
  1452. {
  1453. config_wx = (int)LOWORD( lParam );
  1454. config_wy = (int)HIWORD( lParam );
  1455. set_aot( 1 );
  1456. }
  1457. }
  1458. }
  1459. #endif
  1460. break;
  1461. case WM_SETCURSOR:
  1462. switch ( HIWORD( lParam ) )
  1463. {
  1464. case WM_LBUTTONDOWN:
  1465. case WM_RBUTTONDOWN:
  1466. case WM_MBUTTONDOWN:
  1467. case WM_XBUTTONDOWN:
  1468. DisabledWindow_OnMouseClick( hwnd );
  1469. break;
  1470. }
  1471. if ( config_usecursors && !disable_skin_cursors )
  1472. {
  1473. if ( (HWND)wParam == hMainWindow && HIWORD( lParam ) == WM_MOUSEMOVE )
  1474. ui_handlecursor();
  1475. return TRUE;
  1476. }
  1477. else
  1478. SetCursor( LoadCursorW( NULL, IDC_ARROW ) );
  1479. break;
  1480. }
  1481. return ( DefWindowProcW( hwnd, uMsg, wParam, lParam ) );
  1482. }
  1483. static LRESULT Main_OnSysCommand( HWND hwnd, UINT cmd, int x, int y )
  1484. {
  1485. // char buf[512];
  1486. // wsprintf(buf,"got WM_SYSCOMMAND %08x\n",cmd);
  1487. // OutputDebugString(buf);
  1488. // video
  1489. if ( ( ( cmd & 0xfff0 ) == SC_SCREENSAVE || ( cmd & 0xfff0 ) == SC_MONITORPOWER ) && config_video_noss && video_isVideoPlaying() )
  1490. {
  1491. return -1;
  1492. }
  1493. if ( !Main_OnCommand( hwnd, cmd, (HWND)x, (UINT)y ) )
  1494. FORWARD_WM_SYSCOMMAND( hwnd, cmd, x, y, DefWindowProcW );
  1495. return 1;
  1496. }
  1497. static LRESULT WINAPI browseCheckBoxProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
  1498. {
  1499. switch ( uMsg )
  1500. {
  1501. case WM_INITDIALOG:
  1502. {
  1503. if ( !( config_rofiob & 2 ) )
  1504. CheckDlgButton( hwndDlg, IDC_CHECK1, BST_CHECKED );
  1505. break;
  1506. }
  1507. case WM_COMMAND:
  1508. {
  1509. if ( LOWORD( wParam ) == IDC_CHECK1 )
  1510. {
  1511. config_rofiob &= ~2;
  1512. if ( !IsDlgButtonChecked( hwndDlg, IDC_CHECK1 ) )
  1513. config_rofiob |= 2;
  1514. config_write( 0 );
  1515. }
  1516. break;
  1517. }
  1518. }
  1519. return 0;
  1520. }
  1521. BOOL CALLBACK browseEnumProc( HWND hwnd, LPARAM lParam )
  1522. {
  1523. char cl[ 32 ] = { 0 };
  1524. GetClassNameA( hwnd, cl, ARRAYSIZE( cl ) );
  1525. if ( !lstrcmpiA( cl, WC_TREEVIEWA ) )
  1526. {
  1527. PostMessageW( hwnd, TVM_ENSUREVISIBLE, 0, (LPARAM)TreeView_GetSelection( hwnd ) );
  1528. return FALSE;
  1529. }
  1530. return TRUE;
  1531. }
  1532. int CALLBACK WINAPI BrowseCallbackProc( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData )
  1533. {
  1534. switch ( uMsg )
  1535. {
  1536. case BFFM_INITIALIZED:
  1537. {
  1538. SetWindowTextW( hwnd, getStringW( ( !lpData ? IDS_OPENDIR : IDS_ADD_FOLDER ), NULL, 0 ) );
  1539. SendMessageW( hwnd, BFFM_SETSELECTIONW, 1, (LPARAM)config_cwd );
  1540. HWND h = FindWindowExW( hwnd, NULL, NULL, L"__foo" );
  1541. if ( h )
  1542. ShowWindow( h, SW_HIDE );
  1543. h = LPCreateDialogW( IDD_BROWSE_RECDLG, hwnd, browseCheckBoxProc );
  1544. SetWindowPos( h, 0, 4, 4, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
  1545. ShowWindow( h, SW_SHOWNA );
  1546. // this is not nice but it fixes the selection not working correctly on all OSes
  1547. EnumChildWindows( hwnd, browseEnumProc, 0 );
  1548. }
  1549. }
  1550. return 0;
  1551. }
  1552. LRESULT sendMlIpc( int msg, WPARAM param )
  1553. {
  1554. static LRESULT IPC_GETMLWINDOW;
  1555. static HWND mlwnd;
  1556. if ( !IPC_GETMLWINDOW ) IPC_GETMLWINDOW = wa_register_ipc( ( WPARAM ) & "LibraryGetWnd" );
  1557. if ( !mlwnd || (int)mlwnd == 1 )
  1558. mlwnd = (HWND)SendMessageW( hMainWindow, WM_WA_IPC, 0, IPC_GETMLWINDOW );
  1559. if ( param == 0 && msg == 0 ) return (LRESULT)mlwnd;
  1560. if ( IsWindow( mlwnd ) )
  1561. return SendMessageW( mlwnd, WM_ML_IPC, param, msg );
  1562. return 0;
  1563. }
  1564. void tealike_crappy_code( unsigned long v[ 2 ], unsigned long k[ 4 ] )
  1565. {
  1566. unsigned long y = v[ 0 ], z = v[ 1 ], sum = 0, /* set up */
  1567. delta = 0x9e3779b9UL, n = 32; /* key schedule constant*/
  1568. while ( n-- > 0 )
  1569. {
  1570. /* basic cycle start */
  1571. sum += delta;
  1572. y += ( ( z << 4 ) + k[ 0 ] ) ^ ( z + sum ) ^ ( ( z >> 5 ) + k[ 1 ] );
  1573. z += ( ( y << 4 ) + k[ 2 ] ) ^ ( y + sum ) ^ ( ( y >> 5 ) + k[ 3 ] ); /* end cycle */
  1574. }
  1575. v[ 0 ] = y; v[ 1 ] = z;
  1576. }
  1577. // command line parsing, for IPC or normal modes
  1578. // goes to a lot of trouble to look for "'s.
  1579. HWND find_otherwinamp( wchar_t *cmdline )
  1580. {
  1581. int y = 0;
  1582. wchar_t buf[ MAX_PATH ] = { 0 };
  1583. StringCchPrintfW( buf, MAX_PATH, L"%s_%x_CLASS", szAppName, APP_VERSION_NUM );
  1584. again:
  1585. g_hEventRunning = CreateEventW( 0, 1, 0, buf );
  1586. if ( g_hEventRunning && GetLastError() == ERROR_ALREADY_EXISTS )
  1587. {
  1588. int x;
  1589. CloseHandle( g_hEventRunning );
  1590. g_hEventRunning = 0;
  1591. // check for window for 4s, then give up
  1592. if ( !bNoHwndOther && ( !config_minst || *cmdline ) ) for ( x = 0; x < 40; x++ )
  1593. {
  1594. HWND lhwnd = NULL;
  1595. int failed = 0;
  1596. while ( ( lhwnd = FindWindowExW( NULL, lhwnd, szAppName, NULL ) ) )
  1597. {
  1598. DWORD_PTR vn = 0; //APP_VERSION_NUM
  1599. if ( lhwnd == hMainWindow )
  1600. continue;
  1601. if ( !SendMessageTimeout( lhwnd, WM_WA_IPC, 0, IPC_GETVERSION, SMTO_NORMAL, 5000, &vn ) )
  1602. {
  1603. failed = 1;
  1604. }
  1605. else if ( vn == APP_VERSION_NUM ) return lhwnd;
  1606. }
  1607. if ( failed ) return NULL; // no valid winamp windows, but one that fucked up
  1608. Sleep( 100 );
  1609. }
  1610. if ( y++ < 20 ) goto again;
  1611. }
  1612. return NULL;
  1613. }
  1614. // returns 0 if showing/hiding sould be aborted
  1615. int Ipc_WindowToggle( INT_PTR which, INT_PTR how )
  1616. {
  1617. return SendMessageW( hMainWindow, WM_WA_IPC, which, how ? IPC_CB_ONSHOWWND : IPC_CB_ONHIDEWND );
  1618. }
  1619. //}
  1620. #ifdef BENSKI_TEST_WM_PRINTCLIENT
  1621. static void PrintWindow( HWND hWnd )
  1622. {
  1623. HDC hDCMem = CreateCompatibleDC( NULL );
  1624. HBITMAP hBmp = NULL;
  1625. RECT rect;
  1626. GetWindowRect( hWnd, &rect );
  1627. {
  1628. HDC hDC = GetDC( hWnd );
  1629. hBmp = CreateCompatibleBitmap( hDC, rect.right - rect.left, rect.bottom - rect.top );
  1630. ReleaseDC( hWnd, hDC );
  1631. }
  1632. {
  1633. HGDIOBJ hOld = SelectObject( hDCMem, hBmp );
  1634. SendMessageW( hWnd, WM_PRINT, (WPARAM)hDCMem, PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED );
  1635. SelectObject( hDCMem, hOld );
  1636. }
  1637. DeleteObject( hDCMem );
  1638. OpenClipboard( hWnd );
  1639. EmptyClipboard();
  1640. SetClipboardData( CF_BITMAP, hBmp );
  1641. CloseClipboard();
  1642. }
  1643. #endif