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