- Sync msimtf, msvfw32, msvidc32, msxml3 to Wine-1.1.43.
[reactos.git] / reactos / dll / win32 / msvfw32 / mciwnd.c
1 /*
2 * Copyright 2000 Eric Pouech
3 * Copyright 2003 Dmitry Timoshkov
4 *
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.
9 *
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.
14 *
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
18 *
19 * FIXME:
20 * Add support for all remaining MCI_ commands and MCIWNDM_ messages.
21 * Add support for MCIWNDF_RECORD.
22 */
23
24 #include <stdarg.h>
25
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/unicode.h"
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(mci);
39
40 extern HMODULE MSVFW32_hModule;
41 static const WCHAR mciWndClassW[] = {'M','C','I','W','n','d','C','l','a','s','s',0};
42
43 typedef struct
44 {
45 DWORD dwStyle;
46 MCIDEVICEID mci;
47 HDRVR hdrv;
48 int alias;
49 UINT dev_type;
50 UINT mode;
51 long position;
52 SIZE size; /* size of the original frame rect */
53 int zoom;
54 LPWSTR lpName;
55 HWND hWnd, hwndOwner;
56 UINT uTimer;
57 MCIERROR lasterror;
58 WCHAR return_string[128];
59 WORD active_timer, inactive_timer;
60 } MCIWndInfo;
61
62 static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
63
64 #define CTL_PLAYSTOP 0x3200
65 #define CTL_MENU 0x3201
66 #define CTL_TRACKBAR 0x3202
67
68 /***********************************************************************
69 * MCIWndRegisterClass [MSVFW32.@]
70 *
71 * NOTE: Native always uses its own hInstance
72 */
73 BOOL VFWAPIV MCIWndRegisterClass(void)
74 {
75 WNDCLASSW wc;
76
77 /* Since we are going to register a class belonging to MSVFW32
78 * and later we will create windows with a different hInstance
79 * CS_GLOBALCLASS is needed. And because the second attempt
80 * to register a global class will fail we need to test whether
81 * the class was already registered.
82 */
83 wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC | CS_GLOBALCLASS;
84 wc.lpfnWndProc = MCIWndProc;
85 wc.cbClsExtra = 0;
86 wc.cbWndExtra = sizeof(MCIWndInfo*);
87 wc.hInstance = MSVFW32_hModule;
88 wc.hIcon = 0;
89 wc.hCursor = LoadCursorW(0, MAKEINTRESOURCEW(IDC_ARROW));
90 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
91 wc.lpszMenuName = NULL;
92 wc.lpszClassName = mciWndClassW;
93
94 if (RegisterClassW(&wc)) return TRUE;
95 if (GetLastError() == ERROR_CLASS_ALREADY_EXISTS) return TRUE;
96
97 return FALSE;
98 }
99
100 /***********************************************************************
101 * MCIWndCreateW [MSVFW32.@]
102 */
103 HWND VFWAPIV MCIWndCreateW(HWND hwndParent, HINSTANCE hInstance,
104 DWORD dwStyle, LPCWSTR szFile)
105 {
106 TRACE("%p %p %x %s\n", hwndParent, hInstance, dwStyle, debugstr_w(szFile));
107
108 MCIWndRegisterClass();
109
110 if (!hInstance) hInstance = GetModuleHandleW(0);
111
112 if (hwndParent)
113 dwStyle |= WS_VISIBLE | WS_BORDER /*| WS_CHILD*/;
114 else
115 dwStyle |= WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
116
117 return CreateWindowExW(0, mciWndClassW, NULL,
118 dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
119 0, 0, 300, 0,
120 hwndParent, 0, hInstance, (LPVOID)szFile);
121 }
122
123 /***********************************************************************
124 * MCIWndCreate [MSVFW32.@]
125 * MCIWndCreateA [MSVFW32.@]
126 */
127 HWND VFWAPIV MCIWndCreateA(HWND hwndParent, HINSTANCE hInstance,
128 DWORD dwStyle, LPCSTR szFile)
129 {
130 HWND ret;
131 UNICODE_STRING fileW;
132
133 if (szFile)
134 RtlCreateUnicodeStringFromAsciiz(&fileW, szFile);
135 else
136 fileW.Buffer = NULL;
137
138 ret = MCIWndCreateW(hwndParent, hInstance, dwStyle, fileW.Buffer);
139
140 RtlFreeUnicodeString(&fileW);
141 return ret;
142 }
143
144 static inline void MCIWND_notify_mode(MCIWndInfo *mwi)
145 {
146 if (mwi->dwStyle & MCIWNDF_NOTIFYMODE)
147 {
148 UINT new_mode = SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0);
149 if (new_mode != mwi->mode)
150 {
151 mwi->mode = new_mode;
152 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMODE, (WPARAM)mwi->hWnd, new_mode);
153 }
154 }
155 }
156
157 static inline void MCIWND_notify_pos(MCIWndInfo *mwi)
158 {
159 if (mwi->dwStyle & MCIWNDF_NOTIFYPOS)
160 {
161 long new_pos = SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 0, 0);
162 if (new_pos != mwi->position)
163 {
164 mwi->position = new_pos;
165 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYPOS, (WPARAM)mwi->hWnd, new_pos);
166 }
167 }
168 }
169
170 static inline void MCIWND_notify_size(MCIWndInfo *mwi)
171 {
172 if (mwi->dwStyle & MCIWNDF_NOTIFYSIZE)
173 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYSIZE, (WPARAM)mwi->hWnd, 0);
174 }
175
176 static inline void MCIWND_notify_error(MCIWndInfo *mwi)
177 {
178 if (mwi->dwStyle & MCIWNDF_NOTIFYERROR)
179 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYERROR, (WPARAM)mwi->hWnd, (LPARAM)mwi->lasterror);
180 }
181
182 static void MCIWND_UpdateState(MCIWndInfo *mwi)
183 {
184 WCHAR buffer[1024];
185
186 if (!mwi->mci)
187 {
188 /* FIXME: get this from resources */
189 static const WCHAR no_deviceW[] = {'N','o',' ','D','e','v','i','c','e',0};
190 SetWindowTextW(mwi->hWnd, no_deviceW);
191 return;
192 }
193
194 MCIWND_notify_pos(mwi);
195
196 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
197 SendDlgItemMessageW(mwi->hWnd, CTL_TRACKBAR, TBM_SETPOS, TRUE, mwi->position);
198
199 if (!(mwi->dwStyle & MCIWNDF_SHOWALL))
200 return;
201
202 if ((mwi->dwStyle & MCIWNDF_SHOWNAME) && mwi->lpName)
203 strcpyW(buffer, mwi->lpName);
204 else
205 *buffer = 0;
206
207 if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
208 {
209 static const WCHAR spaceW[] = {' ',0};
210 static const WCHAR l_braceW[] = {'(',0};
211
212 if (*buffer) strcatW(buffer, spaceW);
213 strcatW(buffer, l_braceW);
214 }
215
216 if (mwi->dwStyle & MCIWNDF_SHOWPOS)
217 {
218 WCHAR posW[64];
219
220 posW[0] = 0;
221 SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 64, (LPARAM)posW);
222 strcatW(buffer, posW);
223 }
224
225 if ((mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) == (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
226 {
227 static const WCHAR dashW[] = {' ','-',' ',0};
228 strcatW(buffer, dashW);
229 }
230
231 if (mwi->dwStyle & MCIWNDF_SHOWMODE)
232 {
233 WCHAR modeW[64];
234
235 modeW[0] = 0;
236 SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 64, (LPARAM)modeW);
237 strcatW(buffer, modeW);
238 }
239
240 if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
241 {
242 static const WCHAR r_braceW[] = {')',0};
243 strcatW(buffer, r_braceW);
244 }
245
246 TRACE("=> %s\n", debugstr_w(buffer));
247 SetWindowTextW(mwi->hWnd, buffer);
248 }
249
250 static LRESULT MCIWND_Create(HWND hWnd, LPCREATESTRUCTW cs)
251 {
252 HWND hChld;
253 MCIWndInfo *mwi;
254 static const WCHAR buttonW[] = {'b','u','t','t','o','n',0};
255
256 mwi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mwi));
257 if (!mwi) return -1;
258
259 SetWindowLongW(hWnd, 0, (LPARAM)mwi);
260
261 mwi->dwStyle = cs->style;
262 /* There is no need to show stats if there is no caption */
263 if ((mwi->dwStyle & WS_CAPTION) != WS_CAPTION)
264 mwi->dwStyle &= ~MCIWNDF_SHOWALL;
265
266 mwi->hWnd = hWnd;
267 mwi->hwndOwner = cs->hwndParent;
268 mwi->active_timer = 500;
269 mwi->inactive_timer = 2000;
270 mwi->mode = MCI_MODE_NOT_READY;
271 mwi->position = -1;
272 mwi->zoom = 100;
273
274 if (!(mwi->dwStyle & MCIWNDF_NOMENU))
275 {
276 static const WCHAR menuW[] = {'M','e','n','u',0};
277
278 hChld = CreateWindowExW(0, buttonW, menuW, WS_CHILD|WS_VISIBLE, 32, cs->cy, 32, 32,
279 hWnd, (HMENU)CTL_MENU, cs->hInstance, 0L);
280 TRACE("Get Button2: %p\n", hChld);
281 }
282
283 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
284 {
285 INITCOMMONCONTROLSEX init;
286 static const WCHAR playW[] = {'P','l','a','y',0};
287
288 /* adding the other elements: play/stop button, menu button, status */
289 hChld = CreateWindowExW(0, buttonW, playW, WS_CHILD|WS_VISIBLE, 0, cs->cy, 32, 32,
290 hWnd, (HMENU)CTL_PLAYSTOP, cs->hInstance, 0L);
291 TRACE("Get Button1: %p\n", hChld);
292
293 init.dwSize = sizeof(init);
294 init.dwICC = ICC_BAR_CLASSES;
295 InitCommonControlsEx(&init);
296
297 hChld = CreateWindowExW(0, TRACKBAR_CLASSW, NULL, WS_CHILD|WS_VISIBLE, 64, cs->cy, cs->cx - 64, 32,
298 hWnd, (HMENU)CTL_TRACKBAR, cs->hInstance, 0L);
299 TRACE("Get status: %p\n", hChld);
300 }
301
302 /* This sets the default window size */
303 SendMessageW(hWnd, MCI_CLOSE, 0, 0);
304
305 if (cs->lpCreateParams)
306 {
307 LPARAM lParam;
308
309 /* MCI wnd class is prepared to be embedded as an MDI child window */
310 if (cs->dwExStyle & WS_EX_MDICHILD)
311 {
312 MDICREATESTRUCTW *mdics = cs->lpCreateParams;
313 lParam = mdics->lParam;
314 }
315 else
316 lParam = (LPARAM)cs->lpCreateParams;
317
318 /* If it's our internal class pointer, file name is a unicode string */
319 if (cs->lpszClass == mciWndClassW)
320 SendMessageW(hWnd, MCIWNDM_OPENW, 0, lParam);
321 else
322 {
323 /* Otherwise let's try to figure out what string format is used */
324 HWND parent = cs->hwndParent;
325 if (!parent) parent = GetWindow(hWnd, GW_OWNER);
326
327 SendMessageW(hWnd, IsWindowUnicode(parent) ? MCIWNDM_OPENW : MCIWNDM_OPENA, 0, lParam);
328 }
329 }
330
331 return 0;
332 }
333
334 static void MCIWND_ToggleState(MCIWndInfo *mwi)
335 {
336 switch (SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0))
337 {
338 case MCI_MODE_NOT_READY:
339 case MCI_MODE_RECORD:
340 case MCI_MODE_SEEK:
341 case MCI_MODE_OPEN:
342 TRACE("Cannot do much...\n");
343 break;
344
345 case MCI_MODE_PAUSE:
346 SendMessageW(mwi->hWnd, MCI_RESUME, 0, 0);
347 break;
348
349 case MCI_MODE_PLAY:
350 SendMessageW(mwi->hWnd, MCI_PAUSE, 0, 0);
351 break;
352
353 case MCI_MODE_STOP:
354 SendMessageW(mwi->hWnd, MCI_STOP, 0, 0);
355 break;
356 }
357 }
358
359 static LRESULT MCIWND_Command(MCIWndInfo *mwi, WPARAM wParam, LPARAM lParam)
360 {
361 switch (LOWORD(wParam))
362 {
363 case CTL_PLAYSTOP: MCIWND_ToggleState(mwi); break;
364 case CTL_MENU:
365 case CTL_TRACKBAR:
366 default:
367 FIXME("support for command %04x not implement yet\n", LOWORD(wParam));
368 }
369 return 0L;
370 }
371
372 static void MCIWND_notify_media(MCIWndInfo *mwi)
373 {
374 if (mwi->dwStyle & (MCIWNDF_NOTIFYMEDIAA | MCIWNDF_NOTIFYMEDIAW))
375 {
376 if (!mwi->lpName)
377 {
378 static const WCHAR empty_str[1];
379 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)empty_str);
380 }
381 else
382 {
383 if (mwi->dwStyle & MCIWNDF_NOTIFYANSI)
384 {
385 char *ansi_name;
386 int len;
387
388 len = WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, NULL, 0, NULL, NULL);
389 ansi_name = HeapAlloc(GetProcessHeap(), 0, len);
390 WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, ansi_name, len, NULL, NULL);
391
392 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)ansi_name);
393
394 HeapFree(GetProcessHeap(), 0, ansi_name);
395 }
396 else
397 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)mwi->lpName);
398 }
399 }
400 }
401
402 static MCIERROR mci_generic_command(MCIWndInfo *mwi, UINT cmd)
403 {
404 MCI_GENERIC_PARMS mci_generic;
405
406 mci_generic.dwCallback = 0;
407 mwi->lasterror = mciSendCommandW(mwi->mci, cmd, 0, (DWORD_PTR)&mci_generic);
408
409 if (mwi->lasterror)
410 return mwi->lasterror;
411
412 MCIWND_notify_mode(mwi);
413 MCIWND_UpdateState(mwi);
414 return 0;
415 }
416
417 static LRESULT mci_get_devcaps(MCIWndInfo *mwi, UINT cap)
418 {
419 MCI_GETDEVCAPS_PARMS mci_devcaps;
420
421 mci_devcaps.dwItem = cap;
422 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
423 MCI_GETDEVCAPS_ITEM,
424 (DWORD_PTR)&mci_devcaps);
425 if (mwi->lasterror)
426 return 0;
427
428 return mci_devcaps.dwReturn;
429 }
430
431 static LRESULT MCIWND_KeyDown(MCIWndInfo *mwi, UINT key)
432 {
433 TRACE("%p, key %04x\n", mwi->hWnd, key);
434
435 switch(key)
436 {
437 case VK_ESCAPE:
438 SendMessageW(mwi->hWnd, MCI_STOP, 0, 0);
439 return 0;
440
441 default:
442 return 0;
443 }
444 }
445
446 static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
447 {
448 MCIWndInfo *mwi;
449
450 TRACE("%p %04x %08lx %08lx\n", hWnd, wMsg, wParam, lParam);
451
452 mwi = (MCIWndInfo*)GetWindowLongPtrW(hWnd, 0);
453 if (!mwi && wMsg != WM_CREATE)
454 return DefWindowProcW(hWnd, wMsg, wParam, lParam);
455
456 switch (wMsg)
457 {
458 case WM_CREATE:
459 MCIWND_Create(hWnd, (CREATESTRUCTW *)lParam);
460 break;
461
462 case WM_DESTROY:
463 if (mwi->uTimer)
464 KillTimer(hWnd, mwi->uTimer);
465
466 if (mwi->mci)
467 SendMessageW(hWnd, MCI_CLOSE, 0, 0);
468
469 HeapFree(GetProcessHeap(), 0, mwi);
470
471 DestroyWindow(GetDlgItem(hWnd, CTL_MENU));
472 DestroyWindow(GetDlgItem(hWnd, CTL_PLAYSTOP));
473 DestroyWindow(GetDlgItem(hWnd, CTL_TRACKBAR));
474 break;
475
476 case WM_PAINT:
477 {
478 MCI_DGV_UPDATE_PARMS mci_update;
479 PAINTSTRUCT ps;
480
481 mci_update.hDC = (wParam) ? (HDC)wParam : BeginPaint(hWnd, &ps);
482
483 mciSendCommandW(mwi->mci, MCI_UPDATE,
484 MCI_DGV_UPDATE_HDC | MCI_DGV_UPDATE_PAINT,
485 (DWORD_PTR)&mci_update);
486
487 if (!wParam) EndPaint(hWnd, &ps);
488 return 1;
489 }
490
491 case WM_COMMAND:
492 return MCIWND_Command(mwi, wParam, lParam);
493
494 case WM_KEYDOWN:
495 return MCIWND_KeyDown(mwi, wParam);
496
497 case WM_NCACTIVATE:
498 if (mwi->uTimer)
499 {
500 KillTimer(hWnd, mwi->uTimer);
501 mwi->uTimer = SetTimer(hWnd, 1, wParam ? mwi->active_timer : mwi->inactive_timer, NULL);
502 }
503 break;
504
505 case WM_TIMER:
506 MCIWND_UpdateState(mwi);
507 return 0;
508
509 case WM_SIZE:
510 SetWindowPos(GetDlgItem(hWnd, CTL_PLAYSTOP), 0, 0, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
511 SetWindowPos(GetDlgItem(hWnd, CTL_MENU), 0, 32, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
512 SetWindowPos(GetDlgItem(hWnd, CTL_TRACKBAR), 0, 64, HIWORD(lParam) - 32, LOWORD(lParam) - 64, 32, SWP_NOACTIVATE);
513
514 if (!(mwi->dwStyle & MCIWNDF_NOAUTOSIZEMOVIE))
515 {
516 RECT rc;
517
518 rc.left = rc.top = 0;
519 rc.right = LOWORD(lParam);
520 rc.bottom = HIWORD(lParam);
521 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
522 rc.bottom -= 32; /* subtract the height of the playbar */
523 SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
524 }
525 MCIWND_notify_size(mwi);
526 break;
527
528 case MM_MCINOTIFY:
529 MCIWND_notify_mode(mwi);
530 MCIWND_UpdateState(mwi);
531 return 0;
532
533 case MCIWNDM_OPENA:
534 {
535 UNICODE_STRING nameW;
536 TRACE("MCIWNDM_OPENA %s\n", debugstr_a((LPSTR)lParam));
537 RtlCreateUnicodeStringFromAsciiz(&nameW, (LPCSTR)lParam);
538 lParam = (LPARAM)nameW.Buffer;
539 }
540 /* fall through */
541 case MCIWNDM_OPENW:
542 {
543 RECT rc;
544 HCURSOR hCursor;
545 MCI_OPEN_PARMSW mci_open;
546 MCI_GETDEVCAPS_PARMS mci_devcaps;
547 WCHAR aliasW[64];
548 WCHAR drv_name[MAX_PATH];
549 static const WCHAR formatW[] = {'%','d',0};
550 static const WCHAR mci32W[] = {'m','c','i','3','2',0};
551 static const WCHAR system_iniW[] = {'s','y','s','t','e','m','.','i','n','i',0};
552
553 TRACE("MCIWNDM_OPENW %s\n", debugstr_w((LPWSTR)lParam));
554
555 if (wParam == MCIWNDOPENF_NEW)
556 {
557 SendMessageW(hWnd, MCIWNDM_NEWW, 0, lParam);
558 goto end_of_mci_open;
559 }
560
561 if (mwi->uTimer)
562 {
563 KillTimer(hWnd, mwi->uTimer);
564 mwi->uTimer = 0;
565 }
566
567 hCursor = LoadCursorW(0, (LPWSTR)IDC_WAIT);
568 hCursor = SetCursor(hCursor);
569
570 mci_open.lpstrElementName = (LPWSTR)lParam;
571 wsprintfW(aliasW, formatW, HandleToLong(hWnd) + 1);
572 mci_open.lpstrAlias = aliasW;
573 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_OPEN,
574 MCI_OPEN_ELEMENT | MCI_OPEN_ALIAS | MCI_WAIT,
575 (DWORD_PTR)&mci_open);
576 SetCursor(hCursor);
577
578 if (mwi->lasterror && !(mwi->dwStyle & MCIWNDF_NOERRORDLG))
579 {
580 /* FIXME: get the caption from resources */
581 static const WCHAR caption[] = {'M','C','I',' ','E','r','r','o','r',0};
582 WCHAR error_str[MAXERRORLENGTH];
583
584 mciGetErrorStringW(mwi->lasterror, error_str, MAXERRORLENGTH);
585 MessageBoxW(hWnd, error_str, caption, MB_ICONEXCLAMATION | MB_OK);
586 MCIWND_notify_error(mwi);
587 goto end_of_mci_open;
588 }
589
590 mwi->mci = mci_open.wDeviceID;
591 mwi->alias = HandleToLong(hWnd) + 1;
592
593 mwi->lpName = HeapAlloc(GetProcessHeap(), 0, (strlenW((LPWSTR)lParam) + 1) * sizeof(WCHAR));
594 strcpyW(mwi->lpName, (LPWSTR)lParam);
595
596 MCIWND_UpdateState(mwi);
597
598 mci_devcaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
599 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
600 MCI_GETDEVCAPS_ITEM,
601 (DWORD_PTR)&mci_devcaps);
602 if (mwi->lasterror)
603 {
604 MCIWND_notify_error(mwi);
605 goto end_of_mci_open;
606 }
607
608 mwi->dev_type = mci_devcaps.dwReturn;
609
610 drv_name[0] = 0;
611 SendMessageW(hWnd, MCIWNDM_GETDEVICEW, 256, (LPARAM)drv_name);
612 if (drv_name[0] && GetPrivateProfileStringW(mci32W, drv_name, NULL,
613 drv_name, MAX_PATH, system_iniW))
614 mwi->hdrv = OpenDriver(drv_name, NULL, 0);
615
616 if (mwi->dev_type == MCI_DEVTYPE_DIGITAL_VIDEO)
617 {
618 MCI_DGV_WINDOW_PARMSW mci_window;
619
620 mci_window.hWnd = hWnd;
621 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WINDOW,
622 MCI_DGV_WINDOW_HWND,
623 (DWORD_PTR)&mci_window);
624 if (mwi->lasterror)
625 {
626 MCIWND_notify_error(mwi);
627 goto end_of_mci_open;
628 }
629 }
630
631 if (SendMessageW(hWnd, MCIWNDM_GET_DEST, 0, (LPARAM)&rc) == 0)
632 {
633 mwi->size.cx = rc.right - rc.left;
634 mwi->size.cy = rc.bottom - rc.top;
635
636 rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
637 rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
638 SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
639 }
640 else
641 {
642 GetClientRect(hWnd, &rc);
643 rc.bottom = rc.top;
644 }
645
646 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
647 rc.bottom += 32; /* add the height of the playbar */
648 AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
649 SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left,
650 rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
651
652 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMIN, 0L, 0L);
653 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1,
654 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0));
655 mwi->uTimer = SetTimer(hWnd, 1, mwi->active_timer, NULL);
656
657 MCIWND_notify_media(mwi);
658
659 end_of_mci_open:
660 if (wMsg == MCIWNDM_OPENA)
661 HeapFree(GetProcessHeap(), 0, (void *)lParam);
662 return mwi->lasterror;
663 }
664
665 case MCIWNDM_GETDEVICEID:
666 TRACE("MCIWNDM_GETDEVICEID\n");
667 return mwi->mci;
668
669 case MCIWNDM_GETALIAS:
670 TRACE("MCIWNDM_GETALIAS\n");
671 return mwi->alias;
672
673 case MCIWNDM_GET_SOURCE:
674 {
675 MCI_DGV_RECT_PARMS mci_rect;
676
677 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WHERE,
678 MCI_DGV_WHERE_SOURCE,
679 (DWORD_PTR)&mci_rect);
680 if (mwi->lasterror)
681 {
682 MCIWND_notify_error(mwi);
683 return mwi->lasterror;
684 }
685 *(RECT *)lParam = mci_rect.rc;
686 TRACE("MCIWNDM_GET_SOURCE: %s\n", wine_dbgstr_rect(&mci_rect.rc));
687 return 0;
688 }
689
690 case MCIWNDM_GET_DEST:
691 {
692 MCI_DGV_RECT_PARMS mci_rect;
693
694 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WHERE,
695 MCI_DGV_WHERE_DESTINATION,
696 (DWORD_PTR)&mci_rect);
697 if (mwi->lasterror)
698 {
699 MCIWND_notify_error(mwi);
700 return mwi->lasterror;
701 }
702 *(RECT *)lParam = mci_rect.rc;
703 TRACE("MCIWNDM_GET_DEST: %s\n", wine_dbgstr_rect(&mci_rect.rc));
704 return 0;
705 }
706
707 case MCIWNDM_PUT_SOURCE:
708 {
709 MCI_DGV_PUT_PARMS mci_put;
710
711 mci_put.rc = *(RECT *)lParam;
712 TRACE("MCIWNDM_PUT_SOURCE: %s\n", wine_dbgstr_rect(&mci_put.rc));
713 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
714 MCI_DGV_PUT_SOURCE,
715 (DWORD_PTR)&mci_put);
716 if (mwi->lasterror)
717 {
718 MCIWND_notify_error(mwi);
719 return mwi->lasterror;
720 }
721 return 0;
722 }
723
724 case MCIWNDM_PUT_DEST:
725 {
726 MCI_DGV_PUT_PARMS mci_put;
727
728 mci_put.rc = *(RECT *)lParam;
729 TRACE("MCIWNDM_PUT_DEST: %s\n", wine_dbgstr_rect(&mci_put.rc));
730
731 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
732 MCI_DGV_PUT_DESTINATION | MCI_DGV_RECT,
733 (DWORD_PTR)&mci_put);
734 if (mwi->lasterror)
735 {
736 MCIWND_notify_error(mwi);
737 return mwi->lasterror;
738 }
739 return 0;
740 }
741
742 case MCIWNDM_GETLENGTH:
743 {
744 MCI_STATUS_PARMS mci_status;
745
746 mci_status.dwItem = MCI_STATUS_LENGTH;
747 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
748 MCI_STATUS_ITEM,
749 (DWORD_PTR)&mci_status);
750 if (mwi->lasterror)
751 {
752 MCIWND_notify_error(mwi);
753 return 0;
754 }
755 TRACE("MCIWNDM_GETLENGTH: %ld\n", mci_status.dwReturn);
756 return mci_status.dwReturn;
757 }
758
759 case MCIWNDM_GETSTART:
760 {
761 MCI_STATUS_PARMS mci_status;
762
763 mci_status.dwItem = MCI_STATUS_POSITION;
764 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
765 MCI_STATUS_ITEM | MCI_STATUS_START,
766 (DWORD_PTR)&mci_status);
767 if (mwi->lasterror)
768 {
769 MCIWND_notify_error(mwi);
770 return 0;
771 }
772 TRACE("MCIWNDM_GETSTART: %ld\n", mci_status.dwReturn);
773 return mci_status.dwReturn;
774 }
775
776 case MCIWNDM_GETEND:
777 {
778 LRESULT start, length;
779
780 start = SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
781 length = SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
782 TRACE("MCIWNDM_GETEND: %ld\n", start + length);
783 return (start + length);
784 }
785
786 case MCIWNDM_GETPOSITIONA:
787 case MCIWNDM_GETPOSITIONW:
788 {
789 MCI_STATUS_PARMS mci_status;
790
791 TRACE("MCIWNDM_GETPOSITION\n");
792
793 /* get position string if requested */
794 if (wParam && lParam)
795 {
796 if (wMsg == MCIWNDM_GETPOSITIONA)
797 {
798 char cmd[64];
799
800 wsprintfA(cmd, "status %d position", mwi->alias);
801 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
802 }
803 else
804 {
805
806 WCHAR cmdW[64];
807 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','p','o','s','i','t','i','o','n',0};
808
809 wsprintfW(cmdW, formatW, mwi->alias);
810 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
811 }
812
813 if (mwi->lasterror)
814 return 0;
815 }
816
817 mci_status.dwItem = MCI_STATUS_POSITION;
818 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
819 MCI_STATUS_ITEM,
820 (DWORD_PTR)&mci_status);
821 if (mwi->lasterror)
822 return 0;
823
824 return mci_status.dwReturn;
825 }
826
827 case MCIWNDM_GETMODEA:
828 case MCIWNDM_GETMODEW:
829 {
830 MCI_STATUS_PARMS mci_status;
831
832 TRACE("MCIWNDM_GETMODE\n");
833
834 if (!mwi->mci)
835 return MCI_MODE_NOT_READY;
836
837 /* get mode string if requested */
838 if (wParam && lParam)
839 {
840 if (wMsg == MCIWNDM_GETMODEA)
841 {
842 char cmd[64];
843
844 wsprintfA(cmd, "status %d mode", mwi->alias);
845 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
846 }
847 else
848 {
849
850 WCHAR cmdW[64];
851 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','m','o','d','e',0};
852
853 wsprintfW(cmdW, formatW, mwi->alias);
854 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
855 }
856
857 if (mwi->lasterror)
858 return MCI_MODE_NOT_READY;
859 }
860
861 mci_status.dwItem = MCI_STATUS_MODE;
862 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
863 MCI_STATUS_ITEM,
864 (DWORD_PTR)&mci_status);
865 if (mwi->lasterror)
866 return MCI_MODE_NOT_READY;
867
868 return mci_status.dwReturn;
869 }
870
871 case MCIWNDM_PLAYFROM:
872 {
873 MCI_PLAY_PARMS mci_play;
874
875 TRACE("MCIWNDM_PLAYFROM %08lx\n", lParam);
876
877 mci_play.dwCallback = (DWORD_PTR)hWnd;
878 mci_play.dwFrom = lParam;
879 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
880 MCI_FROM | MCI_NOTIFY,
881 (DWORD_PTR)&mci_play);
882 if (mwi->lasterror)
883 {
884 MCIWND_notify_error(mwi);
885 return mwi->lasterror;
886 }
887
888 MCIWND_notify_mode(mwi);
889 MCIWND_UpdateState(mwi);
890 return 0;
891 }
892
893 case MCIWNDM_PLAYTO:
894 {
895 MCI_PLAY_PARMS mci_play;
896
897 TRACE("MCIWNDM_PLAYTO %08lx\n", lParam);
898
899 mci_play.dwCallback = (DWORD_PTR)hWnd;
900 mci_play.dwTo = lParam;
901 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
902 MCI_TO | MCI_NOTIFY,
903 (DWORD_PTR)&mci_play);
904 if (mwi->lasterror)
905 {
906 MCIWND_notify_error(mwi);
907 return mwi->lasterror;
908 }
909
910 MCIWND_notify_mode(mwi);
911 MCIWND_UpdateState(mwi);
912 return 0;
913 }
914
915 case MCIWNDM_PLAYREVERSE:
916 {
917 MCI_PLAY_PARMS mci_play;
918 DWORD flags = MCI_NOTIFY;
919
920 TRACE("MCIWNDM_PLAYREVERSE %08lx\n", lParam);
921
922 mci_play.dwCallback = (DWORD_PTR)hWnd;
923 mci_play.dwFrom = lParam;
924 switch (mwi->dev_type)
925 {
926 default:
927 case MCI_DEVTYPE_ANIMATION:
928 flags |= MCI_ANIM_PLAY_REVERSE;
929 break;
930
931 case MCI_DEVTYPE_DIGITAL_VIDEO:
932 flags |= MCI_DGV_PLAY_REVERSE;
933 break;
934
935 #ifdef MCI_VCR_PLAY_REVERSE
936 case MCI_DEVTYPE_VCR:
937 flags |= MCI_VCR_PLAY_REVERSE;
938 break;
939 #endif
940
941 case MCI_DEVTYPE_VIDEODISC:
942 flags |= MCI_VD_PLAY_REVERSE;
943 break;
944
945 }
946 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
947 flags, (DWORD_PTR)&mci_play);
948 if (mwi->lasterror)
949 {
950 MCIWND_notify_error(mwi);
951 return mwi->lasterror;
952 }
953
954 MCIWND_notify_mode(mwi);
955 MCIWND_UpdateState(mwi);
956 return 0;
957 }
958
959 case MCIWNDM_GETERRORA:
960 mciGetErrorStringA(mwi->lasterror, (LPSTR)lParam, wParam);
961 TRACE("MCIWNDM_GETERRORA: %s\n", debugstr_an((LPSTR)lParam, wParam));
962 return mwi->lasterror;
963
964 case MCIWNDM_GETERRORW:
965 mciGetErrorStringW(mwi->lasterror, (LPWSTR)lParam, wParam);
966 TRACE("MCIWNDM_GETERRORW: %s\n", debugstr_wn((LPWSTR)lParam, wParam));
967 return mwi->lasterror;
968
969 case MCIWNDM_SETOWNER:
970 TRACE("MCIWNDM_SETOWNER %p\n", (HWND)wParam);
971 mwi->hwndOwner = (HWND)wParam;
972 return 0;
973
974 case MCIWNDM_SENDSTRINGA:
975 {
976 UNICODE_STRING stringW;
977
978 TRACE("MCIWNDM_SENDSTRINGA %s\n", debugstr_a((LPCSTR)lParam));
979
980 RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
981 lParam = (LPARAM)stringW.Buffer;
982 }
983 /* fall through */
984 case MCIWNDM_SENDSTRINGW:
985 {
986 WCHAR *cmdW, *p;
987
988 TRACE("MCIWNDM_SENDSTRINGW %s\n", debugstr_w((LPCWSTR)lParam));
989
990 p = strchrW((LPCWSTR)lParam, ' ');
991 if (p)
992 {
993 static const WCHAR formatW[] = {'%','d',' ',0};
994 int len, pos;
995
996 pos = p - (WCHAR *)lParam + 1;
997 len = lstrlenW((LPCWSTR)lParam) + 64;
998
999 cmdW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1000
1001 memcpy(cmdW, (void *)lParam, pos * sizeof(WCHAR));
1002 wsprintfW(cmdW + pos, formatW, mwi->alias);
1003 strcatW(cmdW, (WCHAR *)lParam + pos);
1004 }
1005 else
1006 cmdW = (LPWSTR)lParam;
1007
1008 mwi->lasterror = mciSendStringW(cmdW, mwi->return_string,
1009 sizeof(mwi->return_string)/sizeof(mwi->return_string[0]),
1010 0);
1011 if (mwi->lasterror)
1012 MCIWND_notify_error(mwi);
1013
1014 if (cmdW != (LPWSTR)lParam)
1015 HeapFree(GetProcessHeap(), 0, cmdW);
1016
1017 if (wMsg == MCIWNDM_SENDSTRINGA)
1018 HeapFree(GetProcessHeap(), 0, (void *)lParam);
1019
1020 MCIWND_UpdateState(mwi);
1021 return mwi->lasterror;
1022 }
1023
1024 case MCIWNDM_RETURNSTRINGA:
1025 WideCharToMultiByte(CP_ACP, 0, mwi->return_string, -1, (LPSTR)lParam, wParam, NULL, NULL);
1026 TRACE("MCIWNDM_RETURNTRINGA %s\n", debugstr_an((LPSTR)lParam, wParam));
1027 return mwi->lasterror;
1028
1029 case MCIWNDM_RETURNSTRINGW:
1030 lstrcpynW((LPWSTR)lParam, mwi->return_string, wParam);
1031 TRACE("MCIWNDM_RETURNTRINGW %s\n", debugstr_wn((LPWSTR)lParam, wParam));
1032 return mwi->lasterror;
1033
1034 case MCIWNDM_SETTIMERS:
1035 TRACE("MCIWNDM_SETTIMERS active %d ms, inactive %d ms\n", (int)wParam, (int)lParam);
1036 mwi->active_timer = (WORD)wParam;
1037 mwi->inactive_timer = (WORD)lParam;
1038 return 0;
1039
1040 case MCIWNDM_SETACTIVETIMER:
1041 TRACE("MCIWNDM_SETACTIVETIMER %d ms\n", (int)wParam);
1042 mwi->active_timer = (WORD)wParam;
1043 return 0;
1044
1045 case MCIWNDM_SETINACTIVETIMER:
1046 TRACE("MCIWNDM_SETINACTIVETIMER %d ms\n", (int)wParam);
1047 mwi->inactive_timer = (WORD)wParam;
1048 return 0;
1049
1050 case MCIWNDM_GETACTIVETIMER:
1051 TRACE("MCIWNDM_GETACTIVETIMER: %d ms\n", mwi->active_timer);
1052 return mwi->active_timer;
1053
1054 case MCIWNDM_GETINACTIVETIMER:
1055 TRACE("MCIWNDM_GETINACTIVETIMER: %d ms\n", mwi->inactive_timer);
1056 return mwi->inactive_timer;
1057
1058 case MCIWNDM_CHANGESTYLES:
1059 TRACE("MCIWNDM_CHANGESTYLES mask %08lx, set %08lx\n", wParam, lParam);
1060 /* FIXME: update the visual window state as well:
1061 * add/remove trackbar, autosize, etc.
1062 */
1063 mwi->dwStyle &= ~wParam;
1064 mwi->dwStyle |= lParam & wParam;
1065 return 0;
1066
1067 case MCIWNDM_GETSTYLES:
1068 TRACE("MCIWNDM_GETSTYLES: %08x\n", mwi->dwStyle & 0xffff);
1069 return mwi->dwStyle & 0xffff;
1070
1071 case MCIWNDM_GETDEVICEA:
1072 {
1073 MCI_SYSINFO_PARMSA mci_sysinfo;
1074
1075 mci_sysinfo.lpstrReturn = (LPSTR)lParam;
1076 mci_sysinfo.dwRetSize = wParam;
1077 mwi->lasterror = mciSendCommandA(mwi->mci, MCI_SYSINFO,
1078 MCI_SYSINFO_INSTALLNAME,
1079 (DWORD_PTR)&mci_sysinfo);
1080 TRACE("MCIWNDM_GETDEVICEA: %s\n", debugstr_an((LPSTR)lParam, wParam));
1081 return 0;
1082 }
1083
1084 case MCIWNDM_GETDEVICEW:
1085 {
1086 MCI_SYSINFO_PARMSW mci_sysinfo;
1087
1088 mci_sysinfo.lpstrReturn = (LPWSTR)lParam;
1089 mci_sysinfo.dwRetSize = wParam;
1090 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SYSINFO,
1091 MCI_SYSINFO_INSTALLNAME,
1092 (DWORD_PTR)&mci_sysinfo);
1093 TRACE("MCIWNDM_GETDEVICEW: %s\n", debugstr_wn((LPWSTR)lParam, wParam));
1094 return 0;
1095 }
1096
1097 case MCIWNDM_VALIDATEMEDIA:
1098 TRACE("MCIWNDM_VALIDATEMEDIA\n");
1099 if (mwi->mci)
1100 {
1101 SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
1102 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
1103 }
1104 return 0;
1105
1106 case MCIWNDM_GETFILENAMEA:
1107 TRACE("MCIWNDM_GETFILENAMEA: %s\n", debugstr_w(mwi->lpName));
1108 if (mwi->lpName)
1109 WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, (LPSTR)lParam, wParam, NULL, NULL);
1110 return 0;
1111
1112 case MCIWNDM_GETFILENAMEW:
1113 TRACE("MCIWNDM_GETFILENAMEW: %s\n", debugstr_w(mwi->lpName));
1114 if (mwi->lpName)
1115 lstrcpynW((LPWSTR)lParam, mwi->lpName, wParam);
1116 return 0;
1117
1118 case MCIWNDM_GETTIMEFORMATA:
1119 case MCIWNDM_GETTIMEFORMATW:
1120 {
1121 MCI_STATUS_PARMS mci_status;
1122
1123 TRACE("MCIWNDM_GETTIMEFORMAT %08lx %08lx\n", wParam, lParam);
1124
1125 /* get format string if requested */
1126 if (wParam && lParam)
1127 {
1128 if (wMsg == MCIWNDM_GETTIMEFORMATA)
1129 {
1130 char cmd[64];
1131
1132 wsprintfA(cmd, "status %d time format", mwi->alias);
1133 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
1134 if (mwi->lasterror)
1135 return 0;
1136 }
1137 else
1138 {
1139 WCHAR cmdW[64];
1140 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',0};
1141
1142 wsprintfW(cmdW, formatW, mwi->alias);
1143 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
1144 if (mwi->lasterror)
1145 return 0;
1146 }
1147 }
1148
1149 mci_status.dwItem = MCI_STATUS_TIME_FORMAT ;
1150 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
1151 MCI_STATUS_ITEM,
1152 (DWORD_PTR)&mci_status);
1153 if (mwi->lasterror)
1154 return 0;
1155
1156 return mci_status.dwReturn;
1157 }
1158
1159 case MCIWNDM_SETTIMEFORMATA:
1160 {
1161 UNICODE_STRING stringW;
1162
1163 TRACE("MCIWNDM_SETTIMEFORMATA %s\n", debugstr_a((LPSTR)lParam));
1164
1165 RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
1166 lParam = (LPARAM)stringW.Buffer;
1167 }
1168 /* fall through */
1169 case MCIWNDM_SETTIMEFORMATW:
1170 {
1171 static const WCHAR formatW[] = {'s','e','t',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',' ',0};
1172 WCHAR *cmdW;
1173
1174 TRACE("MCIWNDM_SETTIMEFORMATW %s\n", debugstr_w((LPWSTR)lParam));
1175
1176 if (mwi->mci)
1177 {
1178 cmdW = HeapAlloc(GetProcessHeap(), 0, (lstrlenW((LPCWSTR)lParam) + 64) * sizeof(WCHAR));
1179 wsprintfW(cmdW, formatW, mwi->alias);
1180 strcatW(cmdW, (WCHAR *)lParam);
1181
1182 mwi->lasterror = mciSendStringW(cmdW, NULL, 0, 0);
1183
1184 /* fix the range tracking according to the new time format */
1185 if (!mwi->lasterror)
1186 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1,
1187 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0));
1188
1189 HeapFree(GetProcessHeap(), 0, cmdW);
1190 }
1191
1192 if (wMsg == MCIWNDM_SETTIMEFORMATA)
1193 HeapFree(GetProcessHeap(), 0, (void *)lParam);
1194
1195 return 0;
1196 }
1197
1198 case MCIWNDM_CAN_PLAY:
1199 TRACE("MCIWNDM_CAN_PLAY\n");
1200 if (mwi->mci)
1201 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_PLAY);
1202 return 0;
1203
1204 case MCIWNDM_CAN_RECORD:
1205 TRACE("MCIWNDM_CAN_RECORD\n");
1206 if (mwi->mci)
1207 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_RECORD);
1208 return 0;
1209
1210 case MCIWNDM_CAN_SAVE:
1211 TRACE("MCIWNDM_CAN_SAVE\n");
1212 if (mwi->mci)
1213 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_SAVE);
1214 return 0;
1215
1216 case MCIWNDM_CAN_EJECT:
1217 TRACE("MCIWNDM_CAN_EJECT\n");
1218 if (mwi->mci)
1219 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_EJECT);
1220 return 0;
1221
1222 case MCIWNDM_CAN_WINDOW:
1223 TRACE("MCIWNDM_CAN_WINDOW\n");
1224 switch (mwi->dev_type)
1225 {
1226 case MCI_DEVTYPE_ANIMATION:
1227 case MCI_DEVTYPE_DIGITAL_VIDEO:
1228 case MCI_DEVTYPE_OVERLAY:
1229 return 1;
1230 }
1231 return 0;
1232
1233 case MCIWNDM_CAN_CONFIG:
1234 TRACE("MCIWNDM_CAN_CONFIG\n");
1235 if (mwi->hdrv)
1236 return SendDriverMessage(mwi->hdrv, DRV_QUERYCONFIGURE, 0, 0);
1237 return 0;
1238
1239 case MCIWNDM_SETZOOM:
1240 TRACE("MCIWNDM_SETZOOM %ld\n", lParam);
1241 mwi->zoom = lParam;
1242
1243 if (mwi->mci && !(mwi->dwStyle & MCIWNDF_NOAUTOSIZEWINDOW))
1244 {
1245 RECT rc;
1246
1247 rc.left = rc.top = 0;
1248 rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
1249 rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
1250
1251 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
1252 rc.bottom += 32; /* add the height of the playbar */
1253 AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
1254 SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
1255 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1256 }
1257 return 0;
1258
1259 case MCIWNDM_GETZOOM:
1260 TRACE("MCIWNDM_GETZOOM: %d\n", mwi->zoom);
1261 return mwi->zoom;
1262
1263 case MCIWNDM_EJECT:
1264 {
1265 MCI_SET_PARMS mci_set;
1266
1267 TRACE("MCIWNDM_EJECT\n");
1268
1269 mci_set.dwCallback = (DWORD_PTR)hWnd;
1270 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SET,
1271 MCI_SET_DOOR_OPEN | MCI_NOTIFY,
1272 (DWORD_PTR)&mci_set);
1273 MCIWND_notify_mode(mwi);
1274 MCIWND_UpdateState(mwi);
1275 return mwi->lasterror;
1276 }
1277
1278 case MCIWNDM_SETVOLUME:
1279 case MCIWNDM_GETVOLUME:
1280 case MCIWNDM_SETSPEED:
1281 case MCIWNDM_GETSPEED:
1282 case MCIWNDM_SETREPEAT:
1283 case MCIWNDM_GETREPEAT:
1284 case MCIWNDM_REALIZE:
1285 case MCIWNDM_GETPALETTE:
1286 case MCIWNDM_SETPALETTE:
1287 case MCIWNDM_NEWA:
1288 case MCIWNDM_NEWW:
1289 case MCIWNDM_PALETTEKICK:
1290 case MCIWNDM_OPENINTERFACE:
1291 FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
1292 return 0;
1293
1294 case MCI_PLAY:
1295 {
1296 LRESULT end = SendMessageW(hWnd, MCIWNDM_GETEND, 0, 0);
1297 return SendMessageW(hWnd, MCIWNDM_PLAYTO, 0, end);
1298 }
1299
1300 case MCI_SEEK:
1301 case MCI_STEP:
1302 {
1303 MCI_SEEK_PARMS mci_seek; /* Layout is usable as MCI_XYZ_STEP_PARMS */
1304 DWORD flags = MCI_STEP == wMsg ? 0 :
1305 MCIWND_START == lParam ? MCI_SEEK_TO_START :
1306 MCIWND_END == lParam ? MCI_SEEK_TO_END : MCI_TO;
1307
1308 mci_seek.dwTo = lParam;
1309 mwi->lasterror = mciSendCommandW(mwi->mci, wMsg,
1310 flags, (DWORD_PTR)&mci_seek);
1311 if (mwi->lasterror)
1312 {
1313 MCIWND_notify_error(mwi);
1314 return mwi->lasterror;
1315 }
1316 /* update window to reflect the state */
1317 else InvalidateRect(hWnd, NULL, TRUE);
1318 return 0;
1319 }
1320
1321 case MCI_CLOSE:
1322 {
1323 RECT rc;
1324 MCI_GENERIC_PARMS mci_generic;
1325
1326 if (mwi->hdrv)
1327 {
1328 CloseDriver(mwi->hdrv, 0, 0);
1329 mwi->hdrv = 0;
1330 }
1331
1332 if (mwi->mci)
1333 {
1334 mci_generic.dwCallback = 0;
1335 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_CLOSE,
1336 0, (DWORD_PTR)&mci_generic);
1337 mwi->mci = 0;
1338 }
1339
1340 mwi->mode = MCI_MODE_NOT_READY;
1341 mwi->position = -1;
1342
1343 HeapFree(GetProcessHeap(), 0, mwi->lpName);
1344 mwi->lpName = NULL;
1345 MCIWND_UpdateState(mwi);
1346
1347 GetClientRect(hWnd, &rc);
1348 rc.bottom = rc.top;
1349 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
1350 rc.bottom += 32; /* add the height of the playbar */
1351 AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
1352 SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left,
1353 rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1354
1355 MCIWND_notify_media(mwi);
1356 return 0;
1357 }
1358
1359 case MCI_PAUSE:
1360 case MCI_STOP:
1361 case MCI_RESUME:
1362 mci_generic_command(mwi, wMsg);
1363 return mwi->lasterror;
1364
1365 case MCI_CONFIGURE:
1366 if (mwi->hdrv)
1367 SendDriverMessage(mwi->hdrv, DRV_CONFIGURE, (LPARAM)hWnd, 0);
1368 return 0;
1369
1370 case MCI_BREAK:
1371 case MCI_CAPTURE:
1372 case MCI_COPY:
1373 case MCI_CUE:
1374 case MCI_CUT:
1375 case MCI_DELETE:
1376 case MCI_ESCAPE:
1377 case MCI_FREEZE:
1378 case MCI_GETDEVCAPS:
1379 /*case MCI_INDEX:*/
1380 case MCI_INFO:
1381 case MCI_LIST:
1382 case MCI_LOAD:
1383 /*case MCI_MARK:*/
1384 case MCI_MONITOR:
1385 case MCI_OPEN:
1386 case MCI_PASTE:
1387 case MCI_PUT:
1388 case MCI_QUALITY:
1389 case MCI_REALIZE:
1390 case MCI_RECORD:
1391 case MCI_RESERVE:
1392 case MCI_RESTORE:
1393 case MCI_SAVE:
1394 case MCI_SET:
1395 case MCI_SETAUDIO:
1396 /*case MCI_SETTIMECODE:*/
1397 /*case MCI_SETTUNER:*/
1398 case MCI_SETVIDEO:
1399 case MCI_SIGNAL:
1400 case MCI_SPIN:
1401 case MCI_STATUS:
1402 case MCI_SYSINFO:
1403 case MCI_UNDO:
1404 case MCI_UNFREEZE:
1405 case MCI_UPDATE:
1406 case MCI_WHERE:
1407 case MCI_WINDOW:
1408 FIXME("support for MCI_ command %04x not implemented\n", wMsg);
1409 return 0;
1410 }
1411
1412 if (wMsg >= WM_USER)
1413 {
1414 FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
1415 return 0;
1416 }
1417
1418 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1419 return DefMDIChildProcW(hWnd, wMsg, wParam, lParam);
1420
1421 return DefWindowProcW(hWnd, wMsg, wParam, lParam);
1422 }