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
20 * Add support for all remaining MCI_ commands and MCIWNDM_ messages.
21 * Add support for all MCIWNDF_ flags.
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};
53 SIZE size; /* size of the original frame rect */
59 WCHAR return_string[128];
60 WORD active_timer, inactive_timer;
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)
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;
87 wc.cbWndExtra = sizeof(MCIWndInfo*);
88 wc.hInstance = MSVFW32_hModule;
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;
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();
112 dwStyle |= WS_VISIBLE | WS_BORDER /*| WS_CHILD*/;
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,
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)
130 UNICODE_STRING fileW;
133 RtlCreateUnicodeStringFromAsciiz(&fileW, szFile);
137 ret = MCIWndCreateW(hwndParent, hInstance, dwStyle, fileW.Buffer);
139 RtlFreeUnicodeString(&fileW);
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)
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);
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);
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)
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)
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)
250 static const WCHAR buttonW[] = {'b','u','t','t','o','n',0};
252 mwi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mwi));
255 SetWindowLongW(hWnd, 0, (LPARAM)mwi);
257 mwi->dwStyle = cs->style;
259 mwi->hwndOwner = cs->hwndParent;
260 mwi->active_timer = 500;
261 mwi->inactive_timer = 2000;
262 mwi->mode = MCI_MODE_NOT_READY;
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)
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;
308 lParam = (LPARAM)cs->lpCreateParams;
309 /* yes, A variant of the message */
310 SendMessageW(hWnd, MCIWNDM_OPENA, 0, lParam);
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:
324 TRACE("Cannot do much...\n");
328 SendMessageW(mwi->hWnd, MCI_RESUME, 0, 0);
332 SendMessageW(mwi->hWnd, MCI_PAUSE, 0, 0);
336 SendMessageW(mwi->hWnd, MCI_STOP, 0, 0);
341 static LRESULT MCIWND_Command(MCIWndInfo *mwi, WPARAM wParam, LPARAM lParam)
343 switch (LOWORD(wParam))
345 case CTL_PLAYSTOP: MCIWND_ToggleState(mwi); break;
349 FIXME("support for command %04x not implement yet\n", LOWORD(wParam));
354 static void MCIWND_notify_media(MCIWndInfo *mwi)
356 if (mwi->dwStyle & (MCIWNDF_NOTIFYMEDIAA | MCIWNDF_NOTIFYMEDIAW))
360 static const WCHAR empty_str[1];
361 SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)empty_str);
365 if (mwi->dwStyle & MCIWNDF_NOTIFYANSI)
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);
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);
392 return mwi->lasterror;
394 MCIWND_notify_mode(mwi);
395 MCIWND_UpdateState(mwi);
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,
406 (DWORD_PTR)&mci_devcaps);
410 return mci_devcaps.dwReturn;
413 static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
417 TRACE("%p %04x %08x %08lx\n", hWnd, wMsg, wParam, lParam);
419 mwi = (MCIWndInfo*)GetWindowLongW(hWnd, 0);
420 if (!mwi && wMsg != WM_CREATE)
421 return DefWindowProcW(hWnd, wMsg, wParam, lParam);
426 MCIWND_Create(hWnd, (CREATESTRUCTW *)lParam);
431 KillTimer(hWnd, mwi->uTimer);
434 SendMessageW(hWnd, MCI_CLOSE, 0, 0);
436 HeapFree(GetProcessHeap(), 0, mwi);
438 DestroyWindow(GetDlgItem(hWnd, CTL_MENU));
439 DestroyWindow(GetDlgItem(hWnd, CTL_PLAYSTOP));
440 DestroyWindow(GetDlgItem(hWnd, CTL_TRACKBAR));
448 hdc = (wParam) ? (HDC)wParam : BeginPaint(hWnd, &ps);
449 /* something to do ? */
450 if (!wParam) EndPaint(hWnd, &ps);
455 return MCIWND_Command(mwi, wParam, lParam);
460 KillTimer(hWnd, mwi->uTimer);
461 mwi->uTimer = SetTimer(hWnd, 1, wParam ? mwi->active_timer : mwi->inactive_timer, NULL);
466 MCIWND_UpdateState(mwi);
470 SetWindowPos(GetDlgItem(hWnd, CTL_PLAYSTOP), 0, 0, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
471 SetWindowPos(GetDlgItem(hWnd, CTL_MENU), 0, 32, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
472 SetWindowPos(GetDlgItem(hWnd, CTL_TRACKBAR), 0, 64, HIWORD(lParam) - 32, LOWORD(lParam) - 64, 32, SWP_NOACTIVATE);
474 MCIWND_notify_size(mwi);
478 MCIWND_notify_mode(mwi);
479 MCIWND_UpdateState(mwi);
484 UNICODE_STRING nameW;
485 TRACE("MCIWNDM_OPENA %s\n", debugstr_a((LPSTR)lParam));
486 RtlCreateUnicodeStringFromAsciiz(&nameW, (LPCSTR)lParam);
487 lParam = (LPARAM)nameW.Buffer;
494 MCI_OPEN_PARMSW mci_open;
495 MCI_GETDEVCAPS_PARMS mci_devcaps;
497 WCHAR drv_name[MAX_PATH];
498 static const WCHAR formatW[] = {'%','d',0};
499 static const WCHAR mci32W[] = {'m','c','i','3','2',0};
500 static const WCHAR system_iniW[] = {'s','y','s','t','e','m','.','i','n','i',0};
502 TRACE("MCIWNDM_OPENW %s\n", debugstr_w((LPWSTR)lParam));
504 if (wParam == MCIWNDOPENF_NEW)
506 SendMessageW(hWnd, MCIWNDM_NEWW, 0, lParam);
507 goto end_of_mci_open;
512 KillTimer(hWnd, mwi->uTimer);
516 hCursor = LoadCursorW(0, (LPWSTR)IDC_WAIT);
517 hCursor = SetCursor(hCursor);
519 mci_open.lpstrElementName = (LPWSTR)lParam;
520 wsprintfW(aliasW, formatW, (int)hWnd + 1);
521 mci_open.lpstrAlias = aliasW;
522 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_OPEN,
523 MCI_OPEN_ELEMENT | MCI_OPEN_ALIAS | MCI_WAIT,
524 (DWORD_PTR)&mci_open);
529 /* FIXME: get the caption from resources */
530 static const WCHAR caption[] = {'M','C','I',' ','E','r','r','o','r',0};
531 WCHAR error_str[MAXERRORLENGTH];
533 mciGetErrorStringW(mwi->lasterror, error_str, MAXERRORLENGTH);
534 MessageBoxW(hWnd, error_str, caption, MB_ICONEXCLAMATION | MB_OK);
535 MCIWND_notify_error(mwi);
536 goto end_of_mci_open;
539 mwi->mci = mci_open.wDeviceID;
540 mwi->alias = (int)hWnd + 1;
542 mwi->lpName = HeapAlloc(GetProcessHeap(), 0, (strlenW((LPWSTR)lParam) + 1) * sizeof(WCHAR));
543 strcpyW(mwi->lpName, (LPWSTR)lParam);
545 MCIWND_UpdateState(mwi);
547 mci_devcaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
548 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
550 (DWORD_PTR)&mci_devcaps);
553 MCIWND_notify_error(mwi);
554 goto end_of_mci_open;
557 mwi->dev_type = mci_devcaps.dwReturn;
560 SendMessageW(hWnd, MCIWNDM_GETDEVICEW, 256, (LPARAM)drv_name);
561 if (drv_name[0] && GetPrivateProfileStringW(mci32W, drv_name, NULL,
562 drv_name, MAX_PATH, system_iniW))
563 mwi->hdrv = OpenDriver(drv_name, NULL, 0);
565 if (mwi->dev_type == MCI_DEVTYPE_DIGITAL_VIDEO)
567 MCI_DGV_WINDOW_PARMSW mci_window;
569 mci_window.hWnd = hWnd;
570 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WINDOW,
572 (DWORD_PTR)&mci_window);
575 MCIWND_notify_error(mwi);
576 goto end_of_mci_open;
580 if (SendMessageW(hWnd, MCIWNDM_GET_DEST, 0, (LPARAM)&rc) == 0)
582 mwi->size.cx = rc.right - rc.left;
583 mwi->size.cy = rc.bottom - rc.top;
585 rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
586 rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
587 SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
591 GetClientRect(hWnd, &rc);
595 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
596 rc.bottom += 32; /* add the height of the playbar */
597 AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
598 SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left,
599 rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
601 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMIN, 0L, 0L);
602 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1,
603 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0));
604 mwi->uTimer = SetTimer(hWnd, 1, mwi->active_timer, NULL);
606 MCIWND_notify_media(mwi);
609 if (wMsg == MCIWNDM_OPENA)
610 HeapFree(GetProcessHeap(), 0, (void *)lParam);
611 return mwi->lasterror;
614 case MCIWNDM_GETDEVICEID:
617 case MCIWNDM_GETALIAS:
620 case MCIWNDM_GET_SOURCE:
622 MCI_DGV_RECT_PARMS mci_rect;
624 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WHERE,
625 MCI_DGV_WHERE_SOURCE,
626 (DWORD_PTR)&mci_rect);
629 MCIWND_notify_error(mwi);
630 return mwi->lasterror;
632 *(RECT *)lParam = mci_rect.rc;
636 case MCIWNDM_GET_DEST:
638 MCI_DGV_RECT_PARMS mci_rect;
640 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WHERE,
641 MCI_DGV_WHERE_DESTINATION,
642 (DWORD_PTR)&mci_rect);
645 MCIWND_notify_error(mwi);
646 return mwi->lasterror;
648 *(RECT *)lParam = mci_rect.rc;
652 case MCIWNDM_PUT_SOURCE:
654 MCI_DGV_PUT_PARMS mci_put;
656 mci_put.rc = *(RECT *)lParam;
657 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
659 (DWORD_PTR)&mci_put);
662 MCIWND_notify_error(mwi);
663 return mwi->lasterror;
668 case MCIWNDM_PUT_DEST:
670 MCI_DGV_PUT_PARMS mci_put;
672 mci_put.rc = *(RECT *)lParam;
673 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
674 MCI_DGV_PUT_DESTINATION | MCI_DGV_RECT,
675 (DWORD_PTR)&mci_put);
678 MCIWND_notify_error(mwi);
679 return mwi->lasterror;
684 case MCIWNDM_GETLENGTH:
686 MCI_STATUS_PARMS mci_status;
688 mci_status.dwItem = MCI_STATUS_LENGTH;
689 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
691 (DWORD_PTR)&mci_status);
694 MCIWND_notify_error(mwi);
697 return mci_status.dwReturn;
700 case MCIWNDM_GETSTART:
702 MCI_STATUS_PARMS mci_status;
704 mci_status.dwItem = MCI_STATUS_POSITION;
705 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
706 MCI_STATUS_ITEM | MCI_STATUS_START,
707 (DWORD_PTR)&mci_status);
710 MCIWND_notify_error(mwi);
713 return mci_status.dwReturn;
718 LRESULT start, length;
720 start = SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
721 length = SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
722 return (start + length);
725 case MCIWNDM_GETPOSITIONA:
726 case MCIWNDM_GETPOSITIONW:
728 MCI_STATUS_PARMS mci_status;
730 /* get position string if requested */
731 if (wParam && lParam)
733 if (wMsg == MCIWNDM_GETPOSITIONA)
737 wsprintfA(cmd, "status %d position", mwi->alias);
738 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
744 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','p','o','s','i','t','i','o','n',0};
746 wsprintfW(cmdW, formatW, mwi->alias);
747 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
754 mci_status.dwItem = MCI_STATUS_POSITION;
755 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
757 (DWORD_PTR)&mci_status);
761 return mci_status.dwReturn;
764 case MCIWNDM_GETMODEA:
765 case MCIWNDM_GETMODEW:
767 MCI_STATUS_PARMS mci_status;
770 return MCI_MODE_NOT_READY;
772 /* get mode string if requested */
773 if (wParam && lParam)
775 if (wMsg == MCIWNDM_GETMODEA)
779 wsprintfA(cmd, "status %d mode", mwi->alias);
780 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
786 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','m','o','d','e',0};
788 wsprintfW(cmdW, formatW, mwi->alias);
789 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
793 return MCI_MODE_NOT_READY;
796 mci_status.dwItem = MCI_STATUS_MODE;
797 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
799 (DWORD_PTR)&mci_status);
801 return MCI_MODE_NOT_READY;
803 return mci_status.dwReturn;
806 case MCIWNDM_PLAYFROM:
808 MCI_PLAY_PARMS mci_play;
810 mci_play.dwCallback = (DWORD_PTR)hWnd;
811 mci_play.dwFrom = lParam;
812 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
813 MCI_FROM | MCI_NOTIFY,
814 (DWORD_PTR)&mci_play);
817 MCIWND_notify_error(mwi);
818 return mwi->lasterror;
821 MCIWND_notify_mode(mwi);
822 MCIWND_UpdateState(mwi);
828 MCI_PLAY_PARMS mci_play;
830 mci_play.dwCallback = (DWORD_PTR)hWnd;
831 mci_play.dwTo = lParam;
832 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
834 (DWORD_PTR)&mci_play);
837 MCIWND_notify_error(mwi);
838 return mwi->lasterror;
841 MCIWND_notify_mode(mwi);
842 MCIWND_UpdateState(mwi);
847 case MCIWNDM_PLAYREVERSE:
849 MCI_PLAY_PARMS mci_play;
850 DWORD flags = MCI_NOTIFY;
852 mci_play.dwCallback = (DWORD_PTR)hWnd;
853 mci_play.dwFrom = lParam;
854 switch (mwi->dev_type)
857 case MCI_DEVTYPE_ANIMATION:
858 flags |= MCI_ANIM_PLAY_REVERSE;
861 case MCI_DEVTYPE_DIGITAL_VIDEO:
862 flags |= MCI_DGV_PLAY_REVERSE;
865 #ifdef MCI_VCR_PLAY_REVERSE
866 case MCI_DEVTYPE_VCR:
867 flags |= MCI_VCR_PLAY_REVERSE;
871 case MCI_DEVTYPE_VIDEODISC:
872 flags |= MCI_VD_PLAY_REVERSE;
876 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
877 flags, (DWORD_PTR)&mci_play);
880 MCIWND_notify_error(mwi);
881 return mwi->lasterror;
884 MCIWND_notify_mode(mwi);
885 MCIWND_UpdateState(mwi);
889 case MCIWNDM_GETERRORA:
890 mciGetErrorStringA(mwi->lasterror, (LPSTR)lParam, wParam);
891 return mwi->lasterror;
893 case MCIWNDM_GETERRORW:
894 mciGetErrorStringW(mwi->lasterror, (LPWSTR)lParam, wParam);
895 return mwi->lasterror;
897 case MCIWNDM_SETOWNER:
898 mwi->hwndOwner = (HWND)wParam;
901 case MCIWNDM_SENDSTRINGA:
903 UNICODE_STRING stringW;
904 RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
905 lParam = (LPARAM)stringW.Buffer;
908 case MCIWNDM_SENDSTRINGW:
912 p = strchrW((LPCWSTR)lParam, ' ');
915 static const WCHAR formatW[] = {'%','d',' ',0};
918 pos = p - (WCHAR *)lParam + 1;
919 len = lstrlenW((LPCWSTR)lParam) + 64;
921 cmdW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
923 memcpy(cmdW, (void *)lParam, pos * sizeof(WCHAR));
924 wsprintfW(cmdW + pos, formatW, mwi->alias);
925 strcatW(cmdW, (WCHAR *)lParam + pos);
928 cmdW = (LPWSTR)lParam;
930 mwi->lasterror = mciSendStringW(cmdW, mwi->return_string,
931 sizeof(mwi->return_string)/sizeof(mwi->return_string[0]),
934 MCIWND_notify_error(mwi);
936 if (cmdW != (LPWSTR)lParam)
937 HeapFree(GetProcessHeap(), 0, cmdW);
939 if (wMsg == MCIWNDM_SENDSTRINGA)
940 HeapFree(GetProcessHeap(), 0, (void *)lParam);
942 MCIWND_UpdateState(mwi);
943 return mwi->lasterror;
946 case MCIWNDM_RETURNSTRINGA:
947 WideCharToMultiByte(CP_ACP, 0, mwi->return_string, -1, (LPSTR)lParam, wParam, NULL, NULL);
948 return mwi->lasterror;
950 case MCIWNDM_RETURNSTRINGW:
951 strncpyW((LPWSTR)lParam, mwi->return_string, wParam);
952 return mwi->lasterror;
954 case MCIWNDM_SETTIMERS:
955 mwi->active_timer = (WORD)wParam;
956 mwi->inactive_timer = (WORD)lParam;
959 case MCIWNDM_SETACTIVETIMER:
960 mwi->active_timer = (WORD)wParam;
963 case MCIWNDM_SETINACTIVETIMER:
964 mwi->inactive_timer = (WORD)wParam;
967 case MCIWNDM_GETACTIVETIMER:
968 return mwi->active_timer;
970 case MCIWNDM_GETINACTIVETIMER:
971 return mwi->inactive_timer;
973 case MCIWNDM_CHANGESTYLES:
974 /* FIXME: update the visual window state as well:
975 * add/remove trackbar, autosize, etc.
977 mwi->dwStyle &= ~wParam;
978 mwi->dwStyle |= lParam & wParam;
981 case MCIWNDM_GETSTYLES:
982 return mwi->dwStyle & 0xffff;
984 case MCIWNDM_GETDEVICEA:
986 MCI_SYSINFO_PARMSA mci_sysinfo;
988 mci_sysinfo.lpstrReturn = (LPSTR)lParam;
989 mci_sysinfo.dwRetSize = wParam;
990 mwi->lasterror = mciSendCommandA(mwi->mci, MCI_SYSINFO,
991 MCI_SYSINFO_INSTALLNAME,
992 (DWORD_PTR)&mci_sysinfo);
996 case MCIWNDM_GETDEVICEW:
998 MCI_SYSINFO_PARMSW mci_sysinfo;
1000 mci_sysinfo.lpstrReturn = (LPWSTR)lParam;
1001 mci_sysinfo.dwRetSize = wParam;
1002 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SYSINFO,
1003 MCI_SYSINFO_INSTALLNAME,
1004 (DWORD_PTR)&mci_sysinfo);
1008 case MCIWNDM_VALIDATEMEDIA:
1011 SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
1012 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
1016 case MCIWNDM_GETFILENAMEA:
1018 WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, (LPSTR)lParam, wParam, NULL, NULL);
1021 case MCIWNDM_GETFILENAMEW:
1023 strncpyW((LPWSTR)lParam, mwi->lpName, wParam);
1026 case MCIWNDM_GETTIMEFORMATA:
1027 case MCIWNDM_GETTIMEFORMATW:
1029 MCI_STATUS_PARMS mci_status;
1031 /* get format string if requested */
1032 if (wParam && lParam)
1034 if (wMsg == MCIWNDM_GETTIMEFORMATA)
1038 wsprintfA(cmd, "status %d time format", mwi->alias);
1039 mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
1046 static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',0};
1048 wsprintfW(cmdW, formatW, mwi->alias);
1049 mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
1055 mci_status.dwItem = MCI_STATUS_TIME_FORMAT ;
1056 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
1058 (DWORD_PTR)&mci_status);
1062 return mci_status.dwReturn;
1065 case MCIWNDM_SETTIMEFORMATA:
1067 UNICODE_STRING stringW;
1069 RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
1070 lParam = (LPARAM)stringW.Buffer;
1073 case MCIWNDM_SETTIMEFORMATW:
1075 static const WCHAR formatW[] = {'s','e','t',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',' ',0};
1080 cmdW = HeapAlloc(GetProcessHeap(), 0, (lstrlenW((LPCWSTR)lParam) + 64) * sizeof(WCHAR));
1081 wsprintfW(cmdW, formatW, mwi->alias);
1082 strcatW(cmdW, (WCHAR *)lParam);
1084 mwi->lasterror = mciSendStringW(cmdW, NULL, 0, 0);
1086 /* fix the range tracking according to the new time format */
1087 if (!mwi->lasterror)
1088 SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1,
1089 SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0));
1092 if (wMsg == MCIWNDM_SETTIMEFORMATA)
1093 HeapFree(GetProcessHeap(), 0, (void *)lParam);
1098 case MCIWNDM_CAN_PLAY:
1100 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_PLAY);
1103 case MCIWNDM_CAN_RECORD:
1105 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_RECORD);
1108 case MCIWNDM_CAN_SAVE:
1110 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_SAVE);
1113 case MCIWNDM_CAN_EJECT:
1115 return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_EJECT);
1118 case MCIWNDM_CAN_WINDOW:
1119 switch (mwi->dev_type)
1121 case MCI_DEVTYPE_ANIMATION:
1122 case MCI_DEVTYPE_DIGITAL_VIDEO:
1123 case MCI_DEVTYPE_OVERLAY:
1128 case MCIWNDM_CAN_CONFIG:
1130 return SendDriverMessage(mwi->hdrv, DRV_QUERYCONFIGURE, 0, 0);
1133 case MCIWNDM_SETZOOM:
1141 rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
1142 rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
1143 SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
1145 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
1146 rc.bottom += 32; /* add the height of the playbar */
1147 AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
1148 SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
1149 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1153 case MCIWNDM_GETZOOM:
1158 MCI_SET_PARMS mci_set;
1160 mci_set.dwCallback = (DWORD_PTR)hWnd;
1161 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SET,
1162 MCI_SET_DOOR_OPEN | MCI_NOTIFY,
1163 (DWORD_PTR)&mci_set);
1164 MCIWND_notify_mode(mwi);
1165 MCIWND_UpdateState(mwi);
1166 return mwi->lasterror;
1169 case MCIWNDM_SETVOLUME:
1170 case MCIWNDM_GETVOLUME:
1171 case MCIWNDM_SETSPEED:
1172 case MCIWNDM_GETSPEED:
1173 case MCIWNDM_SETREPEAT:
1174 case MCIWNDM_GETREPEAT:
1175 case MCIWNDM_REALIZE:
1176 case MCIWNDM_GETPALETTE:
1177 case MCIWNDM_SETPALETTE:
1180 case MCIWNDM_PALETTEKICK:
1181 case MCIWNDM_OPENINTERFACE:
1182 FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
1187 LRESULT end = SendMessageW(hWnd, MCIWNDM_GETEND, 0, 0);
1188 return SendMessageW(hWnd, MCIWNDM_PLAYTO, 0, end);
1193 MCI_SEEK_PARMS mci_seek;
1198 lParam = SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
1202 lParam = SendMessageW(hWnd, MCIWNDM_GETEND, 0, 0);
1206 mci_seek.dwTo = lParam;
1207 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SEEK,
1208 MCI_TO, (DWORD_PTR)&mci_seek);
1211 MCIWND_notify_error(mwi);
1212 return mwi->lasterror;
1220 MCI_GENERIC_PARMS mci_generic;
1224 CloseDriver(mwi->hdrv, 0, 0);
1230 mci_generic.dwCallback = 0;
1231 mwi->lasterror = mciSendCommandW(mwi->mci, MCI_CLOSE,
1232 0, (DWORD_PTR)&mci_generic);
1236 mwi->mode = MCI_MODE_NOT_READY;
1241 HeapFree(GetProcessHeap(), 0, mwi->lpName);
1244 MCIWND_UpdateState(mwi);
1246 GetClientRect(hWnd, &rc);
1248 if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
1249 rc.bottom += 32; /* add the height of the playbar */
1250 AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
1251 SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left,
1252 rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
1254 MCIWND_notify_media(mwi);
1262 return mci_generic_command(mwi, wMsg);
1266 SendDriverMessage(mwi->hdrv, DRV_CONFIGURE, (LPARAM)hWnd, 0);
1277 case MCI_GETDEVCAPS:
1295 /*case MCI_SETTIMECODE:*/
1296 /*case MCI_SETTUNER:*/
1307 FIXME("support for MCI_ command %04x not implemented\n", wMsg);
1311 if (wMsg >= WM_USER)
1313 FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
1317 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
1318 return DefMDIChildProcW(hWnd, wMsg, wParam, lParam);
1320 return DefWindowProcW(hWnd, wMsg, wParam, lParam);