#include #include #include "../osdep/keycodes.h" #include "../input/input.h" #include "../mp_msg.h" #include "video_out.h" #include "aspect.h" #include "w32_common.h" extern void mplayer_put_key(int code); static const char* classname = "MPlayer - Media player for Win32"; int vo_vm = 0; HDC vo_hdc = 0; uint32_t o_dwidth; uint32_t o_dheight; static HINSTANCE hInstance; static HWND vo_hwnd = 0; static HGLRC wglContext = 0; static int cursor = 1; static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_DESTROY: mp_input_queue_cmd(mp_input_parse_cmd("quit")); break; case WM_SYSCOMMAND: switch (wParam) { case SC_SCREENSAVE: case SC_MONITORPOWER: mp_msg(MSGT_VO, MSGL_V, "vo: win32: killing screensaver\n"); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_KEYDOWN: switch (wParam) { case VK_LEFT: mplayer_put_key(KEY_LEFT); break; case VK_UP: mplayer_put_key(KEY_UP); break; case VK_RIGHT: mplayer_put_key(KEY_RIGHT); break; case VK_DOWN: mplayer_put_key(KEY_DOWN); break; case VK_TAB: mplayer_put_key(KEY_TAB); break; case VK_CONTROL: mplayer_put_key(KEY_CTRL); break; case VK_DELETE: mplayer_put_key(KEY_DELETE); break; case VK_INSERT: mplayer_put_key(KEY_INSERT); break; case VK_HOME: mplayer_put_key(KEY_HOME); break; case VK_END: mplayer_put_key(KEY_END); break; case VK_PRIOR: mplayer_put_key(KEY_PAGE_UP); break; case VK_NEXT: mplayer_put_key(KEY_PAGE_DOWN); break; case VK_ESCAPE: mplayer_put_key(KEY_ESC); break; } break; case WM_CHAR: mplayer_put_key(wParam); break; case WM_LBUTTONDOWN: if (!vo_fs) { ReleaseCapture(); SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0); return 0; } break; } return DefWindowProc(hWnd, message, wParam, lParam); } int vo_w32_check_events(void) { MSG msg; int r = 0; while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); switch (msg.message) { case WM_ACTIVATE: r |= VO_EVENT_EXPOSE; break; } } return r; } static void changeMode(void) { DEVMODE dm; dm.dmSize = sizeof dm; dm.dmDriverExtra = 0; dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; dm.dmBitsPerPel = vo_depthonscreen; dm.dmPelsWidth = vo_screenwidth; dm.dmPelsHeight = vo_screenheight; if (vo_vm) { int bestMode = -1; int bestScore = INT_MAX; int i; for (i = 0; EnumDisplaySettings(0, i, &dm); ++i) { if (dm.dmBitsPerPel != vo_depthonscreen) continue; if (dm.dmPelsWidth < o_dwidth) continue; if (dm.dmPelsHeight < o_dheight) continue; int score = (dm.dmPelsWidth - o_dwidth) * (dm.dmPelsHeight - o_dheight); if (score < bestScore) { bestScore = score; bestMode = i; } } if (bestMode != -1) EnumDisplaySettings(0, bestMode, &dm); } vo_screenwidth = dm.dmPelsWidth; vo_screenheight = dm.dmPelsHeight; aspect_save_screenres(vo_screenwidth, vo_screenheight); vo_dwidth = vo_screenwidth; vo_dheight = vo_screenheight; ChangeDisplaySettings(&dm, CDS_FULLSCREEN); } static void resetMode(void) { ChangeDisplaySettings(0, 0); DEVMODE dm; dm.dmSize = sizeof dm; dm.dmDriverExtra = 0; dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; if (!EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &dm)) { mp_msg(MSGT_VO, MSGL_ERR, "vo: win32: unable to enumerate display settings!\n"); return; } vo_screenwidth = dm.dmPelsWidth; vo_screenheight = dm.dmPelsHeight; vo_depthonscreen = dm.dmBitsPerPel; aspect_save_screenres(vo_screenwidth, vo_screenheight); vo_dwidth = o_dwidth; vo_dheight = o_dheight; } int createRenderingContext(void) { if (wglContext) return 1; if (vo_fs) { changeMode(); SetWindowPos(vo_hwnd, HWND_TOPMOST, 0, 0, vo_screenwidth, vo_screenheight, SWP_SHOWWINDOW); if (cursor) { ShowCursor(0); cursor = 0; } } else { resetMode(); SetWindowPos(vo_hwnd, HWND_NOTOPMOST, (vo_screenwidth - vo_dwidth) / 2, (vo_screenheight - vo_dheight) / 2, vo_dwidth, vo_dheight, SWP_SHOWWINDOW); if (!cursor) { ShowCursor(1); cursor = 1; } } PIXELFORMATDESCRIPTOR pfd; memset(&pfd, 0, sizeof pfd); pfd.nSize = sizeof pfd; pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 24; pfd.iLayerType = PFD_MAIN_PLANE; int pf = ChoosePixelFormat(vo_hdc, &pfd); if (!pf) { mp_msg(MSGT_VO, MSGL_ERR, "vo: win32: unable to select a valid pixel format!\n"); return 0; } SetPixelFormat(vo_hdc, pf, &pfd); wglContext = wglCreateContext(vo_hdc); if (!wglContext) { mp_msg(MSGT_VO, MSGL_ERR, "vo: win32: unable to create wgl rendering context!\n"); return 0; } if (!wglMakeCurrent(vo_hdc, wglContext)) { mp_msg(MSGT_VO, MSGL_ERR, "vo: win32: unable to make wgl rendering context current!\n"); return 0; } mp_msg(MSGT_VO, MSGL_V, "vo: win32: running at %dx%d with depth %d\n", vo_screenwidth, vo_screenheight, vo_depthonscreen); return 1; } void destroyRenderingContext(void) { if (wglContext) { wglMakeCurrent(0, 0); wglDeleteContext(wglContext); wglContext = 0; resetMode(); } } int vo_init(void) { HICON mplayerIcon = 0; char exedir[MAX_PATH]; DEVMODE dm; if (vo_hwnd) return 1; hInstance = GetModuleHandle(0); if (GetModuleFileName(0, exedir, MAX_PATH)) mplayerIcon = ExtractIcon(hInstance, exedir, 0); if (!mplayerIcon) mplayerIcon = LoadIcon(0, IDI_APPLICATION); WNDCLASSEX wcex = { sizeof wcex, CS_OWNDC, WndProc, 0, 0, hInstance, mplayerIcon, LoadCursor(0, IDC_ARROW), (HBRUSH)GetStockObject(BLACK_BRUSH), 0, classname, mplayerIcon }; if (!RegisterClassEx(&wcex)) { mp_msg(MSGT_VO, MSGL_ERR, "vo: win32: unable to register window class!\n"); return 0; } vo_hwnd = CreateWindowEx(0, classname, classname, WS_POPUP, CW_USEDEFAULT, 0, 100, 100, 0, 0, hInstance, 0); if (!vo_hwnd) { mp_msg(MSGT_VO, MSGL_ERR, "vo: win32: unable to create window!\n"); return 0; } vo_hdc = GetDC(vo_hwnd); dm.dmSize = sizeof dm; dm.dmDriverExtra = 0; dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; if (!EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &dm)) { mp_msg(MSGT_VO, MSGL_ERR, "vo: win32: unable to enumerate display settings!\n"); return 0; } vo_screenwidth = dm.dmPelsWidth; vo_screenheight = dm.dmPelsHeight; vo_depthonscreen = dm.dmBitsPerPel; return 1; } void vo_w32_fullscreen(void) { vo_fs = !vo_fs; destroyRenderingContext(); createRenderingContext(); } void vo_w32_uninit() { mp_msg(MSGT_VO, MSGL_V, "vo: win32: uninit\n"); resetMode(); ShowCursor(1); vo_depthonscreen = 0; destroyRenderingContext(); DestroyWindow(vo_hwnd); vo_hwnd = 0; UnregisterClass(classname, 0); }