gdi32: Improve EMF DC cleanup when CloseEnhMetafile is not called.
[wine.git] / dlls / msvfw32 / mciwnd.c
blobe5f387a0bab5f46071599217ab0b2d9af9cbc007
1 /*
2 * Copyright 2000 Eric Pouech
3 * Copyright 2003 Dmitry Timoshkov
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 * FIXME:
20 * Add support for all remaining MCI_ commands and MCIWNDM_ messages.
21 * Add support for MCIWNDF_RECORD.
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnls.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "winternl.h"
32 #include "vfw.h"
33 #include "digitalv.h"
34 #include "commctrl.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(mci);
39 extern HMODULE MSVFW32_hModule;
40 static const WCHAR mciWndClassW[] = {'M','C','I','W','n','d','C','l','a','s','s',0};
41 static const WCHAR mciWndNameW[] = {'M','C','I','W','n','d','C','r','e','a','t','e',
42 'W','i','n','e','I','n','t','e','r','n','a','l', 0};
44 typedef struct
46 DWORD dwStyle;
47 MCIDEVICEID mci;
48 HDRVR hdrv;
49 int alias;
50 UINT dev_type;
51 UINT mode;
52 LONG position;
53 SIZE size; /* size of the original frame rect */
54 int zoom;
55 LPWSTR lpName;
56 HWND hWnd, hwndOwner;
57 UINT uTimer;
58 MCIERROR lasterror;
59 WCHAR return_string[128];
60 WORD active_timer, inactive_timer;
61 } MCIWndInfo;
63 static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
65 #define CTL_PLAYSTOP 0x3200
66 #define CTL_MENU 0x3201
67 #define CTL_TRACKBAR 0x3202
69 /***********************************************************************
70 * MCIWndRegisterClass [MSVFW32.@]
72 * NOTE: Native always uses its own hInstance
74 BOOL VFWAPIV MCIWndRegisterClass(void)
76 WNDCLASSW wc;
78 /* Since we are going to register a class belonging to MSVFW32
79 * and later we will create windows with a different hInstance
80 * CS_GLOBALCLASS is needed. And because the second attempt
81 * to register a global class will fail we need to test whether
82 * the class was already registered.
84 wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC | CS_GLOBALCLASS;
85 wc.lpfnWndProc = MCIWndProc;
86 wc.cbClsExtra = 0;
87 wc.cbWndExtra = sizeof(MCIWndInfo*);
88 wc.hInstance = MSVFW32_hModule;
89 wc.hIcon = 0;
90 wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
91 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
92 wc.lpszMenuName = NULL;
93 wc.lpszClassName = mciWndClassW;
95 if (RegisterClassW(&wc)) return TRUE;
96 if (GetLastError() == ERROR_CLASS_ALREADY_EXISTS) return TRUE;
98 return FALSE;
101 /***********************************************************************
102 * MCIWndCreateW [MSVFW32.@]
104 HWND VFWAPIV MCIWndCreateW(HWND hwndParent, HINSTANCE hInstance,
105 DWORD dwStyle, LPCWSTR szFile)
107 TRACE("%p %p %lx %s\n", hwndParent, hInstance, dwStyle, debugstr_w(szFile));
109 MCIWndRegisterClass();
111 if (!hInstance) hInstance = GetModuleHandleW(0);
113 if (hwndParent)
114 dwStyle |= WS_VISIBLE | WS_BORDER /*| WS_CHILD*/;
115 else
116 dwStyle |= WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
118 return CreateWindowExW(0, mciWndClassW, mciWndNameW,
119 dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
120 0, 0, 300, 0,
121 hwndParent, 0, hInstance, (LPVOID)szFile);
124 /***********************************************************************
125 * MCIWndCreate [MSVFW32.@]
126 * MCIWndCreateA [MSVFW32.@]
128 HWND VFWAPIV MCIWndCreateA(HWND hwndParent, HINSTANCE hInstance,
129 DWORD dwStyle, LPCSTR szFile)
131 HWND ret;
132 UNICODE_STRING fileW;
134 if (szFile)
135 RtlCreateUnicodeStringFromAsciiz(&fileW, szFile);
136 else
137 fileW.Buffer = NULL;
139 ret = MCIWndCreateW(hwndParent, hInstance, dwStyle, fileW.Buffer);
141 RtlFreeUnicodeString(&fileW);
142 return ret;
145 static inline void MCIWND_notify_mode(MCIWndInfo *mwi)
147 if (mwi->dwStyle & MCIWNDF_NOTIFYMODE)
149 UINT new_mode = SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0);
150 if (new_mode != mwi->mode)
152 mwi->mode = new_mode;
153 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMODE, (WPARAM)mwi->hWnd, new_mode);
158 static inline void MCIWND_notify_pos(MCIWndInfo *mwi)
160 if (mwi->dwStyle & MCIWNDF_NOTIFYPOS)
162 LONG new_pos = SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 0, 0);
163 if (new_pos != mwi->position)
165 mwi->position = new_pos;
166 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYPOS, (WPARAM)mwi->hWnd, new_pos);
171 static inline void MCIWND_notify_size(MCIWndInfo *mwi)
173 if (mwi->dwStyle & MCIWNDF_NOTIFYSIZE)
174 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYSIZE, (WPARAM)mwi->hWnd, 0);
177 static inline void MCIWND_notify_error(MCIWndInfo *mwi)
179 if (mwi->dwStyle & MCIWNDF_NOTIFYERROR)
180 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYERROR, (WPARAM)mwi->hWnd, (LPARAM)mwi->lasterror);
183 static void MCIWND_UpdateState(MCIWndInfo *mwi)
185 WCHAR buffer[1024];
187 if (!mwi->mci)
189 /* FIXME: get this from resources */
190 static const WCHAR no_deviceW[] = {'N','o',' ','D','e','v','i','c','e',0};
191 SetWindowTextW(mwi->hWnd, no_deviceW);
192 return;
195 MCIWND_notify_pos(mwi);
197 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
198 SendDlgItemMessageW(mwi->hWnd, CTL_TRACKBAR, TBM_SETPOS, TRUE, mwi->position);
200 if (!(mwi->dwStyle & MCIWNDF_SHOWALL))
201 return;
203 if ((mwi->dwStyle & MCIWNDF_SHOWNAME) && mwi->lpName)
204 lstrcpyW(buffer, mwi->lpName);
205 else
206 *buffer = 0;
208 if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
210 static const WCHAR spaceW[] = {' ',0};
211 static const WCHAR l_braceW[] = {'(',0};
213 if (*buffer) lstrcatW(buffer, spaceW);
214 lstrcatW(buffer, l_braceW);
217 if (mwi->dwStyle & MCIWNDF_SHOWPOS)
219 WCHAR posW[64];
221 posW[0] = 0;
222 SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 64, (LPARAM)posW);
223 lstrcatW(buffer, posW);
226 if ((mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) == (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
228 static const WCHAR dashW[] = {' ','-',' ',0};
229 lstrcatW(buffer, dashW);
232 if (mwi->dwStyle & MCIWNDF_SHOWMODE)
234 WCHAR modeW[64];
236 modeW[0] = 0;
237 SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 64, (LPARAM)modeW);
238 lstrcatW(buffer, modeW);
241 if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
243 static const WCHAR r_braceW[] = {')',0};
244 lstrcatW(buffer, r_braceW);
247 TRACE("=> %s\n", debugstr_w(buffer));
248 SetWindowTextW(mwi->hWnd, buffer);
251 static LRESULT MCIWND_Create(HWND hWnd, LPCREATESTRUCTW cs)
253 HWND hChld;
254 MCIWndInfo *mwi;
255 static const WCHAR buttonW[] = {'b','u','t','t','o','n',0};
257 mwi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mwi));
258 if (!mwi) return -1;
260 SetWindowLongW(hWnd, 0, (LPARAM)mwi);
262 mwi->dwStyle = cs->style;
263 /* There is no need to show stats if there is no caption */
264 if ((mwi->dwStyle & WS_CAPTION) != WS_CAPTION)
265 mwi->dwStyle &= ~MCIWNDF_SHOWALL;
267 mwi->hWnd = hWnd;
268 mwi->hwndOwner = cs->hwndParent;
269 mwi->active_timer = 500;
270 mwi->inactive_timer = 2000;
271 mwi->mode = MCI_MODE_NOT_READY;
272 mwi->position = -1;
273 mwi->zoom = 100;
275 if (!(mwi->dwStyle & MCIWNDF_NOMENU))
277 static const WCHAR menuW[] = {'M','e','n','u',0};
279 hChld = CreateWindowExW(0, buttonW, menuW, WS_CHILD|WS_VISIBLE, 32, cs->cy, 32, 32,
280 hWnd, (HMENU)CTL_MENU, cs->hInstance, 0L);
281 TRACE("Get Button2: %p\n", hChld);
284 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
286 INITCOMMONCONTROLSEX init;
287 static const WCHAR playW[] = {'P','l','a','y',0};
289 /* adding the other elements: play/stop button, menu button, status */
290 hChld = CreateWindowExW(0, buttonW, playW, WS_CHILD|WS_VISIBLE, 0, cs->cy, 32, 32,
291 hWnd, (HMENU)CTL_PLAYSTOP, cs->hInstance, 0L);
292 TRACE("Get Button1: %p\n", hChld);
294 init.dwSize = sizeof(init);
295 init.dwICC = ICC_BAR_CLASSES;
296 InitCommonControlsEx(&init);
298 hChld = CreateWindowExW(0, TRACKBAR_CLASSW, NULL, WS_CHILD|WS_VISIBLE, 64, cs->cy, cs->cx - 64, 32,
299 hWnd, (HMENU)CTL_TRACKBAR, cs->hInstance, 0L);
300 TRACE("Get status: %p\n", hChld);
303 /* This sets the default window size */
304 SendMessageW(hWnd, MCI_CLOSE, 0, 0);
306 if (cs->lpCreateParams)
308 LPARAM lParam;
310 /* MCI wnd class is prepared to be embedded as an MDI child window */
311 if (cs->dwExStyle & WS_EX_MDICHILD)
313 MDICREATESTRUCTW *mdics = cs->lpCreateParams;
314 lParam = mdics->lParam;
316 else
317 lParam = (LPARAM)cs->lpCreateParams;
319 /* If it's our internal window name, we are being called from MCIWndCreateA/W,
320 * so file name is a unicode string */
321 if (!lstrcmpW(cs->lpszName, mciWndNameW))
322 SendMessageW(hWnd, MCIWNDM_OPENW, 0, lParam);
323 else
325 /* Otherwise let's try to figure out what string format is used */
326 HWND parent = cs->hwndParent;
327 if (!parent) parent = GetWindow(hWnd, GW_OWNER);
329 SendMessageW(hWnd, IsWindowUnicode(parent) ? MCIWNDM_OPENW : MCIWNDM_OPENA, 0, lParam);
333 return 0;
336 static void MCIWND_ToggleState(MCIWndInfo *mwi)
338 switch (SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0))
340 case MCI_MODE_NOT_READY:
341 case MCI_MODE_RECORD:
342 case MCI_MODE_SEEK:
343 case MCI_MODE_OPEN:
344 TRACE("Cannot do much...\n");
345 break;
347 case MCI_MODE_PAUSE:
348 SendMessageW(mwi->hWnd, MCI_RESUME, 0, 0);
349 break;
351 case MCI_MODE_PLAY:
352 SendMessageW(mwi->hWnd, MCI_PAUSE, 0, 0);
353 break;
355 case MCI_MODE_STOP:
356 SendMessageW(mwi->hWnd, MCI_STOP, 0, 0);
357 break;
361 static LRESULT MCIWND_Command(MCIWndInfo *mwi, WPARAM wParam, LPARAM lParam)
363 switch (LOWORD(wParam))
365 case CTL_PLAYSTOP: MCIWND_ToggleState(mwi); break;
366 case CTL_MENU:
367 case CTL_TRACKBAR:
368 default:
369 FIXME("support for command %04x not implement yet\n", LOWORD(wParam));
371 return 0L;
374 static void MCIWND_notify_media(MCIWndInfo *mwi)
376 if (mwi->dwStyle & (MCIWNDF_NOTIFYMEDIAA | MCIWNDF_NOTIFYMEDIAW))
378 if (!mwi->lpName)
380 static const WCHAR empty_str[1];
381 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)empty_str);
383 else
385 if (mwi->dwStyle & MCIWNDF_NOTIFYANSI)
387 char *ansi_name;
388 int len;
390 len = WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, NULL, 0, NULL, NULL);
391 ansi_name = HeapAlloc(GetProcessHeap(), 0, len);
392 WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, ansi_name, len, NULL, NULL);
394 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)ansi_name);
396 HeapFree(GetProcessHeap(), 0, ansi_name);
398 else
399 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)mwi->lpName);
404 static MCIERROR mci_generic_command(MCIWndInfo *mwi, UINT cmd)
406 MCI_GENERIC_PARMS mci_generic;
408 mci_generic.dwCallback = 0;
409 mwi->lasterror = mciSendCommandW(mwi->mci, cmd, 0, (DWORD_PTR)&mci_generic);
411 if (mwi->lasterror)
412 return mwi->lasterror;
414 MCIWND_notify_mode(mwi);
415 MCIWND_UpdateState(mwi);
416 return 0;
419 static LRESULT mci_get_devcaps(MCIWndInfo *mwi, UINT cap)
421 MCI_GETDEVCAPS_PARMS mci_devcaps;
423 mci_devcaps.dwItem = cap;
424 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
425 MCI_GETDEVCAPS_ITEM,
426 (DWORD_PTR)&mci_devcaps);
427 if (mwi->lasterror)
428 return 0;
430 return mci_devcaps.dwReturn;
433 static LRESULT MCIWND_KeyDown(MCIWndInfo *mwi, UINT key)
435 TRACE("%p, key %04x\n", mwi->hWnd, key);
437 switch(key)
439 case VK_ESCAPE:
440 SendMessageW(mwi->hWnd, MCI_STOP, 0, 0);
441 return 0;
443 default:
444 return 0;
448 static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
450 MCIWndInfo *mwi;
452 TRACE("%p %04x %08Ix %08Ix\n", hWnd, wMsg, wParam, lParam);
454 mwi = (MCIWndInfo*)GetWindowLongPtrW(hWnd, 0);
455 if (!mwi && wMsg != WM_CREATE)
456 return DefWindowProcW(hWnd, wMsg, wParam, lParam);
458 switch (wMsg)
460 case WM_CREATE:
461 MCIWND_Create(hWnd, (CREATESTRUCTW *)lParam);
462 break;
464 case WM_DESTROY:
465 if (mwi->uTimer)
466 KillTimer(hWnd, mwi->uTimer);
468 if (mwi->mci)
469 SendMessageW(hWnd, MCI_CLOSE, 0, 0);
471 HeapFree(GetProcessHeap(), 0, mwi);
473 DestroyWindow(GetDlgItem(hWnd, CTL_MENU));
474 DestroyWindow(GetDlgItem(hWnd, CTL_PLAYSTOP));
475 DestroyWindow(GetDlgItem(hWnd, CTL_TRACKBAR));
476 break;
478 case WM_PAINT:
480 MCI_DGV_UPDATE_PARMS mci_update;
481 PAINTSTRUCT ps;
483 mci_update.hDC = (wParam) ? (HDC)wParam : BeginPaint(hWnd, &ps);
485 mciSendCommandW(mwi->mci, MCI_UPDATE,
486 MCI_DGV_UPDATE_HDC | MCI_DGV_UPDATE_PAINT,
487 (DWORD_PTR)&mci_update);
489 if (!wParam) EndPaint(hWnd, &ps);
490 return 1;
493 case WM_COMMAND:
494 return MCIWND_Command(mwi, wParam, lParam);
496 case WM_KEYDOWN:
497 return MCIWND_KeyDown(mwi, wParam);
499 case WM_NCACTIVATE:
500 if (mwi->uTimer)
502 KillTimer(hWnd, mwi->uTimer);
503 mwi->uTimer = SetTimer(hWnd, 1, wParam ? mwi->active_timer : mwi->inactive_timer, NULL);
505 break;
507 case WM_TIMER:
508 MCIWND_UpdateState(mwi);
509 return 0;
511 case WM_SIZE:
512 SetWindowPos(GetDlgItem(hWnd, CTL_PLAYSTOP), 0, 0, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
513 SetWindowPos(GetDlgItem(hWnd, CTL_MENU), 0, 32, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
514 SetWindowPos(GetDlgItem(hWnd, CTL_TRACKBAR), 0, 64, HIWORD(lParam) - 32, LOWORD(lParam) - 64, 32, SWP_NOACTIVATE);
516 if (!(mwi->dwStyle & MCIWNDF_NOAUTOSIZEMOVIE))
518 RECT rc;
520 rc.left = rc.top = 0;
521 rc.right = LOWORD(lParam);
522 rc.bottom = HIWORD(lParam);
523 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
524 rc.bottom -= 32; /* subtract the height of the playbar */
525 SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
527 MCIWND_notify_size(mwi);
528 break;
530 case MM_MCINOTIFY:
531 MCIWND_notify_mode(mwi);
532 MCIWND_UpdateState(mwi);
533 return 0;
535 case MCIWNDM_OPENA:
537 UNICODE_STRING nameW;
538 TRACE("MCIWNDM_OPENA %s\n", debugstr_a((LPSTR)lParam));
539 RtlCreateUnicodeStringFromAsciiz(&nameW, (LPCSTR)lParam);
540 lParam = (LPARAM)nameW.Buffer;
542 /* fall through */
543 case MCIWNDM_OPENW:
545 RECT rc;
546 HCURSOR hCursor;
547 MCI_OPEN_PARMSW mci_open;
548 MCI_GETDEVCAPS_PARMS mci_devcaps;
549 WCHAR aliasW[64];
550 WCHAR drv_name[MAX_PATH];
551 static const WCHAR formatW[] = {'%','d',0};
552 static const WCHAR mci32W[] = {'m','c','i','3','2',0};
553 static const WCHAR system_iniW[] = {'s','y','s','t','e','m','.','i','n','i',0};
555 TRACE("MCIWNDM_OPENW %s\n", debugstr_w((LPWSTR)lParam));
557 if (wParam == MCIWNDOPENF_NEW)
559 SendMessageW(hWnd, MCIWNDM_NEWW, 0, lParam);
560 goto end_of_mci_open;
563 if (mwi->uTimer)
565 KillTimer(hWnd, mwi->uTimer);
566 mwi->uTimer = 0;
569 hCursor = LoadCursorW(0, (LPWSTR)IDC_WAIT);
570 hCursor = SetCursor(hCursor);
572 mci_open.lpstrElementName = (LPWSTR)lParam;
573 wsprintfW(aliasW, formatW, HandleToLong(hWnd) + 1);
574 mci_open.lpstrAlias = aliasW;
575 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_OPEN,
576 MCI_OPEN_ELEMENT | MCI_OPEN_ALIAS | MCI_WAIT,
577 (DWORD_PTR)&mci_open);
578 SetCursor(hCursor);
580 if (mwi->lasterror && !(mwi->dwStyle & MCIWNDF_NOERRORDLG))
582 /* FIXME: get the caption from resources */
583 static const WCHAR caption[] = {'M','C','I',' ','E','r','r','o','r',0};
584 WCHAR error_str[MAXERRORLENGTH];
586 mciGetErrorStringW(mwi->lasterror, error_str, MAXERRORLENGTH);
587 MessageBoxW(hWnd, error_str, caption, MB_ICONEXCLAMATION | MB_OK);
588 MCIWND_notify_error(mwi);
589 goto end_of_mci_open;
592 mwi->mci = mci_open.wDeviceID;
593 mwi->alias = HandleToLong(hWnd) + 1;
595 mwi->lpName = HeapAlloc(GetProcessHeap(), 0, (lstrlenW((LPWSTR)lParam) + 1) * sizeof(WCHAR));
596 lstrcpyW(mwi->lpName, (LPWSTR)lParam);
598 MCIWND_UpdateState(mwi);
600 mci_devcaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
601 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
602 MCI_GETDEVCAPS_ITEM,
603 (DWORD_PTR)&mci_devcaps);
604 if (mwi->lasterror)
606 MCIWND_notify_error(mwi);
607 goto end_of_mci_open;
610 mwi->dev_type = mci_devcaps.dwReturn;
612 drv_name[0] = 0;
613 SendMessageW(hWnd, MCIWNDM_GETDEVICEW, 256, (LPARAM)drv_name);
614 if (drv_name[0] && GetPrivateProfileStringW(mci32W, drv_name, NULL,
615 drv_name, MAX_PATH, system_iniW))
616 mwi->hdrv = OpenDriver(drv_name, NULL, 0);
618 if (mwi->dev_type == MCI_DEVTYPE_DIGITAL_VIDEO)
620 MCI_DGV_WINDOW_PARMSW mci_window;
622 mci_window.hWnd = hWnd;
623 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WINDOW,
624 MCI_DGV_WINDOW_HWND,
625 (DWORD_PTR)&mci_window);
626 if (mwi->lasterror)
628 MCIWND_notify_error(mwi);
629 goto end_of_mci_open;
633 if (SendMessageW(hWnd, MCIWNDM_GET_DEST, 0, (LPARAM)&rc) == 0)
635 mwi->size.cx = rc.right - rc.left;
636 mwi->size.cy = rc.bottom - rc.top;
638 rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
639 rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
640 SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
642 else
644 GetClientRect(hWnd, &rc);
645 rc.bottom = rc.top;
648 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
649 rc.bottom += 32; /* add the height of the playbar */
650 AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
651 SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left,
652 rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
654 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMIN, 0L, 0L);
655 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1,
656 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0));
657 mwi->uTimer = SetTimer(hWnd, 1, mwi->active_timer, NULL);
659 MCIWND_notify_media(mwi);
661 end_of_mci_open:
662 if (wMsg == MCIWNDM_OPENA)
663 HeapFree(GetProcessHeap(), 0, (void *)lParam);
664 return mwi->lasterror;
667 case MCIWNDM_GETDEVICEID:
668 TRACE("MCIWNDM_GETDEVICEID\n");
669 return mwi->mci;
671 case MCIWNDM_GETALIAS:
672 TRACE("MCIWNDM_GETALIAS\n");
673 return mwi->alias;
675 case MCIWNDM_GET_SOURCE:
677 MCI_DGV_RECT_PARMS mci_rect;
679 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WHERE,
680 MCI_DGV_WHERE_SOURCE,
681 (DWORD_PTR)&mci_rect);
682 if (mwi->lasterror)
684 MCIWND_notify_error(mwi);
685 return mwi->lasterror;
687 *(RECT *)lParam = mci_rect.rc;
688 TRACE("MCIWNDM_GET_SOURCE: %s\n", wine_dbgstr_rect(&mci_rect.rc));
689 return 0;
692 case MCIWNDM_GET_DEST:
694 MCI_DGV_RECT_PARMS mci_rect;
696 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WHERE,
697 MCI_DGV_WHERE_DESTINATION,
698 (DWORD_PTR)&mci_rect);
699 if (mwi->lasterror)
701 MCIWND_notify_error(mwi);
702 return mwi->lasterror;
704 *(RECT *)lParam = mci_rect.rc;
705 TRACE("MCIWNDM_GET_DEST: %s\n", wine_dbgstr_rect(&mci_rect.rc));
706 return 0;
709 case MCIWNDM_PUT_SOURCE:
711 MCI_DGV_PUT_PARMS mci_put;
713 mci_put.rc = *(RECT *)lParam;
714 TRACE("MCIWNDM_PUT_SOURCE: %s\n", wine_dbgstr_rect(&mci_put.rc));
715 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
716 MCI_DGV_PUT_SOURCE,
717 (DWORD_PTR)&mci_put);
718 if (mwi->lasterror)
720 MCIWND_notify_error(mwi);
721 return mwi->lasterror;
723 return 0;
726 case MCIWNDM_PUT_DEST:
728 MCI_DGV_PUT_PARMS mci_put;
730 mci_put.rc = *(RECT *)lParam;
731 TRACE("MCIWNDM_PUT_DEST: %s\n", wine_dbgstr_rect(&mci_put.rc));
733 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
734 MCI_DGV_PUT_DESTINATION | MCI_DGV_RECT,
735 (DWORD_PTR)&mci_put);
736 if (mwi->lasterror)
738 MCIWND_notify_error(mwi);
739 return mwi->lasterror;
741 return 0;
744 case MCIWNDM_GETLENGTH:
746 MCI_STATUS_PARMS mci_status;
748 mci_status.dwItem = MCI_STATUS_LENGTH;
749 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
750 MCI_STATUS_ITEM,
751 (DWORD_PTR)&mci_status);
752 if (mwi->lasterror)
754 MCIWND_notify_error(mwi);
755 return 0;
757 TRACE("MCIWNDM_GETLENGTH: %Id\n", mci_status.dwReturn);
758 return mci_status.dwReturn;
761 case MCIWNDM_GETSTART:
763 MCI_STATUS_PARMS mci_status;
765 mci_status.dwItem = MCI_STATUS_POSITION;
766 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
767 MCI_STATUS_ITEM | MCI_STATUS_START,
768 (DWORD_PTR)&mci_status);
769 if (mwi->lasterror)
771 MCIWND_notify_error(mwi);
772 return 0;
774 TRACE("MCIWNDM_GETSTART: %Id\n", mci_status.dwReturn);
775 return mci_status.dwReturn;
778 case MCIWNDM_GETEND:
780 LRESULT start, length;
782 start = SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
783 length = SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
784 TRACE("MCIWNDM_GETEND: %Id\n", start + length);
785 return (start + length);
788 case MCIWNDM_GETPOSITIONA:
789 case MCIWNDM_GETPOSITIONW:
791 MCI_STATUS_PARMS mci_status;
793 TRACE("MCIWNDM_GETPOSITION\n");
795 /* get position string if requested */
796 if (wParam && lParam)
798 if (wMsg == MCIWNDM_GETPOSITIONA)
800 char cmd[64];
802 wsprintfA(cmd, "status %d position", mwi->alias);
803 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
805 else
808 WCHAR cmdW[64];
809 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','p','o','s','i','t','i','o','n',0};
811 wsprintfW(cmdW, formatW, mwi->alias);
812 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
815 if (mwi->lasterror)
816 return 0;
819 mci_status.dwItem = MCI_STATUS_POSITION;
820 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
821 MCI_STATUS_ITEM,
822 (DWORD_PTR)&mci_status);
823 if (mwi->lasterror)
824 return 0;
826 return mci_status.dwReturn;
829 case MCIWNDM_GETMODEA:
830 case MCIWNDM_GETMODEW:
832 MCI_STATUS_PARMS mci_status;
834 TRACE("MCIWNDM_GETMODE\n");
836 if (!mwi->mci)
837 return MCI_MODE_NOT_READY;
839 /* get mode string if requested */
840 if (wParam && lParam)
842 if (wMsg == MCIWNDM_GETMODEA)
844 char cmd[64];
846 wsprintfA(cmd, "status %d mode", mwi->alias);
847 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
849 else
852 WCHAR cmdW[64];
853 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','m','o','d','e',0};
855 wsprintfW(cmdW, formatW, mwi->alias);
856 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
859 if (mwi->lasterror)
860 return MCI_MODE_NOT_READY;
863 mci_status.dwItem = MCI_STATUS_MODE;
864 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
865 MCI_STATUS_ITEM,
866 (DWORD_PTR)&mci_status);
867 if (mwi->lasterror)
868 return MCI_MODE_NOT_READY;
870 return mci_status.dwReturn;
873 case MCIWNDM_PLAYFROM:
875 MCI_PLAY_PARMS mci_play;
877 TRACE("MCIWNDM_PLAYFROM %08Ix\n", lParam);
879 mci_play.dwCallback = (DWORD_PTR)hWnd;
880 mci_play.dwFrom = lParam;
881 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
882 MCI_FROM | MCI_NOTIFY,
883 (DWORD_PTR)&mci_play);
884 if (mwi->lasterror)
886 MCIWND_notify_error(mwi);
887 return mwi->lasterror;
890 MCIWND_notify_mode(mwi);
891 MCIWND_UpdateState(mwi);
892 return 0;
895 case MCIWNDM_PLAYTO:
897 MCI_PLAY_PARMS mci_play;
899 TRACE("MCIWNDM_PLAYTO %08Ix\n", lParam);
901 mci_play.dwCallback = (DWORD_PTR)hWnd;
902 mci_play.dwTo = lParam;
903 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
904 MCI_TO | MCI_NOTIFY,
905 (DWORD_PTR)&mci_play);
906 if (mwi->lasterror)
908 MCIWND_notify_error(mwi);
909 return mwi->lasterror;
912 MCIWND_notify_mode(mwi);
913 MCIWND_UpdateState(mwi);
914 return 0;
917 case MCIWNDM_PLAYREVERSE:
919 MCI_PLAY_PARMS mci_play;
920 DWORD flags = MCI_NOTIFY;
922 TRACE("MCIWNDM_PLAYREVERSE %08Ix\n", lParam);
924 mci_play.dwCallback = (DWORD_PTR)hWnd;
925 mci_play.dwFrom = lParam;
926 switch (mwi->dev_type)
928 default:
929 case MCI_DEVTYPE_ANIMATION:
930 flags |= MCI_ANIM_PLAY_REVERSE;
931 break;
933 case MCI_DEVTYPE_DIGITAL_VIDEO:
934 flags |= MCI_DGV_PLAY_REVERSE;
935 break;
937 #ifdef MCI_VCR_PLAY_REVERSE
938 case MCI_DEVTYPE_VCR:
939 flags |= MCI_VCR_PLAY_REVERSE;
940 break;
941 #endif
943 case MCI_DEVTYPE_VIDEODISC:
944 flags |= MCI_VD_PLAY_REVERSE;
945 break;
948 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
949 flags, (DWORD_PTR)&mci_play);
950 if (mwi->lasterror)
952 MCIWND_notify_error(mwi);
953 return mwi->lasterror;
956 MCIWND_notify_mode(mwi);
957 MCIWND_UpdateState(mwi);
958 return 0;
961 case MCIWNDM_GETERRORA:
962 mciGetErrorStringA(mwi->lasterror, (LPSTR)lParam, wParam);
963 TRACE("MCIWNDM_GETERRORA: %s\n", debugstr_an((LPSTR)lParam, wParam));
964 return mwi->lasterror;
966 case MCIWNDM_GETERRORW:
967 mciGetErrorStringW(mwi->lasterror, (LPWSTR)lParam, wParam);
968 TRACE("MCIWNDM_GETERRORW: %s\n", debugstr_wn((LPWSTR)lParam, wParam));
969 return mwi->lasterror;
971 case MCIWNDM_SETOWNER:
972 TRACE("MCIWNDM_SETOWNER %p\n", (HWND)wParam);
973 mwi->hwndOwner = (HWND)wParam;
974 return 0;
976 case MCIWNDM_SENDSTRINGA:
978 UNICODE_STRING stringW;
980 TRACE("MCIWNDM_SENDSTRINGA %s\n", debugstr_a((LPCSTR)lParam));
982 RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
983 lParam = (LPARAM)stringW.Buffer;
985 /* fall through */
986 case MCIWNDM_SENDSTRINGW:
988 WCHAR *cmdW, *p;
990 TRACE("MCIWNDM_SENDSTRINGW %s\n", debugstr_w((LPCWSTR)lParam));
992 p = wcschr((LPCWSTR)lParam, ' ');
993 if (p)
995 static const WCHAR formatW[] = {'%','d',' ',0};
996 int len, pos;
998 pos = p - (WCHAR *)lParam + 1;
999 len = lstrlenW((LPCWSTR)lParam) + 64;
1001 cmdW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1003 memcpy(cmdW, (void *)lParam, pos * sizeof(WCHAR));
1004 wsprintfW(cmdW + pos, formatW, mwi->alias);
1005 lstrcatW(cmdW, (WCHAR *)lParam + pos);
1007 else
1008 cmdW = (LPWSTR)lParam;
1010 mwi->lasterror = mciSendStringW(cmdW, mwi->return_string,
1011 ARRAY_SIZE(mwi->return_string), 0);
1012 if (mwi->lasterror)
1013 MCIWND_notify_error(mwi);
1015 if (cmdW != (LPWSTR)lParam)
1016 HeapFree(GetProcessHeap(), 0, cmdW);
1018 if (wMsg == MCIWNDM_SENDSTRINGA)
1019 HeapFree(GetProcessHeap(), 0, (void *)lParam);
1021 MCIWND_UpdateState(mwi);
1022 return mwi->lasterror;
1025 case MCIWNDM_RETURNSTRINGA:
1026 WideCharToMultiByte(CP_ACP, 0, mwi->return_string, -1, (LPSTR)lParam, wParam, NULL, NULL);
1027 TRACE("MCIWNDM_RETURNTRINGA %s\n", debugstr_an((LPSTR)lParam, wParam));
1028 return mwi->lasterror;
1030 case MCIWNDM_RETURNSTRINGW:
1031 lstrcpynW((LPWSTR)lParam, mwi->return_string, wParam);
1032 TRACE("MCIWNDM_RETURNTRINGW %s\n", debugstr_wn((LPWSTR)lParam, wParam));
1033 return mwi->lasterror;
1035 case MCIWNDM_SETTIMERS:
1036 TRACE("MCIWNDM_SETTIMERS active %d ms, inactive %d ms\n", (int)wParam, (int)lParam);
1037 mwi->active_timer = (WORD)wParam;
1038 mwi->inactive_timer = (WORD)lParam;
1039 return 0;
1041 case MCIWNDM_SETACTIVETIMER:
1042 TRACE("MCIWNDM_SETACTIVETIMER %d ms\n", (int)wParam);
1043 mwi->active_timer = (WORD)wParam;
1044 return 0;
1046 case MCIWNDM_SETINACTIVETIMER:
1047 TRACE("MCIWNDM_SETINACTIVETIMER %d ms\n", (int)wParam);
1048 mwi->inactive_timer = (WORD)wParam;
1049 return 0;
1051 case MCIWNDM_GETACTIVETIMER:
1052 TRACE("MCIWNDM_GETACTIVETIMER: %d ms\n", mwi->active_timer);
1053 return mwi->active_timer;
1055 case MCIWNDM_GETINACTIVETIMER:
1056 TRACE("MCIWNDM_GETINACTIVETIMER: %d ms\n", mwi->inactive_timer);
1057 return mwi->inactive_timer;
1059 case MCIWNDM_CHANGESTYLES:
1060 TRACE("MCIWNDM_CHANGESTYLES mask %08Ix, set %08Ix\n", wParam, lParam);
1061 /* FIXME: update the visual window state as well:
1062 * add/remove trackbar, autosize, etc.
1064 mwi->dwStyle &= ~wParam;
1065 mwi->dwStyle |= lParam & wParam;
1066 return 0;
1068 case MCIWNDM_GETSTYLES:
1069 TRACE("MCIWNDM_GETSTYLES: %08lx\n", mwi->dwStyle & 0xffff);
1070 return mwi->dwStyle & 0xffff;
1072 case MCIWNDM_GETDEVICEA:
1074 int len = 0;
1075 char *str = (char *)lParam;
1076 MCI_SYSINFO_PARMSA mci_sysinfo;
1078 mci_sysinfo.lpstrReturn = str;
1079 mci_sysinfo.dwRetSize = wParam;
1080 mwi->lasterror = mciSendCommandA(mwi->mci, MCI_SYSINFO,
1081 MCI_SYSINFO_INSTALLNAME,
1082 (DWORD_PTR)&mci_sysinfo);
1083 while(len < wParam && str[len]) len++;
1084 TRACE("MCIWNDM_GETDEVICEA: %s\n", debugstr_an(str, len));
1085 return 0;
1088 case MCIWNDM_GETDEVICEW:
1090 int len = 0;
1091 WCHAR *str = (WCHAR *)lParam;
1092 MCI_SYSINFO_PARMSW mci_sysinfo;
1094 mci_sysinfo.lpstrReturn = str;
1095 mci_sysinfo.dwRetSize = wParam;
1096 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SYSINFO,
1097 MCI_SYSINFO_INSTALLNAME,
1098 (DWORD_PTR)&mci_sysinfo);
1099 while(len < wParam && str[len]) len++;
1100 TRACE("MCIWNDM_GETDEVICEW: %s\n", debugstr_wn(str, len));
1101 return 0;
1104 case MCIWNDM_VALIDATEMEDIA:
1105 TRACE("MCIWNDM_VALIDATEMEDIA\n");
1106 if (mwi->mci)
1108 SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
1109 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
1111 return 0;
1113 case MCIWNDM_GETFILENAMEA:
1114 TRACE("MCIWNDM_GETFILENAMEA: %s\n", debugstr_w(mwi->lpName));
1115 if (mwi->lpName)
1116 WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, (LPSTR)lParam, wParam, NULL, NULL);
1117 return 0;
1119 case MCIWNDM_GETFILENAMEW:
1120 TRACE("MCIWNDM_GETFILENAMEW: %s\n", debugstr_w(mwi->lpName));
1121 if (mwi->lpName)
1122 lstrcpynW((LPWSTR)lParam, mwi->lpName, wParam);
1123 return 0;
1125 case MCIWNDM_GETTIMEFORMATA:
1126 case MCIWNDM_GETTIMEFORMATW:
1128 MCI_STATUS_PARMS mci_status;
1130 TRACE("MCIWNDM_GETTIMEFORMAT %08Ix %08Ix\n", wParam, lParam);
1132 /* get format string if requested */
1133 if (wParam && lParam)
1135 if (wMsg == MCIWNDM_GETTIMEFORMATA)
1137 char cmd[64];
1139 wsprintfA(cmd, "status %d time format", mwi->alias);
1140 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
1141 if (mwi->lasterror)
1142 return 0;
1144 else
1146 WCHAR cmdW[64];
1147 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',0};
1149 wsprintfW(cmdW, formatW, mwi->alias);
1150 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
1151 if (mwi->lasterror)
1152 return 0;
1156 mci_status.dwItem = MCI_STATUS_TIME_FORMAT ;
1157 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
1158 MCI_STATUS_ITEM,
1159 (DWORD_PTR)&mci_status);
1160 if (mwi->lasterror)
1161 return 0;
1163 return mci_status.dwReturn;
1166 case MCIWNDM_SETTIMEFORMATA:
1168 UNICODE_STRING stringW;
1170 TRACE("MCIWNDM_SETTIMEFORMATA %s\n", debugstr_a((LPSTR)lParam));
1172 RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
1173 lParam = (LPARAM)stringW.Buffer;
1175 /* fall through */
1176 case MCIWNDM_SETTIMEFORMATW:
1178 static const WCHAR formatW[] = {'s','e','t',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',' ',0};
1179 WCHAR *cmdW;
1181 TRACE("MCIWNDM_SETTIMEFORMATW %s\n", debugstr_w((LPWSTR)lParam));
1183 if (mwi->mci)
1185 cmdW = HeapAlloc(GetProcessHeap(), 0, (lstrlenW((LPCWSTR)lParam) + 64) * sizeof(WCHAR));
1186 wsprintfW(cmdW, formatW, mwi->alias);
1187 lstrcatW(cmdW, (WCHAR *)lParam);
1189 mwi->lasterror = mciSendStringW(cmdW, NULL, 0, 0);
1191 /* fix the range tracking according to the new time format */
1192 if (!mwi->lasterror)
1193 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1,
1194 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0));
1196 HeapFree(GetProcessHeap(), 0, cmdW);
1199 if (wMsg == MCIWNDM_SETTIMEFORMATA)
1200 HeapFree(GetProcessHeap(), 0, (void *)lParam);
1202 return 0;
1205 case MCIWNDM_CAN_PLAY:
1206 TRACE("MCIWNDM_CAN_PLAY\n");
1207 if (mwi->mci)
1208 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_PLAY);
1209 return 0;
1211 case MCIWNDM_CAN_RECORD:
1212 TRACE("MCIWNDM_CAN_RECORD\n");
1213 if (mwi->mci)
1214 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_RECORD);
1215 return 0;
1217 case MCIWNDM_CAN_SAVE:
1218 TRACE("MCIWNDM_CAN_SAVE\n");
1219 if (mwi->mci)
1220 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_SAVE);
1221 return 0;
1223 case MCIWNDM_CAN_EJECT:
1224 TRACE("MCIWNDM_CAN_EJECT\n");
1225 if (mwi->mci)
1226 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_EJECT);
1227 return 0;
1229 case MCIWNDM_CAN_WINDOW:
1230 TRACE("MCIWNDM_CAN_WINDOW\n");
1231 switch (mwi->dev_type)
1233 case MCI_DEVTYPE_ANIMATION:
1234 case MCI_DEVTYPE_DIGITAL_VIDEO:
1235 case MCI_DEVTYPE_OVERLAY:
1236 return 1;
1238 return 0;
1240 case MCIWNDM_CAN_CONFIG:
1241 TRACE("MCIWNDM_CAN_CONFIG\n");
1242 if (mwi->hdrv)
1243 return SendDriverMessage(mwi->hdrv, DRV_QUERYCONFIGURE, 0, 0);
1244 return 0;
1246 case MCIWNDM_SETZOOM:
1247 TRACE("MCIWNDM_SETZOOM %Id\n", lParam);
1248 mwi->zoom = lParam;
1250 if (mwi->mci && !(mwi->dwStyle & MCIWNDF_NOAUTOSIZEWINDOW))
1252 RECT rc;
1254 rc.left = rc.top = 0;
1255 rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
1256 rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
1258 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
1259 rc.bottom += 32; /* add the height of the playbar */
1260 AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
1261 SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
1262 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1264 return 0;
1266 case MCIWNDM_GETZOOM:
1267 TRACE("MCIWNDM_GETZOOM: %d\n", mwi->zoom);
1268 return mwi->zoom;
1270 case MCIWNDM_EJECT:
1272 MCI_SET_PARMS mci_set;
1274 TRACE("MCIWNDM_EJECT\n");
1276 mci_set.dwCallback = (DWORD_PTR)hWnd;
1277 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SET,
1278 MCI_SET_DOOR_OPEN | MCI_NOTIFY,
1279 (DWORD_PTR)&mci_set);
1280 MCIWND_notify_mode(mwi);
1281 MCIWND_UpdateState(mwi);
1282 return mwi->lasterror;
1285 case MCIWNDM_SETVOLUME:
1286 case MCIWNDM_GETVOLUME:
1287 case MCIWNDM_SETSPEED:
1288 case MCIWNDM_GETSPEED:
1289 case MCIWNDM_SETREPEAT:
1290 case MCIWNDM_GETREPEAT:
1291 case MCIWNDM_REALIZE:
1292 case MCIWNDM_GETPALETTE:
1293 case MCIWNDM_SETPALETTE:
1294 case MCIWNDM_NEWA:
1295 case MCIWNDM_NEWW:
1296 case MCIWNDM_PALETTEKICK:
1297 case MCIWNDM_OPENINTERFACE:
1298 FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
1299 return 0;
1301 case MCI_PLAY:
1303 LRESULT end = SendMessageW(hWnd, MCIWNDM_GETEND, 0, 0);
1304 return SendMessageW(hWnd, MCIWNDM_PLAYTO, 0, end);
1307 case MCI_SEEK:
1308 case MCI_STEP:
1310 MCI_SEEK_PARMS mci_seek; /* Layout is usable as MCI_XYZ_STEP_PARMS */
1311 DWORD flags = MCI_STEP == wMsg ? 0 :
1312 MCIWND_START == lParam ? MCI_SEEK_TO_START :
1313 MCIWND_END == lParam ? MCI_SEEK_TO_END : MCI_TO;
1315 mci_seek.dwTo = lParam;
1316 mwi->lasterror = mciSendCommandW(mwi->mci, wMsg,
1317 flags, (DWORD_PTR)&mci_seek);
1318 if (mwi->lasterror)
1320 MCIWND_notify_error(mwi);
1321 return mwi->lasterror;
1323 /* update window to reflect the state */
1324 else InvalidateRect(hWnd, NULL, TRUE);
1325 return 0;
1328 case MCI_CLOSE:
1330 RECT rc;
1331 MCI_GENERIC_PARMS mci_generic;
1333 if (mwi->hdrv)
1335 CloseDriver(mwi->hdrv, 0, 0);
1336 mwi->hdrv = 0;
1339 if (mwi->mci)
1341 mci_generic.dwCallback = 0;
1342 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_CLOSE,
1343 0, (DWORD_PTR)&mci_generic);
1344 mwi->mci = 0;
1347 mwi->mode = MCI_MODE_NOT_READY;
1348 mwi->position = -1;
1350 HeapFree(GetProcessHeap(), 0, mwi->lpName);
1351 mwi->lpName = NULL;
1352 MCIWND_UpdateState(mwi);
1354 GetClientRect(hWnd, &rc);
1355 rc.bottom = rc.top;
1356 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
1357 rc.bottom += 32; /* add the height of the playbar */
1358 AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
1359 SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left,
1360 rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1362 MCIWND_notify_media(mwi);
1363 return 0;
1366 case MCI_PAUSE:
1367 case MCI_STOP:
1368 case MCI_RESUME:
1369 mci_generic_command(mwi, wMsg);
1370 return mwi->lasterror;
1372 case MCI_CONFIGURE:
1373 if (mwi->hdrv)
1374 SendDriverMessage(mwi->hdrv, DRV_CONFIGURE, (LPARAM)hWnd, 0);
1375 return 0;
1377 case MCI_BREAK:
1378 case MCI_CAPTURE:
1379 case MCI_COPY:
1380 case MCI_CUE:
1381 case MCI_CUT:
1382 case MCI_DELETE:
1383 case MCI_ESCAPE:
1384 case MCI_FREEZE:
1385 case MCI_GETDEVCAPS:
1386 /*case MCI_INDEX:*/
1387 case MCI_INFO:
1388 case MCI_LIST:
1389 case MCI_LOAD:
1390 /*case MCI_MARK:*/
1391 case MCI_MONITOR:
1392 case MCI_OPEN:
1393 case MCI_PASTE:
1394 case MCI_PUT:
1395 case MCI_QUALITY:
1396 case MCI_REALIZE:
1397 case MCI_RECORD:
1398 case MCI_RESERVE:
1399 case MCI_RESTORE:
1400 case MCI_SAVE:
1401 case MCI_SET:
1402 case MCI_SETAUDIO:
1403 /*case MCI_SETTIMECODE:*/
1404 /*case MCI_SETTUNER:*/
1405 case MCI_SETVIDEO:
1406 case MCI_SIGNAL:
1407 case MCI_SPIN:
1408 case MCI_STATUS:
1409 case MCI_SYSINFO:
1410 case MCI_UNDO:
1411 case MCI_UNFREEZE:
1412 case MCI_UPDATE:
1413 case MCI_WHERE:
1414 case MCI_WINDOW:
1415 FIXME("support for MCI_ command %04x not implemented\n", wMsg);
1416 return 0;
1419 if (wMsg >= WM_USER)
1421 FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
1422 return 0;
1425 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1426 return DefMDIChildProcW(hWnd, wMsg, wParam, lParam);
1428 return DefWindowProcW(hWnd, wMsg, wParam, lParam);