Browser.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. #include "Main.h"
  2. #include "Browser.h"
  3. #include "menuv5.h"
  4. #include "ExternalCOM.h"
  5. #include "wa_dlg.h"
  6. #include "resource.h"
  7. #include "../nu/ns_wc.h"
  8. Browser *browser = 0;
  9. static WNDPROC oldBrowserProc = 0;
  10. static DWORD browserThreadId=0;
  11. static HANDLE killBrowserEvent=0;
  12. static HANDLE browserThreadHandle=0;
  13. static BOOL fUnicode = FALSE;
  14. static LRESULT WINAPI BrowserSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  15. {
  16. switch (msg)
  17. {
  18. case WM_PAINT:
  19. {
  20. HDC out = GetDC(hwnd);
  21. RECT r;
  22. GetClientRect(hwnd, &r);
  23. r.left = 11;
  24. r.top = 20;
  25. r.right -= 8;
  26. r.bottom -= 14;
  27. HBRUSH b = CreateSolidBrush(WADlg_getColor(WADLG_WNDBG));
  28. FillRect(out, &r, b);
  29. DeleteObject(b);
  30. ValidateRect(hwnd, &r);
  31. }
  32. break;
  33. case WM_USER + 0x100:
  34. if (wParam == 1 && lParam)
  35. {
  36. config_si_wx = ((POINT *)lParam)->x;
  37. config_si_wy = ((POINT *)lParam)->y;
  38. }
  39. break;
  40. case WM_USER + 0x101:
  41. if (wParam == 1 && lParam)
  42. {
  43. config_si_width = ((POINT *)lParam)->x;
  44. config_si_height = ((POINT *)lParam)->y;
  45. }
  46. break;
  47. case WM_USER + 0x102:
  48. {
  49. if (wParam == 1)
  50. {
  51. if (!config_minimized)
  52. ShowWindow(browser->m_hwnd, SW_SHOW);
  53. config_si_open = 1;
  54. const char *url = PlayList_getbrowser(PlayList_getPosition());
  55. if (url && *url)
  56. browser->NavigateToName(url);
  57. }
  58. else
  59. {
  60. ShowWindow(browser->m_hwnd, SW_HIDE);
  61. config_si_open = 0;
  62. }
  63. browser->SetMenuCheckMark();
  64. }
  65. break;
  66. case WM_USER + 101:
  67. {
  68. ShowWindow(hwnd, SW_HIDE);
  69. ShowWindow(browser->m_hwnd, SW_HIDE);
  70. config_si_open = 0;
  71. browser->SetMenuCheckMark();
  72. return 0;
  73. }
  74. break;
  75. case WM_DESTROY:
  76. browser->m_hwnd = 0;
  77. SetEvent(killBrowserEvent);
  78. return 0;
  79. }
  80. if (oldBrowserProc) return (fUnicode) ? CallWindowProcW(oldBrowserProc, hwnd, msg, wParam, lParam) : CallWindowProcA(oldBrowserProc, hwnd, msg, wParam, lParam);
  81. else return (fUnicode) ? DefWindowProcW(hwnd, msg, wParam, lParam) : DefWindowProcA(hwnd, msg, wParam, lParam);
  82. }
  83. // {25CE50EF-3EE2-4356-A638-6E495C44BFB8}
  84. static const GUID StationInfoGUID =
  85. { 0x25ce50ef, 0x3ee2, 0x4356, { 0xa6, 0x38, 0x6e, 0x49, 0x5c, 0x44, 0xbf, 0xb8 } };
  86. Browser::Browser()
  87. : minimised(false), threadId(0), state(0)
  88. {
  89. }
  90. Browser::~Browser()
  91. {
  92. }
  93. HWND Browser::CreateHWND()
  94. {
  95. if (!m_hwnd)
  96. {
  97. threadId = GetCurrentThreadId();
  98. state.flags = EMBED_FLAGS_NOWINDOWMENU;
  99. state.me = 0;
  100. state.r.left = config_si_wx;
  101. state.r.right = config_si_wx + config_si_width;
  102. state.r.top = config_si_wy;
  103. state.r.bottom = config_si_wy + config_si_height;
  104. state.flags |= EMBED_FLAGS_GUID;
  105. void *blah = state.extra_data+4;
  106. memcpy(blah, &StationInfoGUID, sizeof(GUID));
  107. HWND owner = (HWND)SendMessage(hMainWindow, WM_WA_IPC, (WPARAM)&state, IPC_GET_EMBEDIF);
  108. m_hwnd = owner;
  109. setLocation(11, 20, config_si_width - 19, config_si_height - 34);
  110. fUnicode = IsWindowUnicode(owner);
  111. oldBrowserProc = (WNDPROC) ((fUnicode) ? SetWindowLongPtrW(owner, GWLP_WNDPROC, (LONG_PTR)BrowserSubclassProc) :
  112. SetWindowLongPtrA(owner, GWLP_WNDPROC, (LONG_PTR)BrowserSubclassProc));
  113. wchar_t langBuf[1024];
  114. SetWindowTextW(owner, getStringW(IDS_STATIONINFOCAPTION, langBuf, 1024));
  115. }
  116. EnableMenuItem(main_menu, WINAMP_BROWSER_ID, MF_BYCOMMAND | MF_ENABLED);
  117. if (config_si_autoshow || (config_si_open/* && !visible*/))
  118. {
  119. if(g_showcode!=SW_SHOWMINIMIZED && !config_minimized)
  120. ShowWindow(m_hwnd, SW_SHOW);
  121. else
  122. browser->minimised = 1;
  123. config_si_open = 1;
  124. browser->SetMenuCheckMark();
  125. }
  126. return m_hwnd;
  127. }
  128. // ---------------------------------------------------------------
  129. void Browser::NavigateToName(LPCTSTR pszUrl)
  130. {
  131. if (!config_si_open)
  132. return ;
  133. if (!m_pweb) return ;
  134. DWORD dwChars = lstrlen (pszUrl) + 1;
  135. LPWSTR pwszUrl = (LPWSTR)LocalAlloc (LPTR, dwChars * sizeof (WCHAR));
  136. long moptions = navNoReadFromCache | navNoWriteToCache | navNoHistory;
  137. VARIANT options;
  138. memset( (void*)&options, 0, sizeof(VARIANT));
  139. V_VT(&options) = VT_I4;
  140. V_I4(&options) = moptions;
  141. if (pwszUrl)
  142. {
  143. MultiByteToWideCharSZ(CP_ACP, 0, pszUrl, -1, pwszUrl, dwChars);
  144. m_pweb->Navigate (pwszUrl, &options , 0, 0, 0);
  145. LocalFree (pwszUrl);
  146. }
  147. }
  148. #define VIDEO_GENFF_SIZEREQUEST (WM_USER+2048)
  149. void Browser::Resized(unsigned long width, unsigned long height)
  150. {
  151. if (!config_si_autosize)
  152. return ;
  153. setLocation(11, 20, width, height);
  154. config_si_width = width + 19;
  155. config_si_height = height + 34;
  156. if (GetParent(m_hwnd))
  157. SendMessage(GetParent(m_hwnd), VIDEO_GENFF_SIZEREQUEST, width, height);
  158. else
  159. SetWindowPos(m_hwnd, 0, 0, 0, width + 19, height + 34, SWP_NOMOVE | SWP_ASYNCWINDOWPOS);
  160. InvalidateRect(m_hwnd, NULL, TRUE);
  161. }
  162. HRESULT Browser::GetExternal(IDispatch __RPC_FAR *__RPC_FAR *ppDispatch)
  163. {
  164. *ppDispatch = (IDispatch *) & externalCOM;
  165. return S_OK;
  166. }
  167. void Browser::ToggleVisible(int showing)
  168. {
  169. if ((!config_si_open && !showing) || (showing && minimised))
  170. {
  171. if(minimised) minimised = 0;
  172. CreateHWND();
  173. if (m_hwnd)
  174. PostMessage(m_hwnd, WM_USER + 0x102, 1, 0);
  175. }
  176. else if(!showing)
  177. {
  178. if(minimised) minimised = 0;
  179. if (m_hwnd)
  180. PostMessage(m_hwnd, WM_USER + 0x102, 0, 0);
  181. }
  182. }
  183. void Browser::OnNavigateComplete()
  184. {
  185. setVisible(TRUE);
  186. RECT r;
  187. GetClientRect(m_hwnd, &r);
  188. setLocation(11, 20, r.right - 19, r.bottom - 34);
  189. }
  190. void Browser::SetMenuCheckMark()
  191. {
  192. MENUITEMINFO i = {sizeof(i), MIIM_STATE , MFT_STRING, config_si_open ? MFS_CHECKED : MFS_UNCHECKED, WINAMP_BROWSER_ID};
  193. SetMenuItemInfo(main_menu, WINAMP_BROWSER_ID, FALSE, &i);
  194. }
  195. /* ---- APCs ---- */
  196. VOID CALLBACK ToggleVisibleAPC(ULONG_PTR param)
  197. {
  198. browser->ToggleVisible(param);
  199. }
  200. VOID CALLBACK SetVisibleAPC(ULONG_PTR param)
  201. {
  202. BOOL visible = (BOOL)param;
  203. browser->setVisible(visible);
  204. }
  205. VOID CALLBACK NavigateAPC(ULONG_PTR param)
  206. {
  207. char *url = (char *)param;
  208. browser->NavigateToName(url);
  209. free(url);
  210. }
  211. VOID CALLBACK CreateHWNDAPC(ULONG_PTR param)
  212. {
  213. browser->CreateHWND();
  214. }
  215. HANDLE browserEvent=0;
  216. /* ---- ---- */
  217. static DWORD CALLBACK BrowserThread(LPVOID param)
  218. {
  219. if (!browser)
  220. browser = new Browser;
  221. killBrowserEvent = CreateEvent(0, TRUE, FALSE, 0);
  222. SetEvent(browserEvent);
  223. while (1)
  224. {
  225. DWORD dwStatus = MsgWaitForMultipleObjectsEx(1, &killBrowserEvent,
  226. INFINITE, QS_ALLINPUT,
  227. MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
  228. if (dwStatus == WAIT_OBJECT_0)
  229. {
  230. browser->remove();
  231. browser->close();
  232. browser->Release();
  233. CloseHandle(killBrowserEvent);
  234. return 0;
  235. }
  236. else if (dwStatus == WAIT_OBJECT_0 + 1)
  237. {
  238. MSG msg;
  239. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  240. {
  241. if (msg.message == WM_QUIT)
  242. {
  243. browser->remove();
  244. browser->close();
  245. browser->Release();
  246. CloseHandle(killBrowserEvent);
  247. return 0;
  248. }
  249. if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN ||
  250. msg.message == WM_KEYUP || msg.message == WM_SYSKEYUP)
  251. {
  252. if (!browser->translateKey(&msg))
  253. {
  254. PostMessage(hMainWindow, msg.message, msg.wParam, msg.lParam);
  255. }
  256. }
  257. else
  258. {
  259. if (!browser->translateKey(&msg))
  260. TranslateMessage(&msg);
  261. DispatchMessage(&msg);
  262. }
  263. }
  264. }
  265. }
  266. return 0;
  267. }
  268. static void CreateBrowser()
  269. {
  270. if (!browser)
  271. {
  272. browserEvent = CreateEvent(0, TRUE, FALSE, 0);
  273. browserThreadHandle = CreateThread(0, 0, BrowserThread, 0, 0, &browserThreadId);
  274. WaitForSingleObject(browserEvent, INFINITE);
  275. }
  276. }
  277. static void CallAPC(PAPCFUNC func, ULONG_PTR param)
  278. {
  279. if (browserThreadHandle)
  280. {
  281. DWORD curThreadId = GetCurrentThreadId();
  282. if (curThreadId == browserThreadId)
  283. func(param);
  284. else
  285. {
  286. QueueUserAPC(func, browserThreadHandle, param);
  287. }
  288. }
  289. }
  290. void Browser_toggleVisible(int showing)
  291. {
  292. CreateBrowser();
  293. CallAPC(ToggleVisibleAPC, showing);
  294. }
  295. void CloseBrowser()
  296. {
  297. if (!browser || !browser->m_hwnd)
  298. return ;
  299. if (config_si_autohide)
  300. PostMessage(browser->m_hwnd, WM_USER + 0x102, 0, 0);
  301. else
  302. CallAPC(SetVisibleAPC, FALSE);
  303. }
  304. void LaunchBrowser(const char *url)
  305. {
  306. OpenBrowser();
  307. CallAPC(NavigateAPC, (ULONG_PTR)_strdup(url));
  308. }
  309. void OpenBrowser()
  310. {
  311. CreateBrowser();
  312. CallAPC(CreateHWNDAPC, 0);
  313. }
  314. void Browser_init()
  315. {
  316. MENUITEMINFO i = {sizeof(i), MIIM_ID | MIIM_STATE | MIIM_TYPE, MFT_STRING, MFS_UNCHECKED, WINAMP_BROWSER_ID};
  317. i.dwTypeData = getString(IDS_STATIONINFO_MENU,NULL,0);;
  318. InsertMenuItem(main_menu, 10 + g_mm_optionsbase_adj, TRUE, &i);
  319. g_mm_optionsbase_adj++;
  320. }
  321. void Browser_kill()
  322. {
  323. if (browserThreadHandle)
  324. {
  325. SetEvent(killBrowserEvent); // just in case, so we don't hang here
  326. WaitForSingleObject(browserThreadHandle, INFINITE);
  327. CloseHandle(browserThreadHandle);
  328. browserThreadHandle=0;
  329. }
  330. }