mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-12-29 18:16:06 +00:00
368 lines
8.4 KiB
C++
368 lines
8.4 KiB
C++
|
#include "Main.h"
|
||
|
#include "Browser.h"
|
||
|
#include "menuv5.h"
|
||
|
#include "ExternalCOM.h"
|
||
|
#include "wa_dlg.h"
|
||
|
#include "resource.h"
|
||
|
#include "../nu/ns_wc.h"
|
||
|
|
||
|
Browser *browser = 0;
|
||
|
static WNDPROC oldBrowserProc = 0;
|
||
|
static DWORD browserThreadId=0;
|
||
|
static HANDLE killBrowserEvent=0;
|
||
|
static HANDLE browserThreadHandle=0;
|
||
|
static BOOL fUnicode = FALSE;
|
||
|
static LRESULT WINAPI BrowserSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
switch (msg)
|
||
|
{
|
||
|
case WM_PAINT:
|
||
|
{
|
||
|
HDC out = GetDC(hwnd);
|
||
|
RECT r;
|
||
|
GetClientRect(hwnd, &r);
|
||
|
r.left = 11;
|
||
|
r.top = 20;
|
||
|
r.right -= 8;
|
||
|
r.bottom -= 14;
|
||
|
|
||
|
HBRUSH b = CreateSolidBrush(WADlg_getColor(WADLG_WNDBG));
|
||
|
FillRect(out, &r, b);
|
||
|
DeleteObject(b);
|
||
|
ValidateRect(hwnd, &r);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_USER + 0x100:
|
||
|
if (wParam == 1 && lParam)
|
||
|
{
|
||
|
config_si_wx = ((POINT *)lParam)->x;
|
||
|
config_si_wy = ((POINT *)lParam)->y;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_USER + 0x101:
|
||
|
if (wParam == 1 && lParam)
|
||
|
{
|
||
|
config_si_width = ((POINT *)lParam)->x;
|
||
|
config_si_height = ((POINT *)lParam)->y;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_USER + 0x102:
|
||
|
{
|
||
|
if (wParam == 1)
|
||
|
{
|
||
|
if (!config_minimized)
|
||
|
ShowWindow(browser->m_hwnd, SW_SHOW);
|
||
|
config_si_open = 1;
|
||
|
const char *url = PlayList_getbrowser(PlayList_getPosition());
|
||
|
if (url && *url)
|
||
|
browser->NavigateToName(url);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ShowWindow(browser->m_hwnd, SW_HIDE);
|
||
|
config_si_open = 0;
|
||
|
}
|
||
|
browser->SetMenuCheckMark();
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_USER + 101:
|
||
|
{
|
||
|
ShowWindow(hwnd, SW_HIDE);
|
||
|
ShowWindow(browser->m_hwnd, SW_HIDE);
|
||
|
config_si_open = 0;
|
||
|
browser->SetMenuCheckMark();
|
||
|
return 0;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
browser->m_hwnd = 0;
|
||
|
SetEvent(killBrowserEvent);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if (oldBrowserProc) return (fUnicode) ? CallWindowProcW(oldBrowserProc, hwnd, msg, wParam, lParam) : CallWindowProcA(oldBrowserProc, hwnd, msg, wParam, lParam);
|
||
|
else return (fUnicode) ? DefWindowProcW(hwnd, msg, wParam, lParam) : DefWindowProcA(hwnd, msg, wParam, lParam);
|
||
|
}
|
||
|
// {25CE50EF-3EE2-4356-A638-6E495C44BFB8}
|
||
|
static const GUID StationInfoGUID =
|
||
|
{ 0x25ce50ef, 0x3ee2, 0x4356, { 0xa6, 0x38, 0x6e, 0x49, 0x5c, 0x44, 0xbf, 0xb8 } };
|
||
|
|
||
|
Browser::Browser()
|
||
|
: minimised(false), threadId(0), state(0)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
Browser::~Browser()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
HWND Browser::CreateHWND()
|
||
|
{
|
||
|
if (!m_hwnd)
|
||
|
{
|
||
|
threadId = GetCurrentThreadId();
|
||
|
|
||
|
state.flags = EMBED_FLAGS_NOWINDOWMENU;
|
||
|
state.me = 0;
|
||
|
state.r.left = config_si_wx;
|
||
|
state.r.right = config_si_wx + config_si_width;
|
||
|
state.r.top = config_si_wy;
|
||
|
state.r.bottom = config_si_wy + config_si_height;
|
||
|
|
||
|
state.flags |= EMBED_FLAGS_GUID;
|
||
|
void *blah = state.extra_data+4;
|
||
|
memcpy(blah, &StationInfoGUID, sizeof(GUID));
|
||
|
|
||
|
HWND owner = (HWND)SendMessage(hMainWindow, WM_WA_IPC, (WPARAM)&state, IPC_GET_EMBEDIF);
|
||
|
|
||
|
m_hwnd = owner;
|
||
|
setLocation(11, 20, config_si_width - 19, config_si_height - 34);
|
||
|
fUnicode = IsWindowUnicode(owner);
|
||
|
oldBrowserProc = (WNDPROC) ((fUnicode) ? SetWindowLongPtrW(owner, GWLP_WNDPROC, (LONG_PTR)BrowserSubclassProc) :
|
||
|
SetWindowLongPtrA(owner, GWLP_WNDPROC, (LONG_PTR)BrowserSubclassProc));
|
||
|
wchar_t langBuf[1024];
|
||
|
SetWindowTextW(owner, getStringW(IDS_STATIONINFOCAPTION, langBuf, 1024));
|
||
|
}
|
||
|
EnableMenuItem(main_menu, WINAMP_BROWSER_ID, MF_BYCOMMAND | MF_ENABLED);
|
||
|
|
||
|
if (config_si_autoshow || (config_si_open/* && !visible*/))
|
||
|
{
|
||
|
if(g_showcode!=SW_SHOWMINIMIZED && !config_minimized)
|
||
|
ShowWindow(m_hwnd, SW_SHOW);
|
||
|
else
|
||
|
browser->minimised = 1;
|
||
|
config_si_open = 1;
|
||
|
browser->SetMenuCheckMark();
|
||
|
}
|
||
|
|
||
|
return m_hwnd;
|
||
|
}
|
||
|
|
||
|
// ---------------------------------------------------------------
|
||
|
void Browser::NavigateToName(LPCTSTR pszUrl)
|
||
|
{
|
||
|
if (!config_si_open)
|
||
|
return ;
|
||
|
if (!m_pweb) return ;
|
||
|
DWORD dwChars = lstrlen (pszUrl) + 1;
|
||
|
LPWSTR pwszUrl = (LPWSTR)LocalAlloc (LPTR, dwChars * sizeof (WCHAR));
|
||
|
long moptions = navNoReadFromCache | navNoWriteToCache | navNoHistory;
|
||
|
VARIANT options;
|
||
|
memset( (void*)&options, 0, sizeof(VARIANT));
|
||
|
V_VT(&options) = VT_I4;
|
||
|
V_I4(&options) = moptions;
|
||
|
if (pwszUrl)
|
||
|
{
|
||
|
MultiByteToWideCharSZ(CP_ACP, 0, pszUrl, -1, pwszUrl, dwChars);
|
||
|
m_pweb->Navigate (pwszUrl, &options , 0, 0, 0);
|
||
|
LocalFree (pwszUrl);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define VIDEO_GENFF_SIZEREQUEST (WM_USER+2048)
|
||
|
void Browser::Resized(unsigned long width, unsigned long height)
|
||
|
{
|
||
|
if (!config_si_autosize)
|
||
|
return ;
|
||
|
setLocation(11, 20, width, height);
|
||
|
config_si_width = width + 19;
|
||
|
config_si_height = height + 34;
|
||
|
if (GetParent(m_hwnd))
|
||
|
SendMessage(GetParent(m_hwnd), VIDEO_GENFF_SIZEREQUEST, width, height);
|
||
|
else
|
||
|
SetWindowPos(m_hwnd, 0, 0, 0, width + 19, height + 34, SWP_NOMOVE | SWP_ASYNCWINDOWPOS);
|
||
|
|
||
|
InvalidateRect(m_hwnd, NULL, TRUE);
|
||
|
}
|
||
|
|
||
|
HRESULT Browser::GetExternal(IDispatch __RPC_FAR *__RPC_FAR *ppDispatch)
|
||
|
{
|
||
|
*ppDispatch = (IDispatch *) & externalCOM;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
void Browser::ToggleVisible(int showing)
|
||
|
{
|
||
|
if ((!config_si_open && !showing) || (showing && minimised))
|
||
|
{
|
||
|
if(minimised) minimised = 0;
|
||
|
CreateHWND();
|
||
|
if (m_hwnd)
|
||
|
PostMessage(m_hwnd, WM_USER + 0x102, 1, 0);
|
||
|
}
|
||
|
else if(!showing)
|
||
|
{
|
||
|
if(minimised) minimised = 0;
|
||
|
if (m_hwnd)
|
||
|
PostMessage(m_hwnd, WM_USER + 0x102, 0, 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Browser::OnNavigateComplete()
|
||
|
{
|
||
|
setVisible(TRUE);
|
||
|
RECT r;
|
||
|
GetClientRect(m_hwnd, &r);
|
||
|
setLocation(11, 20, r.right - 19, r.bottom - 34);
|
||
|
}
|
||
|
|
||
|
void Browser::SetMenuCheckMark()
|
||
|
{
|
||
|
MENUITEMINFO i = {sizeof(i), MIIM_STATE , MFT_STRING, config_si_open ? MFS_CHECKED : MFS_UNCHECKED, WINAMP_BROWSER_ID};
|
||
|
SetMenuItemInfo(main_menu, WINAMP_BROWSER_ID, FALSE, &i);
|
||
|
}
|
||
|
|
||
|
/* ---- APCs ---- */
|
||
|
VOID CALLBACK ToggleVisibleAPC(ULONG_PTR param)
|
||
|
{
|
||
|
browser->ToggleVisible(param);
|
||
|
}
|
||
|
|
||
|
VOID CALLBACK SetVisibleAPC(ULONG_PTR param)
|
||
|
{
|
||
|
BOOL visible = (BOOL)param;
|
||
|
browser->setVisible(visible);
|
||
|
}
|
||
|
|
||
|
VOID CALLBACK NavigateAPC(ULONG_PTR param)
|
||
|
{
|
||
|
char *url = (char *)param;
|
||
|
browser->NavigateToName(url);
|
||
|
free(url);
|
||
|
}
|
||
|
|
||
|
VOID CALLBACK CreateHWNDAPC(ULONG_PTR param)
|
||
|
{
|
||
|
browser->CreateHWND();
|
||
|
}
|
||
|
|
||
|
HANDLE browserEvent=0;
|
||
|
/* ---- ---- */
|
||
|
static DWORD CALLBACK BrowserThread(LPVOID param)
|
||
|
{
|
||
|
if (!browser)
|
||
|
browser = new Browser;
|
||
|
killBrowserEvent = CreateEvent(0, TRUE, FALSE, 0);
|
||
|
SetEvent(browserEvent);
|
||
|
|
||
|
while (1)
|
||
|
{
|
||
|
DWORD dwStatus = MsgWaitForMultipleObjectsEx(1, &killBrowserEvent,
|
||
|
INFINITE, QS_ALLINPUT,
|
||
|
MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
|
||
|
if (dwStatus == WAIT_OBJECT_0)
|
||
|
{
|
||
|
browser->remove();
|
||
|
browser->close();
|
||
|
browser->Release();
|
||
|
CloseHandle(killBrowserEvent);
|
||
|
return 0;
|
||
|
}
|
||
|
else if (dwStatus == WAIT_OBJECT_0 + 1)
|
||
|
{
|
||
|
MSG msg;
|
||
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
||
|
{
|
||
|
if (msg.message == WM_QUIT)
|
||
|
{
|
||
|
browser->remove();
|
||
|
browser->close();
|
||
|
browser->Release();
|
||
|
CloseHandle(killBrowserEvent);
|
||
|
return 0;
|
||
|
}
|
||
|
if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN ||
|
||
|
msg.message == WM_KEYUP || msg.message == WM_SYSKEYUP)
|
||
|
{
|
||
|
if (!browser->translateKey(&msg))
|
||
|
{
|
||
|
PostMessage(hMainWindow, msg.message, msg.wParam, msg.lParam);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!browser->translateKey(&msg))
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void CreateBrowser()
|
||
|
{
|
||
|
if (!browser)
|
||
|
{
|
||
|
browserEvent = CreateEvent(0, TRUE, FALSE, 0);
|
||
|
browserThreadHandle = CreateThread(0, 0, BrowserThread, 0, 0, &browserThreadId);
|
||
|
WaitForSingleObject(browserEvent, INFINITE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void CallAPC(PAPCFUNC func, ULONG_PTR param)
|
||
|
{
|
||
|
if (browserThreadHandle)
|
||
|
{
|
||
|
DWORD curThreadId = GetCurrentThreadId();
|
||
|
if (curThreadId == browserThreadId)
|
||
|
func(param);
|
||
|
else
|
||
|
{
|
||
|
QueueUserAPC(func, browserThreadHandle, param);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Browser_toggleVisible(int showing)
|
||
|
{
|
||
|
CreateBrowser();
|
||
|
CallAPC(ToggleVisibleAPC, showing);
|
||
|
}
|
||
|
|
||
|
void CloseBrowser()
|
||
|
{
|
||
|
if (!browser || !browser->m_hwnd)
|
||
|
return ;
|
||
|
if (config_si_autohide)
|
||
|
PostMessage(browser->m_hwnd, WM_USER + 0x102, 0, 0);
|
||
|
else
|
||
|
CallAPC(SetVisibleAPC, FALSE);
|
||
|
}
|
||
|
|
||
|
void LaunchBrowser(const char *url)
|
||
|
{
|
||
|
OpenBrowser();
|
||
|
CallAPC(NavigateAPC, (ULONG_PTR)_strdup(url));
|
||
|
}
|
||
|
|
||
|
void OpenBrowser()
|
||
|
{
|
||
|
CreateBrowser();
|
||
|
CallAPC(CreateHWNDAPC, 0);
|
||
|
}
|
||
|
|
||
|
void Browser_init()
|
||
|
{
|
||
|
MENUITEMINFO i = {sizeof(i), MIIM_ID | MIIM_STATE | MIIM_TYPE, MFT_STRING, MFS_UNCHECKED, WINAMP_BROWSER_ID};
|
||
|
i.dwTypeData = getString(IDS_STATIONINFO_MENU,NULL,0);;
|
||
|
InsertMenuItem(main_menu, 10 + g_mm_optionsbase_adj, TRUE, &i);
|
||
|
g_mm_optionsbase_adj++;
|
||
|
}
|
||
|
|
||
|
void Browser_kill()
|
||
|
{
|
||
|
if (browserThreadHandle)
|
||
|
{
|
||
|
SetEvent(killBrowserEvent); // just in case, so we don't hang here
|
||
|
WaitForSingleObject(browserThreadHandle, INFINITE);
|
||
|
CloseHandle(browserThreadHandle);
|
||
|
browserThreadHandle=0;
|
||
|
}
|
||
|
}
|