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);
422 if (wMsg
== WM_CREATE
)
423 return MCIWND_Create(hWnd
, (CREATESTRUCTW
*)lParam
);
425 return DefWindowProcW(hWnd
, wMsg
, wParam
, lParam
);
432 KillTimer(hWnd
, mwi
->uTimer
);
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
));
449 hdc
= (wParam
) ? (HDC
)wParam
: BeginPaint(hWnd
, &ps
);
450 /* something to do ? */
451 if (!wParam
) EndPaint(hWnd
, &ps
);
456 return MCIWND_Command(mwi
, wParam
, lParam
);
461 KillTimer(hWnd
, mwi
->uTimer
);
462 mwi
->uTimer
= SetTimer(hWnd
, 1, wParam
? mwi
->active_timer
: mwi
->inactive_timer
, NULL
);
467 MCIWND_UpdateState(mwi
);
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
);
481 MCIWND_notify_mode(mwi
);
482 MCIWND_UpdateState(mwi
);
487 UNICODE_STRING nameW
;
488 TRACE("MCIWNDM_OPENA %s\n", debugstr_a((LPSTR
)lParam
));
489 RtlCreateUnicodeStringFromAsciiz(&nameW
, (LPCSTR
)lParam
);
490 lParam
= (LPARAM
)nameW
.Buffer
;
497 MCI_OPEN_PARMSW mci_open
;
498 MCI_GETDEVCAPS_PARMS mci_devcaps
;
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
;
515 KillTimer(hWnd
, mwi
->uTimer
);
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
);
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
,
553 (DWORD_PTR
)&mci_devcaps
);
556 MCIWND_notify_error(mwi
);
557 goto end_of_mci_open
;
560 mwi
->dev_type
= mci_devcaps
.dwReturn
;
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
,
575 (DWORD_PTR
)&mci_window
);
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
);
594 GetClientRect(hWnd
, &rc
);
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
);
612 if (wMsg
== MCIWNDM_OPENA
)
613 HeapFree(GetProcessHeap(), 0, (void *)lParam
);
614 return mwi
->lasterror
;
617 case MCIWNDM_GETDEVICEID
:
620 case MCIWNDM_GETALIAS
:
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
);
632 MCIWND_notify_error(mwi
);
633 return mwi
->lasterror
;
635 *(RECT
*)lParam
= mci_rect
.rc
;
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
);
648 MCIWND_notify_error(mwi
);
649 return mwi
->lasterror
;
651 *(RECT
*)lParam
= mci_rect
.rc
;
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
,
662 (DWORD_PTR
)&mci_put
);
665 MCIWND_notify_error(mwi
);
666 return mwi
->lasterror
;
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
);
681 MCIWND_notify_error(mwi
);
682 return mwi
->lasterror
;
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
,
694 (DWORD_PTR
)&mci_status
);
697 MCIWND_notify_error(mwi
);
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
);
713 MCIWND_notify_error(mwi
);
716 return mci_status
.dwReturn
;
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
)
740 wsprintfA(cmd
, "status %d position", mwi
->alias
);
741 mwi
->lasterror
= mciSendStringA(cmd
, (LPSTR
)lParam
, wParam
, 0);
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);
757 mci_status
.dwItem
= MCI_STATUS_POSITION
;
758 mwi
->lasterror
= mciSendCommandW(mwi
->mci
, MCI_STATUS
,
760 (DWORD_PTR
)&mci_status
);
764 return mci_status
.dwReturn
;
767 case MCIWNDM_GETMODEA
:
768 case MCIWNDM_GETMODEW
:
770 MCI_STATUS_PARMS mci_status
;
773 return MCI_MODE_NOT_READY
;
775 /* get mode string if requested */
776 if (wParam
&& lParam
)
778 if (wMsg
== MCIWNDM_GETMODEA
)
782 wsprintfA(cmd
, "status %d mode", mwi
->alias
);
783 mwi
->lasterror
= mciSendStringA(cmd
, (LPSTR
)lParam
, wParam
, 0);
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);
796 return MCI_MODE_NOT_READY
;
799 mci_status
.dwItem
= MCI_STATUS_MODE
;
800 mwi
->lasterror
= mciSendCommandW(mwi
->mci
, MCI_STATUS
,
802 (DWORD_PTR
)&mci_status
);
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
);
820 MCIWND_notify_error(mwi
);
821 return mwi
->lasterror
;
824 MCIWND_notify_mode(mwi
);
825 MCIWND_UpdateState(mwi
);
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
,
837 (DWORD_PTR
)&mci_play
);
840 MCIWND_notify_error(mwi
);
841 return mwi
->lasterror
;
844 MCIWND_notify_mode(mwi
);
845 MCIWND_UpdateState(mwi
);
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
)
860 case MCI_DEVTYPE_ANIMATION
:
861 flags
|= MCI_ANIM_PLAY_REVERSE
;
864 case MCI_DEVTYPE_DIGITAL_VIDEO
:
865 flags
|= MCI_DGV_PLAY_REVERSE
;
868 #ifdef MCI_VCR_PLAY_REVERSE
869 case MCI_DEVTYPE_VCR
:
870 flags
|= MCI_VCR_PLAY_REVERSE
;
874 case MCI_DEVTYPE_VIDEODISC
:
875 flags
|= MCI_VD_PLAY_REVERSE
;
879 mwi
->lasterror
= mciSendCommandW(mwi
->mci
, MCI_PLAY
,
880 flags
, (DWORD_PTR
)&mci_play
);
883 MCIWND_notify_error(mwi
);
884 return mwi
->lasterror
;
887 MCIWND_notify_mode(mwi
);
888 MCIWND_UpdateState(mwi
);
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
;
904 case MCIWNDM_SENDSTRINGA
:
906 UNICODE_STRING stringW
;
907 RtlCreateUnicodeStringFromAsciiz(&stringW
, (LPCSTR
)lParam
);
908 lParam
= (LPARAM
)stringW
.Buffer
;
911 case MCIWNDM_SENDSTRINGW
:
915 p
= strchrW((LPCWSTR
)lParam
, ' ');
918 static const WCHAR formatW
[] = {'%','d',' ',0};
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
);
931 cmdW
= (LPWSTR
)lParam
;
933 mwi
->lasterror
= mciSendStringW(cmdW
, mwi
->return_string
,
934 sizeof(mwi
->return_string
)/sizeof(mwi
->return_string
[0]),
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
;
962 case MCIWNDM_SETACTIVETIMER
:
963 mwi
->active_timer
= (WORD
)wParam
;
966 case MCIWNDM_SETINACTIVETIMER
:
967 mwi
->inactive_timer
= (WORD
)wParam
;
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
;
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
);
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
);
1011 case MCIWNDM_VALIDATEMEDIA
:
1014 SendMessageW(hWnd
, MCIWNDM_GETSTART
, 0, 0);
1015 SendMessageW(hWnd
, MCIWNDM_GETLENGTH
, 0, 0);
1019 case MCIWNDM_GETFILENAMEA
:
1021 WideCharToMultiByte(CP_ACP
, 0, mwi
->lpName
, -1, (LPSTR
)lParam
, wParam
, NULL
, NULL
);
1024 case MCIWNDM_GETFILENAMEW
:
1026 strncpyW((LPWSTR
)lParam
, mwi
->lpName
, wParam
);
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
)
1041 wsprintfA(cmd
, "status %d time format", mwi
->alias
);
1042 mwi
->lasterror
= mciSendStringA(cmd
, (LPSTR
)lParam
, wParam
, 0);
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);
1058 mci_status
.dwItem
= MCI_STATUS_TIME_FORMAT
;
1059 mwi
->lasterror
= mciSendCommandW(mwi
->mci
, MCI_STATUS
,
1061 (DWORD_PTR
)&mci_status
);
1065 return mci_status
.dwReturn
;
1068 case MCIWNDM_SETTIMEFORMATA
:
1070 UNICODE_STRING stringW
;
1072 RtlCreateUnicodeStringFromAsciiz(&stringW
, (LPCSTR
)lParam
);
1073 lParam
= (LPARAM
)stringW
.Buffer
;
1076 case MCIWNDM_SETTIMEFORMATW
:
1078 static const WCHAR formatW
[] = {'s','e','t',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',' ',0};
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
);
1101 case MCIWNDM_CAN_PLAY
:
1103 return mci_get_devcaps(mwi
, MCI_GETDEVCAPS_CAN_PLAY
);
1106 case MCIWNDM_CAN_RECORD
:
1108 return mci_get_devcaps(mwi
, MCI_GETDEVCAPS_CAN_RECORD
);
1111 case MCIWNDM_CAN_SAVE
:
1113 return mci_get_devcaps(mwi
, MCI_GETDEVCAPS_CAN_SAVE
);
1116 case MCIWNDM_CAN_EJECT
:
1118 return mci_get_devcaps(mwi
, MCI_GETDEVCAPS_CAN_EJECT
);
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
:
1131 case MCIWNDM_CAN_CONFIG
:
1133 return SendDriverMessage(mwi
->hdrv
, DRV_QUERYCONFIGURE
, 0, 0);
1136 case MCIWNDM_SETZOOM
:
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
);
1156 case MCIWNDM_GETZOOM
:
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
:
1183 case MCIWNDM_PALETTEKICK
:
1184 case MCIWNDM_OPENINTERFACE
:
1185 FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg
- WM_USER
);
1190 LRESULT end
= SendMessageW(hWnd
, MCIWNDM_GETEND
, 0, 0);
1191 return SendMessageW(hWnd
, MCIWNDM_PLAYTO
, 0, end
);
1196 MCI_SEEK_PARMS mci_seek
;
1201 lParam
= SendMessageW(hWnd
, MCIWNDM_GETSTART
, 0, 0);
1205 lParam
= SendMessageW(hWnd
, MCIWNDM_GETEND
, 0, 0);
1209 mci_seek
.dwTo
= lParam
;
1210 mwi
->lasterror
= mciSendCommandW(mwi
->mci
, MCI_SEEK
,
1211 MCI_TO
, (DWORD_PTR
)&mci_seek
);
1214 MCIWND_notify_error(mwi
);
1215 return mwi
->lasterror
;
1223 MCI_GENERIC_PARMS mci_generic
;
1227 CloseDriver(mwi
->hdrv
, 0, 0);
1233 mci_generic
.dwCallback
= 0;
1234 mwi
->lasterror
= mciSendCommandW(mwi
->mci
, MCI_CLOSE
,
1235 0, (DWORD_PTR
)&mci_generic
);
1239 mwi
->mode
= MCI_MODE_NOT_READY
;
1244 HeapFree(GetProcessHeap(), 0, mwi
->lpName
);
1247 MCIWND_UpdateState(mwi
);
1249 GetClientRect(hWnd
, &rc
);
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
);
1265 return mci_generic_command(mwi
, wMsg
);
1269 SendDriverMessage(mwi
->hdrv
, DRV_CONFIGURE
, (LPARAM
)hWnd
, 0);
1280 case MCI_GETDEVCAPS
:
1298 /*case MCI_SETTIMECODE:*/
1299 /*case MCI_SETTUNER:*/
1310 FIXME("support for MCI_ command %04x not implemented\n", wMsg
);
1314 if (wMsg
>= WM_USER
)
1316 FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg
- WM_USER
);
1320 if (GetWindowLongW(hWnd
, GWL_EXSTYLE
) & WS_EX_MDICHILD
)
1321 return DefMDIChildProcW(hWnd
, wMsg
, wParam
, lParam
);
1323 return DefWindowProcW(hWnd
, wMsg
, wParam
, lParam
);