diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/Winamp/VideoOutput.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/Winamp/VideoOutput.cpp')
-rw-r--r-- | Src/Winamp/VideoOutput.cpp | 1040 |
1 files changed, 1040 insertions, 0 deletions
diff --git a/Src/Winamp/VideoOutput.cpp b/Src/Winamp/VideoOutput.cpp new file mode 100644 index 00000000..9dac1c52 --- /dev/null +++ b/Src/Winamp/VideoOutput.cpp @@ -0,0 +1,1040 @@ +#include <windowsx.h> + +#include "main.h" +#include "VideoOutput.h" +#include "VideoOutputChild.h" +#include "vid_none.h" +#include "vid_ddraw.h" +#include "vid_overlay.h" +#include "vid_d3d.h" +#include <cassert> +#include "directdraw.h" +#include "video.h" +#include "api.h" +#include "WinampAttributes.h" +#include "resource.h" +#include "../nu/AutoWide.h" +#include "stats.h" +#include "IVideoD3DOSD.h" + +extern "C" int is_fullscreen_video; +#define WM_VIDEO_UPDATE_STATUS_TEXT WM_USER+0x874 +#define WM_VIDEO_OPEN WM_USER+0x875 +#define WM_VIDEO_CLOSE WM_USER+0x876 +#define WM_VIDEO_RESIZE WM_USER+0x877 +#define WM_VIDEO_OSDCHANGE WM_USER+0x888 +#define WM_VIDEO_CREATE WM_USER+0x900 +int g_bitmap_id = IDB_VIDEOLOGO; +int VideoOutput::class_refcnt = 0; +wchar_t vidoutbuf_save[1024] = {0}; + +static bool input_plugin_thread_safe = false; + +//#define USE_GDIPLUS_VIDEO_RENDERER + +IVideoOSD *posd = new IVideoD3DOSD; + +HRESULT(WINAPI *_DirectDrawCreate)(GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter) = 0; + +void OpenDirectDraw() +{ + static int a = 0; + if (!_DirectDrawCreate && !a) + { + a++; + HINSTANCE h = LoadLibraryW(L"ddraw.dll"); + if (h) + { + *(void**)&_DirectDrawCreate = (void*)GetProcAddress(h, "DirectDrawCreate"); + } + } +} + +HMENU BuildPopupMenu() +{ + HMENU menu = GetSubMenu(GetSubMenu(top_menu, 3), 13); + { + static int menuset = 0; + if (!menuset) + { + InsertMenu(menu, (UINT)-1, MF_BYPOSITION | MF_SEPARATOR, 0, 0); + InsertMenuA(menu, (UINT)-1, MF_BYPOSITION | MF_POPUP, (UINT_PTR)GetSubMenu(top_menu, 0), "Winamp"); + menuset = 1; + } + } + updateTrackSubmenu(); + return menu; +} + +void VideoOutput::mainthread_Create() +{ + if (!video_created) + { + m_video_output = new Direct3DVideoOutput(video_hwnd, this); + video_created=true; + } +} + +VideoOutput::VideoOutput(HWND parent_hwnd, int initxpos, int initypos) + : m_logo(0), + m_logo_w(0), + m_logo_h(0), + userVideo(false) +{ + video_palette = 0; + video_created = false; + AutoLock autoLock(guard LOCKNAME("VideoOutput::VideoOutput")); + WNDCLASSW wc = {0, }; + + wc.style = CS_DBLCLKS; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.lpfnWndProc = WndProc; + wc.hInstance = GetModuleHandle(NULL); + wc.lpszClassName = L"WinampVideoChild"; + wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + if (!class_refcnt) RegisterClassW(&wc); + class_refcnt++; + + m_tracksel = NULL; + fs_reparented_rgn = 0; + fs_reparented = 0; + m_ignore_change = false; + fs_has_resized = false; + m_opened = 0; + + last_fullscreen_exit_time = 0; + + curSubtitle = NULL; + m_statusmsg = 0; + m_bufferstate = -1; + m_msgcallback = 0; + m_msgcallback_tok = 0; + video_hwnd = 0; + + aspect = 1.0; + m_need_change = false; + + is_fs = 0; + memset(&oldfsrect, 0, sizeof(oldfsrect)); + memset(&lastfsrect, 0, sizeof(lastfsrect)); + + m_video_output = NULL; + resetSubtitle(); + m_lastbufinvalid = NULL; + + CreateWindowExW(0, wc.lpszClassName, L"WinampVideoChildWindow", + parent_hwnd ? WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS : + (WS_OVERLAPPEDWINDOW & (~WS_MAXIMIZEBOX)), + 0, 0, 1, 1, + parent_hwnd, NULL, wc.hInstance, (void*)this); + posd->SetParent(video_hwnd); +} + +VideoOutput::~VideoOutput() +{ + AutoLock autoLock(guard LOCKNAME("VideoOutput::~VideoOutput")); + free(m_statusmsg); + posd->Hide(); + if (m_video_output) m_video_output->close(); + m_video_output = 0; + DestroyWindow(video_hwnd); + if (m_logo) + DeleteObject(m_logo); + m_logo = 0; + if (posd) + { + delete posd; + posd = NULL; + } +} + +void VideoOutput::LoadLogo() +{ + static wchar_t logo_tmp[MAX_PATH]; + if(!logo_tmp[0]) StringCchPrintfW(logo_tmp,MAX_PATH,L"%s\\videologo.bmp",CONFIGDIR); + if(PathFileExistsW(logo_tmp)) m_logo = (HBITMAP)LoadImageW(0,logo_tmp,IMAGE_BITMAP,0,0,LR_LOADFROMFILE); + + if(!m_logo) m_logo = (HBITMAP)LoadImage(hMainInstance, MAKEINTRESOURCE(g_bitmap_id), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); + BITMAP bm; + GetObject(m_logo, sizeof(BITMAP), &bm); + m_logo_w = bm.bmWidth; + m_logo_h = bm.bmHeight; + if (m_logo_h < 0) + m_logo_h = -m_logo_h; +} + +void VideoOutput::UpdateText(const wchar_t *videoInfo) +{ + { + //AutoLock lock(textGuard); + StringCchCopyW(vidoutbuf_save, 1023, (wchar_t*)videoInfo); // 1023 so that we can guarantee that this will be null terminated even in the middle of a strcpy + } + PostMessageW(hVideoWindow, WM_VIDEO_UPDATE_STATUS_TEXT, (WPARAM)vidoutbuf_save, 0); + PostMessageW(hMainWindow, WM_WA_IPC, IPC_CB_MISC_VIDEOINFO, IPC_CB_MISC); +} + +INT_PTR VideoOutput::extended(INT_PTR param1, INT_PTR param2, INT_PTR param3) +{ + switch (param1) // nonlocking commands + { + case VIDUSER_GET_VIDEOHWND: + return (INT_PTR)video_hwnd; + + case VIDUSER_SET_INFOSTRING: + if (param2) + UpdateText(AutoWide((const char *)param2)); + return 0; + + case VIDUSER_SET_INFOSTRINGW: + if (param2) + UpdateText((const wchar_t *)param2); + return 0; + } + AutoLock autoLock(guard LOCKNAME("VideoOutput::extended")); + switch (param1) + { + case VIDUSER_SET_PALETTE: + { + RGBQUAD *palette = (RGBQUAD *)param2; + if (m_video_output) + m_video_output->setPalette(palette); + else + video_palette = palette; + return 0; + } + + case VIDUSER_SET_VFLIP: + { + if (m_video_output) + m_video_output->setVFlip(param2); + return 0; + } + + case VIDUSER_SET_TRACKSELINTERFACE: + m_tracksel = (ITrackSelector *)param2; + return 0; + + case VIDUSER_OPENVIDEORENDERER: + {/* + userVideo = true; + m_video_output = (VideoRenderer *)param2; + VideoOpenStruct *openStruct = (VideoOpenStruct *)param3; + int x = openUser(openStruct->w, openStruct->h, openStruct->vflip, openStruct->aspectratio, openStruct->fmt); + if (x) + { + m_video_output = 0; + userVideo = false; + return 0; + } + else*/ + return 1; + } + case VIDUSER_CLOSEVIDEORENDERER: + close(); + userVideo = false; + return 1; + + case VIDUSER_GETPOPUPMENU: + return (INT_PTR)BuildPopupMenu(); + + case VIDUSER_SET_THREAD_SAFE: + input_plugin_thread_safe = !!param2; + break; + } + return 0; +} + +int VideoOutput::get_latency() +{ + return config_video_vsync2 ? 15 : 0; +} + +void VideoOutput::adjustAspect(RECT &rd) +{ + AutoLock autoLock(guard LOCKNAME("VideoOutput::adjustAspect")); + + if (posd->Showing() /*&& config_video_osd*/) + { + rd.top += posd->GetBarHeight(); + rd.bottom -= posd->GetBarHeight(); + } + + if (config_video_aspectadj) + { + int outh = rd.bottom - rd.top; + int outw = rd.right - rd.left; + + double outputaspect = aspect; + + if (config_video_useratio && config_video_ratio1 && config_video_ratio2) + { + RECT r; + getViewport(&r, hVideoWindow, 1, NULL); + int screenx = r.right - r.left; + int screeny = r.bottom - r.top; + + if (screenx && screeny) + { + outputaspect *= config_video_ratio1 * screeny / ((double)screenx * (double)config_video_ratio2); + } + } + + int newh = (int)((outputaspect * height * outw) / (double)width); + int neww = (int)((width * outh) / (height * outputaspect)); + + if (outh > newh) // black bars on top and bottom + { + int d = outh - newh; + rd.top += d / 2; + rd.bottom -= d - d / 2; + } + else if (outw > neww) // black bars on left and right + { + int d = outw - neww; + rd.left += d / 2; + rd.right -= d - d / 2; + } + } +} + +LRESULT CALLBACK VideoOutput::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + + if (uMsg == g_scrollMsg) // can't check against variables in case statements + { + wParam <<= 16; + uMsg = WM_MOUSEWHEEL; + } + + if (FALSE != IsDirectMouseWheelMessage(uMsg)) + { + SendMessageW(hwnd, WM_MOUSEWHEEL, wParam, lParam); + return TRUE; + } + + switch (uMsg) + { + case WM_MOUSEWHEEL: + return SendMessageW(hMainWindow, uMsg, wParam, lParam); + + case WM_CREATE: + { + VideoOutput *vid = (VideoOutput *)((CREATESTRUCT *)lParam)->lpCreateParams; + vid->video_hwnd = hwnd; + SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)vid); + } + return 0; + default: /// pass it on to the other window procedure + VideoOutput *_This = (VideoOutput*)GetWindowLongPtrW(hwnd, GWLP_USERDATA); + if (_This) + return _This->WindowProc(hwnd, uMsg, wParam, lParam); + else + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } +} + +void VideoOutput::notifyBufferState(int bufferstate) /* 0-255*/ +{ + m_bufferstate = bufferstate; + if (bufferstate == -1 || bufferstate == 255 || (GetTickCount() - m_lastbufinvalid > 500)) // don't want to do this too often + { + AutoLock autoLock(guard LOCKNAME("VideoOutput::notifyBufferState")); + if (!m_video_output || !m_video_output->onPaint(video_hwnd)) + InvalidateRect(video_hwnd, 0, TRUE); + m_lastbufinvalid = GetTickCount(); + } +} + +void VideoOutput::DrawLogo(HDC out, RECT *canvas_size) +{ + int bufferState = m_bufferstate; + if (m_logo && config_video_logo) + { + HDC dc = CreateCompatibleDC(NULL); + SelectObject(dc, m_logo); + int xp = (canvas_size->right - canvas_size->left - m_logo_w) / 2; + int yp = (canvas_size->bottom - canvas_size->top - m_logo_h) / 2; + BitBlt(out, xp, yp, m_logo_w, m_logo_h, dc, 0, 0, SRCCOPY); + + if (bufferState != -1) + { + if (bufferState < 16) bufferState = 16; + + HGDIOBJ oldobj1 = SelectObject(out, CreateSolidBrush(RGB(0, 0, 0))); + HGDIOBJ oldobj2 = SelectObject(out, CreatePen(PS_SOLID, 0, RGB(0, 0, 0))); + Rectangle(out, canvas_size->left, canvas_size->top, canvas_size->right, yp); + if (m_statusmsg) + Rectangle(out, canvas_size->left, yp + m_logo_h, canvas_size->right, canvas_size->bottom); + else + { + Rectangle(out, canvas_size->left, yp + m_logo_h + 2 + 9, canvas_size->right, canvas_size->bottom); + Rectangle(out, xp + ((bufferState *(m_logo_w + 2)) >> 8), yp + m_logo_h + 2, canvas_size->right, yp + 9 + m_logo_h + 2); + } + Rectangle(out, canvas_size->left, yp, xp - 1, yp + m_logo_h + 9 + 2); + Rectangle(out, xp + m_logo_w + 1, yp, canvas_size->right, yp + m_logo_h + 2); + DeleteObject(SelectObject(out, oldobj2)); + DeleteObject(SelectObject(out, oldobj1)); + } + + if (m_statusmsg) + { + RECT subr = {0, yp + m_logo_h + 2, canvas_size->right, canvas_size->bottom}; + SetTextColor(out, RGB(255, 255, 255)); + SetBkMode(out, TRANSPARENT); + DrawTextA(out, m_statusmsg, -1, &subr, DT_TOP | DT_CENTER | DT_NOCLIP | DT_NOPREFIX); + } + else + { + yp += m_logo_h + 2; + if (bufferState) + { + HGDIOBJ oldobj1 = SelectObject(out, CreateSolidBrush(RGB(128, 128, 128))); + HGDIOBJ oldobj2 = SelectObject(out, CreatePen(PS_SOLID, 0, RGB(255, 255, 255))); + Rectangle(out, xp - 1, yp, xp + ((bufferState *(m_logo_w + 2)) >> 8), yp + 9); + DeleteObject(SelectObject(out, oldobj2)); + DeleteObject(SelectObject(out, oldobj1)); + } + } + DeleteDC(dc); + } +} + +void VideoOutput::PaintLogo(int bufferState) +{ + // TODO: ask renderer to draw this shiz + AutoLock autoLock(guard LOCKNAME("VideoOutput::PaintLogo")); + + PAINTSTRUCT p; + BeginPaint(video_hwnd, &p); + RECT r; + GetClientRect(video_hwnd, &r); + HDC out = p.hdc; + + HRGN hrgn = CreateRectRgnIndirect(&r); + HBRUSH b = (HBRUSH)GetStockObject(BLACK_BRUSH); + FillRgn(out, hrgn, b); + DeleteObject(b); + DeleteObject(hrgn); + + DrawLogo(out, &r); + + EndPaint(video_hwnd, &p); +} + +// the big window procedure +LRESULT VideoOutput::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + // the follow messages are handled w/o a lock + switch (uMsg) + { + case WM_USER + 0x1: + m_need_change = true; + break; + + case WM_USER + 0x2: + m_ignore_change = !!lParam; + break; + + case WM_ERASEBKGND: + return 1; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case ID_VIDEOWND_VIDEOOPTIONS: + prefs_last_page = 24; + prefs_dialog(1); + break; + + case ID_VID_AUDIO0: + case ID_VID_AUDIO1: + case ID_VID_AUDIO2: + case ID_VID_AUDIO3: + case ID_VID_AUDIO4: + case ID_VID_AUDIO5: + case ID_VID_AUDIO6: + case ID_VID_AUDIO7: + case ID_VID_AUDIO8: + case ID_VID_AUDIO9: + case ID_VID_AUDIO10: + case ID_VID_AUDIO11: + case ID_VID_AUDIO12: + case ID_VID_AUDIO13: + case ID_VID_AUDIO14: + case ID_VID_AUDIO15: + { + VideoOutput *out = (VideoOutput *)video_getIVideoOutput(); + if (!out) + break; + + out->getTrackSelector()->setAudioTrack(LOWORD(wParam) - ID_VID_AUDIO0); + break; + } + case ID_VID_VIDEO0: + case ID_VID_VIDEO1: + case ID_VID_VIDEO2: + case ID_VID_VIDEO3: + case ID_VID_VIDEO4: + case ID_VID_VIDEO5: + case ID_VID_VIDEO6: + case ID_VID_VIDEO7: + case ID_VID_VIDEO8: + case ID_VID_VIDEO9: + case ID_VID_VIDEO10: + case ID_VID_VIDEO11: + case ID_VID_VIDEO12: + case ID_VID_VIDEO13: + case ID_VID_VIDEO14: + case ID_VID_VIDEO15: + { + VideoOutput *out = (VideoOutput *)video_getIVideoOutput(); + if (!out) break; + out->getTrackSelector()->setVideoTrack(LOWORD(wParam) - ID_VID_VIDEO0); + break; + } + } + break; + case WM_RBUTTONUP: + if (!is_fs) + { + POINT p; + GetCursorPos(&p); + DoTrackPopup(BuildPopupMenu(), TPM_RIGHTBUTTON | TPM_LEFTBUTTON, p.x, p.y, hwnd); + } + break; + case WM_LBUTTONDOWN: // putting this here prevents a deadlock, but allows a race condition over video drawing =( + { + int x = GET_X_LPARAM(lParam); + int y = GET_Y_LPARAM(lParam); + + if (is_fs && config_video_osd) + { + if (((IVideoD3DOSD *)posd)->isOSDReadyToDraw()) + { + if (posd->MouseDown(x, y, wParam)) + videoToggleFullscreen(); + } + } + else + { + SetCapture(video_hwnd); + clickx = x; + clicky = y; + SetFocus(video_hwnd); + } + } + break; + case WM_MOUSEMOVE: + { + int x = GET_X_LPARAM(lParam); + int y = GET_Y_LPARAM(lParam); + if (is_fs && config_video_osd) + { + if (((IVideoD3DOSD *)posd)->isOSDReadyToDraw()) + { + posd->MouseMove(x, y, wParam); + } + } + else if (GetCapture() == video_hwnd && config_easymove) + { + POINT p = { x, y}; + ClientToScreen(hVideoWindow, &p); + p.x -= clickx; + p.y -= clicky; + SendMessageW(hVideoWindow, WM_USER + 0x100, 1, (LPARAM)&p); + } + } + break; + case WM_LBUTTONUP: + { + int x = GET_X_LPARAM(lParam); + int y = GET_Y_LPARAM(lParam); + if (GetCapture() == video_hwnd) + ReleaseCapture(); + if (is_fs && config_video_osd) + { + if (((IVideoD3DOSD *)posd)->isOSDReadyToDraw()) + if (posd->MouseUp(x, y, wParam)) + videoToggleFullscreen(); + } + SetFocus(hVideoWindow); + } + break; + } + + switch (uMsg) + { + case WM_VIDEO_OSDCHANGE: + { + AutoLock autoLock(guard LOCKNAME("VideoOutput::WM_VIDEO_OSDCHANGE")); + if (m_video_output) + { + m_video_output->Refresh(); + m_video_output->timerCallback(); + } + } + break; + case WM_SHOWWINDOW: + { + AutoLock autoLock(guard LOCKNAME("VideoOutput::WM_SHOWWINDOW")); + if (wParam == TRUE // being shown + && !m_logo) // logo hasn't been loaded yet + LoadLogo(); + } + break; + case WM_INITMENUPOPUP: + { + AutoLock autoLock(guard LOCKNAME("VideoOutput::WM_INITMENUPOPUP")); + return SendMessageW(hMainWindow, uMsg, wParam, lParam); // for popup menus + } + + case WM_WINDOWPOSCHANGED: + case WM_SIZE: + { + AutoLock autoLock(guard LOCKNAME("VideoOutput::WM_SIZE")); + if (m_video_output) + { + m_video_output->OnWindowSize(); + if (is_fs) + if ( ((IVideoD3DOSD *)posd)->isOSDInited() ) + ((IVideoD3DOSD *)posd)->UpdateOSD(hwnd, this); + } + } + break; + + case WM_TIMER: + case WM_WINDOWPOSCHANGING: + case WM_MOVE: + case WM_MOVING: + { + AutoLock autoLock(guard LOCKNAME("VideoOutput::WM_TIMER, etc")); + if (m_video_output && !m_ignore_change) + m_video_output->timerCallback(); + + if (uMsg == WM_TIMER) + return 0; + } + break; + + case WM_LBUTTONDBLCLK: + { + AutoLock autoLock(guard LOCKNAME("VideoOutput::WM_LBUTTONDBLCLK")); + videoToggleFullscreen(); + } + break; + + case WM_PAINT: + { + AutoLock autoLock(guard LOCKNAME("VideoOutput::WM_PAINT")); + if (m_video_output && m_video_output->onPaint(hwnd)) + return 0; + PaintLogo(m_bufferstate); + } + + return 0; + break; + + case WM_PRINTCLIENT: + { + //AutoLock autoLock(guard LOCKNAME("VideoOutput::WM_PAINT")); + //if (m_video_output && m_video_output->onPaint(hwnd)) + // return 0; + RECT r; + GetClientRect(video_hwnd, &r); + DrawLogo((HDC)wParam, &r); + } + + return 0; + break; + + case WM_KEYDOWN: + { + AutoLock autoLock(guard LOCKNAME("VideoOutput::WM_KEYDOWN")); + if (wParam == VK_ESCAPE && is_fs) + { + videoToggleFullscreen(); + //remove_fullscreen(); + return 1; + } + if (!is_fs) + { + if (wParam == '3' || LOWORD(wParam) == 192 /* ` */) + { + SendMessageW(hwnd, WM_COMMAND, ID_VIDEOWND_ZOOM50, 0); return 0; + } + if (wParam == '1') + { + SendMessageW(hwnd, WM_COMMAND, ID_VIDEOWND_ZOOM100, 0); return 0; + } + if (wParam == '2') + { + SendMessageW(hwnd, WM_COMMAND, ID_VIDEOWND_ZOOM200, 0); return 0; + } + } + if (wParam == ' ') + { + SendMessageW(hMainWindow, WM_COMMAND, WINAMP_BUTTON3, 0); return 0; + } + if(wParam == 'F' && (GetAsyncKeyState(VK_SHIFT)&0x8000) && !(GetAsyncKeyState(VK_CONTROL)&0x8000)) + { + SendMessageW(hwnd, WM_COMMAND, ID_VIDEOWND_VERTICALLYFLIP, 0); return 0; + } + } + break; + + case WM_COMMAND: + { + AutoLock autoLock(guard LOCKNAME("VideoOutput::WM_COMMAND")); + switch (LOWORD(wParam)) + { + case ID_VIDEOWND_VERTICALLYFLIP: + { + int new_fliprgb = !config_video_fliprgb;//IsDlgButtonChecked(hwndDlg,IDC_PREFS_VIDEO_FLIPRGB)?1:0; + config_video_fliprgb = 0; + videoSetFlip(new_fliprgb); + config_video_fliprgb = new_fliprgb; + break; + } + + case ID_VIDEOWND_ZOOMFULLSCREEN: + videoGoFullscreen(); + break; + + case ID_VIDEOWND_ZOOM200: + case ID_VIDEOWND_ZOOM100: + case ID_VIDEOWND_ZOOM50: + if (m_video_output) + UpdateVideoSize(width, height, aspect, LOWORD(wParam)); + else + UpdateVideoSize(320, 240, 1.0, LOWORD(wParam)); + break; + + default: + SendMessageW(hMainWindow, WM_COMMAND, wParam, lParam); + break; + } + } + break; + + case WM_SETCURSOR: + { + AutoLock autoLock(guard LOCKNAME("VideoOutput::WM_SETCURSOR")); + if (is_fs) + { + SetCursor(posd->Showing() ? LoadCursor(NULL, IDC_ARROW) : NULL); + return TRUE; + } + else + SetCursor(LoadCursor(NULL, IDC_ARROW)); + } + break; + + case WM_SYSCOMMAND: + { + AutoLock autoLock(guard LOCKNAME("VideoOutput::WM_SYSCOMMAND")); + // eat screen saver message when fullscreen + if (((wParam & 0xfff0) == SC_SCREENSAVE || (wParam & 0xfff0) == SC_MONITORPOWER) && config_video_noss && + video_isVideoPlaying()) + { + return -1; + } + } + break; + } + + if (m_msgcallback) + { + return m_msgcallback(m_msgcallback_tok, hwnd, uMsg, wParam, lParam); + } + + return (DefWindowProc(hwnd, uMsg, wParam, lParam)); +} + +void VideoOutput::fullscreen() +{ + AutoLock autoLock(guard LOCKNAME("VideoOutput::fullscreen")); + if (!m_video_output || !m_opened) + return ; + + if (is_fs) + return ; + + // TODO: let the video renderer handle fullscreen itself, if it can. + + /*if (last_fullscreen_exit_time + 250 > GetTickCount()) // gay hack + return ; // dont let you go back and forth too quickly + */ + + GetWindowRect(hVideoWindow, &oldfsrect); // save the old coordinates + getViewport(&lastfsrect, video_hwnd, 1, NULL); + if (GetParent(hVideoWindow)) + { + fs_reparented_rgn = CreateRectRgn(0, 0, 0, 0); + GetWindowRgn(hVideoWindow, fs_reparented_rgn); + + fs_reparented = SetParent(hVideoWindow, NULL); + SetWindowRgn(hVideoWindow, NULL, FALSE); + + ScreenToClient(fs_reparented, (LPPOINT)&oldfsrect); + ScreenToClient(fs_reparented, ((LPPOINT)&oldfsrect) + 1); + } + + is_fullscreen_video = true; + is_fs = true; + //m_video_output->Fullscreen(true); + SetWindowPos(hVideoWindow, HWND_TOPMOST, lastfsrect.left, lastfsrect.top, lastfsrect.right - lastfsrect.left, lastfsrect.bottom - lastfsrect.top, SWP_DRAWFRAME | SWP_NOACTIVATE); + SetFocus(hVideoWindow); + + resetSubtitle(); +} + +extern "C" HWND hExternalVisWindow; + +int VideoOutput::openUser(int w, int h, int vflip, double aspectratio, unsigned int fmt) +{ +// TODO + return 1; +} + +int VideoOutput::open(int w, int h, int vflip, double aspectratio, unsigned int fmt) +{ + if (!video_created) + SendMessageW(hVideoWindow, WM_VIDEO_CREATE, 0, 0); + + if (!h || !w || !fmt) // check this after creating the video window. some plugins use this call to open the video output early + return 0; + + AutoLock autoLock(guard LOCKNAME("VideoOutput::open")); + + if (!m_need_change) + stats.IncrementStat(Stats::VIDEOS_PLAYED); + + if (hExternalVisWindow) + PostMessageW(hExternalVisWindow, WM_USER + 1666, 1, 15); + + m_opened = false; + userVideo = false; + width = w; + height = h; + + type = fmt; + aspect = aspectratio; + if (m_video_output) + { + if (type == VIDEO_MAKETYPE('N','O','N','E')) + { + m_opened = true; + PostMessageW(hMainWindow, WM_WA_IPC, IPC_CB_MISC_INFO, IPC_CB_MISC); + OpenVideoSize(width, height, aspect); + fs_has_resized = is_fs; + return 0; + } + else if (m_video_output->OpenVideo(w, h, type, vflip, aspect)) + { + if (video_palette) + m_video_output->setPalette(video_palette); + video_palette = 0; + DoTheVistaVideoDance(); + InvalidateRect(video_hwnd, NULL, TRUE); + m_opened = true; + PostMessageW(hMainWindow, WM_WA_IPC, IPC_CB_MISC_INFO, IPC_CB_MISC); + if (!m_need_change) //don't update size when renegotiating video output + { + OpenVideoSize(width, height, aspect); + fs_has_resized = is_fs; + } + return 0; + } + } + return 1; +} + +void VideoOutput::draw(void *frame) +{ + if (!frame) + return ; + AutoLock autoLock(guard LOCKNAME("VideoOutput::draw")); + + if (m_video_output) + { + m_video_output->displayFrame((const char *)frame, 0, 0); + } +} + +extern wchar_t draw_vw_info_lastb[512]; + +void VideoOutput::close() +{ + UpdateText(L""); + AutoLock autoLock(guard); + if (!m_opened) + return ; + m_opened = false; + if (m_video_output) + { + m_video_output->drawSubtitle(0); + m_video_output->close(); + } + m_bufferstate = -1; + + draw_vw_info_lastb[0] = 0; + input_plugin_thread_safe = false; // reset this + InvalidateRect(video_hwnd, NULL, true); + PostMessageW(hVideoWindow, WM_VIDEO_CLOSE, 0, 0); +} + +int VideoOutput::is_fullscreen() +{ + return is_fs; +} + +void VideoOutput::showStatusMsg(const char *text) +{ + AutoLock autoLock(guard); + m_statusmsg = _strdup(text); + PaintLogo(m_bufferstate); + //InvalidateRect(video_hwnd, NULL, TRUE); +} + +void VideoOutput::drawSubtitle(SubsItem *item) +{ + AutoLock autoLock(guard); + if (item == curSubtitle) + return ; + curSubtitle = item; + + if (m_video_output) + m_video_output->drawSubtitle(item); +} + +void VideoOutput::resetSubtitle() +{ + AutoLock autoLock(guard); + curSubtitle = NULL; + if (m_video_output) + m_video_output->resetSubtitle(); + // InvalidateRect(this->getHwnd(), 0, TRUE); +} + +void VideoOutput::remove_fullscreen() +{ + AutoLock autoLock(guard); + if (!is_fs) + { + is_fullscreen_video = false; + return ; + } + + posd->Hide(); + posd->ctrlrects_ready = 0; //tofix + + if (m_video_output) + { + // m_video_output->Fullscreen(false); + } + + resetSubtitle(); + + is_fs = 0; + + if (fs_reparented) + { + SetParent(hVideoWindow, fs_reparented); + SetWindowRgn(hVideoWindow, fs_reparented_rgn, FALSE); + fs_reparented = 0; + SetWindowPos(hVideoWindow, HWND_TOPMOST, oldfsrect.left, oldfsrect.top, oldfsrect.right - oldfsrect.left, oldfsrect.bottom - oldfsrect.top, SWP_NOACTIVATE | SWP_NOZORDER); + } + else + SetWindowPos(hVideoWindow, config_aot ? HWND_TOPMOST : HWND_NOTOPMOST, oldfsrect.left, oldfsrect.top, oldfsrect.right - oldfsrect.left, oldfsrect.bottom - oldfsrect.top, SWP_NOACTIVATE); + + last_fullscreen_exit_time = GetTickCount(); + + posd->Hide(); + + if (!m_opened && m_video_output) + { + m_video_output->close(); + } + + is_fullscreen_video = false; + + if (fs_has_resized) + { + fs_has_resized = false; + if (config_video_updsize) + UpdateVideoSize(width, height, aspect); + } +} + +void VideoOutput::UpdateVideoSize(int newWidth, int newHeight, double newAspect, int zoom) +{ + if (!m_opened) + return; + + // fill in default values if we have 0s + if (!newWidth) + newWidth = 320; + if (!newHeight) + newHeight = 240; + + switch (zoom) + { + case ID_VIDEOWND_ZOOM200: + newWidth *= 2; + newHeight *= 2; + break; + case ID_VIDEOWND_ZOOM50: + newWidth /= 2; + newHeight /= 2; + break; + } + + // establish a minimum window size + if (newWidth < 256) + newWidth = 256; + if (newHeight < 64) + newHeight = 64; + + if (newAspect > 0.001) // floating point can be weird about checking == 0 + { + if (newAspect < 1.0) + newWidth = (int)((double)newWidth / newAspect); + else + newHeight = (int)((double)newHeight * newAspect); + } + + //SendNotifyMessage(hVideoWindow, WM_VIDEO_RESIZE, newWidth, newHeight); + PostMessageW(hVideoWindow, WM_VIDEO_RESIZE, newWidth, newHeight); +} + +void VideoOutput::OpenVideoSize(int newWidth, int newHeight, double newAspect) +{ + // fill in default values if we have 0s + if (!newWidth) + newWidth = 320; + if (!newHeight) + newHeight = 240; + + // establish a minimum window size + if (newWidth < 256) + newWidth = 256; + if (newHeight < 64) + newHeight = 64; + + if (newAspect > 0.001) // floating point can be weird about checking == 0 + { + if (newAspect < 1.0) + newWidth = (int)((double)newWidth / newAspect); + else + newHeight = (int)((double)newHeight * newAspect); + } + + PostMessageW(hVideoWindow, WM_VIDEO_OPEN, newWidth, newHeight); +} + +void VideoOutput::SetVideoPosition(int x, int y, int width, int height) +{ + AutoLock autoLock(guard); + + SetWindowPos(getHwnd(), 0, x, y, width, height, SWP_NOZORDER | SWP_NOACTIVATE); +}
\ No newline at end of file |