main.cpp 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172
  1. #include "main.h"
  2. #include <windowsx.h>
  3. #include <time.h>
  4. #include <rpc.h>
  5. #include "../winamp/gen.h"
  6. #include "resource.h"
  7. #include "childwnd.h"
  8. #include "config.h"
  9. #include "../winamp/ipc_pe.h"
  10. #include "../winamp/wa_dlg.h"
  11. #include "../winamp/strutil.h"
  12. #include "ml.h"
  13. #include "ml_ipc.h"
  14. #include "./folderbrowser.h"
  15. #include "./mldwm.h"
  16. #ifndef _ML_HEADER_IMPMLEMENT
  17. #define _ML_HEADER_IMPMLEMENT
  18. #endif // _ML_HEADER_IMPMLEMENT
  19. #include "ml_ipc_0313.h"
  20. #undef _ML_HEADER_IMPMLEMENT
  21. #include "sendto.h"
  22. #include "../gen_hotkeys/wa_hotkeys.h"
  23. #include "MediaLibraryCOM.h"
  24. #include "../nu/CCVersion.h"
  25. #include "../nu/AutoWideFn.h"
  26. #include "../nu/htmlcontainer2.h"
  27. #include <shlwapi.h>
  28. #include "api__gen_ml.h"
  29. #include <api/service/waServiceFactory.h>
  30. #include "./navigation.h"
  31. //#include "./skinnedwnd.h"
  32. #include "./skinning.h"
  33. #include "../nu/ServiceWatcher.h"
  34. #include "MusicID.h"
  35. #include <tataki/export.h>
  36. #include <strsafe.h>
  37. #include "../Winamp/wasabicfg.h"
  38. // {6B0EDF80-C9A5-11d3-9F26-00C04F39FFC6}
  39. static const GUID library_guid =
  40. { 0x6b0edf80, 0xc9a5, 0x11d3, { 0x9f, 0x26, 0x0, 0xc0, 0x4f, 0x39, 0xff, 0xc6 } };
  41. int m_calling_getfileinfo;
  42. int IPC_GETMLWINDOW, IPC_LIBRARY_SENDTOMENU, IPC_GET_ML_HMENU;
  43. int config_use_ff_scrollbars=1, config_use_alternate_colors=0;
  44. LARGE_INTEGER freq;
  45. C_Config *g_config;
  46. embedWindowState myWindowState;
  47. prefsDlgRecW myPrefsItem, myPrefsItemPlug;
  48. DEFINE_EXTERNAL_SERVICE(api_service, WASABI_API_SVC);
  49. DEFINE_EXTERNAL_SERVICE(api_application, WASABI_API_APP);
  50. DEFINE_EXTERNAL_SERVICE(api_language, WASABI_API_LNG);
  51. DEFINE_EXTERNAL_SERVICE(obj_ombrowser, AGAVE_OBJ_BROWSER);
  52. DEFINE_EXTERNAL_SERVICE(api_mldb, AGAVE_API_MLDB);
  53. DEFINE_EXTERNAL_SERVICE(api_syscb, WASABI_API_SYSCB);
  54. DEFINE_EXTERNAL_SERVICE(api_threadpool, AGAVE_API_THREADPOOL);
  55. DEFINE_EXTERNAL_SERVICE(api_decodefile, AGAVE_API_DECODE);
  56. DEFINE_EXTERNAL_SERVICE(wnd_api, WASABI_API_WND);
  57. DEFINE_EXTERNAL_SERVICE(api_skin, WASABI_API_SKIN);
  58. DEFINE_EXTERNAL_SERVICE(api_config, AGAVE_API_CONFIG);
  59. DEFINE_EXTERNAL_SERVICE(api_palette, WASABI_API_PALETTE);
  60. #ifndef IGNORE_API_GRACENOTE
  61. DEFINE_EXTERNAL_SERVICE(api_gracenote, AGAVE_API_GRACENOTE);
  62. #endif
  63. DEFINE_EXTERNAL_SERVICE(JSAPI2::api_security, AGAVE_API_JSAPI2_SECURITY);
  64. ifc_configitem *ieDisableSEH = 0;
  65. // wasabi based services for localisation support
  66. HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
  67. static ServiceWatcher serviceWatcher;
  68. #ifndef IGNORE_API_GRACENOTE
  69. MusicIDCOM musicIDCOM;
  70. #endif
  71. void config();
  72. void quit();
  73. int init();
  74. BOOL init2(void);
  75. extern "C"
  76. {
  77. HWND g_hwnd, g_ownerwnd;
  78. extern winampGeneralPurposePlugin plugin =
  79. {
  80. GPPHDR_VER_U,
  81. "nullsoft(gen_ml.dll)",
  82. init,
  83. config,
  84. quit,
  85. };
  86. };
  87. HWND g_PEWindow;
  88. HMENU wa_main_menu = NULL;
  89. HMENU wa_windows_menu = NULL;
  90. HMENU wa_playlists_cmdmenu = NULL;
  91. HMENU last_playlistsmenu = NULL;
  92. HMENU last_viewmenu = NULL;
  93. int last_viewmenu_insert = 0;
  94. int g_safeMode = 0, sneak = 0;
  95. HCURSOR hDragNDropCursor;
  96. int profile = 0;
  97. wchar_t pluginPath[MAX_PATH] = {0};
  98. static wchar_t preferencesName[128];
  99. HMENU g_context_menus;
  100. extern C_ItemList m_plugins;
  101. extern HNAVCTRL hNavigation;
  102. //xp theme disabling shit
  103. static HMODULE m_uxdll;
  104. HRESULT (__stdcall *SetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
  105. BOOL (__stdcall *IsAppThemed)(void);
  106. template <class api_T>
  107. void ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
  108. {
  109. if (WASABI_API_SVC)
  110. {
  111. waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(factoryGUID_t);
  112. if (factory)
  113. api_t = reinterpret_cast<api_T *>( factory->getInterface() );
  114. }
  115. }
  116. template <class api_T>
  117. void ServiceRelease(api_T *api_t, GUID factoryGUID_t)
  118. {
  119. if (WASABI_API_SVC && api_t)
  120. {
  121. waServiceFactory *factory = WASABI_API_SVC->service_getServiceByGuid(factoryGUID_t);
  122. if (factory)
  123. factory->releaseInterface(api_t);
  124. }
  125. api_t = NULL;
  126. }
  127. bool IsVisible()
  128. {
  129. return g_hwnd && IsWindowVisible(g_ownerwnd);
  130. }
  131. void MLVisibleChanged(BOOL fVisible)
  132. {
  133. static BOOL visible = FALSE;
  134. if (fVisible != visible)
  135. {
  136. visible = fVisible;
  137. plugin_SendMessage(ML_MSG_MLVISIBLE, visible, 0, 0);
  138. }
  139. }
  140. BOOL MlWindow_SetMinimizedMode(BOOL fMinimized)
  141. {
  142. if (FALSE != fMinimized)
  143. return SetPropW(g_ownerwnd, L"MLWindow_MinimizedMode", (HANDLE)1);
  144. RemovePropW(g_ownerwnd, L"MLWindow_MinimizedMode");
  145. return TRUE;
  146. }
  147. BOOL MlWindow_IsMinimizedMode(void)
  148. {
  149. return (0 != GetPropW(g_ownerwnd, L"MLWindow_MinimizedMode"));
  150. }
  151. void toggleVisible(int closecb)
  152. {
  153. BOOL fVisible, fMinimized;
  154. HWND rootWindow;
  155. fVisible = (0 != (WS_VISIBLE & GetWindowLongPtrW(g_ownerwnd, GWL_STYLE)));//IsWindowVisible(g_ownerwnd);
  156. rootWindow = GetAncestor(g_ownerwnd, GA_ROOT);
  157. if (NULL == rootWindow || rootWindow == g_ownerwnd)
  158. {
  159. rootWindow = (HWND)(HWND)SENDWAIPC(plugin.hwndParent, IPC_GETDIALOGBOXPARENT, 0);
  160. if (NULL == rootWindow)
  161. rootWindow = plugin.hwndParent;
  162. }
  163. fMinimized = IsIconic(rootWindow);
  164. if (FALSE != fVisible || 1 == closecb)
  165. {
  166. if (FALSE == fMinimized && FALSE != fVisible)
  167. {
  168. HWND hwndFocus = GetFocus();
  169. if (hwndFocus == g_ownerwnd || IsChild(g_ownerwnd, hwndFocus))
  170. SendMessageW(plugin.hwndParent, WM_COMMAND, WINAMP_NEXT_WINDOW, 0);
  171. ShowWindow(g_ownerwnd, SW_HIDE);
  172. }
  173. }
  174. else
  175. {
  176. if (init2() && FALSE == fMinimized && FALSE == fVisible)
  177. {
  178. ShowWindow(g_ownerwnd, SW_SHOWNORMAL);
  179. // make sure that we focus the tree to work around some modern skin quirks
  180. if(closecb != 2)
  181. {
  182. SetFocus(NavCtrlI_GetHWND(hNavigation));
  183. }
  184. else
  185. {
  186. // delay the focusing on loading as some machines are too fast and
  187. // may cause the wrong view to the selected (root instead of child)
  188. PostMessage(g_ownerwnd,WM_ML_IPC,0,ML_IPC_FOCUS_TREE);
  189. }
  190. }
  191. }
  192. if (FALSE != fMinimized && 1 != closecb)
  193. {
  194. MlWindow_SetMinimizedMode(TRUE);
  195. if (NULL != g_config)
  196. g_config->WriteInt(L"visible", (FALSE == fVisible));
  197. UINT menuFlags = (FALSE == fVisible) ? MF_CHECKED : MF_UNCHECKED;
  198. menuFlags |= MF_BYCOMMAND;
  199. INT szMenu[] = { 0, 4, };
  200. for (INT i = 0; i < ARRAYSIZE(szMenu); i++)
  201. {
  202. HMENU hMenu = (HMENU)SendMessage(plugin.hwndParent, WM_WA_IPC, szMenu[i], IPC_GET_HMENU);
  203. if (NULL != hMenu)
  204. CheckMenuItem(hMenu, WA_MENUITEM_ID, menuFlags);
  205. }
  206. }
  207. }
  208. static WNDPROC wa_oldWndProc;
  209. static BOOL Winamp_OnIPC(HWND hwnd, UINT uMsg, INT_PTR param, LRESULT *pResult)
  210. {
  211. if (IPC_GETMLWINDOW == uMsg && IPC_GETMLWINDOW > 65536)
  212. {
  213. if (param == -1 && !g_hwnd) init2();
  214. *pResult = (LRESULT)g_hwnd;
  215. return TRUE;
  216. }
  217. else if (IPC_LIBRARY_SENDTOMENU == uMsg && IPC_LIBRARY_SENDTOMENU > 65536)
  218. {
  219. librarySendToMenuStruct *s = (librarySendToMenuStruct*)param;
  220. if (!s || s->mode == 0)
  221. {
  222. *pResult = 0xFFFFFFFF;
  223. return TRUE;
  224. }
  225. if (s->mode == 1)
  226. {
  227. if (!s->ctx[0])
  228. {
  229. if (!g_hwnd) init2();
  230. SendToMenu *stm = new SendToMenu();
  231. if (s->build_start_id && s->build_end_id)
  232. {
  233. stm->buildmenu(s->build_hMenu, s->data_type, s->ctx[1], s->ctx[2], s->build_start_id, s->build_end_id);
  234. }
  235. else
  236. {
  237. stm->buildmenu(s->build_hMenu, s->data_type, s->ctx[1], s->ctx[2]);
  238. }
  239. s->ctx[0] = (intptr_t)stm;
  240. *pResult = 0xFFFFFFFF;
  241. return TRUE;
  242. }
  243. }
  244. else if (s->mode == 2)
  245. {
  246. SendToMenu *stm = (SendToMenu *)s->ctx[0];
  247. if (stm && stm->isourcmd(s->menu_id))
  248. {
  249. *pResult = 0xFFFFFFFF;
  250. return TRUE;
  251. }
  252. }
  253. else if (s->mode == 3)
  254. {
  255. SendToMenu *stm = (SendToMenu *)s->ctx[0];
  256. if (stm)
  257. {
  258. *pResult = stm->handlecmd(s->hwnd, s->menu_id, s->data_type, s->data);
  259. return TRUE;
  260. }
  261. }
  262. else if (s->mode == 4)
  263. {
  264. delete (SendToMenu *)s->ctx[0];
  265. s->ctx[0] = 0;
  266. }
  267. *pResult = TRUE;
  268. return TRUE;
  269. }
  270. else if (IPC_GET_ML_HMENU == uMsg && IPC_GET_ML_HMENU > 65536)
  271. {
  272. *pResult = (LRESULT)g_context_menus;
  273. return TRUE;
  274. }
  275. switch(uMsg)
  276. {
  277. case IPC_CB_RESETFONT:
  278. PostMessageW(g_hwnd, WM_DISPLAYCHANGE, 0, 0);
  279. break;
  280. case IPC_CB_GETTOOLTIPW:
  281. if (param == 16 && g_config->ReadInt(L"attachlbolt", 0))
  282. {
  283. static wchar_t tlStr[64];
  284. *pResult = (LRESULT)WASABI_API_LNGSTRINGW_BUF(IDS_TOGGLE_LIBRARY,tlStr,64);
  285. return TRUE;
  286. }
  287. break;
  288. case IPC_GET_EXTENDED_FILE_INFO_HOOKABLE:
  289. if (!m_calling_getfileinfo)
  290. {
  291. extendedFileInfoStruct *extendedInfo;
  292. extendedInfo = (extendedFileInfoStruct*)param;
  293. if (NULL != extendedInfo &&
  294. NULL != extendedInfo->filename &&
  295. NULL != extendedInfo->metadata)
  296. {
  297. if (plugin_SendMessage(ML_IPC_HOOKEXTINFO, param, 0, 0))
  298. {
  299. *pResult = 1;
  300. return TRUE;
  301. }
  302. }
  303. }
  304. break;
  305. case IPC_GET_EXTENDED_FILE_INFOW_HOOKABLE:
  306. if (!m_calling_getfileinfo)
  307. {
  308. extendedFileInfoStructW *extendedInfo;
  309. extendedInfo = (extendedFileInfoStructW*)param;
  310. if (NULL != extendedInfo &&
  311. NULL != extendedInfo->filename &&
  312. NULL != extendedInfo->metadata)
  313. {
  314. if (plugin_SendMessage(ML_IPC_HOOKEXTINFOW, param, 0, 0))
  315. {
  316. *pResult = 1;
  317. return TRUE;
  318. }
  319. }
  320. }
  321. break;
  322. case IPC_HOOK_TITLES:
  323. if (NULL != param)
  324. {
  325. waHookTitleStruct *hookTitle;
  326. hookTitle = (waHookTitleStruct*)param;
  327. if (NULL != hookTitle->filename &&
  328. plugin_SendMessage(ML_IPC_HOOKTITLE, param, 0, 0))
  329. {
  330. *pResult = 1;
  331. return TRUE;
  332. }
  333. }
  334. break;
  335. case IPC_HOOK_TITLESW:
  336. if (NULL != param)
  337. {
  338. waHookTitleStructW *hookTitle;
  339. hookTitle = (waHookTitleStructW*)param;
  340. if (NULL != hookTitle->filename &&
  341. plugin_SendMessage(ML_IPC_HOOKTITLEW, param, 0, 0))
  342. {
  343. *pResult = 1;
  344. return TRUE;
  345. }
  346. }
  347. break;
  348. case IPC_ADD_PREFS_DLG:
  349. case IPC_ADD_PREFS_DLGW:
  350. if (param && !((prefsDlgRec*)param)->where)
  351. {
  352. prefsDlgRec *p = (prefsDlgRec *)param;
  353. // we use the dialog proc for the preferences to determine the hinstance of the module and
  354. // use that to then determine if we set it as a child of the media library preference node
  355. // it also handles localised versions of the preference pages as the dialog proceedure is
  356. // going to be in the true plug-in dll and so can be matched to the main ml plugins list!
  357. MEMORY_BASIC_INFORMATION mbi = {0};
  358. if(VirtualQuery(p->proc, &mbi, sizeof(mbi)))
  359. {
  360. int i = m_plugins.GetSize();
  361. while (i-- > 0)
  362. {
  363. winampMediaLibraryPlugin *mlplugin = (winampMediaLibraryPlugin *)m_plugins.Get(i);
  364. if (mlplugin->hDllInstance == (HINSTANCE)mbi.AllocationBase)
  365. {
  366. p->where = (intptr_t)(INT_PTR)&myPrefsItem;
  367. break;
  368. }
  369. }
  370. }
  371. }
  372. break;
  373. case IPC_CB_ONSHOWWND:
  374. if ((HWND)param == g_ownerwnd) MLVisibleChanged(TRUE);
  375. break;
  376. case IPC_HOOK_OKTOQUIT:
  377. {
  378. if (plugin_SendMessage(ML_MSG_NOTOKTOQUIT, 0, 0, 0))
  379. {
  380. *pResult = 0;
  381. return TRUE;
  382. }
  383. }
  384. break;
  385. case IPC_PLAYING_FILEW:
  386. plugin_SendMessage(ML_MSG_PLAYING_FILE, param, 0, 0);
  387. break;
  388. case IPC_WRITECONFIG:
  389. plugin_SendMessage(ML_MSG_WRITE_CONFIG, param, 0, 0);
  390. break;
  391. }
  392. return FALSE;
  393. }
  394. static LRESULT WINAPI wa_newWndProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  395. {
  396. switch(uMsg)
  397. {
  398. // far from ideal fix but deals with differing plugin load orders (mainly from FAT32 drives)
  399. // and not being able to unload/clean up properly the scrollbar bitmaps used - DRO 29/09/07
  400. case WM_CLOSE:
  401. SkinnedScrollWnd_Quit();
  402. break;
  403. case WM_WA_IPC:
  404. {
  405. LRESULT result = 0;
  406. if (Winamp_OnIPC(hwndDlg, (UINT)lParam, (INT_PTR)wParam, &result)) return result;
  407. break;
  408. }
  409. case WM_SIZE:
  410. if (wParam == SIZE_RESTORED)
  411. {
  412. if (FALSE != MlWindow_IsMinimizedMode())
  413. {
  414. MlWindow_SetMinimizedMode(FALSE);
  415. int showCommand = (0 != g_config->ReadInt(L"visible", 1)) ? SW_SHOWNA : SW_HIDE;
  416. ShowWindow(g_ownerwnd, showCommand);
  417. }
  418. }
  419. break;
  420. case WM_COMMAND:
  421. case WM_SYSCOMMAND:
  422. {
  423. WORD lowP = LOWORD(wParam);
  424. if (lowP == WA_MENUITEM_ID || lowP == WINAMP_LIGHTNING_CLICK)
  425. {
  426. if (lowP != WINAMP_LIGHTNING_CLICK || g_config->ReadInt(L"attachlbolt", 0))
  427. {
  428. toggleVisible();
  429. return 0;
  430. }
  431. }
  432. #if 0 // no radio - don't delete yet - tag will need to do this in ml_online
  433. else if (lowP == WINAMP_VIDEO_TVBUTTON) // && g_config->ReadInt("attachtv",1))
  434. {
  435. if (!g_hwnd || !IsWindowVisible(g_ownerwnd)) toggleVisible();
  436. PostMessage(g_ownerwnd, WM_NEXTDLGCTL, (WPARAM)g_hwnd, TRUE);
  437. HWND hwndTree = GetTreeHWND(g_hwnd);
  438. HTREEITEM hti = findByParam(hwndTree, TREE_INTERNET_VIDEO, TVI_ROOT);
  439. if (hti)
  440. {
  441. TreeView_SelectItem(hwndTree, hti);
  442. return 0;
  443. }
  444. }
  445. #endif
  446. // done like this since ml_online can't really subclass winamp to get the notification
  447. else if (lowP == WINAMP_VIDEO_TVBUTTON)
  448. {
  449. if (!g_hwnd || !IsWindowVisible(g_ownerwnd)) toggleVisible();
  450. HNAVITEM hDefItem = NavCtrlI_FindItemByName(hNavigation, LOCALE_USER_DEFAULT, NICF_INVARIANT_I | NICF_DISPLAY_I | NICF_IGNORECASE_I, L"Shoutcast TV", -1);
  451. if(!hDefItem)
  452. {
  453. // work with the localised version of the Online Services root (if there...)
  454. wchar_t OSName[64] = {L"Online Services"};
  455. WASABI_API_LNG->GetStringFromGUIDW(MlOnlineLangGUID,WASABI_API_ORIG_HINST,1,OSName,64);
  456. // just incase the localised dll was there but the file was missing the translation
  457. if(!lstrcmpiW(OSName,L"Error loading string"))
  458. lstrcpynW(OSName,L"Online Services",64);
  459. hDefItem = NavCtrlI_FindItemByName(hNavigation, LOCALE_USER_DEFAULT, NICF_INVARIANT_I | NICF_DISPLAY_I | NICF_IGNORECASE_I, OSName, -1);
  460. }
  461. if (hDefItem)
  462. {
  463. NavItemI_Select(hDefItem);
  464. NavCtrlI_Show(hNavigation, SW_SHOWNA);
  465. }
  466. else
  467. {
  468. wchar_t titleStr[128] = {0};
  469. MessageBoxW(hwndDlg,WASABI_API_LNGSTRINGW(IDS_ONLINE_SERVICES_NOT_PRESENT),
  470. WASABI_API_LNGSTRINGW_BUF(IDS_ERROR_SWITCHING_TO_VIEW,titleStr,128),0);
  471. }
  472. return 0;
  473. }
  474. if (lowP == WINAMP_SHOWLIBRARY)
  475. {
  476. if (!g_hwnd || !IsWindowVisible(g_hwnd))
  477. toggleVisible((2 == HIWORD(wParam) ? 2 : 0));
  478. }
  479. else if (lowP == WINAMP_CLOSELIBRARY)
  480. {
  481. if (g_hwnd && IsWindowVisible(g_ownerwnd)) toggleVisible();
  482. }
  483. }
  484. break;
  485. case WM_DWMCOMPOSITIONCHANGED:
  486. if (IsWindow(g_hwnd)) PostMessageW(g_hwnd, WM_DWMCOMPOSITIONCHANGED, 0, 0L);
  487. break;
  488. }
  489. return CallWindowProcW(wa_oldWndProc, hwndDlg, uMsg, wParam, lParam);
  490. }
  491. INT_PTR CALLBACK dialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  492. BOOL init2(void)
  493. {
  494. if (!g_hwnd)
  495. {
  496. WADlg_init(plugin.hwndParent);
  497. //xp theme disabling shit
  498. m_uxdll = LoadLibraryA("uxtheme.dll");
  499. if (m_uxdll)
  500. {
  501. IsAppThemed = (BOOL (__stdcall *)(void))GetProcAddress(m_uxdll, "IsAppThemed");
  502. SetWindowTheme = (HRESULT (__stdcall *)(struct HWND__ *, LPCWSTR , LPCWSTR ))GetProcAddress(m_uxdll, "SetWindowTheme");
  503. }
  504. else
  505. {
  506. IsAppThemed = NULL;
  507. SetWindowTheme = NULL;
  508. }
  509. g_context_menus = WASABI_API_LOADMENU(IDR_CONTEXTMENUS);
  510. // 02/11/08 DrO
  511. // defaults were 100,100,500,400 and not visible but these now make it align when opened under
  512. // a clean install starting with a classic skin and is also visible on start now as with modern
  513. myWindowState.r.left = g_config->ReadInt(L"mw_xpos", 301);
  514. myWindowState.r.top = g_config->ReadInt(L"mw_ypos", 29);
  515. myWindowState.r.right = myWindowState.r.left + g_config->ReadInt(L"mw_width", 500);
  516. myWindowState.r.bottom = myWindowState.r.top + g_config->ReadInt(L"mw_height", 348);
  517. SET_EMBED_GUID((&myWindowState), library_guid);
  518. g_ownerwnd = (HWND)SendMessage(plugin.hwndParent, WM_WA_IPC, (LPARAM) & myWindowState, IPC_GET_EMBEDIF);
  519. if (!g_ownerwnd) return FALSE;
  520. if (NULL != WASABI_API_APP) WASABI_API_APP->app_registerGlobalWindow(g_ownerwnd);
  521. SetWindowTextW(g_ownerwnd, WASABI_API_LNGSTRINGW(IDS_WINAMP_LIBRARY));
  522. g_hwnd = WASABI_API_CREATEDIALOGW(IDD_MAIN, g_ownerwnd, dialogProc);
  523. if (!g_hwnd)
  524. {
  525. DestroyWindow(g_ownerwnd);
  526. g_ownerwnd = NULL;
  527. return FALSE;
  528. }
  529. }
  530. return TRUE;
  531. }
  532. wchar_t WINAMP_INI[MAX_PATH] = {0}, WINAMP_INI_DIR[MAX_PATH] = {0};
  533. MediaLibraryCOM mediaLibraryCOM;
  534. IDispatch *winampExternal = 0;
  535. void TAG_FMT_EXT(const wchar_t *filename, void *f, void *ff, void *p, wchar_t *out, int out_len, int extended)
  536. {
  537. waFormatTitleExtended fmt;
  538. fmt.filename=filename;
  539. fmt.useExtendedInfo=extended;
  540. fmt.out = out;
  541. fmt.out_len = out_len;
  542. fmt.p = p;
  543. fmt.spec = 0;
  544. *(void **)&fmt.TAGFUNC = f;
  545. *(void **)&fmt.TAGFREEFUNC = ff;
  546. *out = 0;
  547. int oldCallingGetFileInfo=m_calling_getfileinfo;
  548. m_calling_getfileinfo=1;
  549. SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&fmt, IPC_FORMAT_TITLE_EXTENDED);
  550. m_calling_getfileinfo=oldCallingGetFileInfo;
  551. }
  552. wchar_t *itemrecordTagFunc(wchar_t *tag, void * p) //return 0 if not found
  553. {
  554. itemRecord *t = (itemRecord *)p;
  555. char buf[128] = {0};
  556. char *value = NULL;
  557. if (!_wcsicmp(tag, L"artist")) value = t->artist;
  558. else if (!_wcsicmp(tag, L"album")) value = t->album;
  559. else if (!_wcsicmp(tag, L"filename")) value = t->filename;
  560. else if (!_wcsicmp(tag, L"title")) value = t->title;
  561. else if ( !_wcsicmp( tag, L"ext" ) ) value = t->ext;
  562. else if (!_wcsicmp(tag, L"year"))
  563. {
  564. if (t->year > 0)
  565. {
  566. StringCchPrintfA(buf, 128, "%04d", t->year);
  567. value = buf;
  568. }
  569. }
  570. else if (!_wcsicmp(tag, L"genre")) value = t->genre;
  571. else if (!_wcsicmp(tag, L"comment")) value = t->comment;
  572. else if (!_wcsicmp(tag, L"tracknumber") || !_wcsicmp(tag, L"track"))
  573. {
  574. if (t->track > 0)
  575. {
  576. StringCchPrintfA(buf, 128, "%02d", t->track);
  577. value = buf;
  578. }
  579. }
  580. else if (!_wcsicmp(tag, L"rating")) value = getRecordExtendedItem(t, "RATING");
  581. else if (!_wcsicmp(tag, L"playcount")) value = getRecordExtendedItem(t, "PLAYCOUNT");
  582. else if (!_wcsicmp(tag, L"bitrate")) value = getRecordExtendedItem(t, "BITRATE");
  583. else
  584. return 0;
  585. if (!value) return reinterpret_cast<wchar_t *>(-1);
  586. else return AutoWideDup(value);
  587. }
  588. wchar_t *itemrecordWTagFunc(wchar_t *tag, void * p) //return 0 if not found
  589. {
  590. itemRecordW *t = (itemRecordW *)p;
  591. wchar_t buf[128] = {0};
  592. wchar_t *value = NULL;
  593. // TODO: more fields
  594. if (!_wcsicmp(tag, L"artist")) value = t->artist;
  595. else if (!_wcsicmp(tag, L"album")) value = t->album;
  596. else if (!_wcsicmp(tag, L"albumartist")) value = t->albumartist;
  597. else if (!_wcsicmp(tag, L"category")) value = t->category;
  598. else if (!_wcsicmp(tag, L"comment")) value = t->comment;
  599. else if (!_wcsicmp(tag, L"composer")) value = t->composer;
  600. else if (!_wcsicmp(tag, L"publisher")) value = t->publisher;
  601. else if (!_wcsicmp(tag, L"filename")) value = t->filename;
  602. else if (!_wcsicmp(tag, L"title")) value = t->title;
  603. else if (!_wcsicmp(tag, L"year"))
  604. {
  605. if (t->year > 0)
  606. {
  607. StringCchPrintfW(buf, 128, L"%04d", t->year);
  608. value = buf;
  609. }
  610. }
  611. else if (!_wcsicmp(tag, L"genre")) value = t->genre;
  612. else if (!_wcsicmp(tag, L"comment")) value = t->comment;
  613. else if (!_wcsicmp(tag, L"tracknumber") || !_wcsicmp(tag, L"track"))
  614. {
  615. if (t->track > 0)
  616. {
  617. StringCchPrintfW(buf, 128, L"%02d", t->track);
  618. value = buf;
  619. }
  620. }
  621. else if (!_wcsicmp(tag, L"rating"))
  622. {
  623. if (t->rating > 0)
  624. {
  625. StringCchPrintfW(buf, 128, L"%d", t->rating);
  626. value = buf;
  627. }
  628. }
  629. else if (!_wcsicmp(tag, L"playcount"))
  630. {
  631. if (t->playcount > 0)
  632. {
  633. StringCchPrintfW(buf, 128, L"%d", t->playcount);
  634. value = buf;
  635. }
  636. }
  637. else if (!_wcsicmp(tag, L"bitrate"))
  638. {
  639. if (t->bitrate > 0)
  640. {
  641. StringCchPrintfW(buf, 128, L"%d", t->bitrate);
  642. value = buf;
  643. }
  644. }
  645. else
  646. return 0;
  647. if (!value) return reinterpret_cast<wchar_t *>(-1);
  648. else return _wcsdup(value);
  649. }
  650. void fieldTagFuncFree(wchar_t * tag, void * p)
  651. {
  652. free(tag);
  653. }
  654. void main_playItemRecordList(itemRecordList *obj, int enqueue, int startplaying)
  655. {
  656. if (obj->Size && !enqueue) SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_DELETE);
  657. int x;
  658. wchar_t title[2048]=L"";
  659. for (x = 0; x < obj->Size; x ++)
  660. {
  661. if (obj->Items[x].filename && *obj->Items[x].filename)
  662. {
  663. AutoWideFn wfn( obj->Items[ x ].filename );
  664. TAG_FMT_EXT(wfn, itemrecordTagFunc, fieldTagFuncFree, (void*)&obj->Items[x], title, 2048, 1);
  665. {
  666. enqueueFileWithMetaStructW s;
  667. s.filename = wfn;
  668. s.title = title;
  669. s.ext = NULL;
  670. s.length = obj->Items[x].length;
  671. SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&s, IPC_PLAYFILEW);
  672. }
  673. }
  674. }
  675. if (obj->Size && !enqueue && startplaying) SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_STARTPLAY);
  676. }
  677. void main_playItemRecordListW(itemRecordListW *obj, int enqueue, int startplaying)
  678. {
  679. if (obj->Size && !enqueue) SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_DELETE);
  680. int x;
  681. wchar_t title[2048]=L"";
  682. for (x = 0; x < obj->Size; x ++)
  683. {
  684. if (obj->Items[x].filename && *obj->Items[x].filename)
  685. {
  686. TAG_FMT_EXT(obj->Items[x].filename, itemrecordWTagFunc, fieldTagFuncFree, (void*)&obj->Items[x], title, 2048, 1);
  687. {
  688. enqueueFileWithMetaStructW s;
  689. s.filename = obj->Items[x].filename;
  690. s.title = title;
  691. s.ext = NULL;
  692. s.length = obj->Items[x].length;
  693. SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&s, IPC_PLAYFILEW);
  694. }
  695. }
  696. }
  697. if (obj->Size && !enqueue && startplaying) SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_STARTPLAY);
  698. }
  699. void OpenMediaLibraryPreferences()
  700. {
  701. SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&myPrefsItem, IPC_OPENPREFSTOPAGE);
  702. }
  703. int AddTreeImageBmp(int resourceId)
  704. {
  705. HMLIMGLST hmlilNavigation = MLNavCtrl_GetImageList(g_hwnd);
  706. MLIMAGESOURCE mlis = {sizeof(MLIMAGESOURCE),0};
  707. MLIMAGELISTITEM item = {0};
  708. item.cbSize = sizeof(MLIMAGELISTITEM);
  709. item.hmlil = hmlilNavigation;
  710. item.filterUID = MLIF_FILTER1_UID;
  711. item.pmlImgSource = &mlis;
  712. mlis.hInst = WASABI_API_ORIG_HINST;
  713. mlis.bpp = 24;
  714. mlis.lpszName = MAKEINTRESOURCEW(resourceId);
  715. mlis.type = SRC_TYPE_BMP;
  716. mlis.flags = ISF_FORCE_BPP;
  717. return MLImageList_Add(g_hwnd, &item);
  718. }
  719. void SkinnedScrollWnd_Init();
  720. void SkinnedScrollWnd_Quit();
  721. int init()
  722. {
  723. wchar_t g_path[MAX_PATH] = {0};
  724. QueryPerformanceFrequency(&freq);
  725. WASABI_API_SVC = (api_service*)SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GET_API_SERVICE);
  726. if (!WASABI_API_SVC || WASABI_API_SVC == (api_service *)1)
  727. return GEN_INIT_FAILURE;
  728. HTMLContainer2_Initialize();
  729. Tataki::Init(WASABI_API_SVC);
  730. // loader so that we can get the localisation service api for use
  731. ServiceBuild(WASABI_API_LNG, languageApiGUID);
  732. ServiceBuild(WASABI_API_SYSCB, syscbApiServiceGuid);
  733. ServiceBuild(AGAVE_API_DECODE, decodeFileGUID);
  734. ServiceBuild(AGAVE_API_JSAPI2_SECURITY, JSAPI2::api_securityGUID);
  735. ServiceBuild(AGAVE_OBJ_BROWSER, OBJ_OmBrowser);
  736. #ifndef IGNORE_API_GRACENOTE
  737. ServiceBuild(AGAVE_API_GRACENOTE, gracenoteApiGUID);
  738. #endif
  739. ServiceBuild(WASABI_API_APP, applicationApiServiceGuid);
  740. ServiceBuild(AGAVE_API_CONFIG, AgaveConfigGUID);
  741. ServiceBuild(WASABI_API_PALETTE, PaletteManagerGUID);
  742. ServiceBuild(AGAVE_API_THREADPOOL, ThreadPoolGUID);
  743. // no guarantee that AGAVE_API_MLDB will be available yet, so we'll start a watcher for it
  744. serviceWatcher.WatchWith(WASABI_API_SVC);
  745. serviceWatcher.WatchFor(&AGAVE_API_MLDB, mldbApiGuid);
  746. serviceWatcher.WatchFor(&WASABI_API_SKIN, skinApiServiceGuid);
  747. serviceWatcher.WatchFor(&WASABI_API_WND,wndApiServiceGuid);
  748. WASABI_API_SYSCB->syscb_registerCallback(&serviceWatcher);
  749. SkinnedScrollWnd_Init();
  750. // need to have this initialised before we try to do anything with localisation features
  751. WASABI_API_START_LANG(plugin.hDllInstance,GenMlLangGUID);
  752. // Build plugin description string...
  753. static wchar_t szDescription[256];
  754. StringCchPrintfW(szDescription, ARRAYSIZE(szDescription),
  755. WASABI_API_LNGSTRINGW(IDS_NULLSOFT_ML_STR),
  756. LOWORD(PLUGIN_VERSION) >> 8,
  757. PLUGIN_VERSION & 0xFF);
  758. plugin.description = (char*)szDescription;
  759. DispatchInfo dispatchInfo;
  760. dispatchInfo.name = L"MediaLibrary";
  761. dispatchInfo.dispatch = &mediaLibraryCOM;
  762. SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&dispatchInfo, IPC_ADD_DISPATCH_OBJECT);
  763. #ifndef IGNORE_API_GRACENOTE
  764. dispatchInfo.name = L"MusicID";
  765. dispatchInfo.dispatch = &musicIDCOM;
  766. SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&dispatchInfo, IPC_ADD_DISPATCH_OBJECT);
  767. #endif
  768. IPC_LIBRARY_SENDTOMENU = (INT)SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&"LibrarySendToMenu", IPC_REGISTER_WINAMP_IPCMESSAGE);
  769. IPC_GETMLWINDOW = (INT)SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&"LibraryGetWnd", IPC_REGISTER_WINAMP_IPCMESSAGE);
  770. IPC_GET_ML_HMENU = (INT)SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&"LibraryGetHmenu", IPC_REGISTER_WINAMP_IPCMESSAGE);
  771. lstrcpynW(WINAMP_INI, (wchar_t*)SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GETINIFILEW), MAX_PATH);
  772. lstrcpynW(WINAMP_INI_DIR, (wchar_t*)SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GETINIDIRECTORYW), MAX_PATH);
  773. PathCombineW(g_path, WINAMP_INI_DIR, L"Plugins");
  774. CreateDirectoryW(g_path, NULL);
  775. wchar_t *dir = (wchar_t*)SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GETPLUGINDIRECTORYW);
  776. if (dir == (wchar_t *)1 || dir == 0)
  777. lstrcpynW(pluginPath, g_path, MAX_PATH);
  778. else
  779. lstrcpynW(pluginPath, dir, MAX_PATH);
  780. hDragNDropCursor = LoadCursor(plugin.hDllInstance, MAKEINTRESOURCE(ML_IDC_DRAGDROP));
  781. profile = GetPrivateProfileIntW(L"winamp", L"profile", 0, WINAMP_INI);
  782. wchar_t configName[1024 + 32] = {0};
  783. StringCchPrintfW(configName, 1024 + 32, L"%s\\gen_ml.ini", g_path);
  784. g_config = new C_Config(configName);
  785. config_use_ff_scrollbars = g_config->ReadInt(L"ffsb", 1);
  786. config_use_alternate_colors = g_config->ReadInt(L"alternate_items", 1);
  787. int vis = g_config->ReadInt(L"visible", 1);
  788. wa_main_menu = (HMENU)SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_GET_HMENU);
  789. wa_windows_menu = (HMENU)SendMessage(plugin.hwndParent, WM_WA_IPC, 4, IPC_GET_HMENU);
  790. wa_playlists_cmdmenu = NULL;
  791. if (wa_main_menu || wa_windows_menu)
  792. {
  793. if (wa_main_menu)
  794. {
  795. MENUITEMINFOW i = {sizeof(i), MIIM_ID | MIIM_STATE | MIIM_TYPE, MFT_STRING, vis ? (UINT)MFS_CHECKED : 0, WA_MENUITEM_ID};
  796. int prior_item = GetMenuItemID(wa_main_menu,9);
  797. if(prior_item <= 0) prior_item = GetMenuItemID(wa_main_menu,8);
  798. i.dwTypeData = WASABI_API_LNGSTRINGW(IDS_ML_ALT_L_SHORTCUT);
  799. // append before the video menu entry (more reliable than inserting into position '9' in the menu
  800. InsertMenuItemW(wa_main_menu, prior_item, FALSE, &i);
  801. SendMessage(plugin.hwndParent, WM_WA_IPC, 1, IPC_ADJUST_OPTIONSMENUPOS);
  802. }
  803. if (wa_windows_menu)
  804. {
  805. MENUITEMINFOW i = {sizeof(i), MIIM_ID | MIIM_STATE | MIIM_TYPE, MFT_STRING, vis ? (UINT)MFS_CHECKED : 0, WA_MENUITEM_ID};
  806. int prior_item = GetMenuItemID(wa_windows_menu,3);
  807. if(prior_item <= 0) prior_item = GetMenuItemID(wa_windows_menu,2);
  808. i.dwTypeData = WASABI_API_LNGSTRINGW(IDS_ML_ALT_L_SHORTCUT);
  809. InsertMenuItemW(wa_windows_menu, prior_item, FALSE, &i);
  810. SendMessage(plugin.hwndParent, WM_WA_IPC, 1, IPC_ADJUST_FFWINDOWSMENUPOS);
  811. }
  812. }
  813. // subclass the winamp window to get our leet menu item to work
  814. wa_oldWndProc = (WNDPROC)(LONG_PTR)SetWindowLongPtrW(plugin.hwndParent, GWLP_WNDPROC, (LONGX86)(LONG_PTR)wa_newWndProc);
  815. myPrefsItem.dlgID = IDD_PREFSFR;
  816. myPrefsItem.name = WASABI_API_LNGSTRINGW_BUF(IDS_MEDIA_LIBRARY,preferencesName,128);
  817. myPrefsItem.proc = (void*)PrefsProc;
  818. myPrefsItem.hInst = WASABI_API_LNG_HINST;
  819. myPrefsItem.where = -6; // to become root based item
  820. SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&myPrefsItem, IPC_ADD_PREFS_DLGW);
  821. myPrefsItemPlug.dlgID = IDD_MLPLUGINS;
  822. myPrefsItemPlug.name = preferencesName;
  823. myPrefsItemPlug.proc = (void*)PluginsProc;
  824. myPrefsItemPlug.hInst = WASABI_API_LNG_HINST;
  825. myPrefsItemPlug.where = 1;
  826. SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&myPrefsItemPlug, IPC_ADD_PREFS_DLGW);
  827. g_PEWindow = (HWND)SendMessage(plugin.hwndParent, WM_WA_IPC, IPC_GETWND_PE, IPC_GETWND);
  828. g_safeMode = SendMessage(plugin.hwndParent, WM_WA_IPC, 0, IPC_IS_SAFEMODE);
  829. // we're gonna go ahead and make this directory just to be safe.
  830. // if a plugin tries to use it as an INI directory but it doesn't exist, things go wrong
  831. wchar_t mldir[MAX_PATH] = {0};
  832. PathCombineW(mldir, g_path, L"ml");
  833. CreateDirectoryW(mldir, NULL);
  834. PathCombineW(mldir, mldir, L"views");
  835. CreateDirectoryW(mldir, NULL);
  836. //add general hotkey
  837. int m_genhotkeys_add_ipc = (INT)SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&"GenHotkeysAdd", IPC_REGISTER_WINAMP_IPCMESSAGE);
  838. static genHotkeysAddStruct ghas = {
  839. (char*)_wcsdup(WASABI_API_LNGSTRINGW(IDS_ML_GHK_STR)),
  840. HKF_BRING_TO_FRONT|HKF_UNICODE_NAME,
  841. WM_COMMAND,
  842. WA_MENUITEM_ID,
  843. 0,
  844. // specifically set the id str now so that it'll work correctly with whatever lngpack is in use
  845. "ML: Show/Hide Media Library"
  846. };
  847. if (m_genhotkeys_add_ipc > 65536) PostMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM)&ghas, m_genhotkeys_add_ipc); //post so gen_hotkeys will catch it if not inited yet
  848. init2();
  849. // register the art view window classes
  850. {
  851. extern void InitSmoothScrollList();
  852. extern void InitHeaderIconList();
  853. InitSmoothScrollList();
  854. InitHeaderIconList();
  855. RegisterFolderBrowserControl(plugin.hDllInstance);
  856. }
  857. NavCtrlI_BeginUpdate(hNavigation, NUF_LOCK_NONE_I);
  858. loadMlPlugins();
  859. #if 0
  860. #ifdef _DEBUG
  861. #define BETA
  862. #endif
  863. #ifdef BETA
  864. sneak = GetPrivateProfileIntW(L"winamp", L"sneak", 0, WINAMP_INI);
  865. if (!(sneak & 1))
  866. {
  867. NAVINSERTSTRUCT nis = {0};
  868. nis.item.cbSize = sizeof(NAVITEM);
  869. nis.item.pszText = L"Winamp Labs";
  870. nis.item.pszInvariant = L"winamp_labs";
  871. nis.item.mask = NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_IMAGE | NIMF_IMAGESEL | NIMF_STYLE;
  872. nis.item.iImage = nis.item.iSelectedImage = AddTreeImageBmp(IDB_TREEITEM_LABS);
  873. nis.item.style = NIS_BOLD;
  874. nis.hInsertAfter = NCI_FIRST;
  875. NAVITEM nvItem = {sizeof(NAVITEM),0,NIMF_ITEMID,};
  876. nvItem.hItem = MLNavCtrl_InsertItem(g_hwnd, &nis);
  877. }
  878. #endif
  879. #endif
  880. NavCtrlI_EndUpdate(hNavigation);
  881. if (SW_SHOWMINIMIZED == SENDWAIPC(plugin.hwndParent, IPC_INITIAL_SHOW_STATE, 0))
  882. {
  883. MlWindow_SetMinimizedMode(TRUE);
  884. }
  885. else if (0 != vis)
  886. {
  887. PostMessageW(plugin.hwndParent, WM_COMMAND, MAKEWPARAM(WINAMP_SHOWLIBRARY, 2), 0L);
  888. }
  889. return GEN_INIT_SUCCESS;
  890. }
  891. void quit()
  892. {
  893. serviceWatcher.StopWatching();
  894. serviceWatcher.Clear();
  895. MlWindow_SetMinimizedMode(FALSE);
  896. if (g_ownerwnd)
  897. {
  898. g_config->WriteInt(L"mw_xpos", myWindowState.r.left);
  899. g_config->WriteInt(L"mw_ypos", myWindowState.r.top);
  900. g_config->WriteInt(L"mw_width", myWindowState.r.right - myWindowState.r.left);
  901. g_config->WriteInt(L"mw_height", myWindowState.r.bottom - myWindowState.r.top);
  902. if (NULL != WASABI_API_APP) WASABI_API_APP->app_unregisterGlobalWindow(g_ownerwnd);
  903. DestroyWindow(g_ownerwnd);
  904. g_ownerwnd = NULL;
  905. }
  906. // unload any services from ml_ plugins before unloading the plugins
  907. ServiceRelease(AGAVE_API_MLDB, mldbApiGuid);
  908. #ifndef IGNORE_API_GRACENOTE
  909. musicIDCOM.Quit();
  910. #endif
  911. unloadMlPlugins();
  912. WADlg_close();
  913. if (g_config)
  914. {
  915. delete g_config;
  916. g_config = NULL;
  917. }
  918. if (m_uxdll)
  919. {
  920. FreeLibrary(m_uxdll);
  921. m_uxdll = NULL;
  922. }
  923. SkinnedScrollWnd_Quit();
  924. #ifndef IGNORE_API_GRACENOTE
  925. ServiceRelease(AGAVE_API_GRACENOTE, gracenoteApiGUID);
  926. #endif
  927. ServiceRelease(WASABI_API_SYSCB, syscbApiServiceGuid);
  928. ServiceRelease(AGAVE_API_DECODE, decodeFileGUID);
  929. ServiceRelease(AGAVE_API_JSAPI2_SECURITY, JSAPI2::api_securityGUID);
  930. ServiceRelease(AGAVE_OBJ_BROWSER, OBJ_OmBrowser);
  931. ServiceRelease(WASABI_API_LNG, languageApiGUID);
  932. ServiceRelease(WASABI_API_WND, wndApiServiceGuid);
  933. ServiceRelease(WASABI_API_SKIN, skinApiServiceGuid);
  934. ServiceRelease(WASABI_API_APP, applicationApiServiceGuid);
  935. ServiceRelease(AGAVE_API_CONFIG, AgaveConfigGUID);
  936. ServiceRelease(WASABI_API_PALETTE, PaletteManagerGUID);
  937. Tataki::Quit();
  938. HTMLContainer2_Uninitialize();
  939. ServiceRelease(AGAVE_API_THREADPOOL, ThreadPoolGUID);
  940. }
  941. void config()
  942. {
  943. OpenMediaLibraryPreferences();
  944. }
  945. INT MediaLibrary_TrackPopupEx(HMENU hMenu, UINT fuFlags, INT x, INT y, HWND hwnd, LPTPMPARAMS lptpm, HMLIMGLST hmlil,
  946. INT width, UINT skinStyle, MENUCUSTOMIZEPROC customProc, ULONG_PTR customParam)
  947. {
  948. if (NULL == hMenu)
  949. return NULL;
  950. return IsSkinnedPopupEnabled(FALSE) ?
  951. TrackSkinnedPopupMenuEx(hMenu, fuFlags, x, y, hwnd, lptpm, hmlil, width, skinStyle, customProc, customParam) :
  952. TrackPopupMenuEx(hMenu, fuFlags, x, y, hwnd, lptpm);
  953. }
  954. INT MediaLibrary_TrackPopup(HMENU hMenu, UINT fuFlags, INT x, INT y, HWND hwnd)
  955. {
  956. return MediaLibrary_TrackPopupEx(hMenu, fuFlags, x, y, hwnd, NULL, NULL, 0, SMS_USESKINFONT, NULL, NULL);
  957. }
  958. HANDLE MediaLibrary_InitSkinnedPopupHook(HWND hwnd, HMLIMGLST hmlil, INT width, UINT skinStyle, MENUCUSTOMIZEPROC customProc, ULONG_PTR customParam)
  959. {
  960. if (FALSE == IsSkinnedPopupEnabled(FALSE))
  961. return FALSE;
  962. return InitSkinnedPopupHook(hwnd, hmlil, width, skinStyle, customProc, customParam);
  963. }
  964. BOOL
  965. MediaLibrary_OpenUrl(HWND ownerWindow, const wchar_t *url, BOOL forceExternal)
  966. {
  967. BOOL result;
  968. HCURSOR cursor;
  969. cursor = LoadCursor(NULL, IDC_APPSTARTING);
  970. if (NULL != cursor)
  971. cursor = SetCursor(cursor);
  972. if (FALSE != forceExternal)
  973. {
  974. HINSTANCE instance;
  975. if (NULL == ownerWindow)
  976. ownerWindow = (HWND)SENDWAIPC(plugin.hwndParent, IPC_GETDIALOGBOXPARENT, 0);
  977. instance = ShellExecuteW(ownerWindow, L"open", url, NULL, NULL, SW_SHOWNORMAL);
  978. result = ((INT_PTR)instance > 32) ? TRUE: FALSE;
  979. }
  980. else
  981. {
  982. SENDWAIPC(plugin.hwndParent, IPC_OPEN_URL, url);
  983. result = TRUE;
  984. }
  985. if (NULL != cursor)
  986. SetCursor(cursor);
  987. return result;
  988. }
  989. BOOL
  990. MediaLibrary_OpenHelpUrl(const wchar_t *helpUrl)
  991. {
  992. HWND ownerWindow;
  993. ownerWindow = (HWND)SENDWAIPC(plugin.hwndParent, IPC_GETDIALOGBOXPARENT, 0);
  994. return MediaLibrary_OpenUrl(ownerWindow, helpUrl, FALSE);
  995. }
  996. extern "C"
  997. {
  998. int getFileInfo(const char *filename, const char *metadata, char *dest, int len)
  999. {
  1000. m_calling_getfileinfo = 1;
  1001. dest[0] = 0;
  1002. extendedFileInfoStruct efis = {
  1003. filename,
  1004. metadata,
  1005. dest,
  1006. (size_t)len,
  1007. };
  1008. int r = (INT)SendMessage(plugin.hwndParent, WM_WA_IPC, (WPARAM) & efis, IPC_GET_EXTENDED_FILE_INFO); //will return 1 if wa2 supports this IPC call
  1009. m_calling_getfileinfo = 0;
  1010. return r;
  1011. }
  1012. __declspec(dllexport) winampGeneralPurposePlugin *winampGetGeneralPurposePlugin()
  1013. {
  1014. return &plugin;
  1015. }
  1016. };