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