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