- move IShellFolder_fnGetDisplayNameOf() contents into a new function
[wine/testsucceed.git] / dlls / msvideo / mciwnd.c
blob13f62bae595da52466428304ec7a7130a35c0278
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * FIXME:
20 * Add support for all remaining MCI_ commands and MCIWNDM_ messages.
21 * Add support for all MCIWNDF_ flags.
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 "winreg.h"
32 #include "winternl.h"
33 #include "vfw.h"
34 #include "digitalv.h"
35 #include "commctrl.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(mci);
41 extern HMODULE MSVFW32_hModule;
42 static const WCHAR mciWndClassW[] = {'M','C','I','W','n','d','C','l','a','s','s',0};
44 typedef struct
46 DWORD dwStyle;
47 MCIDEVICEID mci;
48 HDRVR hdrv;
49 int alias;
50 UINT dev_type;
51 UINT mode;
52 long position;
53 SIZE size; /* size of the original frame rect */
54 int zoom;
55 LPWSTR lpName;
56 HWND hWnd, hwndOwner;
57 UINT uTimer;
58 MCIERROR lasterror;
59 WCHAR return_string[128];
60 WORD active_timer, inactive_timer;
61 } MCIWndInfo;
63 static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
65 #define CTL_PLAYSTOP 0x3200
66 #define CTL_MENU 0x3201
67 #define CTL_TRACKBAR 0x3202
69 /***********************************************************************
70 * MCIWndRegisterClass [MSVFW32.@]
72 * NOTE: Native always uses its own hInstance
74 BOOL VFWAPIV MCIWndRegisterClass(void)
76 WNDCLASSW wc;
78 /* Since we are going to register a class belonging to MSVFW32
79 * and later we will create windows with a different hInstance
80 * CS_GLOBALCLASS is needed. And because the second attempt
81 * to register a global class will fail we need to test whether
82 * the class was already registered.
84 wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC | CS_GLOBALCLASS;
85 wc.lpfnWndProc = MCIWndProc;
86 wc.cbClsExtra = 0;
87 wc.cbWndExtra = sizeof(MCIWndInfo*);
88 wc.hInstance = MSVFW32_hModule;
89 wc.hIcon = 0;
90 wc.hCursor = LoadCursorW(0, MAKEINTRESOURCEW(IDC_ARROW));
91 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
92 wc.lpszMenuName = NULL;
93 wc.lpszClassName = mciWndClassW;
95 if (RegisterClassW(&wc)) return TRUE;
96 if (GetLastError() == ERROR_CLASS_ALREADY_EXISTS) return TRUE;
98 return FALSE;
101 /***********************************************************************
102 * MCIWndCreateW [MSVFW32.@]
104 HWND VFWAPIV MCIWndCreateW(HWND hwndParent, HINSTANCE hInstance,
105 DWORD dwStyle, LPCWSTR szFile)
107 TRACE("%p %p %lx %s\n", hwndParent, hInstance, dwStyle, debugstr_w(szFile));
109 MCIWndRegisterClass();
111 if (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_SHOWNAME) && mwi->lpName)
199 strcpyW(buffer, mwi->lpName);
200 else
201 *buffer = 0;
203 if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
205 static const WCHAR spaceW[] = {' ',0};
206 static const WCHAR l_braceW[] = {'(',0};
208 if (*buffer) strcatW(buffer, spaceW);
209 strcatW(buffer, l_braceW);
212 if (mwi->dwStyle & MCIWNDF_SHOWPOS)
214 WCHAR posW[64];
216 posW[0] = 0;
217 SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 64, (LPARAM)posW);
218 strcatW(buffer, posW);
221 if ((mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) == (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
223 static const WCHAR dashW[] = {' ','-',' ',0};
224 strcatW(buffer, dashW);
227 if (mwi->dwStyle & MCIWNDF_SHOWMODE)
229 WCHAR modeW[64];
231 modeW[0] = 0;
232 SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 64, (LPARAM)modeW);
233 strcatW(buffer, modeW);
236 if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
238 static const WCHAR r_braceW[] = {')',0};
239 strcatW(buffer, r_braceW);
242 TRACE("=> '%s'\n", debugstr_w(buffer));
243 SetWindowTextW(mwi->hWnd, buffer);
246 static LRESULT MCIWND_Create(HWND hWnd, LPCREATESTRUCTW cs)
248 HWND hChld;
249 MCIWndInfo *mwi;
250 static const WCHAR buttonW[] = {'b','u','t','t','o','n',0};
252 mwi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mwi));
253 if (!mwi) return -1;
255 SetWindowLongW(hWnd, 0, (LPARAM)mwi);
257 mwi->dwStyle = cs->style;
258 mwi->hWnd = hWnd;
259 mwi->hwndOwner = cs->hwndParent;
260 mwi->active_timer = 500;
261 mwi->inactive_timer = 2000;
262 mwi->mode = MCI_MODE_NOT_READY;
263 mwi->position = -1;
264 mwi->zoom = 100;
266 if (!(mwi->dwStyle & MCIWNDF_NOMENU))
268 static const WCHAR menuW[] = {'M','e','n','u',0};
270 hChld = CreateWindowExW(0, buttonW, menuW, WS_CHILD|WS_VISIBLE, 32, cs->cy, 32, 32,
271 hWnd, (HMENU)CTL_MENU, cs->hInstance, 0L);
272 TRACE("Get Button2: %p\n", hChld);
275 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
277 INITCOMMONCONTROLSEX init;
278 static const WCHAR playW[] = {'P','l','a','y',0};
280 /* adding the other elements: play/stop button, menu button, status */
281 hChld = CreateWindowExW(0, buttonW, playW, WS_CHILD|WS_VISIBLE, 0, cs->cy, 32, 32,
282 hWnd, (HMENU)CTL_PLAYSTOP, cs->hInstance, 0L);
283 TRACE("Get Button1: %p\n", hChld);
285 init.dwSize = sizeof(init);
286 init.dwICC = ICC_BAR_CLASSES;
287 InitCommonControlsEx(&init);
289 hChld = CreateWindowExW(0, TRACKBAR_CLASSW, NULL, WS_CHILD|WS_VISIBLE, 64, cs->cy, cs->cx - 64, 32,
290 hWnd, (HMENU)CTL_TRACKBAR, cs->hInstance, 0L);
291 TRACE("Get status: %p\n", hChld);
294 /* This sets the default window size */
295 SendMessageW(hWnd, MCI_CLOSE, 0, 0);
297 if (cs->lpCreateParams)
299 LPARAM lParam;
301 /* MCI wnd class is prepared to be embedded as an MDI child window */
302 if (cs->dwExStyle & WS_EX_MDICHILD)
304 MDICREATESTRUCTW *mdics = (MDICREATESTRUCTW *)cs->lpCreateParams;
305 lParam = mdics->lParam;
307 else
308 lParam = (LPARAM)cs->lpCreateParams;
309 /* yes, A variant of the message */
310 SendMessageW(hWnd, MCIWNDM_OPENA, 0, lParam);
313 return 0;
316 static void MCIWND_ToggleState(MCIWndInfo *mwi)
318 switch (SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0))
320 case MCI_MODE_NOT_READY:
321 case MCI_MODE_RECORD:
322 case MCI_MODE_SEEK:
323 case MCI_MODE_OPEN:
324 TRACE("Cannot do much...\n");
325 break;
327 case MCI_MODE_PAUSE:
328 SendMessageW(mwi->hWnd, MCI_RESUME, 0, 0);
329 break;
331 case MCI_MODE_PLAY:
332 SendMessageW(mwi->hWnd, MCI_PAUSE, 0, 0);
333 break;
335 case MCI_MODE_STOP:
336 SendMessageW(mwi->hWnd, MCI_STOP, 0, 0);
337 break;
341 static LRESULT MCIWND_Command(MCIWndInfo *mwi, WPARAM wParam, LPARAM lParam)
343 switch (LOWORD(wParam))
345 case CTL_PLAYSTOP: MCIWND_ToggleState(mwi); break;
346 case CTL_MENU:
347 case CTL_TRACKBAR:
348 default:
349 FIXME("support for command %04x not implement yet\n", LOWORD(wParam));
351 return 0L;
354 static void MCIWND_notify_media(MCIWndInfo *mwi)
356 if (mwi->dwStyle & (MCIWNDF_NOTIFYMEDIAA | MCIWNDF_NOTIFYMEDIAW))
358 if (!mwi->lpName)
360 static const WCHAR empty_str[1];
361 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)empty_str);
363 else
365 if (mwi->dwStyle & MCIWNDF_NOTIFYANSI)
367 char *ansi_name;
368 int len;
370 len = WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, NULL, 0, NULL, NULL);
371 ansi_name = HeapAlloc(GetProcessHeap(), 0, len);
372 WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, ansi_name, len, NULL, NULL);
374 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)ansi_name);
376 HeapFree(GetProcessHeap(), 0, ansi_name);
378 else
379 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)mwi->lpName);
384 static MCIERROR mci_generic_command(MCIWndInfo *mwi, UINT cmd)
386 MCI_GENERIC_PARMS mci_generic;
388 mci_generic.dwCallback = 0;
389 mwi->lasterror = mciSendCommandW(mwi->mci, cmd, 0, (DWORD_PTR)&mci_generic);
391 if (mwi->lasterror)
392 return mwi->lasterror;
394 MCIWND_notify_mode(mwi);
395 MCIWND_UpdateState(mwi);
396 return 0;
399 static LRESULT mci_get_devcaps(MCIWndInfo *mwi, UINT cap)
401 MCI_GETDEVCAPS_PARMS mci_devcaps;
403 mci_devcaps.dwItem = cap;
404 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
405 MCI_GETDEVCAPS_ITEM,
406 (DWORD_PTR)&mci_devcaps);
407 if (mwi->lasterror)
408 return 0;
410 return mci_devcaps.dwReturn;
413 static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
415 MCIWndInfo *mwi;
417 TRACE("%p %04x %08x %08lx\n", hWnd, wMsg, wParam, lParam);
419 mwi = (MCIWndInfo*)GetWindowLongW(hWnd, 0);
420 if (!mwi)
422 if (wMsg == WM_CREATE)
423 return MCIWND_Create(hWnd, (CREATESTRUCTW *)lParam);
425 return DefWindowProcW(hWnd, wMsg, wParam, lParam);
428 switch (wMsg)
430 case WM_DESTROY:
431 if (mwi->uTimer)
432 KillTimer(hWnd, mwi->uTimer);
434 if (mwi->mci)
435 SendMessageW(hWnd, MCI_CLOSE, 0, 0);
437 HeapFree(GetProcessHeap(), 0, mwi);
439 DestroyWindow(GetDlgItem(hWnd, CTL_MENU));
440 DestroyWindow(GetDlgItem(hWnd, CTL_PLAYSTOP));
441 DestroyWindow(GetDlgItem(hWnd, CTL_TRACKBAR));
442 return 0;
444 case WM_PAINT:
446 HDC hdc;
447 PAINTSTRUCT ps;
449 hdc = (wParam) ? (HDC)wParam : BeginPaint(hWnd, &ps);
450 /* something to do ? */
451 if (!wParam) EndPaint(hWnd, &ps);
452 return 1;
455 case WM_COMMAND:
456 return MCIWND_Command(mwi, wParam, lParam);
458 case WM_NCACTIVATE:
459 if (mwi->uTimer)
461 KillTimer(hWnd, mwi->uTimer);
462 mwi->uTimer = SetTimer(hWnd, 1, wParam ? mwi->active_timer : mwi->inactive_timer, NULL);
464 break;
466 case WM_TIMER:
467 MCIWND_UpdateState(mwi);
468 return 0;
470 case WM_SIZE:
472 SetWindowPos(GetDlgItem(hWnd, CTL_PLAYSTOP), 0, 0, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
473 SetWindowPos(GetDlgItem(hWnd, CTL_MENU), 0, 32, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
474 SetWindowPos(GetDlgItem(hWnd, CTL_TRACKBAR), 0, 64, HIWORD(lParam) - 32, LOWORD(lParam) - 64, 32, SWP_NOACTIVATE);
476 MCIWND_notify_size(mwi);
477 return 0;
480 case MM_MCINOTIFY:
481 MCIWND_notify_mode(mwi);
482 MCIWND_UpdateState(mwi);
483 return 0;
485 case MCIWNDM_OPENA:
487 UNICODE_STRING nameW;
488 TRACE("MCIWNDM_OPENA %s\n", debugstr_a((LPSTR)lParam));
489 RtlCreateUnicodeStringFromAsciiz(&nameW, (LPCSTR)lParam);
490 lParam = (LPARAM)nameW.Buffer;
492 /* fall through */
493 case MCIWNDM_OPENW:
495 RECT rc;
496 HCURSOR hCursor;
497 MCI_OPEN_PARMSW mci_open;
498 MCI_GETDEVCAPS_PARMS mci_devcaps;
499 WCHAR aliasW[64];
500 WCHAR drv_name[MAX_PATH];
501 static const WCHAR formatW[] = {'%','d',0};
502 static const WCHAR mci32W[] = {'m','c','i','3','2',0};
503 static const WCHAR system_iniW[] = {'s','y','s','t','e','m','.','i','n','i',0};
505 TRACE("MCIWNDM_OPENW %s\n", debugstr_w((LPWSTR)lParam));
507 if (wParam == MCIWNDOPENF_NEW)
509 SendMessageW(hWnd, MCIWNDM_NEWW, 0, lParam);
510 goto end_of_mci_open;
513 if (mwi->uTimer)
515 KillTimer(hWnd, mwi->uTimer);
516 mwi->uTimer = 0;
519 hCursor = LoadCursorW(0, (LPWSTR)IDC_WAIT);
520 hCursor = SetCursor(hCursor);
522 mci_open.lpstrElementName = (LPWSTR)lParam;
523 wsprintfW(aliasW, formatW, (int)hWnd + 1);
524 mci_open.lpstrAlias = aliasW;
525 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_OPEN,
526 MCI_OPEN_ELEMENT | MCI_OPEN_ALIAS | MCI_WAIT,
527 (DWORD_PTR)&mci_open);
528 SetCursor(hCursor);
530 if (mwi->lasterror)
532 /* FIXME: get the caption from resources */
533 static const WCHAR caption[] = {'M','C','I',' ','E','r','r','o','r',0};
534 WCHAR error_str[MAXERRORLENGTH];
536 mciGetErrorStringW(mwi->lasterror, error_str, MAXERRORLENGTH);
537 MessageBoxW(hWnd, error_str, caption, MB_ICONEXCLAMATION | MB_OK);
538 MCIWND_notify_error(mwi);
539 goto end_of_mci_open;
542 mwi->mci = mci_open.wDeviceID;
543 mwi->alias = (int)hWnd + 1;
545 mwi->lpName = HeapAlloc(GetProcessHeap(), 0, (strlenW((LPWSTR)lParam) + 1) * sizeof(WCHAR));
546 strcpyW(mwi->lpName, (LPWSTR)lParam);
548 MCIWND_UpdateState(mwi);
550 mci_devcaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
551 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
552 MCI_GETDEVCAPS_ITEM,
553 (DWORD_PTR)&mci_devcaps);
554 if (mwi->lasterror)
556 MCIWND_notify_error(mwi);
557 goto end_of_mci_open;
560 mwi->dev_type = mci_devcaps.dwReturn;
562 drv_name[0] = 0;
563 SendMessageW(hWnd, MCIWNDM_GETDEVICEW, 256, (LPARAM)drv_name);
564 if (drv_name[0] && GetPrivateProfileStringW(mci32W, drv_name, NULL,
565 drv_name, MAX_PATH, system_iniW))
566 mwi->hdrv = OpenDriver(drv_name, NULL, 0);
568 if (mwi->dev_type == MCI_DEVTYPE_DIGITAL_VIDEO)
570 MCI_DGV_WINDOW_PARMSW mci_window;
572 mci_window.hWnd = hWnd;
573 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WINDOW,
574 MCI_DGV_WINDOW_HWND,
575 (DWORD_PTR)&mci_window);
576 if (mwi->lasterror)
578 MCIWND_notify_error(mwi);
579 goto end_of_mci_open;
583 if (SendMessageW(hWnd, MCIWNDM_GET_DEST, 0, (LPARAM)&rc) == 0)
585 mwi->size.cx = rc.right - rc.left;
586 mwi->size.cy = rc.bottom - rc.top;
588 rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
589 rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
590 SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
592 else
594 GetClientRect(hWnd, &rc);
595 rc.bottom = rc.top;
598 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
599 rc.bottom += 32; /* add the height of the playbar */
600 AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
601 SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left,
602 rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
604 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMIN, 0L, 0L);
605 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1,
606 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0));
607 mwi->uTimer = SetTimer(hWnd, 1, mwi->active_timer, NULL);
609 MCIWND_notify_media(mwi);
611 end_of_mci_open:
612 if (wMsg == MCIWNDM_OPENA)
613 HeapFree(GetProcessHeap(), 0, (void *)lParam);
614 return mwi->lasterror;
617 case MCIWNDM_GETDEVICEID:
618 return mwi->mci;
620 case MCIWNDM_GETALIAS:
621 return mwi->alias;
623 case MCIWNDM_GET_SOURCE:
625 MCI_DGV_RECT_PARMS mci_rect;
627 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WHERE,
628 MCI_DGV_WHERE_SOURCE,
629 (DWORD_PTR)&mci_rect);
630 if (mwi->lasterror)
632 MCIWND_notify_error(mwi);
633 return mwi->lasterror;
635 *(RECT *)lParam = mci_rect.rc;
636 return 0;
639 case MCIWNDM_GET_DEST:
641 MCI_DGV_RECT_PARMS mci_rect;
643 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WHERE,
644 MCI_DGV_WHERE_DESTINATION,
645 (DWORD_PTR)&mci_rect);
646 if (mwi->lasterror)
648 MCIWND_notify_error(mwi);
649 return mwi->lasterror;
651 *(RECT *)lParam = mci_rect.rc;
652 return 0;
655 case MCIWNDM_PUT_SOURCE:
657 MCI_DGV_PUT_PARMS mci_put;
659 mci_put.rc = *(RECT *)lParam;
660 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
661 MCI_DGV_PUT_SOURCE,
662 (DWORD_PTR)&mci_put);
663 if (mwi->lasterror)
665 MCIWND_notify_error(mwi);
666 return mwi->lasterror;
668 return 0;
671 case MCIWNDM_PUT_DEST:
673 MCI_DGV_PUT_PARMS mci_put;
675 mci_put.rc = *(RECT *)lParam;
676 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
677 MCI_DGV_PUT_DESTINATION | MCI_DGV_RECT,
678 (DWORD_PTR)&mci_put);
679 if (mwi->lasterror)
681 MCIWND_notify_error(mwi);
682 return mwi->lasterror;
684 return 0;
687 case MCIWNDM_GETLENGTH:
689 MCI_STATUS_PARMS mci_status;
691 mci_status.dwItem = MCI_STATUS_LENGTH;
692 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
693 MCI_STATUS_ITEM,
694 (DWORD_PTR)&mci_status);
695 if (mwi->lasterror)
697 MCIWND_notify_error(mwi);
698 return 0;
700 return mci_status.dwReturn;
703 case MCIWNDM_GETSTART:
705 MCI_STATUS_PARMS mci_status;
707 mci_status.dwItem = MCI_STATUS_POSITION;
708 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
709 MCI_STATUS_ITEM | MCI_STATUS_START,
710 (DWORD_PTR)&mci_status);
711 if (mwi->lasterror)
713 MCIWND_notify_error(mwi);
714 return 0;
716 return mci_status.dwReturn;
719 case MCIWNDM_GETEND:
721 LRESULT start, length;
723 start = SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
724 length = SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
725 return (start + length);
728 case MCIWNDM_GETPOSITIONA:
729 case MCIWNDM_GETPOSITIONW:
731 MCI_STATUS_PARMS mci_status;
733 /* get position string if requested */
734 if (wParam && lParam)
736 if (wMsg == MCIWNDM_GETPOSITIONA)
738 char cmd[64];
740 wsprintfA(cmd, "status %d position", mwi->alias);
741 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
743 else
746 WCHAR cmdW[64];
747 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','p','o','s','i','t','i','o','n',0};
749 wsprintfW(cmdW, formatW, mwi->alias);
750 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
753 if (mwi->lasterror)
754 return 0;
757 mci_status.dwItem = MCI_STATUS_POSITION;
758 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
759 MCI_STATUS_ITEM,
760 (DWORD_PTR)&mci_status);
761 if (mwi->lasterror)
762 return 0;
764 return mci_status.dwReturn;
767 case MCIWNDM_GETMODEA:
768 case MCIWNDM_GETMODEW:
770 MCI_STATUS_PARMS mci_status;
772 if (!mwi->mci)
773 return MCI_MODE_NOT_READY;
775 /* get mode string if requested */
776 if (wParam && lParam)
778 if (wMsg == MCIWNDM_GETMODEA)
780 char cmd[64];
782 wsprintfA(cmd, "status %d mode", mwi->alias);
783 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
785 else
788 WCHAR cmdW[64];
789 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','m','o','d','e',0};
791 wsprintfW(cmdW, formatW, mwi->alias);
792 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
795 if (mwi->lasterror)
796 return MCI_MODE_NOT_READY;
799 mci_status.dwItem = MCI_STATUS_MODE;
800 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
801 MCI_STATUS_ITEM,
802 (DWORD_PTR)&mci_status);
803 if (mwi->lasterror)
804 return MCI_MODE_NOT_READY;
806 return mci_status.dwReturn;
809 case MCIWNDM_PLAYFROM:
811 MCI_PLAY_PARMS mci_play;
813 mci_play.dwCallback = (DWORD_PTR)hWnd;
814 mci_play.dwFrom = lParam;
815 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
816 MCI_FROM | MCI_NOTIFY,
817 (DWORD_PTR)&mci_play);
818 if (mwi->lasterror)
820 MCIWND_notify_error(mwi);
821 return mwi->lasterror;
824 MCIWND_notify_mode(mwi);
825 MCIWND_UpdateState(mwi);
826 return 0;
829 case MCIWNDM_PLAYTO:
831 MCI_PLAY_PARMS mci_play;
833 mci_play.dwCallback = (DWORD_PTR)hWnd;
834 mci_play.dwTo = lParam;
835 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
836 MCI_TO | MCI_NOTIFY,
837 (DWORD_PTR)&mci_play);
838 if (mwi->lasterror)
840 MCIWND_notify_error(mwi);
841 return mwi->lasterror;
844 MCIWND_notify_mode(mwi);
845 MCIWND_UpdateState(mwi);
846 return 0;
850 case MCIWNDM_PLAYREVERSE:
852 MCI_PLAY_PARMS mci_play;
853 DWORD flags = MCI_NOTIFY;
855 mci_play.dwCallback = (DWORD_PTR)hWnd;
856 mci_play.dwFrom = lParam;
857 switch (mwi->dev_type)
859 default:
860 case MCI_DEVTYPE_ANIMATION:
861 flags |= MCI_ANIM_PLAY_REVERSE;
862 break;
864 case MCI_DEVTYPE_DIGITAL_VIDEO:
865 flags |= MCI_DGV_PLAY_REVERSE;
866 break;
868 #ifdef MCI_VCR_PLAY_REVERSE
869 case MCI_DEVTYPE_VCR:
870 flags |= MCI_VCR_PLAY_REVERSE;
871 break;
872 #endif
874 case MCI_DEVTYPE_VIDEODISC:
875 flags |= MCI_VD_PLAY_REVERSE;
876 break;
879 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
880 flags, (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_GETERRORA:
893 mciGetErrorStringA(mwi->lasterror, (LPSTR)lParam, wParam);
894 return mwi->lasterror;
896 case MCIWNDM_GETERRORW:
897 mciGetErrorStringW(mwi->lasterror, (LPWSTR)lParam, wParam);
898 return mwi->lasterror;
900 case MCIWNDM_SETOWNER:
901 mwi->hwndOwner = (HWND)wParam;
902 return 0;
904 case MCIWNDM_SENDSTRINGA:
906 UNICODE_STRING stringW;
907 RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
908 lParam = (LPARAM)stringW.Buffer;
910 /* fall through */
911 case MCIWNDM_SENDSTRINGW:
913 WCHAR *cmdW, *p;
915 p = strchrW((LPCWSTR)lParam, ' ');
916 if (p)
918 static const WCHAR formatW[] = {'%','d',' ',0};
919 int len, pos;
921 pos = p - (WCHAR *)lParam + 1;
922 len = lstrlenW((LPCWSTR)lParam) + 64;
924 cmdW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
926 memcpy(cmdW, (void *)lParam, pos * sizeof(WCHAR));
927 wsprintfW(cmdW + pos, formatW, mwi->alias);
928 strcatW(cmdW, (WCHAR *)lParam + pos);
930 else
931 cmdW = (LPWSTR)lParam;
933 mwi->lasterror = mciSendStringW(cmdW, mwi->return_string,
934 sizeof(mwi->return_string)/sizeof(mwi->return_string[0]),
936 if (mwi->lasterror)
937 MCIWND_notify_error(mwi);
939 if (cmdW != (LPWSTR)lParam)
940 HeapFree(GetProcessHeap(), 0, cmdW);
942 if (wMsg == MCIWNDM_SENDSTRINGA)
943 HeapFree(GetProcessHeap(), 0, (void *)lParam);
945 MCIWND_UpdateState(mwi);
946 return mwi->lasterror;
949 case MCIWNDM_RETURNSTRINGA:
950 WideCharToMultiByte(CP_ACP, 0, mwi->return_string, -1, (LPSTR)lParam, wParam, NULL, NULL);
951 return mwi->lasterror;
953 case MCIWNDM_RETURNSTRINGW:
954 strncpyW((LPWSTR)lParam, mwi->return_string, wParam);
955 return mwi->lasterror;
957 case MCIWNDM_SETTIMERS:
958 mwi->active_timer = (WORD)wParam;
959 mwi->inactive_timer = (WORD)lParam;
960 return 0;
962 case MCIWNDM_SETACTIVETIMER:
963 mwi->active_timer = (WORD)wParam;
964 return 0;
966 case MCIWNDM_SETINACTIVETIMER:
967 mwi->inactive_timer = (WORD)wParam;
968 return 0;
970 case MCIWNDM_GETACTIVETIMER:
971 return mwi->active_timer;
973 case MCIWNDM_GETINACTIVETIMER:
974 return mwi->inactive_timer;
976 case MCIWNDM_CHANGESTYLES:
977 /* FIXME: update the visual window state as well:
978 * add/remove trackbar, autosize, etc.
980 mwi->dwStyle &= ~wParam;
981 mwi->dwStyle |= lParam & wParam;
982 return 0;
984 case MCIWNDM_GETSTYLES:
985 return mwi->dwStyle & 0xffff;
987 case MCIWNDM_GETDEVICEA:
989 MCI_SYSINFO_PARMSA mci_sysinfo;
991 mci_sysinfo.lpstrReturn = (LPSTR)lParam;
992 mci_sysinfo.dwRetSize = wParam;
993 mwi->lasterror = mciSendCommandA(mwi->mci, MCI_SYSINFO,
994 MCI_SYSINFO_INSTALLNAME,
995 (DWORD_PTR)&mci_sysinfo);
996 return 0;
999 case MCIWNDM_GETDEVICEW:
1001 MCI_SYSINFO_PARMSW mci_sysinfo;
1003 mci_sysinfo.lpstrReturn = (LPWSTR)lParam;
1004 mci_sysinfo.dwRetSize = wParam;
1005 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SYSINFO,
1006 MCI_SYSINFO_INSTALLNAME,
1007 (DWORD_PTR)&mci_sysinfo);
1008 return 0;
1011 case MCIWNDM_VALIDATEMEDIA:
1012 if (mwi->mci)
1014 SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
1015 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
1017 return 0;
1019 case MCIWNDM_GETFILENAMEA:
1020 if (mwi->lpName)
1021 WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, (LPSTR)lParam, wParam, NULL, NULL);
1022 return 0;
1024 case MCIWNDM_GETFILENAMEW:
1025 if (mwi->lpName)
1026 strncpyW((LPWSTR)lParam, mwi->lpName, wParam);
1027 return 0;
1029 case MCIWNDM_GETTIMEFORMATA:
1030 case MCIWNDM_GETTIMEFORMATW:
1032 MCI_STATUS_PARMS mci_status;
1034 /* get format string if requested */
1035 if (wParam && lParam)
1037 if (wMsg == MCIWNDM_GETTIMEFORMATA)
1039 char cmd[64];
1041 wsprintfA(cmd, "status %d time format", mwi->alias);
1042 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
1043 if (mwi->lasterror)
1044 return 0;
1046 else
1048 WCHAR cmdW[64];
1049 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',0};
1051 wsprintfW(cmdW, formatW, mwi->alias);
1052 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
1053 if (mwi->lasterror)
1054 return 0;
1058 mci_status.dwItem = MCI_STATUS_TIME_FORMAT ;
1059 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
1060 MCI_STATUS_ITEM,
1061 (DWORD_PTR)&mci_status);
1062 if (mwi->lasterror)
1063 return 0;
1065 return mci_status.dwReturn;
1068 case MCIWNDM_SETTIMEFORMATA:
1070 UNICODE_STRING stringW;
1072 RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
1073 lParam = (LPARAM)stringW.Buffer;
1075 /* fall through */
1076 case MCIWNDM_SETTIMEFORMATW:
1078 static const WCHAR formatW[] = {'s','e','t',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',' ',0};
1079 WCHAR *cmdW;
1081 if (mwi->mci)
1083 cmdW = HeapAlloc(GetProcessHeap(), 0, (lstrlenW((LPCWSTR)lParam) + 64) * sizeof(WCHAR));
1084 wsprintfW(cmdW, formatW, mwi->alias);
1085 strcatW(cmdW, (WCHAR *)lParam);
1087 mwi->lasterror = mciSendStringW(cmdW, NULL, 0, 0);
1089 /* fix the range tracking according to the new time format */
1090 if (!mwi->lasterror)
1091 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1,
1092 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0));
1095 if (wMsg == MCIWNDM_SETTIMEFORMATA)
1096 HeapFree(GetProcessHeap(), 0, (void *)lParam);
1098 return 0;
1101 case MCIWNDM_CAN_PLAY:
1102 if (mwi->mci)
1103 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_PLAY);
1104 return 0;
1106 case MCIWNDM_CAN_RECORD:
1107 if (mwi->mci)
1108 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_RECORD);
1109 return 0;
1111 case MCIWNDM_CAN_SAVE:
1112 if (mwi->mci)
1113 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_SAVE);
1114 return 0;
1116 case MCIWNDM_CAN_EJECT:
1117 if (mwi->mci)
1118 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_EJECT);
1119 return 0;
1121 case MCIWNDM_CAN_WINDOW:
1122 switch (mwi->dev_type)
1124 case MCI_DEVTYPE_ANIMATION:
1125 case MCI_DEVTYPE_DIGITAL_VIDEO:
1126 case MCI_DEVTYPE_OVERLAY:
1127 return 1;
1129 return 0;
1131 case MCIWNDM_CAN_CONFIG:
1132 if (mwi->hdrv)
1133 return SendDriverMessage(mwi->hdrv, DRV_QUERYCONFIGURE, 0, 0);
1134 return 0;
1136 case MCIWNDM_SETZOOM:
1137 mwi->zoom = lParam;
1139 if (mwi->mci)
1141 RECT rc;
1143 SetRectEmpty(&rc);
1144 rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
1145 rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
1146 SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
1148 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
1149 rc.bottom += 32; /* add the height of the playbar */
1150 AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
1151 SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
1152 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1154 return 0;
1156 case MCIWNDM_GETZOOM:
1157 return mwi->zoom;
1159 case MCIWNDM_EJECT:
1161 MCI_SET_PARMS mci_set;
1163 mci_set.dwCallback = (DWORD_PTR)hWnd;
1164 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SET,
1165 MCI_SET_DOOR_OPEN | MCI_NOTIFY,
1166 (DWORD_PTR)&mci_set);
1167 MCIWND_notify_mode(mwi);
1168 MCIWND_UpdateState(mwi);
1169 return mwi->lasterror;
1172 case MCIWNDM_SETVOLUME:
1173 case MCIWNDM_GETVOLUME:
1174 case MCIWNDM_SETSPEED:
1175 case MCIWNDM_GETSPEED:
1176 case MCIWNDM_SETREPEAT:
1177 case MCIWNDM_GETREPEAT:
1178 case MCIWNDM_REALIZE:
1179 case MCIWNDM_GETPALETTE:
1180 case MCIWNDM_SETPALETTE:
1181 case MCIWNDM_NEWA:
1182 case MCIWNDM_NEWW:
1183 case MCIWNDM_PALETTEKICK:
1184 case MCIWNDM_OPENINTERFACE:
1185 FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
1186 return 0;
1188 case MCI_PLAY:
1190 LRESULT end = SendMessageW(hWnd, MCIWNDM_GETEND, 0, 0);
1191 return SendMessageW(hWnd, MCIWNDM_PLAYTO, 0, end);
1194 case MCI_SEEK:
1196 MCI_SEEK_PARMS mci_seek;
1198 switch (lParam)
1200 case MCIWND_START:
1201 lParam = SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
1202 break;
1204 case MCIWND_END:
1205 lParam = SendMessageW(hWnd, MCIWNDM_GETEND, 0, 0);
1206 break;
1209 mci_seek.dwTo = lParam;
1210 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SEEK,
1211 MCI_TO, (DWORD_PTR)&mci_seek);
1212 if (mwi->lasterror)
1214 MCIWND_notify_error(mwi);
1215 return mwi->lasterror;
1217 return 0;
1220 case MCI_CLOSE:
1222 RECT rc;
1223 MCI_GENERIC_PARMS mci_generic;
1225 if (mwi->hdrv)
1227 CloseDriver(mwi->hdrv, 0, 0);
1228 mwi->hdrv = 0;
1231 if (mwi->mci)
1233 mci_generic.dwCallback = 0;
1234 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_CLOSE,
1235 0, (DWORD_PTR)&mci_generic);
1236 mwi->mci = 0;
1239 mwi->mode = MCI_MODE_NOT_READY;
1240 mwi->position = -1;
1242 if (mwi->lpName)
1244 HeapFree(GetProcessHeap(), 0, mwi->lpName);
1245 mwi->lpName = NULL;
1247 MCIWND_UpdateState(mwi);
1249 GetClientRect(hWnd, &rc);
1250 rc.bottom = rc.top;
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,
1255 rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1257 MCIWND_notify_media(mwi);
1258 return 0;
1261 case MCI_PAUSE:
1262 case MCI_STEP:
1263 case MCI_STOP:
1264 case MCI_RESUME:
1265 return mci_generic_command(mwi, wMsg);
1267 case MCI_CONFIGURE:
1268 if (mwi->hdrv)
1269 SendDriverMessage(mwi->hdrv, DRV_CONFIGURE, (LPARAM)hWnd, 0);
1270 return 0;
1272 case MCI_BREAK:
1273 case MCI_CAPTURE:
1274 case MCI_COPY:
1275 case MCI_CUE:
1276 case MCI_CUT:
1277 case MCI_DELETE:
1278 case MCI_ESCAPE:
1279 case MCI_FREEZE:
1280 case MCI_GETDEVCAPS:
1281 /*case MCI_INDEX:*/
1282 case MCI_INFO:
1283 case MCI_LIST:
1284 case MCI_LOAD:
1285 /*case MCI_MARK:*/
1286 case MCI_MONITOR:
1287 case MCI_OPEN:
1288 case MCI_PASTE:
1289 case MCI_PUT:
1290 case MCI_QUALITY:
1291 case MCI_REALIZE:
1292 case MCI_RECORD:
1293 case MCI_RESERVE:
1294 case MCI_RESTORE:
1295 case MCI_SAVE:
1296 case MCI_SET:
1297 case MCI_SETAUDIO:
1298 /*case MCI_SETTIMECODE:*/
1299 /*case MCI_SETTUNER:*/
1300 case MCI_SETVIDEO:
1301 case MCI_SIGNAL:
1302 case MCI_SPIN:
1303 case MCI_STATUS:
1304 case MCI_SYSINFO:
1305 case MCI_UNDO:
1306 case MCI_UNFREEZE:
1307 case MCI_UPDATE:
1308 case MCI_WHERE:
1309 case MCI_WINDOW:
1310 FIXME("support for MCI_ command %04x not implemented\n", wMsg);
1311 return 0;
1314 if (wMsg >= WM_USER)
1316 FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
1317 return 0;
1320 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1321 return DefMDIChildProcW(hWnd, wMsg, wParam, lParam);
1323 return DefWindowProcW(hWnd, wMsg, wParam, lParam);