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