1 /* 2 * Digital video MCI Wine Driver 3 * 4 * Copyright 1999, 2000 Eric POUECH 5 * Copyright 2003 Dmitry Timoshkov 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include <string.h> 23 #include "private_mciavi.h" 24 #include "wine/debug.h" 25 26 WINE_DEFAULT_DEBUG_CHANNEL(mciavi); 27 28 static const WCHAR mciaviW[] = {'M','C','I','A','V','I',0}; 29 30 static LRESULT WINAPI MCIAVI_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 31 { 32 TRACE("hwnd=%p msg=%x wparam=%lx lparam=%lx\n", hWnd, uMsg, wParam, lParam); 33 34 switch (uMsg) { 35 case WM_CREATE: 36 SetWindowLongW(hWnd, 0, (LPARAM)((CREATESTRUCTW *)lParam)->lpCreateParams); 37 return DefWindowProcW(hWnd, uMsg, wParam, lParam); 38 39 case WM_DESTROY: 40 MCIAVI_mciClose(GetWindowLongW(hWnd, 0), MCI_WAIT, NULL); 41 SetWindowLongW(hWnd, 0, 0); 42 return DefWindowProcW(hWnd, uMsg, wParam, lParam); 43 44 case WM_ERASEBKGND: 45 { 46 RECT rect; 47 GetClientRect(hWnd, &rect); 48 FillRect((HDC)wParam, &rect, GetStockObject(BLACK_BRUSH)); 49 } 50 return 1; 51 52 case WM_PAINT: 53 { 54 WINE_MCIAVI *wma = (WINE_MCIAVI *)mciGetDriverData(GetWindowLongW(hWnd, 0)); 55 56 if (!wma) 57 return DefWindowProcW(hWnd, uMsg, wParam, lParam); 58 59 EnterCriticalSection(&wma->cs); 60 61 /* the animation isn't playing, don't paint */ 62 if (wma->dwStatus == MCI_MODE_NOT_READY) 63 { 64 LeaveCriticalSection(&wma->cs); 65 /* default paint handling */ 66 return DefWindowProcW(hWnd, uMsg, wParam, lParam); 67 } 68 69 if (wParam) 70 MCIAVI_PaintFrame(wma, (HDC)wParam); 71 else 72 { 73 PAINTSTRUCT ps; 74 BeginPaint(hWnd, &ps); 75 MCIAVI_PaintFrame(wma, ps.hdc); 76 EndPaint(hWnd, &ps); 77 } 78 79 LeaveCriticalSection(&wma->cs); 80 } 81 return 1; 82 83 default: 84 return DefWindowProcW(hWnd, uMsg, wParam, lParam); 85 } 86 } 87 88 BOOL MCIAVI_UnregisterClass(void) 89 { 90 return UnregisterClassW(mciaviW, MCIAVI_hInstance); 91 } 92 93 BOOL MCIAVI_RegisterClass(void) 94 { 95 WNDCLASSW wndClass; 96 97 ZeroMemory(&wndClass, sizeof(WNDCLASSW)); 98 wndClass.style = CS_DBLCLKS; 99 wndClass.lpfnWndProc = MCIAVI_WindowProc; 100 wndClass.cbWndExtra = sizeof(MCIDEVICEID); 101 wndClass.hInstance = MCIAVI_hInstance; 102 wndClass.hCursor = LoadCursorW(0, (LPCWSTR)IDC_ARROW); 103 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); 104 wndClass.lpszClassName = mciaviW; 105 106 if (RegisterClassW(&wndClass)) return TRUE; 107 if (GetLastError() == ERROR_CLASS_ALREADY_EXISTS) return TRUE; 108 109 return FALSE; 110 } 111 112 BOOL MCIAVI_CreateWindow(WINE_MCIAVI* wma, DWORD dwFlags, LPMCI_DGV_OPEN_PARMSW lpParms) 113 { 114 static const WCHAR captionW[] = {'W','i','n','e',' ','M','C','I','-','A','V','I',' ','p','l','a','y','e','r',0}; 115 HWND hParent = 0; 116 DWORD dwStyle = WS_OVERLAPPEDWINDOW; 117 RECT rc; 118 119 /* what should be done ? */ 120 if (wma->hWnd) return TRUE; 121 122 if (dwFlags & MCI_DGV_OPEN_PARENT) hParent = lpParms->hWndParent; 123 if (dwFlags & MCI_DGV_OPEN_WS) dwStyle = lpParms->dwStyle; 124 125 if (wma->hic) 126 SetRect(&rc, 0, 0, wma->outbih->biWidth, wma->outbih->biHeight); 127 else 128 SetRect(&rc, 0, 0, wma->inbih->biWidth, wma->inbih->biHeight); 129 130 AdjustWindowRect(&rc, dwStyle, FALSE); 131 if (!(dwStyle & (WS_CHILD|WS_POPUP))) /* overlapped window ? */ 132 { 133 rc.right -= rc.left; 134 rc.bottom -= rc.top; 135 rc.left = rc.top = CW_USEDEFAULT; 136 } 137 138 wma->hWnd = CreateWindowW(mciaviW, captionW, 139 dwStyle, rc.left, rc.top, 140 rc.right, rc.bottom, 141 hParent, 0, MCIAVI_hInstance, 142 ULongToPtr(wma->wDevID)); 143 wma->hWndPaint = wma->hWnd; 144 145 TRACE("(%04x, %08X, %p, style %x, parent %p, dimensions %dx%d, hwnd %p)\n", wma->wDevID, 146 dwFlags, lpParms, dwStyle, hParent, rc.right - rc.left, rc.bottom - rc.top, wma->hWnd); 147 return wma->hWnd != 0; 148 } 149 150 /*************************************************************************** 151 * MCIAVI_mciPut [internal] 152 */ 153 DWORD MCIAVI_mciPut(UINT wDevID, DWORD dwFlags, LPMCI_DGV_PUT_PARMS lpParms) 154 { 155 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID); 156 RECT rc; 157 158 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 159 160 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 161 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 162 if (dwFlags & MCI_TEST) return 0; 163 164 EnterCriticalSection(&wma->cs); 165 166 if (dwFlags & MCI_DGV_RECT) { 167 /* In MCI, RECT structure is used differently: rc.right = width & rc.bottom = height 168 * So convert input MCI RECT into a normal RECT */ 169 SetRect(&rc, lpParms->rc.left, lpParms->rc.top, lpParms->rc.left + lpParms->rc.right, 170 lpParms->rc.top + lpParms->rc.bottom); 171 } else { 172 GetClientRect(wma->hWndPaint, &rc); 173 } 174 175 if (dwFlags & MCI_DGV_PUT_CLIENT) { 176 FIXME("PUT_CLIENT %s\n", wine_dbgstr_rect(&rc)); 177 LeaveCriticalSection(&wma->cs); 178 return MCIERR_UNRECOGNIZED_COMMAND; 179 } 180 if (dwFlags & MCI_DGV_PUT_DESTINATION) { 181 TRACE("PUT_DESTINATION %s\n", wine_dbgstr_rect(&rc)); 182 wma->dest = rc; 183 } 184 if (dwFlags & MCI_DGV_PUT_FRAME) { 185 FIXME("PUT_FRAME %s\n", wine_dbgstr_rect(&rc)); 186 LeaveCriticalSection(&wma->cs); 187 return MCIERR_UNRECOGNIZED_COMMAND; 188 } 189 if (dwFlags & MCI_DGV_PUT_SOURCE) { 190 TRACE("PUT_SOURCE %s\n", wine_dbgstr_rect(&rc)); 191 wma->source = rc; 192 } 193 if (dwFlags & MCI_DGV_PUT_VIDEO) { 194 FIXME("PUT_VIDEO %s\n", wine_dbgstr_rect(&rc)); 195 LeaveCriticalSection(&wma->cs); 196 return MCIERR_UNRECOGNIZED_COMMAND; 197 } 198 if (dwFlags & MCI_DGV_PUT_WINDOW) { 199 TRACE("PUT_WINDOW %s\n", wine_dbgstr_rect(&rc)); 200 SetWindowPos(wma->hWndPaint, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER); 201 } 202 LeaveCriticalSection(&wma->cs); 203 return 0; 204 } 205 206 /****************************************************************************** 207 * MCIAVI_mciWhere [internal] 208 */ 209 DWORD MCIAVI_mciWhere(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms) 210 { 211 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID); 212 RECT rc; 213 214 TRACE("(%04x, %08x, %p)\n", wDevID, dwFlags, lpParms); 215 216 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 217 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 218 /* Ignore MCI_TEST flag. */ 219 220 EnterCriticalSection(&wma->cs); 221 222 if (dwFlags & MCI_DGV_WHERE_DESTINATION) { 223 if (dwFlags & MCI_DGV_WHERE_MAX) { 224 GetClientRect(wma->hWndPaint, &rc); 225 TRACE("WHERE_DESTINATION_MAX %s\n", wine_dbgstr_rect(&rc)); 226 } else { 227 TRACE("WHERE_DESTINATION %s\n", wine_dbgstr_rect(&wma->dest)); 228 rc = wma->dest; 229 } 230 } 231 if (dwFlags & MCI_DGV_WHERE_FRAME) { 232 if (dwFlags & MCI_DGV_WHERE_MAX) 233 FIXME("MCI_DGV_WHERE_FRAME_MAX\n"); 234 else 235 FIXME("MCI_DGV_WHERE_FRAME\n"); 236 LeaveCriticalSection(&wma->cs); 237 return MCIERR_UNRECOGNIZED_COMMAND; 238 } 239 if (dwFlags & MCI_DGV_WHERE_SOURCE) { 240 if (dwFlags & MCI_DGV_WHERE_MAX) { 241 SetRect(&rc, 0, 0, wma->inbih->biWidth, wma->inbih->biHeight); 242 TRACE("WHERE_SOURCE_MAX %s\n", wine_dbgstr_rect(&rc)); 243 } else { 244 TRACE("WHERE_SOURCE %s\n", wine_dbgstr_rect(&wma->source)); 245 rc = wma->source; 246 } 247 } 248 if (dwFlags & MCI_DGV_WHERE_VIDEO) { 249 if (dwFlags & MCI_DGV_WHERE_MAX) 250 FIXME("WHERE_VIDEO_MAX\n"); 251 else 252 FIXME("WHERE_VIDEO\n"); 253 LeaveCriticalSection(&wma->cs); 254 return MCIERR_UNRECOGNIZED_COMMAND; 255 } 256 if (dwFlags & MCI_DGV_WHERE_WINDOW) { 257 if (dwFlags & MCI_DGV_WHERE_MAX) { 258 GetWindowRect(GetDesktopWindow(), &rc); 259 TRACE("WHERE_WINDOW_MAX %s\n", wine_dbgstr_rect(&rc)); 260 } else { 261 GetWindowRect(wma->hWndPaint, &rc); 262 TRACE("WHERE_WINDOW %s\n", wine_dbgstr_rect(&rc)); 263 } 264 } 265 266 /* In MCI, RECT structure is used differently: rc.right = width & rc.bottom = height 267 * So convert the normal RECT into a MCI RECT before returning */ 268 SetRect(&lpParms->rc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); 269 270 LeaveCriticalSection(&wma->cs); 271 return 0; 272 } 273 274 /*************************************************************************** 275 * MCIAVI_mciWindow [internal] 276 */ 277 DWORD MCIAVI_mciWindow(UINT wDevID, DWORD dwFlags, LPMCI_DGV_WINDOW_PARMSW lpParms) 278 { 279 WINE_MCIAVI* wma = MCIAVI_mciGetOpenDev(wDevID); 280 281 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 282 283 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; 284 if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; 285 if (dwFlags & MCI_TEST) return 0; 286 287 EnterCriticalSection(&wma->cs); 288 289 if (dwFlags & MCI_DGV_WINDOW_HWND) { 290 if (IsWindow(lpParms->hWnd)) 291 { 292 TRACE("Setting hWnd to %p\n", lpParms->hWnd); 293 if (wma->hWnd) ShowWindow(wma->hWnd, SW_HIDE); 294 wma->hWndPaint = (lpParms->hWnd == MCI_DGV_WINDOW_DEFAULT) ? wma->hWnd : lpParms->hWnd; 295 } 296 } 297 if (dwFlags & MCI_DGV_WINDOW_STATE) { 298 TRACE("Setting nCmdShow to %d\n", lpParms->nCmdShow); 299 ShowWindow(wma->hWndPaint, lpParms->nCmdShow); 300 } 301 if (dwFlags & MCI_DGV_WINDOW_TEXT) { 302 TRACE("Setting caption to %s\n", debugstr_w(lpParms->lpstrText)); 303 SetWindowTextW(wma->hWndPaint, lpParms->lpstrText); 304 } 305 306 LeaveCriticalSection(&wma->cs); 307 return 0; 308 } 309