aboutsummaryrefslogtreecommitdiff
path: root/Src/Winamp/VideoOutput.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Winamp/VideoOutput.cpp')
-rw-r--r--Src/Winamp/VideoOutput.cpp1040
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