1 /* 2 * DirectShow MCI Driver 3 * 4 * Copyright 2009 Christian Costa 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 #include <math.h> 23 #include "windef.h" 24 #include "winbase.h" 25 #include "winuser.h" 26 #include "mmddk.h" 27 #include "wine/debug.h" 28 #include "mciqtz_private.h" 29 #include "digitalv.h" 30 #include "wownt32.h" 31 32 WINE_DEFAULT_DEBUG_CHANNEL(mciqtz); 33 34 static DWORD MCIQTZ_mciClose(UINT, DWORD, LPMCI_GENERIC_PARMS); 35 static DWORD MCIQTZ_mciStop(UINT, DWORD, LPMCI_GENERIC_PARMS); 36 37 /*======================================================================* 38 * MCI QTZ implementation * 39 *======================================================================*/ 40 41 static HINSTANCE MCIQTZ_hInstance = 0; 42 43 /*********************************************************************** 44 * DllMain (MCIQTZ.0) 45 */ 46 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad) 47 { 48 switch (fdwReason) { 49 case DLL_PROCESS_ATTACH: 50 DisableThreadLibraryCalls(hInstDLL); 51 MCIQTZ_hInstance = hInstDLL; 52 break; 53 } 54 return TRUE; 55 } 56 57 /************************************************************************** 58 * MCIQTZ_mciGetOpenDev [internal] 59 */ 60 static WINE_MCIQTZ* MCIQTZ_mciGetOpenDev(UINT wDevID) 61 { 62 WINE_MCIQTZ* wma = (WINE_MCIQTZ*)mciGetDriverData(wDevID); 63 64 if (!wma) { 65 WARN("Invalid wDevID=%u\n", wDevID); 66 return NULL; 67 } 68 return wma; 69 } 70 71 /************************************************************************** 72 * MCIQTZ_drvOpen [internal] 73 */ 74 static DWORD MCIQTZ_drvOpen(LPCWSTR str, LPMCI_OPEN_DRIVER_PARMSW modp) 75 { 76 WINE_MCIQTZ* wma; 77 static const WCHAR mciAviWStr[] = {'M','C','I','A','V','I',0}; 78 79 TRACE("(%s, %p)\n", debugstr_w(str), modp); 80 81 /* session instance */ 82 if (!modp) 83 return 0xFFFFFFFF; 84 85 wma = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCIQTZ)); 86 if (!wma) 87 return 0; 88 89 wma->stop_event = CreateEventW(NULL, FALSE, FALSE, NULL); 90 modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO; 91 wma->wDevID = modp->wDeviceID; 92 modp->wCustomCommandTable = wma->command_table = mciLoadCommandResource(MCIQTZ_hInstance, mciAviWStr, 0); 93 mciSetDriverData(wma->wDevID, (DWORD_PTR)wma); 94 95 return modp->wDeviceID; 96 } 97 98 /************************************************************************** 99 * MCIQTZ_drvClose [internal] 100 */ 101 static DWORD MCIQTZ_drvClose(DWORD dwDevID) 102 { 103 WINE_MCIQTZ* wma; 104 105 TRACE("(%04x)\n", dwDevID); 106 107 wma = MCIQTZ_mciGetOpenDev(dwDevID); 108 109 if (wma) { 110 /* finish all outstanding things */ 111 MCIQTZ_mciClose(dwDevID, MCI_WAIT, NULL); 112 113 mciFreeCommandResource(wma->command_table); 114 mciSetDriverData(dwDevID, 0); 115 CloseHandle(wma->stop_event); 116 HeapFree(GetProcessHeap(), 0, wma); 117 return 1; 118 } 119 120 return (dwDevID == 0xFFFFFFFF) ? 1 : 0; 121 } 122 123 /************************************************************************** 124 * MCIQTZ_drvConfigure [internal] 125 */ 126 static DWORD MCIQTZ_drvConfigure(DWORD dwDevID) 127 { 128 WINE_MCIQTZ* wma; 129 130 TRACE("(%04x)\n", dwDevID); 131 132 wma = MCIQTZ_mciGetOpenDev(dwDevID); 133 if (!wma) 134 return 0; 135 136 MCIQTZ_mciStop(dwDevID, MCI_WAIT, NULL); 137 138 MessageBoxA(0, "Sample QTZ Wine Driver !", "MM-Wine Driver", MB_OK); 139 140 return 1; 141 } 142 143 /************************************************************************** 144 * MCIQTZ_mciNotify [internal] 145 * 146 * Notifications in MCI work like a 1-element queue. 147 * Each new notification request supersedes the previous one. 148 */ 149 static void MCIQTZ_mciNotify(DWORD_PTR hWndCallBack, WINE_MCIQTZ* wma, UINT wStatus) 150 { 151 MCIDEVICEID wDevID = wma->notify_devid; 152 HANDLE old = InterlockedExchangePointer(&wma->callback, NULL); 153 if (old) mciDriverNotify(old, wDevID, MCI_NOTIFY_SUPERSEDED); 154 mciDriverNotify(HWND_32(LOWORD(hWndCallBack)), wDevID, wStatus); 155 } 156 157 /*************************************************************************** 158 * MCIQTZ_mciOpen [internal] 159 */ 160 static DWORD MCIQTZ_mciOpen(UINT wDevID, DWORD dwFlags, 161 LPMCI_DGV_OPEN_PARMSW lpOpenParms) 162 { 163 WINE_MCIQTZ* wma; 164 HRESULT hr; 165 DWORD style = 0; 166 RECT rc = { 0, 0, 0, 0 }; 167 168 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpOpenParms); 169 170 if(!lpOpenParms) 171 return MCIERR_NULL_PARAMETER_BLOCK; 172 173 wma = MCIQTZ_mciGetOpenDev(wDevID); 174 if (!wma) 175 return MCIERR_INVALID_DEVICE_ID; 176 177 MCIQTZ_mciStop(wDevID, MCI_WAIT, NULL); 178 179 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); 180 wma->uninit = SUCCEEDED(hr); 181 182 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, (LPVOID*)&wma->pgraph); 183 if (FAILED(hr)) { 184 TRACE("Cannot create filtergraph (hr = %x)\n", hr); 185 goto err; 186 } 187 188 hr = IGraphBuilder_QueryInterface(wma->pgraph, &IID_IMediaControl, (LPVOID*)&wma->pmctrl); 189 if (FAILED(hr)) { 190 TRACE("Cannot get IMediaControl interface (hr = %x)\n", hr); 191 goto err; 192 } 193 194 hr = IGraphBuilder_QueryInterface(wma->pgraph, &IID_IMediaSeeking, (void**)&wma->seek); 195 if (FAILED(hr)) { 196 TRACE("Cannot get IMediaSeeking interface (hr = %x)\n", hr); 197 goto err; 198 } 199 200 hr = IGraphBuilder_QueryInterface(wma->pgraph, &IID_IMediaEvent, (void**)&wma->mevent); 201 if (FAILED(hr)) { 202 TRACE("Cannot get IMediaEvent interface (hr = %x)\n", hr); 203 goto err; 204 } 205 206 hr = IGraphBuilder_QueryInterface(wma->pgraph, &IID_IVideoWindow, (void**)&wma->vidwin); 207 if (FAILED(hr)) { 208 TRACE("Cannot get IVideoWindow interface (hr = %x)\n", hr); 209 goto err; 210 } 211 212 hr = IGraphBuilder_QueryInterface(wma->pgraph, &IID_IBasicVideo, (void**)&wma->vidbasic); 213 if (FAILED(hr)) { 214 TRACE("Cannot get IBasicVideo interface (hr = %x)\n", hr); 215 goto err; 216 } 217 218 hr = IGraphBuilder_QueryInterface(wma->pgraph, &IID_IBasicAudio, (void**)&wma->audio); 219 if (FAILED(hr)) { 220 TRACE("Cannot get IBasicAudio interface (hr = %x)\n", hr); 221 goto err; 222 } 223 224 if (!(dwFlags & MCI_OPEN_ELEMENT) || (dwFlags & MCI_OPEN_ELEMENT_ID)) { 225 TRACE("Wrong dwFlags %x\n", dwFlags); 226 goto err; 227 } 228 229 if (!lpOpenParms->lpstrElementName || !lpOpenParms->lpstrElementName[0]) { 230 TRACE("Invalid filename specified\n"); 231 goto err; 232 } 233 234 TRACE("Open file %s\n", debugstr_w(lpOpenParms->lpstrElementName)); 235 236 hr = IGraphBuilder_RenderFile(wma->pgraph, lpOpenParms->lpstrElementName, NULL); 237 if (FAILED(hr)) { 238 TRACE("Cannot render file (hr = %x)\n", hr); 239 goto err; 240 } 241 242 IVideoWindow_put_AutoShow(wma->vidwin, OAFALSE); 243 IVideoWindow_put_Visible(wma->vidwin, OAFALSE); 244 if (dwFlags & MCI_DGV_OPEN_WS) 245 style = lpOpenParms->dwStyle; 246 if (dwFlags & MCI_DGV_OPEN_PARENT) { 247 IVideoWindow_put_MessageDrain(wma->vidwin, (OAHWND)lpOpenParms->hWndParent); 248 IVideoWindow_put_WindowState(wma->vidwin, SW_HIDE); 249 IVideoWindow_put_WindowStyle(wma->vidwin, style|WS_CHILD); 250 IVideoWindow_put_Owner(wma->vidwin, (OAHWND)lpOpenParms->hWndParent); 251 GetClientRect(lpOpenParms->hWndParent, &rc); 252 IVideoWindow_SetWindowPosition(wma->vidwin, rc.left, rc.top, rc.right - rc.top, rc.bottom - rc.top); 253 wma->parent = (HWND)lpOpenParms->hWndParent; 254 } 255 else if (style) 256 IVideoWindow_put_WindowStyle(wma->vidwin, style); 257 IBasicVideo_GetVideoSize(wma->vidbasic, &rc.right, &rc.bottom); 258 wma->opened = TRUE; 259 260 if (dwFlags & MCI_NOTIFY) 261 mciDriverNotify(HWND_32(LOWORD(lpOpenParms->dwCallback)), wDevID, MCI_NOTIFY_SUCCESSFUL); 262 263 return 0; 264 265 err: 266 if (wma->audio) 267 IBasicAudio_Release(wma->audio); 268 wma->audio = NULL; 269 if (wma->vidbasic) 270 IBasicVideo_Release(wma->vidbasic); 271 wma->vidbasic = NULL; 272 if (wma->seek) 273 IMediaSeeking_Release(wma->seek); 274 wma->seek = NULL; 275 if (wma->vidwin) 276 IVideoWindow_Release(wma->vidwin); 277 wma->vidwin = NULL; 278 if (wma->pgraph) 279 IGraphBuilder_Release(wma->pgraph); 280 wma->pgraph = NULL; 281 if (wma->mevent) 282 IMediaEvent_Release(wma->mevent); 283 wma->mevent = NULL; 284 if (wma->pmctrl) 285 IMediaControl_Release(wma->pmctrl); 286 wma->pmctrl = NULL; 287 288 if (wma->uninit) 289 CoUninitialize(); 290 wma->uninit = FALSE; 291 292 return MCIERR_INTERNAL; 293 } 294 295 /*************************************************************************** 296 * MCIQTZ_mciClose [internal] 297 */ 298 static DWORD MCIQTZ_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) 299 { 300 WINE_MCIQTZ* wma; 301 302 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 303 304 wma = MCIQTZ_mciGetOpenDev(wDevID); 305 if (!wma) 306 return MCIERR_INVALID_DEVICE_ID; 307 308 MCIQTZ_mciStop(wDevID, MCI_WAIT, NULL); 309 310 if (wma->opened) { 311 IVideoWindow_Release(wma->vidwin); 312 IBasicVideo_Release(wma->vidbasic); 313 IBasicAudio_Release(wma->audio); 314 IMediaSeeking_Release(wma->seek); 315 IMediaEvent_Release(wma->mevent); 316 IGraphBuilder_Release(wma->pgraph); 317 IMediaControl_Release(wma->pmctrl); 318 if (wma->uninit) 319 CoUninitialize(); 320 wma->opened = FALSE; 321 } 322 323 return 0; 324 } 325 326 /*************************************************************************** 327 * MCIQTZ_notifyThread [internal] 328 */ 329 static DWORD CALLBACK MCIQTZ_notifyThread(LPVOID parm) 330 { 331 WINE_MCIQTZ* wma = (WINE_MCIQTZ *)parm; 332 HRESULT hr; 333 HANDLE handle[2]; 334 DWORD n = 0, ret = 0; 335 336 handle[n++] = wma->stop_event; 337 IMediaEvent_GetEventHandle(wma->mevent, (OAEVENT *)&handle[n++]); 338 339 for (;;) { 340 DWORD r; 341 HANDLE old; 342 343 r = WaitForMultipleObjects(n, handle, FALSE, INFINITE); 344 if (r == WAIT_OBJECT_0) { 345 TRACE("got stop event\n"); 346 old = InterlockedExchangePointer(&wma->callback, NULL); 347 if (old) 348 mciDriverNotify(old, wma->notify_devid, MCI_NOTIFY_ABORTED); 349 break; 350 } 351 else if (r == WAIT_OBJECT_0+1) { 352 LONG event_code; 353 LONG_PTR p1, p2; 354 do { 355 hr = IMediaEvent_GetEvent(wma->mevent, &event_code, &p1, &p2, 0); 356 if (SUCCEEDED(hr)) { 357 TRACE("got event_code = 0x%02x\n", event_code); 358 IMediaEvent_FreeEventParams(wma->mevent, event_code, p1, p2); 359 } 360 } while (hr == S_OK && event_code != EC_COMPLETE); 361 if (hr == S_OK && event_code == EC_COMPLETE) { 362 /* Repeat the music by seeking and running again */ 363 if (wma->mci_flags & MCI_DGV_PLAY_REPEAT) { 364 TRACE("repeat media as requested\n"); 365 IMediaControl_Stop(wma->pmctrl); 366 IMediaSeeking_SetPositions(wma->seek, 367 &wma->seek_start, 368 AM_SEEKING_AbsolutePositioning, 369 &wma->seek_stop, 370 AM_SEEKING_AbsolutePositioning); 371 IMediaControl_Run(wma->pmctrl); 372 continue; 373 } 374 old = InterlockedExchangePointer(&wma->callback, NULL); 375 if (old) 376 mciDriverNotify(old, wma->notify_devid, MCI_NOTIFY_SUCCESSFUL); 377 break; 378 } 379 } 380 else { 381 TRACE("Unknown error (%d)\n", (int)r); 382 break; 383 } 384 } 385 386 hr = IMediaControl_Stop(wma->pmctrl); 387 if (FAILED(hr)) { 388 TRACE("Cannot stop filtergraph (hr = %x)\n", hr); 389 ret = MCIERR_INTERNAL; 390 } 391 392 return ret; 393 } 394 395 /*************************************************************************** 396 * MCIQTZ_mciPlay [internal] 397 */ 398 static DWORD MCIQTZ_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms) 399 { 400 WINE_MCIQTZ* wma; 401 HRESULT hr; 402 GUID format; 403 DWORD start_flags; 404 405 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 406 407 if(!lpParms) 408 return MCIERR_NULL_PARAMETER_BLOCK; 409 410 wma = MCIQTZ_mciGetOpenDev(wDevID); 411 if (!wma) 412 return MCIERR_INVALID_DEVICE_ID; 413 414 ResetEvent(wma->stop_event); 415 if (dwFlags & MCI_NOTIFY) { 416 HANDLE old; 417 old = InterlockedExchangePointer(&wma->callback, HWND_32(LOWORD(lpParms->dwCallback))); 418 if (old) 419 mciDriverNotify(old, wma->notify_devid, MCI_NOTIFY_ABORTED); 420 } 421 422 wma->mci_flags = dwFlags; 423 IMediaSeeking_GetTimeFormat(wma->seek, &format); 424 if (dwFlags & MCI_FROM) { 425 wma->seek_start = lpParms->dwFrom; 426 if (IsEqualGUID(&format, &TIME_FORMAT_MEDIA_TIME)) 427 wma->seek_start *= 10000; 428 429 start_flags = AM_SEEKING_AbsolutePositioning; 430 } else { 431 wma->seek_start = 0; 432 start_flags = AM_SEEKING_NoPositioning; 433 } 434 if (dwFlags & MCI_TO) { 435 wma->seek_stop = lpParms->dwTo; 436 if (IsEqualGUID(&format, &TIME_FORMAT_MEDIA_TIME)) 437 wma->seek_stop *= 10000; 438 } else { 439 wma->seek_stop = 0; 440 IMediaSeeking_GetDuration(wma->seek, &wma->seek_stop); 441 } 442 IMediaSeeking_SetPositions(wma->seek, &wma->seek_start, start_flags, 443 &wma->seek_stop, AM_SEEKING_AbsolutePositioning); 444 445 hr = IMediaControl_Run(wma->pmctrl); 446 if (FAILED(hr)) { 447 TRACE("Cannot run filtergraph (hr = %x)\n", hr); 448 return MCIERR_INTERNAL; 449 } 450 451 IVideoWindow_put_Visible(wma->vidwin, OATRUE); 452 453 wma->thread = CreateThread(NULL, 0, MCIQTZ_notifyThread, wma, 0, NULL); 454 if (!wma->thread) { 455 TRACE("Can't create thread\n"); 456 return MCIERR_INTERNAL; 457 } 458 return 0; 459 } 460 461 /*************************************************************************** 462 * MCIQTZ_mciSeek [internal] 463 */ 464 static DWORD MCIQTZ_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms) 465 { 466 WINE_MCIQTZ* wma; 467 HRESULT hr; 468 LONGLONG newpos; 469 470 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 471 472 if(!lpParms) 473 return MCIERR_NULL_PARAMETER_BLOCK; 474 475 wma = MCIQTZ_mciGetOpenDev(wDevID); 476 if (!wma) 477 return MCIERR_INVALID_DEVICE_ID; 478 479 MCIQTZ_mciStop(wDevID, MCI_WAIT, NULL); 480 481 if (dwFlags & MCI_SEEK_TO_START) { 482 newpos = 0; 483 } else if (dwFlags & MCI_SEEK_TO_END) { 484 FIXME("MCI_SEEK_TO_END not implemented yet\n"); 485 return MCIERR_INTERNAL; 486 } else if (dwFlags & MCI_TO) { 487 FIXME("MCI_TO not implemented yet\n"); 488 return MCIERR_INTERNAL; 489 } else { 490 WARN("dwFlag doesn't tell where to seek to...\n"); 491 return MCIERR_MISSING_PARAMETER; 492 } 493 494 hr = IMediaSeeking_SetPositions(wma->seek, &newpos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning); 495 if (FAILED(hr)) { 496 FIXME("Cannot set position (hr = %x)\n", hr); 497 return MCIERR_INTERNAL; 498 } 499 500 if (dwFlags & MCI_NOTIFY) 501 MCIQTZ_mciNotify(lpParms->dwCallback, wma, MCI_NOTIFY_SUCCESSFUL); 502 503 return 0; 504 } 505 506 /*************************************************************************** 507 * MCIQTZ_mciStop [internal] 508 */ 509 static DWORD MCIQTZ_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) 510 { 511 WINE_MCIQTZ* wma; 512 513 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 514 515 wma = MCIQTZ_mciGetOpenDev(wDevID); 516 if (!wma) 517 return MCIERR_INVALID_DEVICE_ID; 518 519 if (!wma->opened) 520 return 0; 521 522 if (wma->thread) { 523 SetEvent(wma->stop_event); 524 WaitForSingleObject(wma->thread, INFINITE); 525 CloseHandle(wma->thread); 526 wma->thread = NULL; 527 } 528 529 if (!wma->parent) 530 IVideoWindow_put_Visible(wma->vidwin, OAFALSE); 531 532 return 0; 533 } 534 535 /*************************************************************************** 536 * MCIQTZ_mciPause [internal] 537 */ 538 static DWORD MCIQTZ_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) 539 { 540 WINE_MCIQTZ* wma; 541 HRESULT hr; 542 543 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 544 545 wma = MCIQTZ_mciGetOpenDev(wDevID); 546 if (!wma) 547 return MCIERR_INVALID_DEVICE_ID; 548 549 hr = IMediaControl_Pause(wma->pmctrl); 550 if (FAILED(hr)) { 551 TRACE("Cannot pause filtergraph (hr = %x)\n", hr); 552 return MCIERR_INTERNAL; 553 } 554 555 return 0; 556 } 557 558 /*************************************************************************** 559 * MCIQTZ_mciResume [internal] 560 */ 561 static DWORD MCIQTZ_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) 562 { 563 WINE_MCIQTZ* wma; 564 HRESULT hr; 565 566 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 567 568 wma = MCIQTZ_mciGetOpenDev(wDevID); 569 if (!wma) 570 return MCIERR_INVALID_DEVICE_ID; 571 572 hr = IMediaControl_Run(wma->pmctrl); 573 if (FAILED(hr)) { 574 TRACE("Cannot run filtergraph (hr = %x)\n", hr); 575 return MCIERR_INTERNAL; 576 } 577 578 return 0; 579 } 580 581 /*************************************************************************** 582 * MCIQTZ_mciGetDevCaps [internal] 583 */ 584 static DWORD MCIQTZ_mciGetDevCaps(UINT wDevID, DWORD dwFlags, LPMCI_GETDEVCAPS_PARMS lpParms) 585 { 586 WINE_MCIQTZ* wma; 587 588 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 589 590 if(!lpParms) 591 return MCIERR_NULL_PARAMETER_BLOCK; 592 593 wma = MCIQTZ_mciGetOpenDev(wDevID); 594 if (!wma) 595 return MCIERR_INVALID_DEVICE_ID; 596 597 if (!(dwFlags & MCI_GETDEVCAPS_ITEM)) 598 return MCIERR_MISSING_PARAMETER; 599 600 switch (lpParms->dwItem) { 601 case MCI_GETDEVCAPS_CAN_RECORD: 602 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); 603 TRACE("MCI_GETDEVCAPS_CAN_RECORD = %08x\n", lpParms->dwReturn); 604 break; 605 case MCI_GETDEVCAPS_HAS_AUDIO: 606 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE); 607 TRACE("MCI_GETDEVCAPS_HAS_AUDIO = %08x\n", lpParms->dwReturn); 608 break; 609 case MCI_GETDEVCAPS_HAS_VIDEO: 610 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE); 611 TRACE("MCI_GETDEVCAPS_HAS_VIDEO = %08x\n", lpParms->dwReturn); 612 break; 613 case MCI_GETDEVCAPS_DEVICE_TYPE: 614 lpParms->dwReturn = MAKEMCIRESOURCE(MCI_DEVTYPE_DIGITAL_VIDEO, MCI_DEVTYPE_DIGITAL_VIDEO); 615 TRACE("MCI_GETDEVCAPS_DEVICE_TYPE = %08x\n", lpParms->dwReturn); 616 break; 617 case MCI_GETDEVCAPS_USES_FILES: 618 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE); 619 TRACE("MCI_GETDEVCAPS_USES_FILES = %08x\n", lpParms->dwReturn); 620 break; 621 case MCI_GETDEVCAPS_COMPOUND_DEVICE: 622 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE); 623 TRACE("MCI_GETDEVCAPS_COMPOUND_DEVICE = %08x\n", lpParms->dwReturn); 624 break; 625 case MCI_GETDEVCAPS_CAN_EJECT: 626 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); 627 TRACE("MCI_GETDEVCAPS_EJECT = %08x\n", lpParms->dwReturn); 628 break; 629 case MCI_GETDEVCAPS_CAN_PLAY: 630 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE); 631 TRACE("MCI_GETDEVCAPS_CAN_PLAY = %08x\n", lpParms->dwReturn); 632 break; 633 case MCI_GETDEVCAPS_CAN_SAVE: 634 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); 635 TRACE("MCI_GETDEVCAPS_CAN_SAVE = %08x\n", lpParms->dwReturn); 636 break; 637 case MCI_DGV_GETDEVCAPS_CAN_REVERSE: 638 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); 639 TRACE("MCI_DGV_GETDEVCAPS_CAN_REVERSE = %08x\n", lpParms->dwReturn); 640 break; 641 case MCI_DGV_GETDEVCAPS_CAN_STRETCH: 642 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); /* FIXME */ 643 TRACE("MCI_DGV_GETDEVCAPS_CAN_STRETCH = %08x\n", lpParms->dwReturn); 644 break; 645 case MCI_DGV_GETDEVCAPS_CAN_LOCK: 646 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); 647 TRACE("MCI_DGV_GETDEVCAPS_CAN_LOCK = %08x\n", lpParms->dwReturn); 648 break; 649 case MCI_DGV_GETDEVCAPS_CAN_FREEZE: 650 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); 651 TRACE("MCI_DGV_GETDEVCAPS_CAN_FREEZE = %08x\n", lpParms->dwReturn); 652 break; 653 case MCI_DGV_GETDEVCAPS_CAN_STR_IN: 654 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); 655 TRACE("MCI_DGV_GETDEVCAPS_CAN_STRETCH_INPUT = %08x\n", lpParms->dwReturn); 656 break; 657 case MCI_DGV_GETDEVCAPS_HAS_STILL: 658 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); 659 TRACE("MCI_DGV_GETDEVCAPS_HAS_STILL = %08x\n", lpParms->dwReturn); 660 break; 661 case MCI_DGV_GETDEVCAPS_CAN_TEST: 662 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE); /* FIXME */ 663 TRACE("MCI_DGV_GETDEVCAPS_CAN_TEST = %08x\n", lpParms->dwReturn); 664 break; 665 case MCI_DGV_GETDEVCAPS_MAX_WINDOWS: 666 lpParms->dwReturn = 1; 667 TRACE("MCI_DGV_GETDEVCAPS_MAX_WINDOWS = %u\n", lpParms->dwReturn); 668 return 0; 669 default: 670 WARN("Unknown capability %08x\n", lpParms->dwItem); 671 /* Fall through */ 672 case MCI_DGV_GETDEVCAPS_MAXIMUM_RATE: /* unknown to w2k */ 673 case MCI_DGV_GETDEVCAPS_MINIMUM_RATE: /* unknown to w2k */ 674 return MCIERR_UNSUPPORTED_FUNCTION; 675 } 676 677 return MCI_RESOURCE_RETURNED; 678 } 679 680 /*************************************************************************** 681 * MCIQTZ_mciSet [internal] 682 */ 683 static DWORD MCIQTZ_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SET_PARMS lpParms) 684 { 685 WINE_MCIQTZ* wma; 686 687 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 688 689 if(!lpParms) 690 return MCIERR_NULL_PARAMETER_BLOCK; 691 692 wma = MCIQTZ_mciGetOpenDev(wDevID); 693 if (!wma) 694 return MCIERR_INVALID_DEVICE_ID; 695 696 if (dwFlags & MCI_SET_TIME_FORMAT) { 697 switch (lpParms->dwTimeFormat) { 698 case MCI_FORMAT_MILLISECONDS: 699 TRACE("MCI_SET_TIME_FORMAT = MCI_FORMAT_MILLISECONDS\n"); 700 wma->time_format = MCI_FORMAT_MILLISECONDS; 701 break; 702 case MCI_FORMAT_FRAMES: 703 TRACE("MCI_SET_TIME_FORMAT = MCI_FORMAT_FRAMES\n"); 704 wma->time_format = MCI_FORMAT_FRAMES; 705 break; 706 default: 707 WARN("Bad time format %u\n", lpParms->dwTimeFormat); 708 return MCIERR_BAD_TIME_FORMAT; 709 } 710 } 711 712 if (dwFlags & MCI_SET_DOOR_OPEN) 713 FIXME("MCI_SET_DOOR_OPEN not implemented yet\n"); 714 if (dwFlags & MCI_SET_DOOR_CLOSED) 715 FIXME("MCI_SET_DOOR_CLOSED not implemented yet\n"); 716 if (dwFlags & MCI_SET_AUDIO) 717 FIXME("MCI_SET_AUDIO not implemented yet\n"); 718 if (dwFlags & MCI_SET_VIDEO) 719 FIXME("MCI_SET_VIDEO not implemented yet\n"); 720 if (dwFlags & MCI_SET_ON) 721 FIXME("MCI_SET_ON not implemented yet\n"); 722 if (dwFlags & MCI_SET_OFF) 723 FIXME("MCI_SET_OFF not implemented yet\n"); 724 if (dwFlags & MCI_SET_AUDIO_LEFT) 725 FIXME("MCI_SET_AUDIO_LEFT not implemented yet\n"); 726 if (dwFlags & MCI_SET_AUDIO_RIGHT) 727 FIXME("MCI_SET_AUDIO_RIGHT not implemented yet\n"); 728 729 if (dwFlags & ~0x7f03 /* All MCI_SET flags mask */) 730 ERR("Unknown flags %08x\n", dwFlags & ~0x7f03); 731 732 return 0; 733 } 734 735 /*************************************************************************** 736 * MCIQTZ_mciStatus [internal] 737 */ 738 static DWORD MCIQTZ_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STATUS_PARMSW lpParms) 739 { 740 WINE_MCIQTZ* wma; 741 HRESULT hr; 742 DWORD ret = MCI_INTEGER_RETURNED; 743 744 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 745 746 if(!lpParms) 747 return MCIERR_NULL_PARAMETER_BLOCK; 748 749 wma = MCIQTZ_mciGetOpenDev(wDevID); 750 if (!wma) 751 return MCIERR_INVALID_DEVICE_ID; 752 753 if (!(dwFlags & MCI_STATUS_ITEM)) { 754 WARN("No status item specified\n"); 755 return MCIERR_UNRECOGNIZED_COMMAND; 756 } 757 758 switch (lpParms->dwItem) { 759 case MCI_STATUS_LENGTH: { 760 LONGLONG duration = -1; 761 GUID format; 762 switch (wma->time_format) { 763 case MCI_FORMAT_MILLISECONDS: format = TIME_FORMAT_MEDIA_TIME; break; 764 case MCI_FORMAT_FRAMES: format = TIME_FORMAT_FRAME; break; 765 default: ERR("Unhandled format %x\n", wma->time_format); break; 766 } 767 hr = IMediaSeeking_SetTimeFormat(wma->seek, &format); 768 if (FAILED(hr)) { 769 FIXME("Cannot set time format (hr = %x)\n", hr); 770 lpParms->dwReturn = 0; 771 break; 772 } 773 hr = IMediaSeeking_GetDuration(wma->seek, &duration); 774 if (FAILED(hr) || duration < 0) { 775 FIXME("Cannot read duration (hr = %x)\n", hr); 776 lpParms->dwReturn = 0; 777 } else if (wma->time_format != MCI_FORMAT_MILLISECONDS) 778 lpParms->dwReturn = duration; 779 else 780 lpParms->dwReturn = duration / 10000; 781 break; 782 } 783 case MCI_STATUS_POSITION: { 784 REFERENCE_TIME curpos; 785 786 hr = IMediaSeeking_GetCurrentPosition(wma->seek, &curpos); 787 if (FAILED(hr)) { 788 FIXME("Cannot get position (hr = %x)\n", hr); 789 return MCIERR_INTERNAL; 790 } 791 lpParms->dwReturn = curpos / 10000; 792 break; 793 } 794 case MCI_STATUS_NUMBER_OF_TRACKS: 795 FIXME("MCI_STATUS_NUMBER_OF_TRACKS not implemented yet\n"); 796 return MCIERR_UNRECOGNIZED_COMMAND; 797 case MCI_STATUS_MODE: { 798 LONG state = State_Stopped; 799 IMediaControl_GetState(wma->pmctrl, -1, &state); 800 if (state == State_Stopped) 801 lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_STOP, MCI_MODE_STOP); 802 else if (state == State_Running) { 803 lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_PLAY, MCI_MODE_PLAY); 804 if (!wma->thread || WaitForSingleObject(wma->thread, 0) == WAIT_OBJECT_0) 805 lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_STOP, MCI_MODE_STOP); 806 } else if (state == State_Paused) 807 lpParms->dwReturn = MAKEMCIRESOURCE(MCI_MODE_PAUSE, MCI_MODE_PAUSE); 808 ret = MCI_RESOURCE_RETURNED; 809 break; 810 } 811 case MCI_STATUS_MEDIA_PRESENT: 812 FIXME("MCI_STATUS_MEDIA_PRESENT not implemented yet\n"); 813 return MCIERR_UNRECOGNIZED_COMMAND; 814 case MCI_STATUS_TIME_FORMAT: 815 lpParms->dwReturn = MAKEMCIRESOURCE(wma->time_format, 816 MCI_FORMAT_RETURN_BASE + wma->time_format); 817 ret = MCI_RESOURCE_RETURNED; 818 break; 819 case MCI_STATUS_READY: 820 FIXME("MCI_STATUS_READY not implemented yet\n"); 821 return MCIERR_UNRECOGNIZED_COMMAND; 822 case MCI_STATUS_CURRENT_TRACK: 823 FIXME("MCI_STATUS_CURRENT_TRACK not implemented yet\n"); 824 return MCIERR_UNRECOGNIZED_COMMAND; 825 default: 826 FIXME("Unknown command %08X\n", lpParms->dwItem); 827 return MCIERR_UNRECOGNIZED_COMMAND; 828 } 829 830 if (dwFlags & MCI_NOTIFY) 831 MCIQTZ_mciNotify(lpParms->dwCallback, wma, MCI_NOTIFY_SUCCESSFUL); 832 833 return ret; 834 } 835 836 /*************************************************************************** 837 * MCIQTZ_mciWhere [internal] 838 */ 839 static DWORD MCIQTZ_mciWhere(UINT wDevID, DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms) 840 { 841 WINE_MCIQTZ* wma; 842 HRESULT hr; 843 HWND hWnd; 844 RECT rc; 845 DWORD ret = MCIERR_UNRECOGNIZED_COMMAND; 846 847 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 848 849 if(!lpParms) 850 return MCIERR_NULL_PARAMETER_BLOCK; 851 852 wma = MCIQTZ_mciGetOpenDev(wDevID); 853 if (!wma) 854 return MCIERR_INVALID_DEVICE_ID; 855 856 hr = IVideoWindow_get_Owner(wma->vidwin, (OAHWND*)&hWnd); 857 if (FAILED(hr)) { 858 TRACE("No video stream, returning no window error\n"); 859 return MCIERR_NO_WINDOW; 860 } 861 862 if (dwFlags & MCI_DGV_WHERE_SOURCE) { 863 if (dwFlags & MCI_DGV_WHERE_MAX) 864 FIXME("MCI_DGV_WHERE_SOURCE_MAX stub\n"); 865 IBasicVideo_GetSourcePosition(wma->vidbasic, &rc.left, &rc.top, &rc.right, &rc.bottom); 866 TRACE("MCI_DGV_WHERE_SOURCE %s\n", wine_dbgstr_rect(&rc)); 867 } 868 if (dwFlags & MCI_DGV_WHERE_DESTINATION) { 869 if (dwFlags & MCI_DGV_WHERE_MAX) 870 FIXME("MCI_DGV_WHERE_DESTINATION_MAX stub\n"); 871 IBasicVideo_GetDestinationPosition(wma->vidbasic, &rc.left, &rc.top, &rc.right, &rc.bottom); 872 TRACE("MCI_DGV_WHERE_DESTINATION %s\n", wine_dbgstr_rect(&rc)); 873 } 874 if (dwFlags & MCI_DGV_WHERE_FRAME) { 875 if (dwFlags & MCI_DGV_WHERE_MAX) 876 FIXME("MCI_DGV_WHERE_FRAME_MAX not supported yet\n"); 877 else 878 FIXME("MCI_DGV_WHERE_FRAME not supported yet\n"); 879 goto out; 880 } 881 if (dwFlags & MCI_DGV_WHERE_VIDEO) { 882 if (dwFlags & MCI_DGV_WHERE_MAX) 883 FIXME("MCI_DGV_WHERE_VIDEO_MAX not supported yet\n"); 884 else 885 FIXME("MCI_DGV_WHERE_VIDEO not supported yet\n"); 886 goto out; 887 } 888 if (dwFlags & MCI_DGV_WHERE_WINDOW) { 889 if (dwFlags & MCI_DGV_WHERE_MAX) { 890 GetWindowRect(GetDesktopWindow(), &rc); 891 rc.right -= rc.left; 892 rc.bottom -= rc.top; 893 TRACE("MCI_DGV_WHERE_WINDOW_MAX %s\n", wine_dbgstr_rect(&rc)); 894 } else { 895 IVideoWindow_GetWindowPosition(wma->vidwin, &rc.left, &rc.top, &rc.right, &rc.bottom); 896 TRACE("MCI_DGV_WHERE_WINDOW %s\n", wine_dbgstr_rect(&rc)); 897 } 898 } 899 ret = 0; 900 out: 901 lpParms->rc = rc; 902 return ret; 903 } 904 905 /*************************************************************************** 906 * MCIQTZ_mciWindow [internal] 907 */ 908 static DWORD MCIQTZ_mciWindow(UINT wDevID, DWORD dwFlags, LPMCI_DGV_WINDOW_PARMSW lpParms) 909 { 910 WINE_MCIQTZ *wma = MCIQTZ_mciGetOpenDev(wDevID); 911 912 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 913 914 if(!lpParms) 915 return MCIERR_NULL_PARAMETER_BLOCK; 916 917 if (!wma) 918 return MCIERR_INVALID_DEVICE_ID; 919 if (dwFlags & MCI_TEST) 920 return 0; 921 922 if (dwFlags & MCI_DGV_WINDOW_HWND && (IsWindow(lpParms->hWnd) || !lpParms->hWnd)) { 923 LONG visible = OATRUE; 924 LONG style = 0; 925 TRACE("Setting hWnd to %p\n", lpParms->hWnd); 926 IVideoWindow_get_Visible(wma->vidwin, &visible); 927 IVideoWindow_put_Visible(wma->vidwin, OAFALSE); 928 IVideoWindow_get_WindowStyle(wma->vidwin, &style); 929 style &= ~WS_CHILD; 930 if (lpParms->hWnd) 931 IVideoWindow_put_WindowStyle(wma->vidwin, style|WS_CHILD); 932 else 933 IVideoWindow_put_WindowStyle(wma->vidwin, style); 934 IVideoWindow_put_Owner(wma->vidwin, (OAHWND)lpParms->hWnd); 935 IVideoWindow_put_MessageDrain(wma->vidwin, (OAHWND)lpParms->hWnd); 936 IVideoWindow_put_Visible(wma->vidwin, visible); 937 wma->parent = lpParms->hWnd; 938 } 939 if (dwFlags & MCI_DGV_WINDOW_STATE) { 940 TRACE("Setting nCmdShow to %d\n", lpParms->nCmdShow); 941 IVideoWindow_put_WindowState(wma->vidwin, lpParms->nCmdShow); 942 } 943 if (dwFlags & MCI_DGV_WINDOW_TEXT) { 944 TRACE("Setting caption to %s\n", debugstr_w(lpParms->lpstrText)); 945 IVideoWindow_put_Caption(wma->vidwin, lpParms->lpstrText); 946 } 947 return 0; 948 } 949 950 /*************************************************************************** 951 * MCIQTZ_mciPut [internal] 952 */ 953 static DWORD MCIQTZ_mciPut(UINT wDevID, DWORD dwFlags, MCI_GENERIC_PARMS *lpParms) 954 { 955 WINE_MCIQTZ *wma = MCIQTZ_mciGetOpenDev(wDevID); 956 MCI_DGV_RECT_PARMS *rectparms; 957 HRESULT hr; 958 959 TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); 960 961 if(!lpParms) 962 return MCIERR_NULL_PARAMETER_BLOCK; 963 964 if (!wma) 965 return MCIERR_INVALID_DEVICE_ID; 966 967 if (!(dwFlags & MCI_DGV_RECT)) { 968 FIXME("No support for non-RECT MCI_PUT\n"); 969 return 1; 970 } 971 972 if (dwFlags & MCI_TEST) 973 return 0; 974 975 dwFlags &= ~MCI_DGV_RECT; 976 rectparms = (MCI_DGV_RECT_PARMS*)lpParms; 977 978 if (dwFlags & MCI_DGV_PUT_DESTINATION) { 979 hr = IVideoWindow_SetWindowPosition(wma->vidwin, 980 rectparms->rc.left, rectparms->rc.top, 981 rectparms->rc.right - rectparms->rc.left, 982 rectparms->rc.bottom - rectparms->rc.top); 983 if(FAILED(hr)) 984 WARN("IVideoWindow_SetWindowPosition failed: 0x%x\n", hr); 985 986 dwFlags &= ~MCI_DGV_PUT_DESTINATION; 987 } 988 989 if (dwFlags & MCI_NOTIFY) { 990 MCIQTZ_mciNotify(lpParms->dwCallback, wma, MCI_NOTIFY_SUCCESSFUL); 991 dwFlags &= ~MCI_NOTIFY; 992 } 993 994 if (dwFlags) 995 FIXME("No support for some flags: 0x%x\n", dwFlags); 996 997 return 0; 998 } 999 1000 /****************************************************************************** 1001 * MCIAVI_mciUpdate [internal] 1002 */ 1003 static DWORD MCIQTZ_mciUpdate(UINT wDevID, DWORD dwFlags, LPMCI_DGV_UPDATE_PARMS lpParms) 1004 { 1005 WINE_MCIQTZ *wma; 1006 DWORD res = 0; 1007 1008 TRACE("%04x, %08x, %p\n", wDevID, dwFlags, lpParms); 1009 1010 if(!lpParms) 1011 return MCIERR_NULL_PARAMETER_BLOCK; 1012 1013 wma = MCIQTZ_mciGetOpenDev(wDevID); 1014 if (!wma) 1015 return MCIERR_INVALID_DEVICE_ID; 1016 1017 if (dwFlags & MCI_DGV_UPDATE_HDC) { 1018 LONG state, size; 1019 BYTE *data; 1020 BITMAPINFO *info; 1021 HRESULT hr; 1022 RECT src, dest; 1023 LONG visible = OATRUE; 1024 1025 res = MCIERR_INTERNAL; 1026 IMediaControl_GetState(wma->pmctrl, -1, &state); 1027 if (state == State_Running) 1028 return MCIERR_UNSUPPORTED_FUNCTION; 1029 /* If in stopped state, nothing has been drawn to screen 1030 * moving to pause, which is needed for the old dib renderer, will result 1031 * in a single frame drawn, so hide the window here */ 1032 IVideoWindow_get_Visible(wma->vidwin, &visible); 1033 if (wma->parent) 1034 IVideoWindow_put_Visible(wma->vidwin, OAFALSE); 1035 /* FIXME: Should we check the original state and restore it? */ 1036 IMediaControl_Pause(wma->pmctrl); 1037 IMediaControl_GetState(wma->pmctrl, -1, &state); 1038 if (FAILED(hr = IBasicVideo_GetCurrentImage(wma->vidbasic, &size, NULL))) { 1039 WARN("Could not get image size (hr = %x)\n", hr); 1040 goto out; 1041 } 1042 data = HeapAlloc(GetProcessHeap(), 0, size); 1043 info = (BITMAPINFO*)data; 1044 IBasicVideo_GetCurrentImage(wma->vidbasic, &size, (LONG*)data); 1045 data += info->bmiHeader.biSize; 1046 1047 IBasicVideo_GetSourcePosition(wma->vidbasic, &src.left, &src.top, &src.right, &src.bottom); 1048 IBasicVideo_GetDestinationPosition(wma->vidbasic, &dest.left, &dest.top, &dest.right, &dest.bottom); 1049 StretchDIBits(lpParms->hDC, 1050 dest.left, dest.top, dest.right + dest.left, dest.bottom + dest.top, 1051 src.left, src.top, src.right + src.left, src.bottom + src.top, 1052 data, info, DIB_RGB_COLORS, SRCCOPY); 1053 HeapFree(GetProcessHeap(), 0, data); 1054 res = 0; 1055 out: 1056 if (wma->parent) 1057 IVideoWindow_put_Visible(wma->vidwin, visible); 1058 } 1059 else if (dwFlags) 1060 FIXME("Unhandled flags %x\n", dwFlags); 1061 return res; 1062 } 1063 1064 /*************************************************************************** 1065 * MCIQTZ_mciSetAudio [internal] 1066 */ 1067 static DWORD MCIQTZ_mciSetAudio(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETAUDIO_PARMSW lpParms) 1068 { 1069 WINE_MCIQTZ *wma; 1070 DWORD ret = 0; 1071 1072 TRACE("(%04x, %08x, %p)\n", wDevID, dwFlags, lpParms); 1073 1074 if(!lpParms) 1075 return MCIERR_NULL_PARAMETER_BLOCK; 1076 1077 wma = MCIQTZ_mciGetOpenDev(wDevID); 1078 if (!wma) 1079 return MCIERR_INVALID_DEVICE_ID; 1080 1081 if (!(dwFlags & MCI_DGV_SETAUDIO_ITEM)) { 1082 FIXME("Unknown flags (%08x)\n", dwFlags); 1083 return 0; 1084 } 1085 1086 if (dwFlags & MCI_DGV_SETAUDIO_ITEM) { 1087 switch (lpParms->dwItem) { 1088 case MCI_DGV_SETAUDIO_VOLUME: 1089 if (dwFlags & MCI_DGV_SETAUDIO_VALUE) { 1090 long vol; 1091 HRESULT hr; 1092 if (lpParms->dwValue > 1000) { 1093 ret = MCIERR_OUTOFRANGE; 1094 break; 1095 } 1096 if (dwFlags & MCI_TEST) 1097 break; 1098 if (lpParms->dwValue != 0) 1099 vol = (long)(2000.0 * (log10(lpParms->dwValue) - 3.0)); 1100 else 1101 vol = -10000; 1102 TRACE("Setting volume to %ld\n", vol); 1103 hr = IBasicAudio_put_Volume(wma->audio, vol); 1104 if (FAILED(hr)) { 1105 WARN("Cannot set volume (hr = %x)\n", hr); 1106 ret = MCIERR_INTERNAL; 1107 } 1108 } 1109 break; 1110 default: 1111 FIXME("Unknown item %08x\n", lpParms->dwItem); 1112 break; 1113 } 1114 } 1115 1116 return ret; 1117 } 1118 1119 /*======================================================================* 1120 * MCI QTZ entry points * 1121 *======================================================================*/ 1122 1123 /************************************************************************** 1124 * DriverProc (MCIQTZ.@) 1125 */ 1126 LRESULT CALLBACK MCIQTZ_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, 1127 LPARAM dwParam1, LPARAM dwParam2) 1128 { 1129 TRACE("(%08lX, %p, %08X, %08lX, %08lX)\n", 1130 dwDevID, hDriv, wMsg, dwParam1, dwParam2); 1131 1132 switch (wMsg) { 1133 case DRV_LOAD: return 1; 1134 case DRV_FREE: return 1; 1135 case DRV_OPEN: return MCIQTZ_drvOpen((LPCWSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSW)dwParam2); 1136 case DRV_CLOSE: return MCIQTZ_drvClose(dwDevID); 1137 case DRV_ENABLE: return 1; 1138 case DRV_DISABLE: return 1; 1139 case DRV_QUERYCONFIGURE: return 1; 1140 case DRV_CONFIGURE: return MCIQTZ_drvConfigure(dwDevID); 1141 case DRV_INSTALL: return DRVCNF_RESTART; 1142 case DRV_REMOVE: return DRVCNF_RESTART; 1143 } 1144 1145 /* session instance */ 1146 if (dwDevID == 0xFFFFFFFF) 1147 return 1; 1148 1149 switch (wMsg) { 1150 case MCI_OPEN_DRIVER: return MCIQTZ_mciOpen (dwDevID, dwParam1, (LPMCI_DGV_OPEN_PARMSW) dwParam2); 1151 case MCI_CLOSE_DRIVER: return MCIQTZ_mciClose (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2); 1152 case MCI_PLAY: return MCIQTZ_mciPlay (dwDevID, dwParam1, (LPMCI_PLAY_PARMS) dwParam2); 1153 case MCI_SEEK: return MCIQTZ_mciSeek (dwDevID, dwParam1, (LPMCI_SEEK_PARMS) dwParam2); 1154 case MCI_STOP: return MCIQTZ_mciStop (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2); 1155 case MCI_PAUSE: return MCIQTZ_mciPause (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2); 1156 case MCI_RESUME: return MCIQTZ_mciResume (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2); 1157 case MCI_GETDEVCAPS: return MCIQTZ_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS) dwParam2); 1158 case MCI_SET: return MCIQTZ_mciSet (dwDevID, dwParam1, (LPMCI_DGV_SET_PARMS) dwParam2); 1159 case MCI_STATUS: return MCIQTZ_mciStatus (dwDevID, dwParam1, (LPMCI_DGV_STATUS_PARMSW) dwParam2); 1160 case MCI_WHERE: return MCIQTZ_mciWhere (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS) dwParam2); 1161 /* Digital Video specific */ 1162 case MCI_SETAUDIO: return MCIQTZ_mciSetAudio (dwDevID, dwParam1, (LPMCI_DGV_SETAUDIO_PARMSW) dwParam2); 1163 case MCI_UPDATE: 1164 return MCIQTZ_mciUpdate(dwDevID, dwParam1, (LPMCI_DGV_UPDATE_PARMS)dwParam2); 1165 case MCI_WINDOW: 1166 return MCIQTZ_mciWindow(dwDevID, dwParam1, (LPMCI_DGV_WINDOW_PARMSW)dwParam2); 1167 case MCI_PUT: 1168 return MCIQTZ_mciPut(dwDevID, dwParam1, (MCI_GENERIC_PARMS*)dwParam2); 1169 case MCI_RECORD: 1170 case MCI_INFO: 1171 case MCI_LOAD: 1172 case MCI_SAVE: 1173 case MCI_FREEZE: 1174 case MCI_REALIZE: 1175 case MCI_UNFREEZE: 1176 case MCI_STEP: 1177 case MCI_COPY: 1178 case MCI_CUT: 1179 case MCI_DELETE: 1180 case MCI_PASTE: 1181 case MCI_CUE: 1182 /* Digital Video specific */ 1183 case MCI_CAPTURE: 1184 case MCI_MONITOR: 1185 case MCI_RESERVE: 1186 case MCI_SIGNAL: 1187 case MCI_SETVIDEO: 1188 case MCI_QUALITY: 1189 case MCI_LIST: 1190 case MCI_UNDO: 1191 case MCI_CONFIGURE: 1192 case MCI_RESTORE: 1193 FIXME("Unimplemented command [%08X]\n", wMsg); 1194 break; 1195 case MCI_SPIN: 1196 case MCI_ESCAPE: 1197 WARN("Unsupported command [%08X]\n", wMsg); 1198 break; 1199 case MCI_OPEN: 1200 case MCI_CLOSE: 1201 FIXME("Shouldn't receive a MCI_OPEN or CLOSE message\n"); 1202 break; 1203 default: 1204 TRACE("Sending msg [%08X] to default driver proc\n", wMsg); 1205 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); 1206 } 1207 1208 return MCIERR_UNRECOGNIZED_COMMAND; 1209 } 1210