riched20/tests: Don't cast NULL.
[wine.git] / dlls / msvfw32 / mciwnd.c
blob0b35bad356c05cec7dac33532b5065750d99b5cd
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};
42 typedef struct
44 DWORD dwStyle;
45 MCIDEVICEID mci;
46 HDRVR hdrv;
47 int alias;
48 UINT dev_type;
49 UINT mode;
50 LONG position;
51 SIZE size; /* size of the original frame rect */
52 int zoom;
53 LPWSTR lpName;
54 HWND hWnd, hwndOwner;
55 UINT uTimer;
56 MCIERROR lasterror;
57 WCHAR return_string[128];
58 WORD active_timer, inactive_timer;
59 } MCIWndInfo;
61 static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
63 #define CTL_PLAYSTOP 0x3200
64 #define CTL_MENU 0x3201
65 #define CTL_TRACKBAR 0x3202
67 /***********************************************************************
68 * MCIWndRegisterClass [MSVFW32.@]
70 * NOTE: Native always uses its own hInstance
72 BOOL VFWAPIV MCIWndRegisterClass(void)
74 WNDCLASSW wc;
76 /* Since we are going to register a class belonging to MSVFW32
77 * and later we will create windows with a different hInstance
78 * CS_GLOBALCLASS is needed. And because the second attempt
79 * to register a global class will fail we need to test whether
80 * the class was already registered.
82 wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC | CS_GLOBALCLASS;
83 wc.lpfnWndProc = MCIWndProc;
84 wc.cbClsExtra = 0;
85 wc.cbWndExtra = sizeof(MCIWndInfo*);
86 wc.hInstance = MSVFW32_hModule;
87 wc.hIcon = 0;
88 wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
89 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
90 wc.lpszMenuName = NULL;
91 wc.lpszClassName = mciWndClassW;
93 if (RegisterClassW(&wc)) return TRUE;
94 if (GetLastError() == ERROR_CLASS_ALREADY_EXISTS) return TRUE;
96 return FALSE;
99 /***********************************************************************
100 * MCIWndCreateW [MSVFW32.@]
102 HWND VFWAPIV MCIWndCreateW(HWND hwndParent, HINSTANCE hInstance,
103 DWORD dwStyle, LPCWSTR szFile)
105 TRACE("%p %p %x %s\n", hwndParent, hInstance, dwStyle, debugstr_w(szFile));
107 MCIWndRegisterClass();
109 if (!hInstance) hInstance = GetModuleHandleW(0);
111 if (hwndParent)
112 dwStyle |= WS_VISIBLE | WS_BORDER /*| WS_CHILD*/;
113 else
114 dwStyle |= WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
116 return CreateWindowExW(0, mciWndClassW, NULL,
117 dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
118 0, 0, 300, 0,
119 hwndParent, 0, hInstance, (LPVOID)szFile);
122 /***********************************************************************
123 * MCIWndCreate [MSVFW32.@]
124 * MCIWndCreateA [MSVFW32.@]
126 HWND VFWAPIV MCIWndCreateA(HWND hwndParent, HINSTANCE hInstance,
127 DWORD dwStyle, LPCSTR szFile)
129 HWND ret;
130 UNICODE_STRING fileW;
132 if (szFile)
133 RtlCreateUnicodeStringFromAsciiz(&fileW, szFile);
134 else
135 fileW.Buffer = NULL;
137 ret = MCIWndCreateW(hwndParent, hInstance, dwStyle, fileW.Buffer);
139 RtlFreeUnicodeString(&fileW);
140 return ret;
143 static inline void MCIWND_notify_mode(MCIWndInfo *mwi)
145 if (mwi->dwStyle & MCIWNDF_NOTIFYMODE)
147 UINT new_mode = SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0);
148 if (new_mode != mwi->mode)
150 mwi->mode = new_mode;
151 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMODE, (WPARAM)mwi->hWnd, new_mode);
156 static inline void MCIWND_notify_pos(MCIWndInfo *mwi)
158 if (mwi->dwStyle & MCIWNDF_NOTIFYPOS)
160 LONG new_pos = SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 0, 0);
161 if (new_pos != mwi->position)
163 mwi->position = new_pos;
164 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYPOS, (WPARAM)mwi->hWnd, new_pos);
169 static inline void MCIWND_notify_size(MCIWndInfo *mwi)
171 if (mwi->dwStyle & MCIWNDF_NOTIFYSIZE)
172 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYSIZE, (WPARAM)mwi->hWnd, 0);
175 static inline void MCIWND_notify_error(MCIWndInfo *mwi)
177 if (mwi->dwStyle & MCIWNDF_NOTIFYERROR)
178 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYERROR, (WPARAM)mwi->hWnd, (LPARAM)mwi->lasterror);
181 static void MCIWND_UpdateState(MCIWndInfo *mwi)
183 WCHAR buffer[1024];
185 if (!mwi->mci)
187 /* FIXME: get this from resources */
188 static const WCHAR no_deviceW[] = {'N','o',' ','D','e','v','i','c','e',0};
189 SetWindowTextW(mwi->hWnd, no_deviceW);
190 return;
193 MCIWND_notify_pos(mwi);
195 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
196 SendDlgItemMessageW(mwi->hWnd, CTL_TRACKBAR, TBM_SETPOS, TRUE, mwi->position);
198 if (!(mwi->dwStyle & MCIWNDF_SHOWALL))
199 return;
201 if ((mwi->dwStyle & MCIWNDF_SHOWNAME) && mwi->lpName)
202 lstrcpyW(buffer, mwi->lpName);
203 else
204 *buffer = 0;
206 if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
208 static const WCHAR spaceW[] = {' ',0};
209 static const WCHAR l_braceW[] = {'(',0};
211 if (*buffer) lstrcatW(buffer, spaceW);
212 lstrcatW(buffer, l_braceW);
215 if (mwi->dwStyle & MCIWNDF_SHOWPOS)
217 WCHAR posW[64];
219 posW[0] = 0;
220 SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 64, (LPARAM)posW);
221 lstrcatW(buffer, posW);
224 if ((mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) == (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
226 static const WCHAR dashW[] = {' ','-',' ',0};
227 lstrcatW(buffer, dashW);
230 if (mwi->dwStyle & MCIWNDF_SHOWMODE)
232 WCHAR modeW[64];
234 modeW[0] = 0;
235 SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 64, (LPARAM)modeW);
236 lstrcatW(buffer, modeW);
239 if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
241 static const WCHAR r_braceW[] = {')',0};
242 lstrcatW(buffer, r_braceW);
245 TRACE("=> %s\n", debugstr_w(buffer));
246 SetWindowTextW(mwi->hWnd, buffer);
249 static LRESULT MCIWND_Create(HWND hWnd, LPCREATESTRUCTW cs)
251 HWND hChld;
252 MCIWndInfo *mwi;
253 static const WCHAR buttonW[] = {'b','u','t','t','o','n',0};
255 mwi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mwi));
256 if (!mwi) return -1;
258 SetWindowLongW(hWnd, 0, (LPARAM)mwi);
260 mwi->dwStyle = cs->style;
261 /* There is no need to show stats if there is no caption */
262 if ((mwi->dwStyle & WS_CAPTION) != WS_CAPTION)
263 mwi->dwStyle &= ~MCIWNDF_SHOWALL;
265 mwi->hWnd = hWnd;
266 mwi->hwndOwner = cs->hwndParent;
267 mwi->active_timer = 500;
268 mwi->inactive_timer = 2000;
269 mwi->mode = MCI_MODE_NOT_READY;
270 mwi->position = -1;
271 mwi->zoom = 100;
273 if (!(mwi->dwStyle & MCIWNDF_NOMENU))
275 static const WCHAR menuW[] = {'M','e','n','u',0};
277 hChld = CreateWindowExW(0, buttonW, menuW, WS_CHILD|WS_VISIBLE, 32, cs->cy, 32, 32,
278 hWnd, (HMENU)CTL_MENU, cs->hInstance, 0L);
279 TRACE("Get Button2: %p\n", hChld);
282 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
284 INITCOMMONCONTROLSEX init;
285 static const WCHAR playW[] = {'P','l','a','y',0};
287 /* adding the other elements: play/stop button, menu button, status */
288 hChld = CreateWindowExW(0, buttonW, playW, WS_CHILD|WS_VISIBLE, 0, cs->cy, 32, 32,
289 hWnd, (HMENU)CTL_PLAYSTOP, cs->hInstance, 0L);
290 TRACE("Get Button1: %p\n", hChld);
292 init.dwSize = sizeof(init);
293 init.dwICC = ICC_BAR_CLASSES;
294 InitCommonControlsEx(&init);
296 hChld = CreateWindowExW(0, TRACKBAR_CLASSW, NULL, WS_CHILD|WS_VISIBLE, 64, cs->cy, cs->cx - 64, 32,
297 hWnd, (HMENU)CTL_TRACKBAR, cs->hInstance, 0L);
298 TRACE("Get status: %p\n", hChld);
301 /* This sets the default window size */
302 SendMessageW(hWnd, MCI_CLOSE, 0, 0);
304 if (cs->lpCreateParams)
306 LPARAM lParam;
308 /* MCI wnd class is prepared to be embedded as an MDI child window */
309 if (cs->dwExStyle & WS_EX_MDICHILD)
311 MDICREATESTRUCTW *mdics = cs->lpCreateParams;
312 lParam = mdics->lParam;
314 else
315 lParam = (LPARAM)cs->lpCreateParams;
317 /* If it's our internal class pointer, file name is a unicode string */
318 if (cs->lpszClass == mciWndClassW)
319 SendMessageW(hWnd, MCIWNDM_OPENW, 0, lParam);
320 else
322 /* Otherwise let's try to figure out what string format is used */
323 HWND parent = cs->hwndParent;
324 if (!parent) parent = GetWindow(hWnd, GW_OWNER);
326 SendMessageW(hWnd, IsWindowUnicode(parent) ? MCIWNDM_OPENW : MCIWNDM_OPENA, 0, lParam);
330 return 0;
333 static void MCIWND_ToggleState(MCIWndInfo *mwi)
335 switch (SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0))
337 case MCI_MODE_NOT_READY:
338 case MCI_MODE_RECORD:
339 case MCI_MODE_SEEK:
340 case MCI_MODE_OPEN:
341 TRACE("Cannot do much...\n");
342 break;
344 case MCI_MODE_PAUSE:
345 SendMessageW(mwi->hWnd, MCI_RESUME, 0, 0);
346 break;
348 case MCI_MODE_PLAY:
349 SendMessageW(mwi->hWnd, MCI_PAUSE, 0, 0);
350 break;
352 case MCI_MODE_STOP:
353 SendMessageW(mwi->hWnd, MCI_STOP, 0, 0);
354 break;
358 static LRESULT MCIWND_Command(MCIWndInfo *mwi, WPARAM wParam, LPARAM lParam)
360 switch (LOWORD(wParam))
362 case CTL_PLAYSTOP: MCIWND_ToggleState(mwi); break;
363 case CTL_MENU:
364 case CTL_TRACKBAR:
365 default:
366 FIXME("support for command %04x not implement yet\n", LOWORD(wParam));
368 return 0L;
371 static void MCIWND_notify_media(MCIWndInfo *mwi)
373 if (mwi->dwStyle & (MCIWNDF_NOTIFYMEDIAA | MCIWNDF_NOTIFYMEDIAW))
375 if (!mwi->lpName)
377 static const WCHAR empty_str[1];
378 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)empty_str);
380 else
382 if (mwi->dwStyle & MCIWNDF_NOTIFYANSI)
384 char *ansi_name;
385 int len;
387 len = WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, NULL, 0, NULL, NULL);
388 ansi_name = HeapAlloc(GetProcessHeap(), 0, len);
389 WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, ansi_name, len, NULL, NULL);
391 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)ansi_name);
393 HeapFree(GetProcessHeap(), 0, ansi_name);
395 else
396 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)mwi->lpName);
401 static MCIERROR mci_generic_command(MCIWndInfo *mwi, UINT cmd)
403 MCI_GENERIC_PARMS mci_generic;
405 mci_generic.dwCallback = 0;
406 mwi->lasterror = mciSendCommandW(mwi->mci, cmd, 0, (DWORD_PTR)&mci_generic);
408 if (mwi->lasterror)
409 return mwi->lasterror;
411 MCIWND_notify_mode(mwi);
412 MCIWND_UpdateState(mwi);
413 return 0;
416 static LRESULT mci_get_devcaps(MCIWndInfo *mwi, UINT cap)
418 MCI_GETDEVCAPS_PARMS mci_devcaps;
420 mci_devcaps.dwItem = cap;
421 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
422 MCI_GETDEVCAPS_ITEM,
423 (DWORD_PTR)&mci_devcaps);
424 if (mwi->lasterror)
425 return 0;
427 return mci_devcaps.dwReturn;
430 static LRESULT MCIWND_KeyDown(MCIWndInfo *mwi, UINT key)
432 TRACE("%p, key %04x\n", mwi->hWnd, key);
434 switch(key)
436 case VK_ESCAPE:
437 SendMessageW(mwi->hWnd, MCI_STOP, 0, 0);
438 return 0;
440 default:
441 return 0;
445 static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
447 MCIWndInfo *mwi;
449 TRACE("%p %04x %08lx %08lx\n", hWnd, wMsg, wParam, lParam);
451 mwi = (MCIWndInfo*)GetWindowLongPtrW(hWnd, 0);
452 if (!mwi && wMsg != WM_CREATE)
453 return DefWindowProcW(hWnd, wMsg, wParam, lParam);
455 switch (wMsg)
457 case WM_CREATE:
458 MCIWND_Create(hWnd, (CREATESTRUCTW *)lParam);
459 break;
461 case WM_DESTROY:
462 if (mwi->uTimer)
463 KillTimer(hWnd, mwi->uTimer);
465 if (mwi->mci)
466 SendMessageW(hWnd, MCI_CLOSE, 0, 0);
468 HeapFree(GetProcessHeap(), 0, mwi);
470 DestroyWindow(GetDlgItem(hWnd, CTL_MENU));
471 DestroyWindow(GetDlgItem(hWnd, CTL_PLAYSTOP));
472 DestroyWindow(GetDlgItem(hWnd, CTL_TRACKBAR));
473 break;
475 case WM_PAINT:
477 MCI_DGV_UPDATE_PARMS mci_update;
478 PAINTSTRUCT ps;
480 mci_update.hDC = (wParam) ? (HDC)wParam : BeginPaint(hWnd, &ps);
482 mciSendCommandW(mwi->mci, MCI_UPDATE,
483 MCI_DGV_UPDATE_HDC | MCI_DGV_UPDATE_PAINT,
484 (DWORD_PTR)&mci_update);
486 if (!wParam) EndPaint(hWnd, &ps);
487 return 1;
490 case WM_COMMAND:
491 return MCIWND_Command(mwi, wParam, lParam);
493 case WM_KEYDOWN:
494 return MCIWND_KeyDown(mwi, wParam);
496 case WM_NCACTIVATE:
497 if (mwi->uTimer)
499 KillTimer(hWnd, mwi->uTimer);
500 mwi->uTimer = SetTimer(hWnd, 1, wParam ? mwi->active_timer : mwi->inactive_timer, NULL);
502 break;
504 case WM_TIMER:
505 MCIWND_UpdateState(mwi);
506 return 0;
508 case WM_SIZE:
509 SetWindowPos(GetDlgItem(hWnd, CTL_PLAYSTOP), 0, 0, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
510 SetWindowPos(GetDlgItem(hWnd, CTL_MENU), 0, 32, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
511 SetWindowPos(GetDlgItem(hWnd, CTL_TRACKBAR), 0, 64, HIWORD(lParam) - 32, LOWORD(lParam) - 64, 32, SWP_NOACTIVATE);
513 if (!(mwi->dwStyle & MCIWNDF_NOAUTOSIZEMOVIE))
515 RECT rc;
517 rc.left = rc.top = 0;
518 rc.right = LOWORD(lParam);
519 rc.bottom = HIWORD(lParam);
520 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
521 rc.bottom -= 32; /* subtract the height of the playbar */
522 SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
524 MCIWND_notify_size(mwi);
525 break;
527 case MM_MCINOTIFY:
528 MCIWND_notify_mode(mwi);
529 MCIWND_UpdateState(mwi);
530 return 0;
532 case MCIWNDM_OPENA:
534 UNICODE_STRING nameW;
535 TRACE("MCIWNDM_OPENA %s\n", debugstr_a((LPSTR)lParam));
536 RtlCreateUnicodeStringFromAsciiz(&nameW, (LPCSTR)lParam);
537 lParam = (LPARAM)nameW.Buffer;
539 /* fall through */
540 case MCIWNDM_OPENW:
542 RECT rc;
543 HCURSOR hCursor;
544 MCI_OPEN_PARMSW mci_open;
545 MCI_GETDEVCAPS_PARMS mci_devcaps;
546 WCHAR aliasW[64];
547 WCHAR drv_name[MAX_PATH];
548 static const WCHAR formatW[] = {'%','d',0};
549 static const WCHAR mci32W[] = {'m','c','i','3','2',0};
550 static const WCHAR system_iniW[] = {'s','y','s','t','e','m','.','i','n','i',0};
552 TRACE("MCIWNDM_OPENW %s\n", debugstr_w((LPWSTR)lParam));
554 if (wParam == MCIWNDOPENF_NEW)
556 SendMessageW(hWnd, MCIWNDM_NEWW, 0, lParam);
557 goto end_of_mci_open;
560 if (mwi->uTimer)
562 KillTimer(hWnd, mwi->uTimer);
563 mwi->uTimer = 0;
566 hCursor = LoadCursorW(0, (LPWSTR)IDC_WAIT);
567 hCursor = SetCursor(hCursor);
569 mci_open.lpstrElementName = (LPWSTR)lParam;
570 wsprintfW(aliasW, formatW, HandleToLong(hWnd) + 1);
571 mci_open.lpstrAlias = aliasW;
572 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_OPEN,
573 MCI_OPEN_ELEMENT | MCI_OPEN_ALIAS | MCI_WAIT,
574 (DWORD_PTR)&mci_open);
575 SetCursor(hCursor);
577 if (mwi->lasterror && !(mwi->dwStyle & MCIWNDF_NOERRORDLG))
579 /* FIXME: get the caption from resources */
580 static const WCHAR caption[] = {'M','C','I',' ','E','r','r','o','r',0};
581 WCHAR error_str[MAXERRORLENGTH];
583 mciGetErrorStringW(mwi->lasterror, error_str, MAXERRORLENGTH);
584 MessageBoxW(hWnd, error_str, caption, MB_ICONEXCLAMATION | MB_OK);
585 MCIWND_notify_error(mwi);
586 goto end_of_mci_open;
589 mwi->mci = mci_open.wDeviceID;
590 mwi->alias = HandleToLong(hWnd) + 1;
592 mwi->lpName = HeapAlloc(GetProcessHeap(), 0, (lstrlenW((LPWSTR)lParam) + 1) * sizeof(WCHAR));
593 lstrcpyW(mwi->lpName, (LPWSTR)lParam);
595 MCIWND_UpdateState(mwi);
597 mci_devcaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
598 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
599 MCI_GETDEVCAPS_ITEM,
600 (DWORD_PTR)&mci_devcaps);
601 if (mwi->lasterror)
603 MCIWND_notify_error(mwi);
604 goto end_of_mci_open;
607 mwi->dev_type = mci_devcaps.dwReturn;
609 drv_name[0] = 0;
610 SendMessageW(hWnd, MCIWNDM_GETDEVICEW, 256, (LPARAM)drv_name);
611 if (drv_name[0] && GetPrivateProfileStringW(mci32W, drv_name, NULL,
612 drv_name, MAX_PATH, system_iniW))
613 mwi->hdrv = OpenDriver(drv_name, NULL, 0);
615 if (mwi->dev_type == MCI_DEVTYPE_DIGITAL_VIDEO)
617 MCI_DGV_WINDOW_PARMSW mci_window;
619 mci_window.hWnd = hWnd;
620 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WINDOW,
621 MCI_DGV_WINDOW_HWND,
622 (DWORD_PTR)&mci_window);
623 if (mwi->lasterror)
625 MCIWND_notify_error(mwi);
626 goto end_of_mci_open;
630 if (SendMessageW(hWnd, MCIWNDM_GET_DEST, 0, (LPARAM)&rc) == 0)
632 mwi->size.cx = rc.right - rc.left;
633 mwi->size.cy = rc.bottom - rc.top;
635 rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
636 rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
637 SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
639 else
641 GetClientRect(hWnd, &rc);
642 rc.bottom = rc.top;
645 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
646 rc.bottom += 32; /* add the height of the playbar */
647 AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
648 SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left,
649 rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
651 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMIN, 0L, 0L);
652 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1,
653 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0));
654 mwi->uTimer = SetTimer(hWnd, 1, mwi->active_timer, NULL);
656 MCIWND_notify_media(mwi);
658 end_of_mci_open:
659 if (wMsg == MCIWNDM_OPENA)
660 HeapFree(GetProcessHeap(), 0, (void *)lParam);
661 return mwi->lasterror;
664 case MCIWNDM_GETDEVICEID:
665 TRACE("MCIWNDM_GETDEVICEID\n");
666 return mwi->mci;
668 case MCIWNDM_GETALIAS:
669 TRACE("MCIWNDM_GETALIAS\n");
670 return mwi->alias;
672 case MCIWNDM_GET_SOURCE:
674 MCI_DGV_RECT_PARMS mci_rect;
676 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WHERE,
677 MCI_DGV_WHERE_SOURCE,
678 (DWORD_PTR)&mci_rect);
679 if (mwi->lasterror)
681 MCIWND_notify_error(mwi);
682 return mwi->lasterror;
684 *(RECT *)lParam = mci_rect.rc;
685 TRACE("MCIWNDM_GET_SOURCE: %s\n", wine_dbgstr_rect(&mci_rect.rc));
686 return 0;
689 case MCIWNDM_GET_DEST:
691 MCI_DGV_RECT_PARMS mci_rect;
693 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WHERE,
694 MCI_DGV_WHERE_DESTINATION,
695 (DWORD_PTR)&mci_rect);
696 if (mwi->lasterror)
698 MCIWND_notify_error(mwi);
699 return mwi->lasterror;
701 *(RECT *)lParam = mci_rect.rc;
702 TRACE("MCIWNDM_GET_DEST: %s\n", wine_dbgstr_rect(&mci_rect.rc));
703 return 0;
706 case MCIWNDM_PUT_SOURCE:
708 MCI_DGV_PUT_PARMS mci_put;
710 mci_put.rc = *(RECT *)lParam;
711 TRACE("MCIWNDM_PUT_SOURCE: %s\n", wine_dbgstr_rect(&mci_put.rc));
712 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
713 MCI_DGV_PUT_SOURCE,
714 (DWORD_PTR)&mci_put);
715 if (mwi->lasterror)
717 MCIWND_notify_error(mwi);
718 return mwi->lasterror;
720 return 0;
723 case MCIWNDM_PUT_DEST:
725 MCI_DGV_PUT_PARMS mci_put;
727 mci_put.rc = *(RECT *)lParam;
728 TRACE("MCIWNDM_PUT_DEST: %s\n", wine_dbgstr_rect(&mci_put.rc));
730 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
731 MCI_DGV_PUT_DESTINATION | MCI_DGV_RECT,
732 (DWORD_PTR)&mci_put);
733 if (mwi->lasterror)
735 MCIWND_notify_error(mwi);
736 return mwi->lasterror;
738 return 0;
741 case MCIWNDM_GETLENGTH:
743 MCI_STATUS_PARMS mci_status;
745 mci_status.dwItem = MCI_STATUS_LENGTH;
746 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
747 MCI_STATUS_ITEM,
748 (DWORD_PTR)&mci_status);
749 if (mwi->lasterror)
751 MCIWND_notify_error(mwi);
752 return 0;
754 TRACE("MCIWNDM_GETLENGTH: %ld\n", mci_status.dwReturn);
755 return mci_status.dwReturn;
758 case MCIWNDM_GETSTART:
760 MCI_STATUS_PARMS mci_status;
762 mci_status.dwItem = MCI_STATUS_POSITION;
763 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
764 MCI_STATUS_ITEM | MCI_STATUS_START,
765 (DWORD_PTR)&mci_status);
766 if (mwi->lasterror)
768 MCIWND_notify_error(mwi);
769 return 0;
771 TRACE("MCIWNDM_GETSTART: %ld\n", mci_status.dwReturn);
772 return mci_status.dwReturn;
775 case MCIWNDM_GETEND:
777 LRESULT start, length;
779 start = SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
780 length = SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
781 TRACE("MCIWNDM_GETEND: %ld\n", start + length);
782 return (start + length);
785 case MCIWNDM_GETPOSITIONA:
786 case MCIWNDM_GETPOSITIONW:
788 MCI_STATUS_PARMS mci_status;
790 TRACE("MCIWNDM_GETPOSITION\n");
792 /* get position string if requested */
793 if (wParam && lParam)
795 if (wMsg == MCIWNDM_GETPOSITIONA)
797 char cmd[64];
799 wsprintfA(cmd, "status %d position", mwi->alias);
800 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
802 else
805 WCHAR cmdW[64];
806 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','p','o','s','i','t','i','o','n',0};
808 wsprintfW(cmdW, formatW, mwi->alias);
809 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
812 if (mwi->lasterror)
813 return 0;
816 mci_status.dwItem = MCI_STATUS_POSITION;
817 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
818 MCI_STATUS_ITEM,
819 (DWORD_PTR)&mci_status);
820 if (mwi->lasterror)
821 return 0;
823 return mci_status.dwReturn;
826 case MCIWNDM_GETMODEA:
827 case MCIWNDM_GETMODEW:
829 MCI_STATUS_PARMS mci_status;
831 TRACE("MCIWNDM_GETMODE\n");
833 if (!mwi->mci)
834 return MCI_MODE_NOT_READY;
836 /* get mode string if requested */
837 if (wParam && lParam)
839 if (wMsg == MCIWNDM_GETMODEA)
841 char cmd[64];
843 wsprintfA(cmd, "status %d mode", mwi->alias);
844 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
846 else
849 WCHAR cmdW[64];
850 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','m','o','d','e',0};
852 wsprintfW(cmdW, formatW, mwi->alias);
853 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
856 if (mwi->lasterror)
857 return MCI_MODE_NOT_READY;
860 mci_status.dwItem = MCI_STATUS_MODE;
861 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
862 MCI_STATUS_ITEM,
863 (DWORD_PTR)&mci_status);
864 if (mwi->lasterror)
865 return MCI_MODE_NOT_READY;
867 return mci_status.dwReturn;
870 case MCIWNDM_PLAYFROM:
872 MCI_PLAY_PARMS mci_play;
874 TRACE("MCIWNDM_PLAYFROM %08lx\n", lParam);
876 mci_play.dwCallback = (DWORD_PTR)hWnd;
877 mci_play.dwFrom = lParam;
878 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
879 MCI_FROM | MCI_NOTIFY,
880 (DWORD_PTR)&mci_play);
881 if (mwi->lasterror)
883 MCIWND_notify_error(mwi);
884 return mwi->lasterror;
887 MCIWND_notify_mode(mwi);
888 MCIWND_UpdateState(mwi);
889 return 0;
892 case MCIWNDM_PLAYTO:
894 MCI_PLAY_PARMS mci_play;
896 TRACE("MCIWNDM_PLAYTO %08lx\n", lParam);
898 mci_play.dwCallback = (DWORD_PTR)hWnd;
899 mci_play.dwTo = lParam;
900 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
901 MCI_TO | MCI_NOTIFY,
902 (DWORD_PTR)&mci_play);
903 if (mwi->lasterror)
905 MCIWND_notify_error(mwi);
906 return mwi->lasterror;
909 MCIWND_notify_mode(mwi);
910 MCIWND_UpdateState(mwi);
911 return 0;
914 case MCIWNDM_PLAYREVERSE:
916 MCI_PLAY_PARMS mci_play;
917 DWORD flags = MCI_NOTIFY;
919 TRACE("MCIWNDM_PLAYREVERSE %08lx\n", lParam);
921 mci_play.dwCallback = (DWORD_PTR)hWnd;
922 mci_play.dwFrom = lParam;
923 switch (mwi->dev_type)
925 default:
926 case MCI_DEVTYPE_ANIMATION:
927 flags |= MCI_ANIM_PLAY_REVERSE;
928 break;
930 case MCI_DEVTYPE_DIGITAL_VIDEO:
931 flags |= MCI_DGV_PLAY_REVERSE;
932 break;
934 #ifdef MCI_VCR_PLAY_REVERSE
935 case MCI_DEVTYPE_VCR:
936 flags |= MCI_VCR_PLAY_REVERSE;
937 break;
938 #endif
940 case MCI_DEVTYPE_VIDEODISC:
941 flags |= MCI_VD_PLAY_REVERSE;
942 break;
945 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
946 flags, (DWORD_PTR)&mci_play);
947 if (mwi->lasterror)
949 MCIWND_notify_error(mwi);
950 return mwi->lasterror;
953 MCIWND_notify_mode(mwi);
954 MCIWND_UpdateState(mwi);
955 return 0;
958 case MCIWNDM_GETERRORA:
959 mciGetErrorStringA(mwi->lasterror, (LPSTR)lParam, wParam);
960 TRACE("MCIWNDM_GETERRORA: %s\n", debugstr_an((LPSTR)lParam, wParam));
961 return mwi->lasterror;
963 case MCIWNDM_GETERRORW:
964 mciGetErrorStringW(mwi->lasterror, (LPWSTR)lParam, wParam);
965 TRACE("MCIWNDM_GETERRORW: %s\n", debugstr_wn((LPWSTR)lParam, wParam));
966 return mwi->lasterror;
968 case MCIWNDM_SETOWNER:
969 TRACE("MCIWNDM_SETOWNER %p\n", (HWND)wParam);
970 mwi->hwndOwner = (HWND)wParam;
971 return 0;
973 case MCIWNDM_SENDSTRINGA:
975 UNICODE_STRING stringW;
977 TRACE("MCIWNDM_SENDSTRINGA %s\n", debugstr_a((LPCSTR)lParam));
979 RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
980 lParam = (LPARAM)stringW.Buffer;
982 /* fall through */
983 case MCIWNDM_SENDSTRINGW:
985 WCHAR *cmdW, *p;
987 TRACE("MCIWNDM_SENDSTRINGW %s\n", debugstr_w((LPCWSTR)lParam));
989 p = wcschr((LPCWSTR)lParam, ' ');
990 if (p)
992 static const WCHAR formatW[] = {'%','d',' ',0};
993 int len, pos;
995 pos = p - (WCHAR *)lParam + 1;
996 len = lstrlenW((LPCWSTR)lParam) + 64;
998 cmdW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1000 memcpy(cmdW, (void *)lParam, pos * sizeof(WCHAR));
1001 wsprintfW(cmdW + pos, formatW, mwi->alias);
1002 lstrcatW(cmdW, (WCHAR *)lParam + pos);
1004 else
1005 cmdW = (LPWSTR)lParam;
1007 mwi->lasterror = mciSendStringW(cmdW, mwi->return_string,
1008 ARRAY_SIZE(mwi->return_string), 0);
1009 if (mwi->lasterror)
1010 MCIWND_notify_error(mwi);
1012 if (cmdW != (LPWSTR)lParam)
1013 HeapFree(GetProcessHeap(), 0, cmdW);
1015 if (wMsg == MCIWNDM_SENDSTRINGA)
1016 HeapFree(GetProcessHeap(), 0, (void *)lParam);
1018 MCIWND_UpdateState(mwi);
1019 return mwi->lasterror;
1022 case MCIWNDM_RETURNSTRINGA:
1023 WideCharToMultiByte(CP_ACP, 0, mwi->return_string, -1, (LPSTR)lParam, wParam, NULL, NULL);
1024 TRACE("MCIWNDM_RETURNTRINGA %s\n", debugstr_an((LPSTR)lParam, wParam));
1025 return mwi->lasterror;
1027 case MCIWNDM_RETURNSTRINGW:
1028 lstrcpynW((LPWSTR)lParam, mwi->return_string, wParam);
1029 TRACE("MCIWNDM_RETURNTRINGW %s\n", debugstr_wn((LPWSTR)lParam, wParam));
1030 return mwi->lasterror;
1032 case MCIWNDM_SETTIMERS:
1033 TRACE("MCIWNDM_SETTIMERS active %d ms, inactive %d ms\n", (int)wParam, (int)lParam);
1034 mwi->active_timer = (WORD)wParam;
1035 mwi->inactive_timer = (WORD)lParam;
1036 return 0;
1038 case MCIWNDM_SETACTIVETIMER:
1039 TRACE("MCIWNDM_SETACTIVETIMER %d ms\n", (int)wParam);
1040 mwi->active_timer = (WORD)wParam;
1041 return 0;
1043 case MCIWNDM_SETINACTIVETIMER:
1044 TRACE("MCIWNDM_SETINACTIVETIMER %d ms\n", (int)wParam);
1045 mwi->inactive_timer = (WORD)wParam;
1046 return 0;
1048 case MCIWNDM_GETACTIVETIMER:
1049 TRACE("MCIWNDM_GETACTIVETIMER: %d ms\n", mwi->active_timer);
1050 return mwi->active_timer;
1052 case MCIWNDM_GETINACTIVETIMER:
1053 TRACE("MCIWNDM_GETINACTIVETIMER: %d ms\n", mwi->inactive_timer);
1054 return mwi->inactive_timer;
1056 case MCIWNDM_CHANGESTYLES:
1057 TRACE("MCIWNDM_CHANGESTYLES mask %08lx, set %08lx\n", wParam, lParam);
1058 /* FIXME: update the visual window state as well:
1059 * add/remove trackbar, autosize, etc.
1061 mwi->dwStyle &= ~wParam;
1062 mwi->dwStyle |= lParam & wParam;
1063 return 0;
1065 case MCIWNDM_GETSTYLES:
1066 TRACE("MCIWNDM_GETSTYLES: %08x\n", mwi->dwStyle & 0xffff);
1067 return mwi->dwStyle & 0xffff;
1069 case MCIWNDM_GETDEVICEA:
1071 int len = 0;
1072 char *str = (char *)lParam;
1073 MCI_SYSINFO_PARMSA mci_sysinfo;
1075 mci_sysinfo.lpstrReturn = str;
1076 mci_sysinfo.dwRetSize = wParam;
1077 mwi->lasterror = mciSendCommandA(mwi->mci, MCI_SYSINFO,
1078 MCI_SYSINFO_INSTALLNAME,
1079 (DWORD_PTR)&mci_sysinfo);
1080 while(len < wParam && str[len]) len++;
1081 TRACE("MCIWNDM_GETDEVICEA: %s\n", debugstr_an(str, len));
1082 return 0;
1085 case MCIWNDM_GETDEVICEW:
1087 int len = 0;
1088 WCHAR *str = (WCHAR *)lParam;
1089 MCI_SYSINFO_PARMSW mci_sysinfo;
1091 mci_sysinfo.lpstrReturn = str;
1092 mci_sysinfo.dwRetSize = wParam;
1093 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SYSINFO,
1094 MCI_SYSINFO_INSTALLNAME,
1095 (DWORD_PTR)&mci_sysinfo);
1096 while(len < wParam && str[len]) len++;
1097 TRACE("MCIWNDM_GETDEVICEW: %s\n", debugstr_wn(str, len));
1098 return 0;
1101 case MCIWNDM_VALIDATEMEDIA:
1102 TRACE("MCIWNDM_VALIDATEMEDIA\n");
1103 if (mwi->mci)
1105 SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
1106 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
1108 return 0;
1110 case MCIWNDM_GETFILENAMEA:
1111 TRACE("MCIWNDM_GETFILENAMEA: %s\n", debugstr_w(mwi->lpName));
1112 if (mwi->lpName)
1113 WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, (LPSTR)lParam, wParam, NULL, NULL);
1114 return 0;
1116 case MCIWNDM_GETFILENAMEW:
1117 TRACE("MCIWNDM_GETFILENAMEW: %s\n", debugstr_w(mwi->lpName));
1118 if (mwi->lpName)
1119 lstrcpynW((LPWSTR)lParam, mwi->lpName, wParam);
1120 return 0;
1122 case MCIWNDM_GETTIMEFORMATA:
1123 case MCIWNDM_GETTIMEFORMATW:
1125 MCI_STATUS_PARMS mci_status;
1127 TRACE("MCIWNDM_GETTIMEFORMAT %08lx %08lx\n", wParam, lParam);
1129 /* get format string if requested */
1130 if (wParam && lParam)
1132 if (wMsg == MCIWNDM_GETTIMEFORMATA)
1134 char cmd[64];
1136 wsprintfA(cmd, "status %d time format", mwi->alias);
1137 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
1138 if (mwi->lasterror)
1139 return 0;
1141 else
1143 WCHAR cmdW[64];
1144 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',0};
1146 wsprintfW(cmdW, formatW, mwi->alias);
1147 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
1148 if (mwi->lasterror)
1149 return 0;
1153 mci_status.dwItem = MCI_STATUS_TIME_FORMAT ;
1154 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
1155 MCI_STATUS_ITEM,
1156 (DWORD_PTR)&mci_status);
1157 if (mwi->lasterror)
1158 return 0;
1160 return mci_status.dwReturn;
1163 case MCIWNDM_SETTIMEFORMATA:
1165 UNICODE_STRING stringW;
1167 TRACE("MCIWNDM_SETTIMEFORMATA %s\n", debugstr_a((LPSTR)lParam));
1169 RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
1170 lParam = (LPARAM)stringW.Buffer;
1172 /* fall through */
1173 case MCIWNDM_SETTIMEFORMATW:
1175 static const WCHAR formatW[] = {'s','e','t',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',' ',0};
1176 WCHAR *cmdW;
1178 TRACE("MCIWNDM_SETTIMEFORMATW %s\n", debugstr_w((LPWSTR)lParam));
1180 if (mwi->mci)
1182 cmdW = HeapAlloc(GetProcessHeap(), 0, (lstrlenW((LPCWSTR)lParam) + 64) * sizeof(WCHAR));
1183 wsprintfW(cmdW, formatW, mwi->alias);
1184 lstrcatW(cmdW, (WCHAR *)lParam);
1186 mwi->lasterror = mciSendStringW(cmdW, NULL, 0, 0);
1188 /* fix the range tracking according to the new time format */
1189 if (!mwi->lasterror)
1190 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1,
1191 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0));
1193 HeapFree(GetProcessHeap(), 0, cmdW);
1196 if (wMsg == MCIWNDM_SETTIMEFORMATA)
1197 HeapFree(GetProcessHeap(), 0, (void *)lParam);
1199 return 0;
1202 case MCIWNDM_CAN_PLAY:
1203 TRACE("MCIWNDM_CAN_PLAY\n");
1204 if (mwi->mci)
1205 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_PLAY);
1206 return 0;
1208 case MCIWNDM_CAN_RECORD:
1209 TRACE("MCIWNDM_CAN_RECORD\n");
1210 if (mwi->mci)
1211 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_RECORD);
1212 return 0;
1214 case MCIWNDM_CAN_SAVE:
1215 TRACE("MCIWNDM_CAN_SAVE\n");
1216 if (mwi->mci)
1217 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_SAVE);
1218 return 0;
1220 case MCIWNDM_CAN_EJECT:
1221 TRACE("MCIWNDM_CAN_EJECT\n");
1222 if (mwi->mci)
1223 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_EJECT);
1224 return 0;
1226 case MCIWNDM_CAN_WINDOW:
1227 TRACE("MCIWNDM_CAN_WINDOW\n");
1228 switch (mwi->dev_type)
1230 case MCI_DEVTYPE_ANIMATION:
1231 case MCI_DEVTYPE_DIGITAL_VIDEO:
1232 case MCI_DEVTYPE_OVERLAY:
1233 return 1;
1235 return 0;
1237 case MCIWNDM_CAN_CONFIG:
1238 TRACE("MCIWNDM_CAN_CONFIG\n");
1239 if (mwi->hdrv)
1240 return SendDriverMessage(mwi->hdrv, DRV_QUERYCONFIGURE, 0, 0);
1241 return 0;
1243 case MCIWNDM_SETZOOM:
1244 TRACE("MCIWNDM_SETZOOM %ld\n", lParam);
1245 mwi->zoom = lParam;
1247 if (mwi->mci && !(mwi->dwStyle & MCIWNDF_NOAUTOSIZEWINDOW))
1249 RECT rc;
1251 rc.left = rc.top = 0;
1252 rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
1253 rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
1255 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
1256 rc.bottom += 32; /* add the height of the playbar */
1257 AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
1258 SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
1259 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1261 return 0;
1263 case MCIWNDM_GETZOOM:
1264 TRACE("MCIWNDM_GETZOOM: %d\n", mwi->zoom);
1265 return mwi->zoom;
1267 case MCIWNDM_EJECT:
1269 MCI_SET_PARMS mci_set;
1271 TRACE("MCIWNDM_EJECT\n");
1273 mci_set.dwCallback = (DWORD_PTR)hWnd;
1274 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SET,
1275 MCI_SET_DOOR_OPEN | MCI_NOTIFY,
1276 (DWORD_PTR)&mci_set);
1277 MCIWND_notify_mode(mwi);
1278 MCIWND_UpdateState(mwi);
1279 return mwi->lasterror;
1282 case MCIWNDM_SETVOLUME:
1283 case MCIWNDM_GETVOLUME:
1284 case MCIWNDM_SETSPEED:
1285 case MCIWNDM_GETSPEED:
1286 case MCIWNDM_SETREPEAT:
1287 case MCIWNDM_GETREPEAT:
1288 case MCIWNDM_REALIZE:
1289 case MCIWNDM_GETPALETTE:
1290 case MCIWNDM_SETPALETTE:
1291 case MCIWNDM_NEWA:
1292 case MCIWNDM_NEWW:
1293 case MCIWNDM_PALETTEKICK:
1294 case MCIWNDM_OPENINTERFACE:
1295 FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
1296 return 0;
1298 case MCI_PLAY:
1300 LRESULT end = SendMessageW(hWnd, MCIWNDM_GETEND, 0, 0);
1301 return SendMessageW(hWnd, MCIWNDM_PLAYTO, 0, end);
1304 case MCI_SEEK:
1305 case MCI_STEP:
1307 MCI_SEEK_PARMS mci_seek; /* Layout is usable as MCI_XYZ_STEP_PARMS */
1308 DWORD flags = MCI_STEP == wMsg ? 0 :
1309 MCIWND_START == lParam ? MCI_SEEK_TO_START :
1310 MCIWND_END == lParam ? MCI_SEEK_TO_END : MCI_TO;
1312 mci_seek.dwTo = lParam;
1313 mwi->lasterror = mciSendCommandW(mwi->mci, wMsg,
1314 flags, (DWORD_PTR)&mci_seek);
1315 if (mwi->lasterror)
1317 MCIWND_notify_error(mwi);
1318 return mwi->lasterror;
1320 /* update window to reflect the state */
1321 else InvalidateRect(hWnd, NULL, TRUE);
1322 return 0;
1325 case MCI_CLOSE:
1327 RECT rc;
1328 MCI_GENERIC_PARMS mci_generic;
1330 if (mwi->hdrv)
1332 CloseDriver(mwi->hdrv, 0, 0);
1333 mwi->hdrv = 0;
1336 if (mwi->mci)
1338 mci_generic.dwCallback = 0;
1339 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_CLOSE,
1340 0, (DWORD_PTR)&mci_generic);
1341 mwi->mci = 0;
1344 mwi->mode = MCI_MODE_NOT_READY;
1345 mwi->position = -1;
1347 HeapFree(GetProcessHeap(), 0, mwi->lpName);
1348 mwi->lpName = NULL;
1349 MCIWND_UpdateState(mwi);
1351 GetClientRect(hWnd, &rc);
1352 rc.bottom = rc.top;
1353 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
1354 rc.bottom += 32; /* add the height of the playbar */
1355 AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
1356 SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left,
1357 rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1359 MCIWND_notify_media(mwi);
1360 return 0;
1363 case MCI_PAUSE:
1364 case MCI_STOP:
1365 case MCI_RESUME:
1366 mci_generic_command(mwi, wMsg);
1367 return mwi->lasterror;
1369 case MCI_CONFIGURE:
1370 if (mwi->hdrv)
1371 SendDriverMessage(mwi->hdrv, DRV_CONFIGURE, (LPARAM)hWnd, 0);
1372 return 0;
1374 case MCI_BREAK:
1375 case MCI_CAPTURE:
1376 case MCI_COPY:
1377 case MCI_CUE:
1378 case MCI_CUT:
1379 case MCI_DELETE:
1380 case MCI_ESCAPE:
1381 case MCI_FREEZE:
1382 case MCI_GETDEVCAPS:
1383 /*case MCI_INDEX:*/
1384 case MCI_INFO:
1385 case MCI_LIST:
1386 case MCI_LOAD:
1387 /*case MCI_MARK:*/
1388 case MCI_MONITOR:
1389 case MCI_OPEN:
1390 case MCI_PASTE:
1391 case MCI_PUT:
1392 case MCI_QUALITY:
1393 case MCI_REALIZE:
1394 case MCI_RECORD:
1395 case MCI_RESERVE:
1396 case MCI_RESTORE:
1397 case MCI_SAVE:
1398 case MCI_SET:
1399 case MCI_SETAUDIO:
1400 /*case MCI_SETTIMECODE:*/
1401 /*case MCI_SETTUNER:*/
1402 case MCI_SETVIDEO:
1403 case MCI_SIGNAL:
1404 case MCI_SPIN:
1405 case MCI_STATUS:
1406 case MCI_SYSINFO:
1407 case MCI_UNDO:
1408 case MCI_UNFREEZE:
1409 case MCI_UPDATE:
1410 case MCI_WHERE:
1411 case MCI_WINDOW:
1412 FIXME("support for MCI_ command %04x not implemented\n", wMsg);
1413 return 0;
1416 if (wMsg >= WM_USER)
1418 FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
1419 return 0;
1422 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1423 return DefMDIChildProcW(hWnd, wMsg, wParam, lParam);
1425 return DefWindowProcW(hWnd, wMsg, wParam, lParam);