Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3188 lines
101 KiB

  1. /******************************************************************************
  2. Copyright (C) Microsoft Corporation 1985-1991. All rights reserved.
  3. Title: graphic.c - Multimedia Systems Media Control Interface
  4. driver for AVI.
  5. *****************************************************************************/
  6. // Define HEARTBEAT to create a permanent thread which can periodically
  7. // dump mciavi device status
  8. //#define HEARTBEAT
  9. #include "graphic.h"
  10. #include "dispdib.h"
  11. //#include "cnfgdlg.h"
  12. #include <string.h>
  13. #ifdef EXPIRE
  14. #include <dos.h>
  15. #endif
  16. #include "avitask.h"
  17. #ifdef DEBUG
  18. #define static
  19. #endif
  20. #ifdef _WIN32
  21. extern BOOL FAR PASCAL WowUseMciavi16(VOID);
  22. #endif
  23. //
  24. // This is the version number of MSVIDEO.DLL we need in order to run
  25. // build 81 is when we added the VideoForWindowsVersion() function to
  26. // MSVIDEO.DLL
  27. //
  28. // in build 85
  29. // we removed the ICDecompressOpen() function and it became a macro.
  30. // we added a parameter to ICGetDisplayFormat()
  31. // we make DrawDibProfileDisplay() take a parameter
  32. //
  33. // in build 108
  34. // Added ICOpenFunction() to open a hic using a function directly,
  35. // without calling ICInstall
  36. // Added some more ICDRAW_ messages
  37. //
  38. // in build 109
  39. // Addded ICMessage() to compman
  40. // removed ICDrawSuggest() made it a macro.
  41. // Added ICMODE_FASTDECOMPRESS to ICLocate()
  42. //
  43. // Under NT the first build is sufficient !!! Is this true now?
  44. //
  45. #ifdef _WIN32
  46. #define MSVIDEO_VERSION (0x01000000) // 1.00.00.00
  47. #else
  48. #define MSVIDEO_VERSION (0x010a0000l+109) // 1.10.00.109
  49. #endif
  50. /* statics */
  51. static INT swCommandTable = -1;
  52. #if 0
  53. #ifdef _WIN32
  54. static SZCODE szDisplayDibLib[] = TEXT("DISPDB32.DLL");
  55. #else
  56. static SZCODE szDisplayDibLib[] = TEXT("DISPDIB.DLL");
  57. #endif
  58. #endif
  59. /*
  60. * files should be UNICODE. function names should not
  61. */
  62. #ifdef _WIN32
  63. STATICDT SZCODE szMSVideo[] = TEXT("MSVFW32"); // With GetModuleHandle
  64. const TCHAR szReject[] = TEXT("RejectWOWOpenCalls");
  65. #else
  66. static SZCODE szMSVideo[] = TEXT("MSVIDEO");
  67. #endif
  68. BOOL gfEvil; // TRUE if we cant close cuz dialog box is up
  69. BOOL gfEvilSysMenu; // TRUE if we cant close cuz system menu is up
  70. NPMCIGRAPHIC npMCIList; // list of all open instances.
  71. #ifdef _WIN32
  72. CRITICAL_SECTION MCIListCritSec; // Must protect access to MCIList entries
  73. #ifdef DEBUG
  74. DWORD ListOwner;
  75. #endif // debug
  76. #endif
  77. /***************************************************************************
  78. *
  79. * @doc INTERNAL MCIAVI
  80. *
  81. * @api void | GraphicInit | This function is called when the DriverProc
  82. * gets a DRV_LOAD message.
  83. *
  84. ***************************************************************************/
  85. BOOL FAR PASCAL GraphicInit(void)
  86. {
  87. InitializeDebugOutput("MCIAVI");
  88. if (!GraphicWindowInit())
  89. return FALSE;
  90. // The command table is name MCIAVI - same as the Ini/Registry/Module
  91. swCommandTable = mciLoadCommandResource(ghModule, szIni, 0);
  92. #ifdef _WIN32
  93. InitializeCriticalSection(&MCIListCritSec);
  94. #endif
  95. return TRUE;
  96. }
  97. /***************************************************************************
  98. *
  99. * @doc INTERNAL MCIAVI
  100. *
  101. * @api DWORD | GraphicDrvOpen | This function is called when the DriverProc
  102. * gets a DRV_OPEN message. This happens each time that a new movie
  103. * is opened thru MCI.
  104. *
  105. * @parm LPMCI_OPEN_DRIVER_PARMS | lpOpen | Far pointer to the standard
  106. * MCI open parameters
  107. *
  108. * @rdesc Returns the mci device id. The installable driver interface will
  109. * pass this ID to the DriverProc in the dwDriverID parameter on all
  110. * subsequent messages. To fail the open, return 0L.
  111. *
  112. ***************************************************************************/
  113. DWORD PASCAL GraphicDrvOpen(LPMCI_OPEN_DRIVER_PARMS lpOpen)
  114. {
  115. /* Specify the custom command table and the device type */
  116. lpOpen->wCustomCommandTable = swCommandTable;
  117. lpOpen->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
  118. /* Set the device ID to the MCI Device ID */
  119. return (DWORD) (UINT)lpOpen->wDeviceID;
  120. }
  121. /***************************************************************************
  122. *
  123. * @doc INTERNAL MCIAVI
  124. *
  125. * @api void | GraphicFree | This function is called when the DriverProc
  126. * gets a DRV_FREE message. This happens when the drivers open count
  127. * reaches 0.
  128. *
  129. ***************************************************************************/
  130. #ifdef HEARTBEAT
  131. BOOL fTerminate = FALSE;
  132. HANDLE hHeartBeatThread= 0;
  133. #endif
  134. void PASCAL GraphicFree(void)
  135. {
  136. if (swCommandTable != -1) {
  137. mciFreeCommandResource(swCommandTable);
  138. swCommandTable = -1;
  139. }
  140. #ifdef HEARTBEAT
  141. if (hHeartBeatThread) {
  142. fTerminate=TRUE;
  143. WaitForSingleObject(hHeartBeatThread, 5000);
  144. CloseHandle(hHeartBeatThread);
  145. }
  146. #endif
  147. #ifdef _WIN32
  148. /*
  149. * unregister class so we can re-register it next time we are loaded
  150. */
  151. GraphicWindowFree();
  152. #ifdef REMOTESTEAL
  153. if (hkey) {
  154. RegCloseKey(hkey);
  155. hkey = 0;
  156. }
  157. #endif
  158. DeleteCriticalSection(&MCIListCritSec);
  159. #endif
  160. }
  161. /***************************************************************************
  162. *
  163. * @doc INTERNAL MCIAVI
  164. *
  165. * @api DWORD | GraphicDelayedNotify | This is a utility function that
  166. * sends a notification saved with GraphicSaveCallback to mmsystem
  167. * which posts a message to the application. Called on either worker
  168. * or (occasionally if ever?) user thread.
  169. *
  170. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data.
  171. *
  172. * @parm UINT | wStatus | The type of notification to use can be one of
  173. * MCI_NOTIFY_SUCCESSFUL, MCI_NOTIFY_SUPERSEDED, MCI_NOTIFY_ABORTED
  174. * or MCI_NOTIFY_FAILURE (see MCI ispec.)
  175. *
  176. ***************************************************************************/
  177. void FAR PASCAL GraphicDelayedNotify(NPMCIGRAPHIC npMCI, UINT wStatus)
  178. {
  179. /* Send any saved notification */
  180. if (npMCI->hCallback) {
  181. DPF2(("GraphicDelayedNotify, npMCI=%8x, Status is %x\n", npMCI, wStatus));
  182. // If the system menu is the only thing keeping us from closing, bring
  183. // it down and then close.
  184. if (gfEvilSysMenu)
  185. SendMessage(npMCI->hwndPlayback, WM_CANCELMODE, 0, 0);
  186. // If a dialog box is up, and keeping us from closing, we can't send the
  187. // notify or it will close us.
  188. if (!gfEvil)
  189. mciDriverNotify(npMCI->hCallback, npMCI->wDevID, wStatus);
  190. npMCI->hCallback = NULL;
  191. }
  192. }
  193. /***************************************************************************
  194. *
  195. * @doc INTERNAL MCIAVI
  196. *
  197. * @api DWORD | GraphicImmediateNotify | This is a utility function that
  198. * sends a successful notification message to mmsystem if the
  199. * notification flag is set and the error field is 0.
  200. *
  201. * @parm UINT | wDevID | device ID.
  202. *
  203. * @parm LPMCI_GENERIC_PARMS | lpParms | Far pointer to an MCI parameter
  204. * block. The first field of every MCI parameter block is the
  205. * callback handle.
  206. *
  207. * @parm DWORD | dwFlags | Parm. block flags - used to check whether the
  208. * callback handle is valid.
  209. *
  210. * @parm DWORD | dwErr | Notification only occurs if the command is not
  211. * returning an error.
  212. *
  213. ***************************************************************************/
  214. void FAR PASCAL GraphicImmediateNotify(UINT wDevID,
  215. LPMCI_GENERIC_PARMS lpParms,
  216. DWORD dwFlags, DWORD dwErr)
  217. {
  218. if (!LOWORD(dwErr) && (dwFlags & MCI_NOTIFY)) {
  219. //Don't have an npMCI - see GraphicDelayedNotify
  220. //if (gfEvil)
  221. //SendMessage(npMCI->hwndPlayback, WM_CANCELMODE, 0, 0);
  222. // If a dialog box is up, and keeping us from closing, we can't send the
  223. // notify or it will close us.
  224. if (!gfEvil) // !!! EVIL !!!
  225. mciDriverNotify((HANDLE) (UINT)lpParms->dwCallback,
  226. wDevID, MCI_NOTIFY_SUCCESSFUL);
  227. }
  228. }
  229. /***************************************************************************
  230. *
  231. * @doc INTERNAL MCIAVI
  232. *
  233. * @api DWORD | GraphicSaveCallback | This is a utility function that saves
  234. * a new callback in the instance data block.
  235. *
  236. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data.
  237. *
  238. * @parm HANDLE | hCallback | callback handle
  239. *
  240. ***************************************************************************/
  241. void NEAR PASCAL GraphicSaveCallback (NPMCIGRAPHIC npMCI, HANDLE hCallback)
  242. {
  243. /* If there's an old callback, kill it. */
  244. GraphicDelayedNotify(npMCI, MCI_NOTIFY_SUPERSEDED);
  245. /* Save new notification callback window handle */
  246. npMCI->hCallback = hCallback;
  247. }
  248. /***************************************************************************
  249. *
  250. * @doc INTERNAL MCIAVI
  251. *
  252. * @api DWORD | GraphicClose | This function closes the movie and
  253. * releases the instance data.
  254. *
  255. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data.
  256. *
  257. * @rdesc Returns an MCI error code.
  258. *
  259. ***************************************************************************/
  260. DWORD PASCAL GraphicClose (NPMCIGRAPHIC npMCI)
  261. {
  262. DWORD dwRet = 0L;
  263. NPMCIGRAPHIC p;
  264. if (npMCI) {
  265. SetNTFlags(npMCI, NTF_CLOSING);
  266. #ifdef DEBUG
  267. npMCI->mciid = MCIIDX;
  268. if (TestNTFlags(npMCI, NTF_AUDIO_OFF)) {
  269. DPF1(("Trying to close while audio command active\n"));
  270. DebugBreak();
  271. }
  272. #endif
  273. dwRet = DeviceClose (npMCI);
  274. Assert(dwRet == 0);
  275. // If the system menu is the only thing keeping us from closing, bring
  276. // it down and then close.
  277. if (gfEvilSysMenu)
  278. SendMessage(npMCI->hwndPlayback, WM_CANCELMODE, 0, 0);
  279. if (gfEvil) {
  280. DPF(("************************************************\n"));
  281. DPF(("** EVIL: Failing the close because we'd die **\n"));
  282. DPF(("************************************************\n"));
  283. ResetNTFlags(npMCI, NTF_CLOSING);
  284. return MCIERR_DRIVER_INTERNAL;
  285. }
  286. //
  287. // find this instance on the list - and remove it
  288. // Do this before destroying any element in this instance
  289. //
  290. EnterList();
  291. if (npMCI == npMCIList) {
  292. npMCIList = npMCI->npMCINext;
  293. }
  294. else {
  295. for (p=npMCIList; p && p->npMCINext != npMCI; p=p->npMCINext)
  296. ;
  297. Assert(p && p->npMCINext == npMCI);
  298. p->npMCINext = npMCI->npMCINext;
  299. }
  300. LeaveList();
  301. if (npMCI->szFilename) {
  302. LocalFree((HANDLE) (npMCI->szFilename));
  303. }
  304. #ifdef _WIN32
  305. #ifdef DEBUG
  306. if (npMCI->hmmio) {
  307. DPF1(("hmmio is still open, npMCI=%8x\n", npMCI));
  308. }
  309. if (npMCI->hmmioAudio) {
  310. DPF1(("hmmioAudio is still open, npMCI=%8x\n", npMCI));
  311. }
  312. #endif
  313. #endif
  314. #ifdef INTERVAL_TIMES
  315. // Free the bucket space
  316. if (npMCI->paIntervals) {
  317. LocalFree(npMCI->paIntervals);
  318. }
  319. #endif
  320. /* Free the instance data block allocated in GraphicOpen */
  321. LocalFree((HANDLE)npMCI);
  322. }
  323. return dwRet;
  324. }
  325. DWORD NEAR PASCAL FixFileName(NPMCIGRAPHIC npMCI, LPCTSTR lpName)
  326. {
  327. TCHAR ach[256];
  328. ach[(NUMELMS(ach)) - 1] = TEXT('\0');
  329. #ifndef _WIN32
  330. _fstrncpy(ach, (LPTSTR) lpName, NUMELMS(ach) - 1);
  331. #else
  332. wcsncpy(ach, (LPTSTR) lpName, NUMELMS(ach) - 1);
  333. #endif
  334. //
  335. // treat any string that starts with a '@' as valid and pass it to the
  336. // device any way.
  337. //
  338. if (ach[0] != TEXT('@'))
  339. {
  340. if (!mmioOpen(ach, NULL, MMIO_PARSE))
  341. return MCIERR_FILENAME_REQUIRED;
  342. }
  343. Assert(0 == npMCI->szFilename);
  344. npMCI->szFilename = (NPTSTR) LocalAlloc(LPTR,
  345. sizeof(TCHAR) * (lstrlen(ach) + 1));
  346. if (!npMCI->szFilename) {
  347. return MCIERR_OUT_OF_MEMORY;
  348. }
  349. lstrcpy(npMCI->szFilename, ach);
  350. return 0L;
  351. }
  352. /**************************************************************************
  353. ***************************************************************************/
  354. #define SLASH(c) ((c) == TEXT('/') || (c) == TEXT('\\'))
  355. LPCTSTR FAR FileName(LPCTSTR szPath)
  356. {
  357. LPCTSTR sz;
  358. sz = &szPath[lstrlen(szPath)];
  359. for (; sz>szPath && !SLASH(*sz) && *sz!=TEXT(':');) {
  360. LPCTSTR pszOld = sz;
  361. if ((sz = CharPrev(szPath, sz)) == pszOld)
  362. break;
  363. }
  364. return (sz>szPath ? sz + 1 : sz);
  365. }
  366. /****************************************************************************
  367. ****************************************************************************/
  368. STATICFN DWORD NEAR PASCAL GetMSVideoVersion()
  369. {
  370. HANDLE h;
  371. extern DWORD FAR PASCAL VideoForWindowsVersion(void);
  372. //
  373. // don't call VideoForWindowsVersion() if it does not exist or KERNEL
  374. // will kill us with a undef dynalink error.
  375. //
  376. if ((h = GetModuleHandle(szMSVideo)) && GetProcAddress(h, (LPSTR) MAKEINTATOM(2)))
  377. return VideoForWindowsVersion();
  378. else
  379. return 0;
  380. }
  381. /***************************************************************************
  382. *
  383. * @doc INTERNAL MCIAVI
  384. *
  385. * @api DWORD | GraphicOpen | This function opens a movie file,
  386. * initializes an instance data block, and creates the default
  387. * stage window.
  388. *
  389. * @parm NPMCIGRAPHIC FAR * | lpnpMCI | Far pointer to a near pointer
  390. * to instance data block to be filled in by this function.
  391. *
  392. * @parm DWORD | dwFlags | Flags for the open message.
  393. *
  394. * @parm LPMCI_DGV_OPEN_PARMS | Parameters for the open message.
  395. *
  396. * @parm UINT | wDeviceID | The MCI Device ID for this instance.
  397. *
  398. * @rdesc Returns an MCI error code.
  399. *
  400. ***************************************************************************/
  401. DWORD PASCAL GraphicOpen (NPMCIGRAPHIC FAR * lpnpMCI, DWORD dwFlags,
  402. LPMCI_DGV_OPEN_PARMS lpOpen, UINT wDeviceID)
  403. {
  404. NPMCIGRAPHIC npMCI;
  405. DWORD dwRet;
  406. if (IsNTWOW()) {
  407. // Thunking nasties... by default we will open a 16 bit request
  408. // on the 32 bit side. Most of the time this is what is wanted.
  409. // However, there can be situations when the user must stay on the
  410. // 16 bit side (e.g. use of 16 bit drawprocs). This is not known
  411. // at this stage. Hence we provide a way through the configure
  412. // dialog for the user to tell us to reject 16 bit open calls.
  413. // The call will then return to 16 bit where it will work.
  414. // However, we provide a way for applications to override this
  415. // default.
  416. // All that is said above is good. Except not many people will notice
  417. // this little "Advanced" button ... In any event code below
  418. // uses wow32's special function to extract this needed information
  419. // (compatibility flag)
  420. #ifdef _WIN32
  421. if (WowUseMciavi16()) {
  422. DPF2(("Compat Flag -- mciavi16 should be used\n"));
  423. return(MCIERR_DEVICE_OPEN);
  424. }
  425. #endif
  426. if ((mmGetProfileInt(szIni, szReject, 0) && !(dwFlags & MCI_DGV_OPEN_32BIT))
  427. || (dwFlags & MCI_DGV_OPEN_16BIT) ) {
  428. DPF2(("Opening device on 16 bit side\n"));
  429. return MCIERR_DEVICE_OPEN; // return an error... any error
  430. }
  431. /*
  432. ** The only wow apps that I now off that specify the MCI_DGV_OPEN_PARENT
  433. ** flag are MS Dangerous Creatures and Tool Book. These apps go on to
  434. ** subclass the AVIWnd32 window. This is very bad on WOW as the
  435. ** subclassing stops all messages being processed for the AVIWnd32
  436. ** window. Therefore, I will reject all open requests that specify
  437. ** this MCI_DGV_OPEN_PARENT flag. This is pretty drastic but I don't
  438. ** know of any other way of identifying these rogue apps.
  439. **
  440. ** StephenE 16th Aug 1994.
  441. */
  442. else if (dwFlags & MCI_DGV_OPEN_PARENT) {
  443. //if (dwFlags & MCI_DGV_OPEN_32BIT) {
  444. // DPF0(("Now what are we meant to do???\n"));
  445. //}
  446. DPF2(("Failing open because APP specified MCI_DGV_OPEN_PARENT\n"));
  447. return MCIERR_DEVICE_OPEN; // return an error... any error
  448. }
  449. else {
  450. DPF2(("might be able to open device on 32 bit side\n"));
  451. }
  452. }
  453. if (dwFlags & MCI_OPEN_SHAREABLE) {
  454. if (lpOpen->lpstrElementName == NULL ||
  455. lpOpen->lpstrElementName[0] != '@') {
  456. return MCIERR_UNSUPPORTED_FUNCTION;
  457. }
  458. }
  459. //
  460. // check the verion of MSVIDEO.DLL before going any further
  461. // if we run a "new" version of MCIAVI on a old MSVIDEO.DLL
  462. // then bad things will happen. We assume all MSVIDEO.DLLs
  463. // will be backward compatible so we check for any version
  464. // greater than the expected version.
  465. //
  466. DPF(("GraphicOpen: Video For Windows Version %d.%02d.%02d.%02d\n", HIBYTE(HIWORD(GetMSVideoVersion())), LOBYTE(HIWORD(GetMSVideoVersion())), HIBYTE(LOWORD(GetMSVideoVersion())), LOBYTE(LOWORD(GetMSVideoVersion())) ));
  467. if (GetMSVideoVersion() < MSVIDEO_VERSION)
  468. {
  469. TCHAR achError[128];
  470. TCHAR ach[40];
  471. LoadString(ghModule, MCIAVI_BADMSVIDEOVERSION, achError, NUMELMS(achError));
  472. LoadString(ghModule, MCIAVI_PRODUCTNAME, ach, NUMELMS(ach));
  473. MessageBox(NULL,achError,ach,
  474. #ifdef BIDI
  475. MB_RTL_READING |
  476. #endif
  477. MB_OK|MB_SYSTEMMODAL|MB_ICONEXCLAMATION);
  478. return MCIERR_DRIVER_INTERNAL;
  479. }
  480. #ifndef _WIN32
  481. #pragma message("Support passing in MMIOHANDLEs with OPEN_ELEMENT_ID?")
  482. #endif
  483. if (lpOpen->lpstrElementName == NULL) {
  484. // they're doing an "open new".
  485. // !!! handle this, probably by not actually reading a file.
  486. // ack.
  487. }
  488. /* Be sure we have a real, non-empty filename, not an id. */
  489. if ((!(dwFlags & MCI_OPEN_ELEMENT))
  490. || (lpOpen->lpstrElementName == NULL)
  491. || (*(lpOpen->lpstrElementName) == '\0'))
  492. return MCIERR_UNSUPPORTED_FUNCTION;
  493. // Allocate an instance data block. Code ASSUMES Zero Init.
  494. if (!(npMCI = (NPMCIGRAPHIC) LocalAlloc(LPTR, sizeof (MCIGRAPHIC))))
  495. return MCIERR_OUT_OF_MEMORY;
  496. #ifdef DEBUG
  497. npMCI->mciid = MCIID;
  498. #ifdef HEARTBEAT
  499. {
  500. // Create a thread that regularly dumps the state of AVI devices.
  501. DWORD HeartBeat(LPVOID lpvThreadData);
  502. if (!hHeartBeatThread) {
  503. DWORD dwThreadId;
  504. hHeartBeatThread = CreateThread(NULL, 0, HeartBeat, (LPVOID)0, 0, &dwThreadId);
  505. if (hHeartBeatThread) {
  506. // We hold the thread handle open until we are unloaded
  507. DPF(("Created a heart beat thread, id=%x\n", dwThreadId));
  508. } else {
  509. // Errors are ignored...
  510. }
  511. }
  512. }
  513. #endif
  514. #endif
  515. //
  516. // add this device to our list
  517. //
  518. EnterList();
  519. npMCI->npMCINext = npMCIList;
  520. npMCIList = npMCI;
  521. LeaveList();
  522. npMCI->wMessageCurrent = MCI_OPEN;
  523. // Allocate some space for the filename
  524. // Copy the filename into the data block
  525. dwRet = FixFileName(npMCI, lpOpen->lpstrElementName);
  526. if (dwRet != 0L) {
  527. GraphicClose(npMCI);
  528. return dwRet;
  529. }
  530. // For the default window, the caller may
  531. // supply style and parent window. Note that the window
  532. // is now created on the background thread in mcaviTask.
  533. if (dwFlags & MCI_DGV_OPEN_PARENT) {
  534. if (!IsWindow(lpOpen->hWndParent)) {
  535. DPF(("Invalid parent window (%d) supplied\n", lpOpen->hWndParent));
  536. GraphicClose(npMCI);
  537. return(MCIERR_CREATEWINDOW);
  538. }
  539. npMCI->hwndParent = lpOpen->hWndParent;
  540. }
  541. else
  542. npMCI->hwndParent = NULL;
  543. if (dwFlags & MCI_DGV_OPEN_WS) {
  544. npMCI->dwStyle = lpOpen->dwStyle;
  545. } else {
  546. npMCI->dwStyle = WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX |
  547. WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
  548. }
  549. /* Fill in some more of the instance data.
  550. ** The rest of the fields are completed in DeviceOpen.
  551. */
  552. // see comment in graphic.h
  553. // If the default window won't be resizable, I don't think we should pay
  554. // attention to zoom by 2 or fixed % window size defaults.
  555. npMCI->fOKToUseDefaultSizing = (BOOL)((npMCI->dwStyle & WS_THICKFRAME) != 0);
  556. npMCI->hCallingTask = GetCurrentTask();
  557. npMCI->hCallback = NULL;
  558. npMCI->wDevID = wDeviceID;
  559. npMCI->hwndDefault = NULL;
  560. npMCI->hwndPlayback = NULL;
  561. npMCI->dwTimeFormat = MCI_FORMAT_FRAMES;
  562. npMCI->dwSpeedFactor = 1000;
  563. npMCI->dwVolume = MAKELONG(500, 500);
  564. npMCI->lTo = 0L;
  565. npMCI->dwFlags = MCIAVI_PLAYAUDIO | MCIAVI_SHOWVIDEO;
  566. npMCI->dwOptionFlags = ReadConfigInfo() | MCIAVIO_STRETCHTOWINDOW;
  567. // perform device-specific initialization
  568. dwRet = DeviceOpen(npMCI, dwFlags);
  569. if (dwRet != 0) {
  570. // see above - we release and delete the critsec within GraphicClose
  571. GraphicClose(npMCI);
  572. return dwRet;
  573. }
  574. // Reset these globals every time we open a device. This is better
  575. // than setting them every time we start playing...
  576. gwHurryTolerance = mmGetProfileInt(szIni, TEXT("Hurry"), 2);
  577. gwSkipTolerance = mmGetProfileInt(szIni, TEXT("Skip"), gwHurryTolerance * 2);
  578. gwMaxSkipEver = mmGetProfileInt(szIni, TEXT("MaxSkip"), max(60, gwSkipTolerance * 10));
  579. #ifdef INTERVAL_TIMES
  580. // Allocate the bucket space
  581. {
  582. LONG n = npMCI->lFrames;
  583. // Allocate bucket space for the whole movie... might be
  584. // expensive(!) so we reduce the count if no memory is
  585. // available
  586. DPF2(("Trying to allocate bucket space for %d frames\n", n));
  587. while( !(npMCI->paIntervals = LocalAlloc(LPTR, n*sizeof(LONG))) && n>10)
  588. n /= 2;
  589. if (npMCI->paIntervals) {
  590. npMCI->cIntervals = n;
  591. DPF2(("Allocated bucket space for %d frames\n", n));
  592. }
  593. }
  594. #endif
  595. *lpnpMCI = npMCI;
  596. npMCI->wMessageCurrent = 0;
  597. return 0L;
  598. }
  599. /***************************************************************************
  600. *
  601. * @doc INTERNAL MCIAVI
  602. *
  603. * @api DWORD | GraphicLoad | This function supports the MCI_LOAD command.
  604. *
  605. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  606. *
  607. * @parm DWORD | dwFlags | Flags for the Load message.
  608. *
  609. * @parm LPMCI_DGV_LOAD_PARMS | lpLoad | Parameters for the LOAD message.
  610. *
  611. * @rdesc Returns an MCI error code.
  612. *
  613. ***************************************************************************/
  614. DWORD NEAR PASCAL GraphicLoad(NPMCIGRAPHIC npMCI,
  615. DWORD dwFlags, LPMCI_DGV_LOAD_PARMS lpLoad)
  616. {
  617. return MCIERR_UNSUPPORTED_FUNCTION;
  618. }
  619. /***************************************************************************
  620. *
  621. * @doc INTERNAL MCIAVI
  622. *
  623. * @api DWORD | GraphicSeek | This function sets the current frame. The
  624. * device state after a seek is MCI_MODE_PAUSE
  625. *
  626. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  627. *
  628. * @parm DWORD | dwFlags | Flags for the seek message.
  629. *
  630. * @parm LPMCI_DGV_SEEK_PARMS | lpSeek | Parameters for the seek message.
  631. *
  632. * @rdesc Returns an MCI error code.
  633. *
  634. ***************************************************************************/
  635. DWORD NEAR PASCAL GraphicSeek (NPMCIGRAPHIC npMCI, DWORD dwFlags,
  636. LPMCI_SEEK_PARMS lpSeek)
  637. {
  638. LONG lTo;
  639. BOOL fTest = FALSE;
  640. LPARAM dwCallback = 0;
  641. /* Do some range checking then pass onto the device-specific routine. */
  642. if (dwFlags & MCI_TEST) {
  643. dwFlags &= ~(MCI_TEST);
  644. fTest = TRUE;
  645. }
  646. /* Ignore the WAIT and NOTIFY flags when parsing the seek parameters */
  647. switch (dwFlags & (~(MCI_WAIT | MCI_NOTIFY))) {
  648. case MCI_TO:
  649. lTo = ConvertToFrames(npMCI, lpSeek->dwTo);
  650. break;
  651. case MCI_SEEK_TO_START:
  652. lTo = 0;
  653. break;
  654. case MCI_SEEK_TO_END:
  655. lTo = npMCI->lFrames;
  656. break;
  657. case 0:
  658. return MCIERR_MISSING_PARAMETER;
  659. default:
  660. if (dwFlags & ~(MCI_TO |
  661. MCI_SEEK_TO_START |
  662. MCI_SEEK_TO_END |
  663. MCI_WAIT |
  664. MCI_NOTIFY))
  665. return MCIERR_UNRECOGNIZED_KEYWORD;
  666. else
  667. return MCIERR_FLAGS_NOT_COMPATIBLE;
  668. break;
  669. }
  670. if (!IsWindow(npMCI->hwndPlayback))
  671. return MCIERR_NO_WINDOW;
  672. if (lTo < 0 || lTo > npMCI->lFrames)
  673. return MCIERR_OUTOFRANGE;
  674. if (fTest)
  675. return 0L;
  676. if (dwFlags & (MCI_NOTIFY)) {
  677. dwCallback = lpSeek->dwCallback;
  678. }
  679. return DeviceSeek(npMCI, lTo, dwFlags, dwCallback);
  680. }
  681. /***************************************************************************
  682. *
  683. * @doc INTERNAL MCIAVI
  684. *
  685. * @api DWORD | GraphicCue | This function gets the movie ready to play,
  686. * but leaves it paused.
  687. *
  688. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  689. *
  690. * @parm DWORD | dwFlags | Flags for the cue message.
  691. *
  692. * @parm LPMCI_DGV_CUE_PARMS | lpCue | Parameters for the cue message.
  693. *
  694. * @rdesc Returns an MCI error code.
  695. *
  696. ***************************************************************************/
  697. DWORD NEAR PASCAL GraphicCue(NPMCIGRAPHIC npMCI, DWORD dwFlags,
  698. LPMCI_DGV_CUE_PARMS lpCue)
  699. {
  700. LONG lTo;
  701. DWORD dwRet = 0L;
  702. if (dwFlags & MCI_DGV_CUE_INPUT)
  703. return MCIERR_UNSUPPORTED_FUNCTION;
  704. if (dwFlags & MCI_DGV_CUE_NOSHOW)
  705. return MCIERR_UNSUPPORTED_FUNCTION;
  706. if (dwFlags & MCI_TO) {
  707. lTo = ConvertToFrames(npMCI, lpCue->dwTo);
  708. if (lTo < 0L || lTo > npMCI->lFrames)
  709. return MCIERR_OUTOFRANGE;
  710. }
  711. /* If the test flag is set, return without doing anything. */
  712. /* Question: do we have to check for more possible errors? */
  713. if (dwFlags & MCI_TEST)
  714. return 0L;
  715. dwRet = DeviceCue(npMCI, lTo, dwFlags, lpCue->dwCallback);
  716. return dwRet;
  717. }
  718. #ifndef _WIN32
  719. #ifdef EXPIRE
  720. //
  721. // return the current date....
  722. //
  723. // dx = year
  724. // ah = month
  725. // al = day
  726. //
  727. #pragma optimize("", off)
  728. DWORD DosGetDate(void)
  729. {
  730. if (0)
  731. return 0;
  732. _asm {
  733. mov ah,2ah
  734. int 21h
  735. mov ax,dx
  736. mov dx,cx
  737. }
  738. }
  739. #pragma optimize("", on)
  740. #endif
  741. #endif
  742. /***************************************************************************
  743. *
  744. * @doc INTERNAL MCIAVI
  745. *
  746. * @api DWORD | GraphicPlay | This function starts playback of the movie. If
  747. * the reverse flag is specified, the movie plays backwards. If the fast
  748. * or slow flags are specified the movie plays faster or slower.
  749. *
  750. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  751. *
  752. * @parm DWORD | dwFlags | Flags for the play message.
  753. *
  754. * @parm LPMCI_DGV_PLAY_PARMS | lpPlay | Parameters for the play message.
  755. *
  756. * @rdesc Returns an MCI error code.
  757. *
  758. ***************************************************************************/
  759. DWORD NEAR PASCAL GraphicPlay (NPMCIGRAPHIC npMCI, DWORD dwFlags,
  760. LPMCI_PLAY_PARMS lpPlay )
  761. {
  762. HINSTANCE hInst;
  763. TCHAR achMod[MAX_PATH];
  764. BOOL fMPlayer;
  765. #ifdef EXPIRE
  766. #pragma message("Remove the expiration code after Beta ships")
  767. if (DosGetDate() >= EXPIRE)
  768. {
  769. return MCIERR_AVI_EXPIRED;
  770. }
  771. #endif
  772. // If we haven't specifically asked for fullscreen or window, and we are
  773. // the default window, listen to the configure options and maybe force
  774. // fullscreen. We will also obey the fullscreen default for MPLAYER's
  775. // window, to make mplayer just like using the default window.
  776. hInst = GetWindowInstance(npMCI->hwndPlayback);
  777. if (hInst)
  778. GetModuleFileName(hInst, achMod, sizeof(achMod) / sizeof(achMod[0]));
  779. fMPlayer = lstrcmpi(FileName(achMod), TEXT ("MPLAY32.EXE")) == 0;
  780. if (!(dwFlags & (MCI_MCIAVI_PLAY_FULLSCREEN | MCI_MCIAVI_PLAY_WINDOW))
  781. && (npMCI->hwndPlayback == npMCI->hwndDefault || fMPlayer)) {
  782. if ((npMCI->dwOptionFlags & MCIAVIO_USEVGABYDEFAULT) ||
  783. (npMCI->rcDest.left == 0 &&
  784. npMCI->rcDest.right == GetSystemMetrics(SM_CXSCREEN)) ||
  785. (npMCI->rcDest.top == 0 &&
  786. npMCI->rcDest.bottom == GetSystemMetrics(SM_CYSCREEN))) {
  787. dwFlags |= MCI_MCIAVI_PLAY_FULLSCREEN;
  788. }
  789. }
  790. // see comment in graphic.h on npMCI->fOKToUseDefaultSizing
  791. // We're playing, which will end up showing the window
  792. // and we may want to pay attention to the registry default
  793. // sizing (zoom by 2, fixed % of screen size, etc.)
  794. // We also do this code when somebody calls "window state show".
  795. // As an extra note I should say that it's important that we
  796. // don't change it until now so that if somebody opens a file
  797. // and does a "where destination" they get the original size,
  798. // because if they're playing in their own window, it will
  799. // not be altered anyway.
  800. if (npMCI->fOKToUseDefaultSizing) {
  801. SetWindowToDefaultSize(npMCI, TRUE);
  802. ResetDestRect(npMCI, TRUE);
  803. }
  804. // Never do this again
  805. npMCI->fOKToUseDefaultSizing = FALSE;
  806. // everything else needs to be on the worker thread to be reliable.
  807. return DevicePlay(npMCI, dwFlags, lpPlay, lpPlay->dwCallback);
  808. }
  809. /***************************************************************************
  810. *
  811. * @doc INTERNAL MCIWAVE
  812. *
  813. * @api DWORD | GraphicStep | This function steps through several frames
  814. * of a movie. If the reverse flag is set, then the step is backwards.
  815. * If the step count is not specified then it defaults to 1. If the
  816. * step count plus the current position exceeds the movie length, the
  817. * step is out of range.
  818. *
  819. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  820. *
  821. * @parm DWORD | dwFlags | Flags for the step message.
  822. *
  823. * @parm LPMCI_DGV_STEP_PARMS | lpStep | Parameters for the step message.
  824. *
  825. * @rdesc Returns an MCI error code.
  826. *
  827. ***************************************************************************/
  828. DWORD NEAR PASCAL GraphicStep (NPMCIGRAPHIC npMCI, DWORD dwFlags,
  829. LPMCI_DGV_STEP_PARMS lpStep)
  830. {
  831. LONG lFrameCur;
  832. LONG lFrames;
  833. DWORD dwRet;
  834. BOOL fReverse;
  835. BOOL fSeekExactOff;
  836. fReverse = (dwFlags & MCI_DGV_STEP_REVERSE) == MCI_DGV_STEP_REVERSE;
  837. // Default to 1 frame step if frame count is not specified
  838. if (dwFlags & MCI_DGV_STEP_FRAMES) {
  839. lFrames = (LONG) lpStep->dwFrames;
  840. if (fReverse) {
  841. if (lFrames < 0)
  842. return MCIERR_FLAGS_NOT_COMPATIBLE;
  843. }
  844. } else
  845. lFrames = 1;
  846. lFrames = fReverse ? -lFrames : lFrames;
  847. /* stop before figuring out whether frame count is within range, */
  848. /* unless the TEST flag is set. */
  849. if (!(dwFlags & MCI_TEST)) {
  850. if (dwRet = DeviceStop(npMCI, MCI_WAIT))
  851. return dwRet;
  852. }
  853. if (dwRet = DevicePosition(npMCI, &lFrameCur))
  854. return dwRet;
  855. if ((lFrames + lFrameCur > npMCI->lFrames) ||
  856. (lFrames + lFrameCur < 0))
  857. return MCIERR_OUTOFRANGE;
  858. if (!IsWindow(npMCI->hwndPlayback))
  859. return MCIERR_NO_WINDOW;
  860. /* If the test flag is set, return without doing anything. */
  861. /* Question: do we have to check for more possible errors? */
  862. if (dwFlags & MCI_TEST)
  863. return 0L;
  864. fSeekExactOff = (npMCI->dwOptionFlags & MCIAVIO_SEEKEXACT) == 0;
  865. npMCI->dwOptionFlags |= MCIAVIO_SEEKEXACT;
  866. npMCI->dwFlags |= MCIAVI_NEEDTOSHOW;
  867. if (fSeekExactOff) {
  868. /* If we were not in seek exact mode, make seek finish
  869. ** before we turn seek exact back off.
  870. */
  871. dwRet = DeviceSeek(npMCI, lFrames + lFrameCur, dwFlags | MCI_WAIT,
  872. lpStep->dwCallback);
  873. npMCI->dwOptionFlags &= ~(MCIAVIO_SEEKEXACT);
  874. } else {
  875. dwRet = DeviceSeek(npMCI, lFrames + lFrameCur, dwFlags,
  876. lpStep->dwCallback);
  877. }
  878. return dwRet;
  879. }
  880. /***************************************************************************
  881. *
  882. * @doc INTERNAL MCIAVI
  883. *
  884. * @api DWORD | GraphicStop | This function stops playback of the movie.
  885. * After a stop the state will be MCI_MODE_STOP. The frame counter
  886. * is not reset.
  887. *
  888. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  889. *
  890. * @parm DWORD | dwFlags | Flags for the stop message.
  891. *
  892. * @rdesc Returns an MCI error code.
  893. *
  894. ***************************************************************************/
  895. DWORD NEAR PASCAL GraphicStop (NPMCIGRAPHIC npMCI, DWORD dwFlags,
  896. LPMCI_GENERIC_PARMS lpParms)
  897. {
  898. if (!IsWindow(npMCI->hwndPlayback))
  899. return MCIERR_NO_WINDOW;
  900. if (dwFlags & MCI_DGV_STOP_HOLD)
  901. return MCIERR_UNSUPPORTED_FUNCTION;
  902. /* If the test flag is set, return without doing anything. */
  903. /* Question: do we have to check for more possible errors? */
  904. if (dwFlags & MCI_TEST)
  905. return 0L;
  906. // this notify should be done on the worker thread if needed, but actually
  907. // I don't think we need it, since the play code will issue it (either
  908. // as an abort or as a success if it reached the right target).
  909. //GraphicDelayedNotify (npMCI, MCI_NOTIFY_ABORTED);
  910. /* Do we need to handle notify here? */
  911. /* Do we have the swing at Luton? */
  912. return DeviceStop(npMCI, dwFlags);
  913. }
  914. /***************************************************************************
  915. *
  916. * @doc INTERNAL MCIAVI
  917. *
  918. * @api DWORD | GraphicPause | Pauses movie playback.
  919. *
  920. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  921. *
  922. * @rdesc Returns an MCI error code.
  923. *
  924. ***************************************************************************/
  925. DWORD NEAR PASCAL GraphicPause(NPMCIGRAPHIC npMCI, DWORD dwFlags,
  926. LPMCI_GENERIC_PARMS lpParms)
  927. {
  928. LPARAM dwCallback;
  929. if (!IsWindow(npMCI->hwndPlayback))
  930. return MCIERR_NO_WINDOW;
  931. /* If the test flag is set, return without doing anything. */
  932. /* Question: do we have to check for more possible errors? */
  933. if (dwFlags & MCI_TEST)
  934. return 0L;
  935. if (lpParms) {
  936. dwCallback = lpParms->dwCallback;
  937. } else {
  938. dwCallback = 0;
  939. }
  940. return DevicePause(npMCI, dwFlags, dwCallback);
  941. }
  942. /***************************************************************************
  943. *
  944. * @doc INTERNAL MCIAVI
  945. *
  946. * @api DWORD | GraphicResume | This function resumes playback of a paused
  947. * movie.
  948. *
  949. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  950. *
  951. * @rdesc Returns an MCI error code.
  952. *
  953. ***************************************************************************/
  954. DWORD NEAR PASCAL GraphicResume (NPMCIGRAPHIC npMCI,
  955. DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
  956. {
  957. LPARAM dwCallback;
  958. // Resume used to be only allowed if MCIAVI is paused or playing
  959. // This is a little strange as some of the MCI commands automatically
  960. // change PAUSED into STOPPED. There is no reason why we shouldn't
  961. // treat resume as equivalent to play. (As does CDPLAYER.)
  962. //
  963. // if you decide to disagree, then don't forget that the DeviceMode()
  964. // check can only safely be done *on the worker thread*
  965. if (!IsWindow(npMCI->hwndPlayback))
  966. return MCIERR_NO_WINDOW;
  967. /* If the test flag is set, return without doing anything. */
  968. /* Question: do we have to check for more possible errors? */
  969. if (dwFlags & MCI_TEST)
  970. return 0L;
  971. if (lpParms) {
  972. dwCallback = lpParms->dwCallback;
  973. } else {
  974. dwCallback = 0;
  975. }
  976. return DeviceResume(npMCI, dwFlags & MCI_WAIT, dwCallback);
  977. }
  978. /***************************************************************************
  979. *
  980. * @doc INTERNAL MCIAVI
  981. *
  982. * @api DWORD | GraphicStatus | This function returns numeric status info.
  983. *
  984. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  985. *
  986. * @parm DWORD | dwFlags | Flags for the status message.
  987. *
  988. * @parm LPMCI_STATUS_PARMS | lpPlay | Parameters for the status message.
  989. *
  990. * @rdesc Returns an MCI error code.
  991. *
  992. ***************************************************************************/
  993. DWORD NEAR PASCAL GraphicStatus (NPMCIGRAPHIC npMCI,
  994. DWORD dwFlags, LPMCI_DGV_STATUS_PARMS lpStatus)
  995. {
  996. DWORD dwRet = 0L;
  997. if (dwFlags & (MCI_DGV_STATUS_DISKSPACE))
  998. return MCIERR_UNSUPPORTED_FUNCTION;
  999. if (dwFlags & MCI_STATUS_ITEM) {
  1000. lpStatus->dwReturn = 0L;
  1001. if ((dwFlags & MCI_TRACK) &&
  1002. !((lpStatus->dwItem == MCI_STATUS_POSITION) ||
  1003. (lpStatus->dwItem == MCI_STATUS_LENGTH)))
  1004. return MCIERR_FLAGS_NOT_COMPATIBLE;
  1005. if ((dwFlags & MCI_STATUS_START) &&
  1006. (lpStatus->dwItem != MCI_STATUS_POSITION))
  1007. return MCIERR_FLAGS_NOT_COMPATIBLE;
  1008. if (dwFlags & MCI_DGV_STATUS_REFERENCE)
  1009. return MCIERR_FLAGS_NOT_COMPATIBLE;
  1010. switch (lpStatus->dwItem) {
  1011. case MCI_STATUS_POSITION:
  1012. if (dwFlags & MCI_TRACK) {
  1013. /* POSITION with TRACK means return the start of the */
  1014. /* track. */
  1015. if (lpStatus->dwTrack != 1)
  1016. dwRet = MCIERR_OUTOFRANGE;
  1017. else
  1018. /* return start frame of track (always 0) */
  1019. lpStatus->dwReturn = 0L;
  1020. } else if (dwFlags & MCI_STATUS_START)
  1021. // POSITION with START means return the starting playable
  1022. // position of the media.
  1023. lpStatus->dwReturn = 0L;
  1024. else {
  1025. /* Otherwise return current frame */
  1026. dwRet = DevicePosition(npMCI, (LPLONG) &lpStatus->dwReturn);
  1027. lpStatus->dwReturn = ConvertFromFrames(npMCI,
  1028. (LONG) lpStatus->dwReturn);
  1029. }
  1030. break;
  1031. case MCI_STATUS_LENGTH:
  1032. if (dwFlags & MCI_TRACK && lpStatus->dwTrack != 1) {
  1033. /* LENGTH with TRACK means return the length of track */
  1034. lpStatus->dwReturn = 0L;
  1035. dwRet = MCIERR_OUTOFRANGE;
  1036. }
  1037. lpStatus->dwReturn = ConvertFromFrames(npMCI, npMCI->lFrames);
  1038. break;
  1039. case MCI_STATUS_NUMBER_OF_TRACKS:
  1040. case MCI_STATUS_CURRENT_TRACK:
  1041. lpStatus->dwReturn = 1L;
  1042. break;
  1043. case MCI_STATUS_READY:
  1044. /* Return TRUE if device can receive commands */
  1045. if (DeviceMode(npMCI) != MCI_MODE_NOT_READY)
  1046. lpStatus->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
  1047. else
  1048. lpStatus->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
  1049. dwRet = MCI_RESOURCE_RETURNED;
  1050. break;
  1051. case MCI_STATUS_MODE:
  1052. {
  1053. WORD wMode;
  1054. wMode = (WORD) DeviceMode(npMCI);
  1055. lpStatus->dwReturn = (DWORD) MAKEMCIRESOURCE(wMode, wMode);
  1056. dwRet = MCI_RESOURCE_RETURNED;
  1057. }
  1058. break;
  1059. case MCI_DGV_STATUS_PAUSE_MODE:
  1060. if (DeviceMode(npMCI) != MCI_MODE_PAUSE)
  1061. dwRet = MCIERR_NONAPPLICABLE_FUNCTION;
  1062. else {
  1063. lpStatus->dwReturn = MAKEMCIRESOURCE(MCI_MODE_PLAY, MCI_MODE_PLAY);
  1064. dwRet = MCI_RESOURCE_RETURNED;
  1065. }
  1066. break;
  1067. case MCI_STATUS_MEDIA_PRESENT:
  1068. lpStatus->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
  1069. dwRet = MCI_RESOURCE_RETURNED;
  1070. break;
  1071. case MCI_DGV_STATUS_FORWARD:
  1072. if (npMCI->dwFlags & MCIAVI_REVERSE)
  1073. lpStatus->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
  1074. else
  1075. lpStatus->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
  1076. dwRet = MCI_RESOURCE_RETURNED;
  1077. break;
  1078. case MCI_DGV_STATUS_HWND:
  1079. lpStatus->dwReturn = (DWORD_PTR)(UINT_PTR)npMCI->hwndPlayback;
  1080. if (!IsWindow(npMCI->hwndPlayback))
  1081. dwRet = MCIERR_NO_WINDOW;
  1082. break;
  1083. case MCI_DGV_STATUS_HPAL:
  1084. // lpStatus->dwReturn = (DWORD) (UINT) DrawDibGetPalette(npMCI->hdd);
  1085. lpStatus->dwReturn = 0;
  1086. if (npMCI->nVideoStreams == 0) {
  1087. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  1088. } else {
  1089. LRESULT l = ICSendMessage(npMCI->hicDraw, ICM_DRAW_GET_PALETTE, 0, 0);
  1090. if (l == ICERR_UNSUPPORTED) {
  1091. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  1092. } else {
  1093. lpStatus->dwReturn = l;
  1094. dwRet = 0;
  1095. }
  1096. }
  1097. DPF2(("Status HPAL returns: %lu\n", lpStatus->dwReturn));
  1098. break;
  1099. case MCI_STATUS_TIME_FORMAT:
  1100. lpStatus->dwReturn = MAKEMCIRESOURCE(npMCI->dwTimeFormat,
  1101. npMCI->dwTimeFormat + MCI_FORMAT_RETURN_BASE);
  1102. dwRet = MCI_RESOURCE_RETURNED;
  1103. break;
  1104. case MCI_DGV_STATUS_AUDIO:
  1105. lpStatus->dwReturn = (npMCI->dwFlags & MCIAVI_PLAYAUDIO) ?
  1106. (MAKEMCIRESOURCE(MCI_ON, MCI_ON_S)) :
  1107. (MAKEMCIRESOURCE(MCI_OFF, MCI_OFF_S));
  1108. dwRet = MCI_RESOURCE_RETURNED | MCI_RESOURCE_DRIVER;
  1109. break;
  1110. case MCI_DGV_STATUS_WINDOW_VISIBLE:
  1111. if (npMCI->hwndPlayback && IsWindowVisible(npMCI->hwndPlayback))
  1112. lpStatus->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
  1113. else
  1114. lpStatus->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
  1115. dwRet = MCI_RESOURCE_RETURNED;
  1116. break;
  1117. case MCI_DGV_STATUS_WINDOW_MINIMIZED:
  1118. if (npMCI->hwndPlayback && IsIconic(npMCI->hwndPlayback))
  1119. lpStatus->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
  1120. else
  1121. lpStatus->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
  1122. dwRet = MCI_RESOURCE_RETURNED;
  1123. break;
  1124. case MCI_DGV_STATUS_WINDOW_MAXIMIZED:
  1125. if (npMCI->hwndPlayback && IsZoomed(npMCI->hwndPlayback))
  1126. lpStatus->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
  1127. else
  1128. lpStatus->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
  1129. dwRet = MCI_RESOURCE_RETURNED;
  1130. break;
  1131. case MCI_DGV_STATUS_SAMPLESPERSEC:
  1132. case MCI_DGV_STATUS_AVGBYTESPERSEC:
  1133. case MCI_DGV_STATUS_BLOCKALIGN:
  1134. case MCI_DGV_STATUS_BITSPERSAMPLE:
  1135. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  1136. break;
  1137. case MCI_DGV_STATUS_BITSPERPEL:
  1138. if (npMCI->psiVideo)
  1139. lpStatus->dwReturn = ((LPBITMAPINFOHEADER)npMCI->psiVideo->lpFormat)->biBitCount;
  1140. else
  1141. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  1142. break;
  1143. #ifndef _WIN32
  1144. #pragma message("Are we going to support brightness/color/contrast/tint?")
  1145. #endif
  1146. case MCI_DGV_STATUS_BRIGHTNESS:
  1147. case MCI_DGV_STATUS_COLOR:
  1148. case MCI_DGV_STATUS_CONTRAST:
  1149. case MCI_DGV_STATUS_TINT:
  1150. case MCI_DGV_STATUS_GAMMA:
  1151. case MCI_DGV_STATUS_SHARPNESS:
  1152. case MCI_DGV_STATUS_FILE_MODE:
  1153. case MCI_DGV_STATUS_FILE_COMPLETION:
  1154. case MCI_DGV_STATUS_KEY_INDEX:
  1155. case MCI_DGV_STATUS_KEY_COLOR:
  1156. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  1157. break;
  1158. case MCI_DGV_STATUS_FILEFORMAT:
  1159. // Fall through to Unsupported case...
  1160. // lpStatus->dwReturn = MAKEMCIRESOURCE(MCI_DGV_FF_AVI,
  1161. // MCI_DGV_FF_AVI);
  1162. // dwRet = MCI_RESOURCE_RETURNED | MCI_RESOURCE_DRIVER;
  1163. // break;
  1164. //
  1165. case MCI_DGV_STATUS_BASS:
  1166. case MCI_DGV_STATUS_TREBLE:
  1167. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  1168. break;
  1169. case MCI_DGV_STATUS_VOLUME:
  1170. {
  1171. WORD wLeftVolume, wRightVolume;
  1172. // Be sure volume is up to date....
  1173. DeviceGetVolume(npMCI);
  1174. wLeftVolume = LOWORD(npMCI->dwVolume);
  1175. wRightVolume = LOWORD(npMCI->dwVolume);
  1176. switch (dwFlags & (MCI_DGV_STATUS_LEFT | MCI_DGV_STATUS_RIGHT)) {
  1177. case MCI_DGV_STATUS_LEFT:
  1178. lpStatus->dwReturn = (DWORD) wLeftVolume;
  1179. break;
  1180. case 0:
  1181. lpStatus->dwReturn = (DWORD) wRightVolume;
  1182. break;
  1183. default:
  1184. lpStatus->dwReturn = ((DWORD) wLeftVolume + (DWORD) wRightVolume) / 2;
  1185. break;
  1186. }
  1187. }
  1188. break;
  1189. case MCI_DGV_STATUS_MONITOR:
  1190. lpStatus->dwReturn = (DWORD)
  1191. MAKEMCIRESOURCE(MCI_DGV_MONITOR_FILE,
  1192. MCI_DGV_FILE_S);
  1193. dwRet = MCI_RESOURCE_RETURNED | MCI_RESOURCE_DRIVER;
  1194. break;
  1195. case MCI_DGV_STATUS_SEEK_EXACTLY:
  1196. lpStatus->dwReturn =
  1197. (npMCI->dwOptionFlags & MCIAVIO_SEEKEXACT) ?
  1198. (MAKEMCIRESOURCE(MCI_ON, MCI_ON_S)) :
  1199. (MAKEMCIRESOURCE(MCI_OFF, MCI_OFF_S));
  1200. dwRet = MCI_RESOURCE_RETURNED | MCI_RESOURCE_DRIVER;
  1201. break;
  1202. case MCI_DGV_STATUS_SIZE:
  1203. /* We haven't reserved any space, so return zero. */
  1204. lpStatus->dwReturn = 0L;
  1205. break;
  1206. case MCI_DGV_STATUS_SMPTE:
  1207. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  1208. break;
  1209. case MCI_DGV_STATUS_UNSAVED:
  1210. lpStatus->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
  1211. dwRet = MCI_RESOURCE_RETURNED;
  1212. break;
  1213. case MCI_DGV_STATUS_VIDEO:
  1214. lpStatus->dwReturn = (npMCI->dwFlags & MCIAVI_SHOWVIDEO) ?
  1215. (MAKEMCIRESOURCE(MCI_ON, MCI_ON_S)) :
  1216. (MAKEMCIRESOURCE(MCI_OFF, MCI_OFF_S));
  1217. dwRet = MCI_RESOURCE_RETURNED | MCI_RESOURCE_DRIVER;
  1218. break;
  1219. case MCI_DGV_STATUS_SPEED:
  1220. lpStatus->dwReturn = npMCI->dwSpeedFactor;
  1221. break;
  1222. case MCI_DGV_STATUS_FRAME_RATE:
  1223. {
  1224. DWORD dwTemp;
  1225. dwTemp = npMCI->dwMicroSecPerFrame;
  1226. /* If they haven't specifically asked for the "nominal"
  1227. ** rate of play, adjust by the current speed.
  1228. */
  1229. if (!(dwFlags & MCI_DGV_STATUS_NOMINAL))
  1230. dwTemp = muldiv32(dwTemp, 1000L, npMCI->dwSpeedFactor);
  1231. if (dwTemp == 0)
  1232. lpStatus->dwReturn = 1000;
  1233. else
  1234. /* Our return value is in "thousandths of frames/sec",
  1235. ** and dwTemp is the number of microseconds per frame.
  1236. ** Thus, we divide a billion microseconds by dwTemp.
  1237. */
  1238. lpStatus->dwReturn = muldiv32(1000000L, 1000L, dwTemp);
  1239. break;
  1240. }
  1241. case MCI_DGV_STATUS_AUDIO_STREAM:
  1242. lpStatus->dwReturn = 0;
  1243. if (npMCI->nAudioStreams) {
  1244. int stream;
  1245. for (stream = 0; stream < npMCI->streams; stream++) {
  1246. if (SH(stream).fccType == streamtypeAUDIO)
  1247. ++lpStatus->dwReturn;
  1248. if (stream == npMCI->nAudioStream)
  1249. break;
  1250. }
  1251. }
  1252. break;
  1253. case MCI_DGV_STATUS_VIDEO_STREAM:
  1254. case MCI_DGV_STATUS_AUDIO_INPUT:
  1255. case MCI_DGV_STATUS_AUDIO_RECORD:
  1256. case MCI_DGV_STATUS_AUDIO_SOURCE:
  1257. case MCI_DGV_STATUS_VIDEO_RECORD:
  1258. case MCI_DGV_STATUS_VIDEO_SOURCE:
  1259. case MCI_DGV_STATUS_VIDEO_SRC_NUM:
  1260. case MCI_DGV_STATUS_MONITOR_METHOD:
  1261. case MCI_DGV_STATUS_STILL_FILEFORMAT:
  1262. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  1263. break;
  1264. case MCI_AVI_STATUS_FRAMES_SKIPPED:
  1265. lpStatus->dwReturn = npMCI->lSkippedFrames;
  1266. break;
  1267. case MCI_AVI_STATUS_AUDIO_BREAKS:
  1268. lpStatus->dwReturn = npMCI->lAudioBreaks;
  1269. break;
  1270. case MCI_AVI_STATUS_LAST_PLAY_SPEED:
  1271. lpStatus->dwReturn = npMCI->dwSpeedPercentage;
  1272. break;
  1273. default:
  1274. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  1275. break;
  1276. } /* end switch (item) */
  1277. } else if (dwFlags & MCI_DGV_STATUS_REFERENCE) {
  1278. if (lpStatus->dwReference > (DWORD) npMCI->lFrames)
  1279. dwRet = MCIERR_OUTOFRANGE;
  1280. else if (npMCI->psiVideo) {
  1281. DWORD dwReference;
  1282. dwReference = MovieToStream(npMCI->psiVideo,
  1283. lpStatus->dwReference);
  1284. lpStatus->dwReturn = FindPrevKeyFrame(npMCI, npMCI->psiVideo,
  1285. dwReference);
  1286. lpStatus->dwReturn = StreamToMovie(npMCI->psiVideo,
  1287. (DWORD) lpStatus->dwReturn);
  1288. }
  1289. else {
  1290. lpStatus->dwReturn = 0;
  1291. }
  1292. } else /* item flag not set */
  1293. dwRet = MCIERR_MISSING_PARAMETER;
  1294. if ((dwFlags & MCI_TEST) && (LOWORD(dwRet) == 0)) {
  1295. /* There is no error, but the test flag is on. Return as little
  1296. ** as possible.
  1297. */
  1298. dwRet = 0;
  1299. lpStatus->dwReturn = 0;
  1300. }
  1301. return dwRet;
  1302. }
  1303. /***************************************************************************
  1304. *
  1305. * @doc INTERNAL MCIAVI
  1306. *
  1307. * @api DWORD | GraphicInfo | This function returns alphanumeric information.
  1308. *
  1309. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  1310. *
  1311. * @parm DWORD | dwFlags | Flags for the info. message.
  1312. *
  1313. * @parm LPMCI_INFO_PARMS | lpPlay | Parameters for the info message.
  1314. *
  1315. * @rdesc Returns an MCI error code.
  1316. *
  1317. ***************************************************************************/
  1318. DWORD NEAR PASCAL GraphicInfo(NPMCIGRAPHIC npMCI, DWORD dwFlags,
  1319. LPMCI_DGV_INFO_PARMS lpInfo)
  1320. {
  1321. DWORD dwRet = 0L;
  1322. TCHAR ch = TEXT('\0');
  1323. BOOL fTest = FALSE;
  1324. if (!lpInfo->lpstrReturn)
  1325. return MCIERR_PARAM_OVERFLOW;
  1326. if (dwFlags & MCI_TEST)
  1327. fTest = TRUE;
  1328. dwFlags &= ~(MCI_WAIT | MCI_NOTIFY | MCI_TEST);
  1329. switch (dwFlags) {
  1330. case 0L:
  1331. return MCIERR_MISSING_PARAMETER;
  1332. case MCI_INFO_FILE:
  1333. if (!npMCI)
  1334. return MCIERR_UNSUPPORTED_FUNCTION;
  1335. if (lpInfo->dwRetSize < (DWORD)(lstrlen(npMCI->szFilename) + 1)) {
  1336. ch = npMCI->szFilename[lpInfo->dwRetSize];
  1337. npMCI->szFilename[lpInfo->dwRetSize] = '\0';
  1338. dwRet = MCIERR_PARAM_OVERFLOW;
  1339. }
  1340. lstrcpy (lpInfo->lpstrReturn, npMCI->szFilename);
  1341. if (ch)
  1342. npMCI->szFilename[lpInfo->dwRetSize] = ch;
  1343. break;
  1344. case MCI_INFO_PRODUCT:
  1345. #ifdef _WIN32
  1346. {
  1347. UINT n;
  1348. #ifdef DEBUG
  1349. TCHAR versionstring[80];
  1350. #endif
  1351. n = LoadString(ghModule, MCIAVI_PRODUCTNAME, lpInfo->lpstrReturn,
  1352. (UINT)lpInfo->dwRetSize);
  1353. #ifdef DEBUG
  1354. #include "verinfo.h"
  1355. n += wsprintf(versionstring,
  1356. TEXT(" (%d.%02d.%02d)"), MMVERSION, MMREVISION, MMRELEASE);
  1357. if (n <= lpInfo->dwRetSize) {
  1358. lstrcat(lpInfo->lpstrReturn, versionstring);
  1359. }
  1360. #endif
  1361. }
  1362. #else // Win16 version follows
  1363. #ifdef DEBUG
  1364. #include "..\verinfo\usa\verinfo.h"
  1365. wsprintf(lpInfo->lpstrReturn,
  1366. TEXT("VfW %d.%02d.%02d"), MMVERSION, MMREVISION, MMRELEASE);
  1367. #else
  1368. /* !!! Not returning PARAM_OVERFLOW here but I am above - lazy eh */
  1369. LoadString(ghModule, MCIAVI_PRODUCTNAME, lpInfo->lpstrReturn,
  1370. (UINT)lpInfo->dwRetSize);
  1371. #endif
  1372. #endif
  1373. break;
  1374. case MCI_DGV_INFO_TEXT:
  1375. if (!npMCI)
  1376. return MCIERR_UNSUPPORTED_FUNCTION;
  1377. if (IsWindow(npMCI->hwndPlayback))
  1378. GetWindowText(npMCI->hwndPlayback, lpInfo->lpstrReturn,
  1379. LOWORD(lpInfo->dwRetSize));
  1380. else
  1381. dwRet = MCIERR_NO_WINDOW;
  1382. break;
  1383. case MCI_INFO_VERSION:
  1384. /* !!! Not returning PARAM_OVERFLOW here but I am above - lazy eh */
  1385. LoadString(ghModule, MCIAVI_VERSION, lpInfo->lpstrReturn,
  1386. (UINT)lpInfo->dwRetSize);
  1387. break;
  1388. case MCI_DGV_INFO_USAGE:
  1389. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  1390. break;
  1391. case MCI_DGV_INFO_ITEM:
  1392. switch (lpInfo->dwItem) {
  1393. case MCI_DGV_INFO_AUDIO_QUALITY:
  1394. case MCI_DGV_INFO_VIDEO_QUALITY:
  1395. case MCI_DGV_INFO_STILL_QUALITY:
  1396. case MCI_DGV_INFO_AUDIO_ALG:
  1397. case MCI_DGV_INFO_VIDEO_ALG:
  1398. case MCI_DGV_INFO_STILL_ALG:
  1399. default:
  1400. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  1401. break;
  1402. }
  1403. break;
  1404. default:
  1405. dwRet = MCIERR_FLAGS_NOT_COMPATIBLE;
  1406. break;
  1407. }
  1408. if (fTest && (LOWORD(dwRet) == 0)) {
  1409. /* There is no error, but the test flag is on. Return as little
  1410. ** as possible.
  1411. */
  1412. dwRet = 0;
  1413. if (lpInfo->dwRetSize)
  1414. lpInfo->lpstrReturn[0] = '\0';
  1415. }
  1416. return dwRet;
  1417. }
  1418. /***************************************************************************
  1419. *
  1420. * @doc INTERNAL MCIAVI
  1421. *
  1422. * @api DWORD | GraphicSet | This function sets various options.
  1423. *
  1424. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  1425. *
  1426. * @parm DWORD | dwFlags | Flags for the set message.
  1427. *
  1428. * @parm LPMCI_SET_PARMS | lpSet | Parameters for the set message.
  1429. *
  1430. * @rdesc Returns an MCI error code.
  1431. *
  1432. ***************************************************************************/
  1433. DWORD NEAR PASCAL GraphicSet (NPMCIGRAPHIC npMCI,
  1434. DWORD dwFlags, LPMCI_DGV_SET_PARMS lpSet)
  1435. {
  1436. DWORD dwRet = 0L;
  1437. DWORD dwAction;
  1438. if (dwFlags & MCI_DGV_SET_FILEFORMAT)
  1439. return MCIERR_UNSUPPORTED_FUNCTION;
  1440. if (dwFlags & MCI_DGV_SET_STILL)
  1441. return MCIERR_UNSUPPORTED_FUNCTION;
  1442. dwAction = dwFlags & (MCI_SET_TIME_FORMAT |
  1443. MCI_SET_VIDEO |
  1444. MCI_SET_AUDIO |
  1445. MCI_DGV_SET_SEEK_EXACTLY |
  1446. MCI_DGV_SET_SPEED
  1447. );
  1448. /* Turn off all but the following three flags */
  1449. dwFlags &= (MCI_SET_ON |
  1450. MCI_SET_OFF |
  1451. MCI_TEST
  1452. );
  1453. /* First, check if the parameters are all okay */
  1454. if (!dwAction)
  1455. return MCIERR_UNSUPPORTED_FUNCTION;
  1456. if (dwAction & MCI_SET_TIME_FORMAT) {
  1457. if (lpSet->dwTimeFormat != MCI_FORMAT_FRAMES
  1458. && lpSet->dwTimeFormat != MCI_FORMAT_MILLISECONDS)
  1459. return MCIERR_UNSUPPORTED_FUNCTION;
  1460. }
  1461. if ((dwAction & MCI_SET_AUDIO) &&
  1462. (lpSet->dwAudio != MCI_SET_AUDIO_ALL)) {
  1463. return MCIERR_UNSUPPORTED_FUNCTION;
  1464. }
  1465. if (dwAction & MCI_DGV_SET_SPEED) {
  1466. if (lpSet->dwSpeed > 100000L)
  1467. return MCIERR_OUTOFRANGE;
  1468. }
  1469. switch (dwFlags & (MCI_SET_ON | MCI_SET_OFF)) {
  1470. case 0:
  1471. if (dwAction & (MCI_SET_AUDIO |
  1472. MCI_SET_VIDEO |
  1473. MCI_DGV_SET_SEEK_EXACTLY))
  1474. return MCIERR_MISSING_PARAMETER;
  1475. break;
  1476. case MCI_SET_ON | MCI_SET_OFF:
  1477. return MCIERR_FLAGS_NOT_COMPATIBLE;
  1478. default:
  1479. if (dwAction & (MCI_DGV_SET_SPEED | MCI_SET_TIME_FORMAT))
  1480. return MCIERR_FLAGS_NOT_COMPATIBLE;
  1481. break;
  1482. }
  1483. /* If the test flag is set, return without doing anything. */
  1484. /* Question: do we have to check for more possible errors? */
  1485. if (dwFlags & MCI_TEST)
  1486. return 0L;
  1487. /* Now, actually carry out the command */
  1488. if (dwAction & MCI_SET_TIME_FORMAT)
  1489. npMCI->dwTimeFormat = lpSet->dwTimeFormat;
  1490. if (dwAction & MCI_SET_VIDEO) {
  1491. npMCI->dwFlags &= ~(MCIAVI_SHOWVIDEO);
  1492. if (dwFlags & MCI_SET_ON) {
  1493. npMCI->dwFlags |= MCIAVI_SHOWVIDEO;
  1494. InvalidateRect(npMCI->hwndPlayback, NULL, FALSE);
  1495. }
  1496. }
  1497. if (dwAction & MCI_DGV_SET_SEEK_EXACTLY) {
  1498. npMCI->dwOptionFlags &= ~(MCIAVIO_SEEKEXACT);
  1499. if (dwFlags & MCI_SET_ON)
  1500. npMCI->dwOptionFlags |= MCIAVIO_SEEKEXACT;
  1501. }
  1502. if (dwAction & MCI_DGV_SET_SPEED) {
  1503. dwRet = DeviceSetSpeed(npMCI, lpSet->dwSpeed);
  1504. }
  1505. if (dwRet == 0L && (dwAction & MCI_SET_AUDIO)) {
  1506. dwRet = DeviceMute(npMCI, dwFlags & MCI_SET_OFF ? TRUE : FALSE);
  1507. }
  1508. return dwRet;
  1509. }
  1510. /***************************************************************************
  1511. *
  1512. * @doc INTERNAL MCIAVI
  1513. *
  1514. * @api DWORD | GraphicSetAudio | This function sets various audio options.
  1515. *
  1516. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  1517. *
  1518. * @parm DWORD | dwFlags | Flags for the set audio message.
  1519. *
  1520. * @parm LPMCI_SET_PARMS | lpSet | Parameters for the set audio message.
  1521. *
  1522. * @rdesc Returns an MCI error code.
  1523. *
  1524. ***************************************************************************/
  1525. DWORD NEAR PASCAL GraphicSetAudio (NPMCIGRAPHIC npMCI,
  1526. DWORD dwFlags, LPMCI_DGV_SETAUDIO_PARMS lpSet)
  1527. {
  1528. DWORD dwRet = 0L;
  1529. if (npMCI->nAudioStreams == 0) {
  1530. return MCIERR_UNSUPPORTED_FUNCTION;
  1531. }
  1532. if ((dwFlags & MCI_DGV_SETAUDIO_ITEM) &&
  1533. (lpSet->dwItem == MCI_DGV_SETAUDIO_VOLUME) &&
  1534. (dwFlags & MCI_DGV_SETAUDIO_VALUE)) {
  1535. WORD wLeft, wRight;
  1536. if (dwFlags & (MCI_DGV_SETAUDIO_ALG |
  1537. MCI_DGV_SETAUDIO_QUALITY |
  1538. MCI_DGV_SETAUDIO_RECORD |
  1539. MCI_DGV_SETAUDIO_CLOCKTIME))
  1540. return MCIERR_UNSUPPORTED_FUNCTION;
  1541. if (lpSet->dwValue > 1000L)
  1542. return MCIERR_OUTOFRANGE;
  1543. if (dwFlags & MCI_TEST)
  1544. return 0L;
  1545. // Be sure volume is up to date....
  1546. DeviceGetVolume(npMCI);
  1547. wLeft = LOWORD(npMCI->dwVolume);
  1548. wRight = HIWORD(npMCI->dwVolume);
  1549. if (!(dwFlags & MCI_DGV_SETAUDIO_RIGHT))
  1550. wLeft = (WORD) lpSet->dwValue;
  1551. if (!(dwFlags & MCI_DGV_SETAUDIO_LEFT))
  1552. wRight = (WORD) lpSet->dwValue;
  1553. dwRet = DeviceSetVolume(npMCI, MAKELONG(wLeft, wRight));
  1554. } else if ((dwFlags & MCI_DGV_SETAUDIO_ITEM) &&
  1555. (lpSet->dwItem == MCI_DGV_SETAUDIO_STREAM) &&
  1556. (dwFlags & MCI_DGV_SETAUDIO_VALUE)) {
  1557. if (dwFlags & (MCI_DGV_SETAUDIO_ALG |
  1558. MCI_DGV_SETAUDIO_QUALITY |
  1559. MCI_DGV_SETAUDIO_RECORD |
  1560. MCI_DGV_SETAUDIO_LEFT |
  1561. MCI_DGV_SETAUDIO_CLOCKTIME |
  1562. MCI_DGV_SETAUDIO_RIGHT))
  1563. return MCIERR_UNSUPPORTED_FUNCTION;
  1564. if (lpSet->dwValue > (DWORD) npMCI->nAudioStreams || lpSet->dwValue == 0)
  1565. return MCIERR_OUTOFRANGE;
  1566. if (dwFlags & MCI_TEST)
  1567. return 0L;
  1568. dwRet = DeviceSetAudioStream(npMCI, (WORD) lpSet->dwValue);
  1569. } else if (dwFlags & (MCI_DGV_SETAUDIO_ITEM |
  1570. MCI_DGV_SETAUDIO_VALUE |
  1571. MCI_DGV_SETAUDIO_ALG |
  1572. MCI_DGV_SETAUDIO_QUALITY |
  1573. MCI_DGV_SETAUDIO_RECORD |
  1574. MCI_DGV_SETAUDIO_LEFT |
  1575. MCI_DGV_SETAUDIO_CLOCKTIME |
  1576. MCI_DGV_SETAUDIO_RIGHT))
  1577. return MCIERR_UNSUPPORTED_FUNCTION;
  1578. dwRet = 0;
  1579. switch (dwFlags & (MCI_SET_ON | MCI_SET_OFF)) {
  1580. case MCI_SET_ON | MCI_SET_OFF:
  1581. dwRet = MCIERR_FLAGS_NOT_COMPATIBLE;
  1582. break;
  1583. case MCI_SET_OFF:
  1584. dwRet = (DWORD)TRUE;
  1585. // Drop through and call DeviceMute
  1586. case MCI_SET_ON:
  1587. if (!(dwFlags & MCI_TEST))
  1588. dwRet = DeviceMute(npMCI, dwRet);
  1589. else
  1590. dwRet = 0;
  1591. break;
  1592. default:
  1593. if (!(dwFlags & MCI_DGV_SETAUDIO_ITEM))
  1594. dwRet = MCIERR_MISSING_PARAMETER;
  1595. break;
  1596. }
  1597. return dwRet;
  1598. }
  1599. /***************************************************************************
  1600. *
  1601. * @doc INTERNAL MCIAVI
  1602. *
  1603. * @api DWORD | GraphicSetVideo | This function sets various Video options.
  1604. *
  1605. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  1606. *
  1607. * @parm DWORD | dwFlags | Flags for the set video message.
  1608. *
  1609. * @parm LPMCI_SET_PARMS | lpSet | Parameters for the set video message.
  1610. *
  1611. * @rdesc Returns an MCI error code.
  1612. *
  1613. ***************************************************************************/
  1614. DWORD NEAR PASCAL GraphicSetVideo (NPMCIGRAPHIC npMCI,
  1615. DWORD dwFlags, LPMCI_DGV_SETVIDEO_PARMS lpSet)
  1616. {
  1617. DWORD dwRet = 0L;
  1618. if (dwFlags & (MCI_DGV_SETVIDEO_RECORD |
  1619. MCI_DGV_SETVIDEO_SRC_NUMBER |
  1620. MCI_DGV_SETVIDEO_QUALITY |
  1621. MCI_DGV_SETVIDEO_ALG |
  1622. MCI_DGV_SETVIDEO_STILL |
  1623. MCI_DGV_SETVIDEO_CLOCKTIME
  1624. ))
  1625. return MCIERR_UNSUPPORTED_FUNCTION;
  1626. if ((dwFlags & MCI_DGV_SETVIDEO_OVER) &&
  1627. (lpSet->dwItem != MCI_AVI_SETVIDEO_PALETTE_COLOR))
  1628. return MCIERR_UNSUPPORTED_FUNCTION;
  1629. if (dwFlags & MCI_DGV_SETVIDEO_ITEM) {
  1630. switch (lpSet->dwItem) {
  1631. case MCI_AVI_SETVIDEO_PALETTE_COLOR:
  1632. if (!(dwFlags & MCI_DGV_SETVIDEO_OVER))
  1633. return MCIERR_MISSING_PARAMETER;
  1634. if (lpSet->dwOver >= npMCI->pbiFormat->biClrUsed) {
  1635. return MCIERR_OUTOFRANGE;
  1636. }
  1637. return DeviceSetPaletteColor(npMCI,
  1638. lpSet->dwOver,
  1639. lpSet->dwValue);
  1640. case MCI_DGV_SETVIDEO_PALHANDLE:
  1641. if (dwFlags & MCI_DGV_SETVIDEO_VALUE) {
  1642. if (lpSet->dwValue &&
  1643. lpSet->dwValue != MCI_AVI_SETVIDEO_PALETTE_HALFTONE &&
  1644. GetObjectType((HPALETTE) lpSet->dwValue) != OBJ_PAL)
  1645. return MCIERR_AVI_BADPALETTE;
  1646. }
  1647. if (!(dwFlags & MCI_TEST))
  1648. dwRet = DeviceSetPalette(npMCI,
  1649. ((dwFlags & MCI_DGV_SETVIDEO_VALUE) ?
  1650. (HPALETTE) lpSet->dwValue : NULL));
  1651. break;
  1652. case MCI_DGV_SETVIDEO_STREAM:
  1653. if (!(dwFlags & MCI_DGV_SETVIDEO_VALUE))
  1654. return MCIERR_UNSUPPORTED_FUNCTION;
  1655. if (lpSet->dwValue == 0 ||
  1656. lpSet->dwValue > (DWORD)npMCI->nVideoStreams + npMCI->nOtherStreams)
  1657. return MCIERR_OUTOFRANGE;
  1658. if (dwFlags & MCI_SET_ON)
  1659. DPF(("SetVideoStream to #%d on\n", (int)lpSet->dwValue));
  1660. else if (dwFlags & MCI_SET_OFF)
  1661. DPF(("SetVideoStream to #%d off\n", (int)lpSet->dwValue));
  1662. else
  1663. DPF(("SetVideoStream to #%d\n", (int)lpSet->dwValue));
  1664. if (!(dwFlags & MCI_TEST)) {
  1665. dwRet = DeviceSetVideoStream(npMCI, (UINT)lpSet->dwValue,
  1666. !(dwFlags & MCI_SET_OFF));
  1667. }
  1668. break;
  1669. case MCI_AVI_SETVIDEO_DRAW_PROCEDURE:
  1670. if (DeviceMode(npMCI) != MCI_MODE_STOP)
  1671. return MCIERR_UNSUPPORTED_FUNCTION;
  1672. if (npMCI->hicDrawDefault) {
  1673. if (npMCI->hicDrawDefault != (HIC) -1)
  1674. ICClose(npMCI->hicDrawDefault);
  1675. npMCI->hicDrawDefault = 0;
  1676. npMCI->dwFlags &= ~(MCIAVI_USERDRAWPROC);
  1677. }
  1678. if (lpSet->dwValue) {
  1679. if (IsBadCodePtr((FARPROC) lpSet->dwValue)) {
  1680. DPF(("Bad code pointer!!!!\n"));
  1681. return MCIERR_OUTOFRANGE; //!!!MCIERR_BAD_PARAM;
  1682. }
  1683. npMCI->hicDrawDefault = ICOpenFunction(streamtypeVIDEO,
  1684. FOURCC_AVIDraw,ICMODE_DRAW,(FARPROC) lpSet->dwValue);
  1685. if (!npMCI->hicDrawDefault) {
  1686. return MCIERR_INTERNAL;
  1687. }
  1688. DPF(("Successfully set new draw procedure....\n"));
  1689. npMCI->dwFlags |= MCIAVI_USERDRAWPROC;
  1690. }
  1691. npMCI->dwFlags |= MCIAVI_NEEDDRAWBEGIN;
  1692. InvalidateRect(npMCI->hwndPlayback, NULL, FALSE);
  1693. return 0;
  1694. default:
  1695. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  1696. break;
  1697. }
  1698. } else if (dwFlags & (MCI_SET_ON | MCI_SET_OFF)) {
  1699. switch (dwFlags & (MCI_SET_ON | MCI_SET_OFF)) {
  1700. case MCI_SET_ON:
  1701. if (!(dwFlags & MCI_TEST)) {
  1702. InvalidateRect(npMCI->hwndPlayback, NULL, FALSE);
  1703. npMCI->dwFlags |= MCIAVI_SHOWVIDEO;
  1704. }
  1705. break;
  1706. case MCI_SET_OFF:
  1707. if (!(dwFlags & MCI_TEST))
  1708. npMCI->dwFlags &= ~(MCIAVI_SHOWVIDEO);
  1709. break;
  1710. case MCI_SET_ON | MCI_SET_OFF:
  1711. dwRet = MCIERR_FLAGS_NOT_COMPATIBLE;
  1712. break;
  1713. }
  1714. } else
  1715. dwRet = MCIERR_MISSING_PARAMETER;
  1716. return dwRet;
  1717. }
  1718. /***************************************************************************
  1719. *
  1720. * @doc INTERNAL MCIAVI
  1721. *
  1722. * @api DWORD | GraphicSignal | This function sets signals.
  1723. *
  1724. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  1725. *
  1726. * @parm DWORD | dwFlags | Flags for the set PositionAdvise message.
  1727. *
  1728. * @parm LPMCI_SIGNAL_PARMS | lpSignal | Parameters for the signal
  1729. * message.
  1730. *
  1731. * @rdesc Returns an MCI error code.
  1732. *
  1733. ***************************************************************************/
  1734. DWORD NEAR PASCAL GraphicSignal(NPMCIGRAPHIC npMCI,
  1735. DWORD dwFlags, LPMCI_DGV_SIGNAL_PARMS lpSignal)
  1736. {
  1737. DWORD dwRet = 0L;
  1738. DWORD dwUser;
  1739. DWORD dwPosition;
  1740. DWORD dwPeriod;
  1741. dwUser = (dwFlags & MCI_DGV_SIGNAL_USERVAL) ? lpSignal->dwUserParm : 0L;
  1742. if (dwFlags & MCI_DGV_SIGNAL_CANCEL) {
  1743. if (dwFlags & (MCI_DGV_SIGNAL_AT |
  1744. MCI_DGV_SIGNAL_EVERY |
  1745. MCI_DGV_SIGNAL_POSITION))
  1746. return MCIERR_FLAGS_NOT_COMPATIBLE;
  1747. if (!npMCI->dwSignals)
  1748. return MCIERR_NONAPPLICABLE_FUNCTION;
  1749. if (dwUser && (npMCI->signal.dwUserParm != dwUser))
  1750. return MCIERR_NONAPPLICABLE_FUNCTION;
  1751. if (!(dwFlags & MCI_TEST))
  1752. --npMCI->dwSignals;
  1753. } else {
  1754. if ((npMCI->dwSignals != 0) && (dwUser != npMCI->signal.dwUserParm)) {
  1755. /* !!! Should we allow more than one signal? */
  1756. return MCIERR_DGV_DEVICE_LIMIT;
  1757. }
  1758. if (dwFlags & MCI_DGV_SIGNAL_AT) {
  1759. /* Use position passed in */
  1760. dwPosition = ConvertToFrames(npMCI, lpSignal->dwPosition);
  1761. if (dwPosition > (DWORD) npMCI->lFrames)
  1762. return MCIERR_OUTOFRANGE;
  1763. } else {
  1764. /* Get current position */
  1765. DevicePosition(npMCI, (LPLONG) &dwPosition);
  1766. }
  1767. if (dwFlags & MCI_DGV_SIGNAL_EVERY) {
  1768. dwPeriod = (DWORD) ConvertToFrames(npMCI, lpSignal->dwPeriod);
  1769. if (dwPeriod == 0 || (dwPeriod > (DWORD) npMCI->lFrames))
  1770. return MCIERR_OUTOFRANGE;
  1771. } else {
  1772. /* It's a one-time signal */
  1773. dwPeriod = 0L;
  1774. }
  1775. if (dwFlags & MCI_TEST)
  1776. return 0;
  1777. npMCI->signal.dwPosition = dwPosition;
  1778. npMCI->signal.dwPeriod = dwPeriod;
  1779. npMCI->signal.dwUserParm = dwUser;
  1780. npMCI->signal.dwCallback = lpSignal->dwCallback;
  1781. npMCI->dwSignalFlags = dwFlags;
  1782. /* The signal isn't really activated until we do this. */
  1783. if (!npMCI->dwSignals)
  1784. ++npMCI->dwSignals;
  1785. }
  1786. return 0L;
  1787. }
  1788. /***************************************************************************
  1789. *
  1790. * @doc INTERNAL MCIAVI
  1791. *
  1792. * @api DWORD | GraphicList | This function supports the MCI_LIST command.
  1793. *
  1794. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  1795. *
  1796. * @parm DWORD | dwFlags | Flags for the List message.
  1797. *
  1798. * @parm LPMCI_DGV_LIST_PARMS | lpList | Parameters for the list message.
  1799. *
  1800. * @rdesc Returns an MCI error code.
  1801. *
  1802. ***************************************************************************/
  1803. DWORD NEAR PASCAL GraphicList(NPMCIGRAPHIC npMCI,
  1804. DWORD dwFlags, LPMCI_DGV_LIST_PARMS lpList)
  1805. {
  1806. return MCIERR_UNSUPPORTED_FUNCTION;
  1807. }
  1808. /***************************************************************************
  1809. *
  1810. * @doc INTERNAL MCIAVI
  1811. *
  1812. * @api DWORD | GraphicGetDevCaps | This function returns device
  1813. * capabilities
  1814. *
  1815. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  1816. *
  1817. * @parm DWORD | dwFlags | Flags for the GetDevCaps message.
  1818. *
  1819. * @parm LPMCI_GETDEVCAPS_PARMS | lpCaps | Parameters for the GetDevCaps
  1820. * message.
  1821. *
  1822. * @rdesc Returns an MCI error code.
  1823. *
  1824. ***************************************************************************/
  1825. DWORD NEAR PASCAL GraphicGetDevCaps (NPMCIGRAPHIC npMCI,
  1826. DWORD dwFlags, LPMCI_GETDEVCAPS_PARMS lpCaps )
  1827. {
  1828. DWORD dwRet = 0L;
  1829. if (dwFlags & MCI_GETDEVCAPS_ITEM)
  1830. {
  1831. switch (lpCaps->dwItem)
  1832. {
  1833. case MCI_GETDEVCAPS_CAN_RECORD:
  1834. case MCI_GETDEVCAPS_CAN_EJECT:
  1835. case MCI_GETDEVCAPS_CAN_SAVE:
  1836. case MCI_DGV_GETDEVCAPS_CAN_LOCK:
  1837. case MCI_DGV_GETDEVCAPS_CAN_STR_IN:
  1838. case MCI_DGV_GETDEVCAPS_CAN_FREEZE:
  1839. case MCI_DGV_GETDEVCAPS_HAS_STILL:
  1840. lpCaps->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
  1841. dwRet = MCI_RESOURCE_RETURNED;
  1842. break;
  1843. case MCI_DGV_GETDEVCAPS_CAN_REVERSE:
  1844. case MCI_GETDEVCAPS_CAN_PLAY:
  1845. case MCI_GETDEVCAPS_HAS_AUDIO:
  1846. case MCI_GETDEVCAPS_HAS_VIDEO:
  1847. case MCI_GETDEVCAPS_USES_FILES:
  1848. case MCI_GETDEVCAPS_COMPOUND_DEVICE:
  1849. case MCI_DGV_GETDEVCAPS_PALETTES:
  1850. case MCI_DGV_GETDEVCAPS_CAN_STRETCH:
  1851. case MCI_DGV_GETDEVCAPS_CAN_TEST:
  1852. lpCaps->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
  1853. dwRet = MCI_RESOURCE_RETURNED;
  1854. break;
  1855. case MCI_GETDEVCAPS_DEVICE_TYPE:
  1856. lpCaps->dwReturn = MAKEMCIRESOURCE(MCI_DEVTYPE_DIGITAL_VIDEO,
  1857. MCI_DEVTYPE_DIGITAL_VIDEO);
  1858. dwRet = MCI_RESOURCE_RETURNED;
  1859. break;
  1860. case MCI_DGV_GETDEVCAPS_MAX_WINDOWS:
  1861. case MCI_DGV_GETDEVCAPS_MAXIMUM_RATE:
  1862. case MCI_DGV_GETDEVCAPS_MINIMUM_RATE:
  1863. default:
  1864. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  1865. break;
  1866. }
  1867. }
  1868. else
  1869. dwRet = MCIERR_MISSING_PARAMETER;
  1870. if ((dwFlags & MCI_TEST) && (LOWORD(dwRet) == 0)) {
  1871. /* There is no error, but the test flag is on. Return as little
  1872. ** as possible.
  1873. */
  1874. dwRet = 0;
  1875. lpCaps->dwReturn = 0;
  1876. }
  1877. return (dwRet);
  1878. }
  1879. /***************************************************************************
  1880. *
  1881. * @doc INTERNAL MCIAVI
  1882. *
  1883. * @api DWORD | GraphicWindow | This function controls the stage window
  1884. *
  1885. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  1886. *
  1887. * @parm DWORD | dwFlags | Flags for the window message.
  1888. *
  1889. * @parm LPMCI_DGV_WINDOW_PARMS | lpPlay | Parameters for the window message.
  1890. *
  1891. * @rdesc Returns an MCI error code.
  1892. *
  1893. ***************************************************************************/
  1894. DWORD NEAR PASCAL GraphicWindow (NPMCIGRAPHIC npMCI, DWORD dwFlags,
  1895. LPMCI_DGV_WINDOW_PARMS lpWindow)
  1896. {
  1897. DWORD dwRet = 0L;
  1898. int i = 0;
  1899. HWND hWndNew;
  1900. if (dwFlags & MCI_DGV_WINDOW_HWND) {
  1901. // Set a new stage window. If the parameter is NULL, then
  1902. // use the default window. Otherwise, hide the default
  1903. // window and use the given window handle.
  1904. if (!lpWindow->hWnd)
  1905. hWndNew = npMCI->hwndDefault;
  1906. else
  1907. hWndNew = lpWindow->hWnd;
  1908. if (!IsWindow(hWndNew))
  1909. return MCIERR_NO_WINDOW;
  1910. /* If the test flag is set, return without doing anything. */
  1911. /* Question: do we have to check for more possible errors? */
  1912. if (dwFlags & MCI_TEST)
  1913. return 0L;
  1914. // only change if the new window handle is different from the current
  1915. // stage window handle
  1916. if (hWndNew != npMCI->hwndPlayback) {
  1917. dwRet = DeviceSetWindow(npMCI, hWndNew);
  1918. if (npMCI->hwndPlayback != npMCI->hwndDefault) {
  1919. // see comment in graphic.h
  1920. // They've specified their own window for playback. Don't use
  1921. // the default registry sizing
  1922. npMCI->fOKToUseDefaultSizing = FALSE;
  1923. if (IsWindow(npMCI->hwndDefault))
  1924. ShowWindow(npMCI->hwndDefault, SW_HIDE);
  1925. }
  1926. }
  1927. }
  1928. /* If the test flag is set, return without doing anything. */
  1929. /* Question: do we have to check for more possible errors? */
  1930. if (dwFlags & MCI_TEST)
  1931. return dwRet;
  1932. if (!dwRet) {
  1933. if (IsWindow(npMCI->hwndPlayback)) {
  1934. if (dwFlags & MCI_DGV_WINDOW_STATE) {
  1935. // see comment in graphic.h on npMCI->fOKToUseDefaultSizing
  1936. // This is the moment of truth. We're showing the window
  1937. // and we may want to pay attention to the registry default
  1938. // sizing (zoom by 2, fixed % of screen size, etc.)
  1939. // As an extra note I should say that it's important that we
  1940. // don't change it until now so that if somebody opens a file
  1941. // and does a "where destination" they get the original size,
  1942. // because if they're playing in their own window, it will
  1943. // not be altered anyway.
  1944. if (lpWindow->nCmdShow != SW_HIDE) {
  1945. if (npMCI->fOKToUseDefaultSizing) {
  1946. SetWindowToDefaultSize(npMCI, TRUE);
  1947. ResetDestRect(npMCI, TRUE);
  1948. }
  1949. // Never do this again
  1950. npMCI->fOKToUseDefaultSizing = FALSE;
  1951. }
  1952. ShowWindow (npMCI->hwndPlayback, lpWindow->nCmdShow);
  1953. }
  1954. if (dwFlags & MCI_DGV_WINDOW_TEXT)
  1955. SetWindowText(npMCI->hwndPlayback, lpWindow->lpstrText);
  1956. } else
  1957. dwRet = MCIERR_NO_WINDOW;
  1958. }
  1959. return dwRet;
  1960. }
  1961. /***************************************************************************
  1962. *
  1963. * @doc INTERNAL MCIAVI
  1964. *
  1965. * @api DWORD | GraphicPut | This function sets the offset and extent
  1966. * of the animation within the client area of the stage window.
  1967. *
  1968. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  1969. *
  1970. * @parm DWORD | dwFlags | Flags for the put message.
  1971. *
  1972. * @parm LPMCI_DGV_RECT_PARMS | lpDestination | Parameters for the
  1973. * destination message.
  1974. *
  1975. * @rdesc Returns an MCI error code.
  1976. *
  1977. ***************************************************************************/
  1978. DWORD NEAR PASCAL GraphicPut ( NPMCIGRAPHIC npMCI,
  1979. DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms)
  1980. {
  1981. BOOL frc;
  1982. RECT rc;
  1983. if (dwFlags & (MCI_DGV_PUT_FRAME | MCI_DGV_PUT_VIDEO))
  1984. return MCIERR_UNSUPPORTED_FUNCTION;
  1985. frc = (dwFlags & MCI_DGV_RECT) == MCI_DGV_RECT;
  1986. if (!IsWindow(npMCI->hwndPlayback))
  1987. return MCIERR_NO_WINDOW;
  1988. switch (dwFlags & (MCI_DGV_PUT_SOURCE | MCI_DGV_PUT_DESTINATION |
  1989. MCI_DGV_PUT_WINDOW)) {
  1990. case 0L:
  1991. return MCIERR_MISSING_PARAMETER;
  1992. case MCI_DGV_PUT_SOURCE:
  1993. // If a rectangle is supplied, use it.
  1994. if (frc) {
  1995. rc.left = lpParms->ptOffset.x;
  1996. rc.top = lpParms->ptOffset.y;
  1997. rc.right = lpParms->ptOffset.x + lpParms->ptExtent.x;
  1998. rc.bottom = lpParms->ptOffset.y + lpParms->ptExtent.y;
  1999. DPF2(("GraphicPut_Source: rc [%d %d %d %d]\n", rc));
  2000. if (lpParms->ptExtent.x <= 0) {
  2001. rc.right = rc.left + (npMCI->rcDest.right - npMCI->rcDest.left);
  2002. }
  2003. if (lpParms->ptExtent.y <= 0) {
  2004. rc.bottom = rc.top + (npMCI->rcDest.bottom - npMCI->rcDest.top);
  2005. }
  2006. } else {
  2007. /* Reset to default */
  2008. rc = npMCI->rcMovie;
  2009. DPF2(("GraphicPut_Source (default): rc [%d %d %d %d]\n", rc));
  2010. }
  2011. break;
  2012. case MCI_DGV_PUT_DESTINATION:
  2013. // If a rectangle is supplied, use it.
  2014. if (frc) {
  2015. rc.left = lpParms->ptOffset.x;
  2016. rc.top = lpParms->ptOffset.y;
  2017. rc.right = lpParms->ptOffset.x + lpParms->ptExtent.x;
  2018. rc.bottom = lpParms->ptOffset.y + lpParms->ptExtent.y;
  2019. DPF2(("GraphicPut_Destination: rc [%d %d %d %d]\n", rc));
  2020. if (lpParms->ptExtent.x <= 0) {
  2021. rc.right = rc.left + (npMCI->rcDest.right - npMCI->rcDest.left);
  2022. }
  2023. if (lpParms->ptExtent.y <= 0) {
  2024. rc.bottom = rc.top + (npMCI->rcDest.bottom - npMCI->rcDest.top);
  2025. }
  2026. } else {
  2027. /* Reset to size of stage window */
  2028. GetClientRect(npMCI->hwndPlayback, &rc);
  2029. DPF2(("GraphicPut_Destination (default): rc [%d %d %d %d]\n", rc));
  2030. }
  2031. break;
  2032. case MCI_DGV_PUT_WINDOW:
  2033. if (dwFlags & MCI_TEST)
  2034. return 0L;
  2035. // De-minimize their window, so we don't end up with
  2036. // a giant icon....
  2037. if (IsIconic(npMCI->hwndPlayback))
  2038. ShowWindow(npMCI->hwndPlayback, SW_RESTORE);
  2039. // If a rectangle is supplied, use it.
  2040. if (frc) {
  2041. RECT rcOld;
  2042. rc.left = lpParms->ptOffset.x;
  2043. rc.right = lpParms->ptOffset.x + lpParms->ptExtent.x;
  2044. rc.top = lpParms->ptOffset.y;
  2045. rc.bottom = lpParms->ptOffset.y + lpParms->ptExtent.y;
  2046. if (dwFlags & MCI_DGV_PUT_CLIENT) {
  2047. AdjustWindowRect(&rc,
  2048. GetWindowLong(npMCI->hwndPlayback, GWL_STYLE),
  2049. FALSE);
  2050. }
  2051. // Default to just moving if width, height == 0....
  2052. GetWindowRect(npMCI->hwndPlayback, &rcOld);
  2053. if (lpParms->ptExtent.x <= 0) {
  2054. rc.right = rc.left + (rcOld.right - rcOld.left);
  2055. }
  2056. if (lpParms->ptExtent.y <= 0) {
  2057. rc.bottom = rc.top + (rcOld.bottom - rcOld.top);
  2058. }
  2059. MoveWindow(npMCI->hwndPlayback,
  2060. rc.left, rc.top,
  2061. rc.right - rc.left, rc.bottom - rc.top, TRUE);
  2062. } else {
  2063. // !!! What should we do if there's no rectangle?
  2064. /* Reset to "natural" size? */
  2065. rc = npMCI->rcMovie;
  2066. if (npMCI->dwOptionFlags & MCIAVIO_ZOOMBY2)
  2067. SetRect(&rc, 0, 0, rc.right*2, rc.bottom*2);
  2068. AdjustWindowRect(&rc, GetWindowLong(npMCI->hwndPlayback, GWL_STYLE),
  2069. FALSE);
  2070. SetWindowPos(npMCI->hwndPlayback, NULL, 0, 0,
  2071. rc.right - rc.left, rc.bottom - rc.top,
  2072. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  2073. }
  2074. // Premiere 1.0 depends on the window always being visible
  2075. // after a PUT_WINDOW command. Make it so.
  2076. ShowWindow(npMCI->hwndPlayback, SW_RESTORE);
  2077. return 0L;
  2078. default:
  2079. return MCIERR_FLAGS_NOT_COMPATIBLE;
  2080. }
  2081. if (dwFlags & MCI_DGV_PUT_CLIENT)
  2082. return MCIERR_FLAGS_NOT_COMPATIBLE;
  2083. /* If the test flag is set, return without doing anything. */
  2084. /* Question: do we have to check for more possible errors? */
  2085. if (dwFlags & MCI_TEST)
  2086. return 0L;
  2087. // see comment in graphic.h
  2088. // Any "put" command is dicking with the playback window and I think that's
  2089. // grounds to not use the default window sizing.
  2090. npMCI->fOKToUseDefaultSizing = FALSE;
  2091. return DevicePut(npMCI, &rc, dwFlags);
  2092. }
  2093. /***************************************************************************
  2094. *
  2095. * @doc INTERNAL MCIAVI
  2096. *
  2097. * @api DWORD | GraphicWhere | This function returns the current
  2098. * source and destination rectangles, in offset/extent form.
  2099. *
  2100. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  2101. *
  2102. * @parm DWORD | dwFlags | Flags for the query source message.
  2103. *
  2104. * @parm LPMCI_DGV_RECT_PARMS | lpParms | Parameters for the message.
  2105. *
  2106. * @rdesc Returns an MCI error code.
  2107. *
  2108. ***************************************************************************/
  2109. DWORD NEAR PASCAL GraphicWhere(NPMCIGRAPHIC npMCI, DWORD dwFlags,
  2110. LPMCI_DGV_RECT_PARMS lpParms)
  2111. {
  2112. RECT rc;
  2113. if (dwFlags & (MCI_DGV_WHERE_FRAME | MCI_DGV_WHERE_VIDEO))
  2114. return MCIERR_UNSUPPORTED_FUNCTION;
  2115. // !!! WHERE_WINDOW?
  2116. switch (dwFlags & (MCI_DGV_WHERE_SOURCE | MCI_DGV_WHERE_DESTINATION |
  2117. MCI_DGV_WHERE_WINDOW)) {
  2118. case 0L:
  2119. return MCIERR_MISSING_PARAMETER;
  2120. case MCI_DGV_WHERE_SOURCE:
  2121. if (dwFlags & MCI_DGV_WHERE_MAX) {
  2122. lpParms->ptOffset.x = npMCI->rcMovie.left;
  2123. lpParms->ptOffset.y = npMCI->rcMovie.top;
  2124. lpParms->ptExtent.x = npMCI->rcMovie.right - npMCI->rcMovie.left;
  2125. lpParms->ptExtent.y = npMCI->rcMovie.bottom - npMCI->rcMovie.top;
  2126. DPF2(("Where source (max): [%d, %d, %d, %d]\n", npMCI->rcMovie));
  2127. } else {
  2128. lpParms->ptOffset.x = npMCI->rcSource.left;
  2129. lpParms->ptOffset.y = npMCI->rcSource.top;
  2130. lpParms->ptExtent.x = npMCI->rcSource.right - npMCI->rcSource.left;
  2131. lpParms->ptExtent.y = npMCI->rcSource.bottom - npMCI->rcSource.top;
  2132. DPF2(("Where source: [%d, %d, %d, %d]\n", npMCI->rcSource));
  2133. }
  2134. break;
  2135. case MCI_DGV_WHERE_DESTINATION:
  2136. if (dwFlags & MCI_DGV_WHERE_MAX) {
  2137. /* Return size of window */
  2138. GetClientRect(npMCI->hwndPlayback, &rc);
  2139. lpParms->ptOffset.x = 0;
  2140. lpParms->ptOffset.y = 0;
  2141. lpParms->ptExtent.x = rc.right;
  2142. lpParms->ptExtent.y = rc.bottom;
  2143. DPF2(("Where destination (max): [%d, %d, %d, %d]\n", rc));
  2144. } else {
  2145. /* Return current destination size */
  2146. lpParms->ptOffset.x = npMCI->rcDest.left;
  2147. lpParms->ptOffset.y = npMCI->rcDest.top;
  2148. lpParms->ptExtent.x = npMCI->rcDest.right - npMCI->rcDest.left;
  2149. lpParms->ptExtent.y = npMCI->rcDest.bottom - npMCI->rcDest.top;
  2150. DPF2(("Where destination: [%d, %d, %d, %d]\n", npMCI->rcDest));
  2151. }
  2152. break;
  2153. case MCI_DGV_WHERE_WINDOW:
  2154. if (dwFlags & MCI_DGV_WHERE_MAX) {
  2155. /* Return maximum size of window */
  2156. GetClientRect(npMCI->hwndPlayback, &rc);
  2157. lpParms->ptOffset.x = 0;
  2158. lpParms->ptOffset.y = 0;
  2159. lpParms->ptExtent.x = GetSystemMetrics(SM_CXSCREEN);
  2160. lpParms->ptExtent.y = GetSystemMetrics(SM_CYSCREEN);
  2161. } else {
  2162. /* Return size of window */
  2163. GetWindowRect(npMCI->hwndPlayback, &rc);
  2164. lpParms->ptOffset.x = rc.left;
  2165. lpParms->ptOffset.y = rc.top;
  2166. lpParms->ptExtent.x = rc.right - rc.left;
  2167. lpParms->ptExtent.y = rc.bottom - rc.top;
  2168. }
  2169. break;
  2170. default:
  2171. return MCIERR_FLAGS_NOT_COMPATIBLE;
  2172. }
  2173. return 0L;
  2174. }
  2175. /***************************************************************************
  2176. *
  2177. * @doc INTERNAL MCIAVI
  2178. *
  2179. * @api DWORD | GraphicRealize | This function realizes the current palette
  2180. *
  2181. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  2182. *
  2183. * @parm DWORD | dwFlags | Flags for the message.
  2184. *
  2185. * @rdesc Returns an MCI error code.
  2186. *
  2187. ***************************************************************************/
  2188. DWORD NEAR PASCAL GraphicRealize(NPMCIGRAPHIC npMCI, DWORD dwFlags)
  2189. {
  2190. /* If the test flag is set, return without doing anything. */
  2191. /* Question: do we have to check for more possible errors? */
  2192. if (dwFlags & MCI_TEST)
  2193. return 0L;
  2194. npMCI->fForceBackground = (dwFlags & MCI_DGV_REALIZE_BKGD) != 0;
  2195. return DeviceRealize(npMCI);
  2196. }
  2197. /***************************************************************************
  2198. *
  2199. * @doc INTERNAL MCIAVI
  2200. *
  2201. * @api DWORD | GraphicUpdate | This function refreshes the current frame.
  2202. *
  2203. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  2204. *
  2205. * @parm DWORD | dwFlags | Flags for the message.
  2206. *
  2207. * @parm LPMCI_DGV_UPDATE_PARMS | lpParms | Parameters for the message.
  2208. *
  2209. * @rdesc Returns an MCI error code.
  2210. *
  2211. ***************************************************************************/
  2212. DWORD NEAR PASCAL GraphicUpdate(NPMCIGRAPHIC npMCI, DWORD dwFlags,
  2213. LPMCI_DGV_UPDATE_PARMS lpParms)
  2214. {
  2215. RECT rc;
  2216. rc.left = lpParms->ptOffset.x;
  2217. rc.top = lpParms->ptOffset.y;
  2218. rc.right = lpParms->ptOffset.x + lpParms->ptExtent.x;
  2219. rc.bottom = lpParms->ptOffset.y + lpParms->ptExtent.y;
  2220. if (!(dwFlags & MCI_DGV_UPDATE_HDC)) {
  2221. InvalidateRect(npMCI->hwndPlayback, (dwFlags & MCI_DGV_RECT) ? &rc : NULL, TRUE);
  2222. // this will cause the winproc thread to do the repaint now
  2223. UpdateWindow(npMCI->hwndPlayback);
  2224. return 0;
  2225. }
  2226. /* If the test flag is set, return without doing anything. */
  2227. /* Question: do we have to check for more possible errors? */
  2228. if (dwFlags & MCI_TEST)
  2229. return 0L;
  2230. return DeviceUpdate (npMCI, dwFlags, lpParms);
  2231. }
  2232. /***************************************************************************
  2233. *
  2234. * @doc INTERNAL MCIAVI
  2235. *
  2236. * @api DWORD | GraphicConfig | This function brings up the configure dialog.
  2237. *
  2238. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  2239. *
  2240. * @parm DWORD | dwFlags | Flags for the message.
  2241. * The only flag bit checked is MCI_TEST
  2242. *
  2243. * @rdesc Returns 0.
  2244. *
  2245. ***************************************************************************/
  2246. DWORD FAR PASCAL GraphicConfig(NPMCIGRAPHIC npMCI, DWORD dwFlags)
  2247. {
  2248. DWORD dwOptions = npMCI->dwOptionFlags;
  2249. if (!(dwFlags & MCI_TEST)) {
  2250. BOOL f;
  2251. gfEvil++;
  2252. f = ConfigDialog(NULL, npMCI);
  2253. if (f) {
  2254. #ifdef DEBUG
  2255. //
  2256. // in DEBUG always reset the dest rect because the user may
  2257. // have played with the DEBUG DrawDib options and we will
  2258. // need to call DrawDibBegin() again.
  2259. //
  2260. if (TRUE) {
  2261. #else
  2262. if ((npMCI->dwOptionFlags & (MCIAVIO_STUPIDMODE|MCIAVIO_ZOOMBY2
  2263. |MCIAVIO_WINDOWSIZEMASK))
  2264. != (dwOptions & (MCIAVIO_STUPIDMODE|MCIAVIO_ZOOMBY2
  2265. |MCIAVIO_WINDOWSIZEMASK)) ) {
  2266. #endif
  2267. npMCI->lFrameDrawn = (- (LONG) npMCI->wEarlyRecords) - 1;
  2268. SetWindowToDefaultSize(npMCI, TRUE);
  2269. // don't do this on the user thread
  2270. //SetRectEmpty(&npMCI->rcDest); //This will force a change!
  2271. ResetDestRect(npMCI, TRUE);
  2272. }
  2273. }
  2274. else {
  2275. npMCI->dwOptionFlags = dwOptions;
  2276. }
  2277. gfEvil--;
  2278. }
  2279. return 0L;
  2280. }
  2281. /***************************************************************************
  2282. *
  2283. * @doc INTERNAL MCIAVI
  2284. *
  2285. * @api DWORD | mciSpecial | This function handles all the MCI
  2286. * commands that don't require instance data such as open.
  2287. *
  2288. * @parm UINT | wDeviceID | The MCI device ID
  2289. *
  2290. * @parm UINT | wMessage | The requested action to be performed.
  2291. *
  2292. * @parm DWORD | dwFlags | Flags for the message.
  2293. *
  2294. * @parm DWORD | lpParms | Parameters for this message.
  2295. *
  2296. * @rdesc Error Constant. 0L on success
  2297. *
  2298. ***************************************************************************/
  2299. DWORD NEAR PASCAL mciSpecial (UINT wDeviceID, UINT wMessage, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
  2300. {
  2301. NPMCIGRAPHIC npMCI = 0L;
  2302. DWORD dwRet;
  2303. /* since there in no instance block, there is no saved notification */
  2304. /* to abort. */
  2305. switch (wMessage) {
  2306. case MCI_OPEN_DRIVER:
  2307. if (dwFlags & (MCI_OPEN_ELEMENT | MCI_OPEN_ELEMENT_ID))
  2308. dwRet = GraphicOpen (&npMCI, dwFlags,
  2309. (LPMCI_DGV_OPEN_PARMS) lpParms, wDeviceID);
  2310. else
  2311. dwRet = 0L;
  2312. mciSetDriverData (wDeviceID, (UINT_PTR)npMCI);
  2313. break;
  2314. case MCI_GETDEVCAPS:
  2315. dwRet = GraphicGetDevCaps(NULL, dwFlags,
  2316. (LPMCI_GETDEVCAPS_PARMS)lpParms);
  2317. break;
  2318. case MCI_CONFIGURE:
  2319. if (!(dwFlags & MCI_TEST))
  2320. ConfigDialog(NULL, NULL);
  2321. dwRet = 0L;
  2322. break;
  2323. case MCI_INFO:
  2324. dwRet = GraphicInfo(NULL, dwFlags, (LPMCI_DGV_INFO_PARMS)lpParms);
  2325. break;
  2326. case MCI_CLOSE_DRIVER:
  2327. dwRet = 0L;
  2328. break;
  2329. default:
  2330. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  2331. break;
  2332. }
  2333. GraphicImmediateNotify (wDeviceID, lpParms, dwFlags, dwRet);
  2334. return (dwRet);
  2335. }
  2336. /***************************************************************************
  2337. *
  2338. * @doc INTERNAL MCIAVI
  2339. *
  2340. * @api DWORD | mciDriverEntry | This function is the MCI handler
  2341. *
  2342. * @parm UINT | wDeviceID | The MCI device ID
  2343. *
  2344. * @parm UINT | wMessage | The requested action to be performed.
  2345. *
  2346. * @parm DWORD | dwFlags | Flags for the message.
  2347. *
  2348. * @parm DWORD | lpParms | Parameters for this message.
  2349. *
  2350. * @rdesc Error Constant. 0L on success
  2351. *
  2352. ***************************************************************************/
  2353. DWORD PASCAL mciDriverEntry (UINT wDeviceID, UINT wMessage, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
  2354. {
  2355. NPMCIGRAPHIC npMCI = 0L;
  2356. DWORD dwRet = MCIERR_UNRECOGNIZED_COMMAND;
  2357. BOOL fDelayed = FALSE;
  2358. BOOL fNested = FALSE;
  2359. /* All current commands require a parameter block. */
  2360. if (!lpParms && (dwFlags & MCI_NOTIFY))
  2361. return (MCIERR_MISSING_PARAMETER);
  2362. npMCI = (NPMCIGRAPHIC) mciGetDriverData(wDeviceID);
  2363. if (!npMCI)
  2364. return mciSpecial(wDeviceID, wMessage, dwFlags, lpParms);
  2365. #ifdef DEBUG
  2366. else
  2367. Assert(npMCI->mciid == MCIID);
  2368. #endif
  2369. /*
  2370. ** If a WOW app has subclassed the AVIWnd32 window,
  2371. ** this is very bad as it stops all "Sent" message processing on
  2372. ** that window, "Posted" messages seem to be OK. This means
  2373. ** that it is not possible to close the movie window.
  2374. */
  2375. if ( IsNTWOW() ) {
  2376. DPF2(( "WOW mcidriverentry\n"));
  2377. if ( IsWindow(npMCI->hwndDefault) ) {
  2378. WNDPROC wndProc = (WNDPROC)GetWindowLongPtr( npMCI->hwndDefault,
  2379. GWLP_WNDPROC );
  2380. if ( wndProc != GraphicWndProc ) {
  2381. DPF2(( "WOW app has subclassed AVIWnd32 window - correcting\n" ));
  2382. SetWindowLongPtr( npMCI->hwndDefault, GWLP_WNDPROC,
  2383. (LONG_PTR)GraphicWndProc );
  2384. }
  2385. wndProc = (WNDPROC)GetClassLongPtr(npMCI->hwndDefault, GCLP_WNDPROC);
  2386. if (wndProc != GraphicWndProc) {
  2387. DPF2(( "WOW app has subclassed AVIWnd32 class! - correcting\n" ));
  2388. SetClassLongPtr( npMCI->hwndDefault, GCLP_WNDPROC,
  2389. (LONG_PTR)GraphicWndProc );
  2390. }
  2391. }
  2392. }
  2393. if (npMCI->wMessageCurrent) {
  2394. fNested = TRUE;
  2395. if (wMessage != MCI_STATUS && wMessage != MCI_GETDEVCAPS &&
  2396. wMessage != MCI_INFO) {
  2397. DPF(("Warning!!!!!\n"));
  2398. DPF(("Warning!!!!! MCIAVI reentered: received %x while processing %x\n", wMessage, npMCI->wMessageCurrent));
  2399. DPF(("Warning!!!!!\n"));
  2400. // Assert(0);
  2401. // return MCIERR_DEVICE_NOT_READY;
  2402. }
  2403. } else
  2404. npMCI->wMessageCurrent = wMessage;
  2405. switch (wMessage) {
  2406. case MCI_CLOSE_DRIVER:
  2407. // Question: Should we set the driver data to NULL
  2408. // before closing the device? It would seem the right order.
  2409. // So... we have moved this line before the call to GraphicClose
  2410. mciSetDriverData(wDeviceID, 0L);
  2411. // note that GraphicClose will release and delete the critsec
  2412. dwRet = GraphicClose(npMCI);
  2413. npMCI = NULL;
  2414. break;
  2415. case MCI_PLAY:
  2416. dwRet = GraphicPlay(npMCI, dwFlags, (LPMCI_PLAY_PARMS)lpParms);
  2417. fDelayed = TRUE;
  2418. break;
  2419. case MCI_CUE:
  2420. dwRet = GraphicCue(npMCI, dwFlags, (LPMCI_DGV_CUE_PARMS)lpParms);
  2421. fDelayed = TRUE;
  2422. break;
  2423. case MCI_STEP:
  2424. dwRet = GraphicStep(npMCI, dwFlags, (LPMCI_DGV_STEP_PARMS)lpParms);
  2425. fDelayed = TRUE;
  2426. break;
  2427. case MCI_STOP:
  2428. dwRet = GraphicStop(npMCI, dwFlags, lpParms);
  2429. break;
  2430. case MCI_SEEK:
  2431. dwRet = GraphicSeek (npMCI, dwFlags, (LPMCI_SEEK_PARMS)lpParms);
  2432. fDelayed = TRUE;
  2433. break;
  2434. case MCI_PAUSE:
  2435. dwRet = GraphicPause(npMCI, dwFlags, lpParms);
  2436. fDelayed = TRUE;
  2437. break;
  2438. case MCI_RESUME:
  2439. dwRet = GraphicResume(npMCI, dwFlags, lpParms);
  2440. fDelayed = TRUE;
  2441. break;
  2442. case MCI_SET:
  2443. dwRet = GraphicSet(npMCI, dwFlags,
  2444. (LPMCI_DGV_SET_PARMS)lpParms);
  2445. break;
  2446. case MCI_STATUS:
  2447. dwRet = GraphicStatus(npMCI, dwFlags,
  2448. (LPMCI_DGV_STATUS_PARMS)lpParms);
  2449. break;
  2450. case MCI_INFO:
  2451. dwRet = GraphicInfo (npMCI, dwFlags, (LPMCI_DGV_INFO_PARMS)lpParms);
  2452. break;
  2453. case MCI_GETDEVCAPS:
  2454. dwRet = GraphicGetDevCaps(npMCI, dwFlags, (LPMCI_GETDEVCAPS_PARMS)lpParms);
  2455. break;
  2456. case MCI_REALIZE:
  2457. dwRet = GraphicRealize(npMCI, dwFlags);
  2458. break;
  2459. case MCI_UPDATE:
  2460. dwRet = GraphicUpdate(npMCI, dwFlags, (LPMCI_DGV_UPDATE_PARMS)lpParms);
  2461. break;
  2462. case MCI_WINDOW:
  2463. dwRet = GraphicWindow(npMCI, dwFlags, (LPMCI_DGV_WINDOW_PARMS)lpParms);
  2464. break;
  2465. case MCI_PUT:
  2466. dwRet = GraphicPut(npMCI, dwFlags, (LPMCI_DGV_RECT_PARMS)lpParms);
  2467. break;
  2468. case MCI_WHERE:
  2469. dwRet = GraphicWhere(npMCI, dwFlags, (LPMCI_DGV_RECT_PARMS)lpParms);
  2470. break;
  2471. case MCI_CONFIGURE:
  2472. dwRet = GraphicConfig(npMCI, dwFlags);
  2473. break;
  2474. case MCI_SETAUDIO:
  2475. dwRet = GraphicSetAudio(npMCI, dwFlags,
  2476. (LPMCI_DGV_SETAUDIO_PARMS) lpParms);
  2477. break;
  2478. case MCI_SETVIDEO:
  2479. dwRet = GraphicSetVideo(npMCI, dwFlags,
  2480. (LPMCI_DGV_SETVIDEO_PARMS) lpParms);
  2481. break;
  2482. case MCI_SIGNAL:
  2483. dwRet = GraphicSignal(npMCI, dwFlags,
  2484. (LPMCI_DGV_SIGNAL_PARMS) lpParms);
  2485. break;
  2486. case MCI_LIST:
  2487. dwRet = GraphicList(npMCI, dwFlags,
  2488. (LPMCI_DGV_LIST_PARMS) lpParms);
  2489. break;
  2490. case MCI_LOAD:
  2491. dwRet = GraphicLoad(npMCI, dwFlags,
  2492. (LPMCI_DGV_LOAD_PARMS) lpParms);
  2493. break;
  2494. case MCI_RECORD:
  2495. case MCI_SAVE:
  2496. case MCI_CUT:
  2497. case MCI_COPY:
  2498. case MCI_PASTE:
  2499. case MCI_UNDO:
  2500. case MCI_DELETE:
  2501. case MCI_CAPTURE:
  2502. case MCI_QUALITY:
  2503. case MCI_MONITOR:
  2504. case MCI_RESERVE:
  2505. case MCI_FREEZE:
  2506. case MCI_UNFREEZE:
  2507. dwRet = MCIERR_UNSUPPORTED_FUNCTION;
  2508. break;
  2509. /* Do we need this case? */
  2510. default:
  2511. dwRet = MCIERR_UNRECOGNIZED_COMMAND;
  2512. break;
  2513. }
  2514. if (!fDelayed || (dwFlags & MCI_TEST)) {
  2515. /* We haven't processed the notify yet. */
  2516. if (npMCI && (dwFlags & MCI_NOTIFY) && (!LOWORD(dwRet)))
  2517. /* Throw away the old notify */
  2518. GraphicDelayedNotify(npMCI, MCI_NOTIFY_SUPERSEDED);
  2519. /* And send the new one out immediately. */
  2520. GraphicImmediateNotify(wDeviceID, lpParms, dwFlags, dwRet);
  2521. }
  2522. if (npMCI) {
  2523. /* Everything from here on relies on npMCI still being around */
  2524. /* If there's an error, don't save the callback.... */
  2525. if (fDelayed && dwRet != 0 && (dwFlags & MCI_NOTIFY)) {
  2526. // this might be too late, of course, but shouldn't do
  2527. // any harm
  2528. npMCI->hCallback = 0;
  2529. }
  2530. //
  2531. // see if we need to tell the DRAW device about moving.
  2532. // MPlayer is sending the status and position command alot
  2533. // so this is a "timer"
  2534. //
  2535. // !!!do we need to do it this often?
  2536. //
  2537. if (npMCI->dwFlags & MCIAVI_WANTMOVE)
  2538. CheckWindowMove(npMCI, FALSE);
  2539. if (!fNested)
  2540. npMCI->wMessageCurrent = 0;
  2541. }
  2542. return dwRet;
  2543. }
  2544. /***************************************************************************
  2545. *
  2546. * @doc INTERNAL MCIAVI
  2547. *
  2548. * @api LONG | ConvertToFrames | Convert from the current time format into
  2549. * frames.
  2550. *
  2551. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  2552. *
  2553. * @parm DWORD | dwTime | Input time.
  2554. *
  2555. ***************************************************************************/
  2556. LONG NEAR PASCAL ConvertToFrames(NPMCIGRAPHIC npMCI, DWORD dwTime)
  2557. {
  2558. if (npMCI->dwTimeFormat == MCI_FORMAT_FRAMES) {
  2559. return (LONG) dwTime;
  2560. } else {
  2561. if (npMCI->dwMicroSecPerFrame > 1000) {
  2562. /* This needs to round down--muldiv32 likes to round off. */
  2563. return (LONG) muldivrd32(dwTime, 1000L, npMCI->dwMicroSecPerFrame);
  2564. } else {
  2565. return (LONG) muldivru32(dwTime, 1000L, npMCI->dwMicroSecPerFrame);
  2566. }
  2567. }
  2568. }
  2569. /***************************************************************************
  2570. *
  2571. * @doc INTERNAL MCIAVI
  2572. *
  2573. * @api DWORD | ConvertFromFrames | Convert from frames into the current
  2574. * time format.
  2575. *
  2576. * @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
  2577. *
  2578. * @parm LONG | lFrame | Frame number to convert.
  2579. *
  2580. ***************************************************************************/
  2581. DWORD NEAR PASCAL ConvertFromFrames(NPMCIGRAPHIC npMCI, LONG lFrame)
  2582. {
  2583. if (npMCI->dwTimeFormat == MCI_FORMAT_FRAMES) {
  2584. return (DWORD)lFrame;
  2585. } else {
  2586. if (npMCI->dwMicroSecPerFrame > 1000)
  2587. return muldivru32(lFrame, npMCI->dwMicroSecPerFrame, 1000L);
  2588. else
  2589. return muldivrd32(lFrame, npMCI->dwMicroSecPerFrame, 1000L);
  2590. }
  2591. }
  2592. #ifdef HEARTBEAT
  2593. DWORD Interval = 60000; // 1 minute
  2594. DWORD HeartBeatBreak = FALSE;
  2595. DWORD HeartBeatDump = FALSE;
  2596. DWORD HeartBeat(LPVOID lpvThreadData)
  2597. {
  2598. NPMCIGRAPHIC npMCI;
  2599. int n;
  2600. while (TRUE) {
  2601. for (n=Interval/1000; n--; ) {
  2602. Sleep(1000);
  2603. if (fTerminate) {
  2604. ExitThread(0);
  2605. }
  2606. }
  2607. if (HeartBeatDump) {
  2608. LPTSTR pszFilename;
  2609. EnterList();
  2610. npMCI = npMCIList;
  2611. while (npMCI) {
  2612. pszFilename = npMCI->szFilename;
  2613. if (!pszFilename) {
  2614. pszFilename = L"<NULL>";
  2615. }
  2616. DPF0(("\nDevice dump : %8x : Name > %ls <\n"
  2617. "\t: CmdCritSec owner=%x, count=%x "
  2618. "\t: WinCritSec owner=%x, count=%x "
  2619. ": HDCCritSec owner=%x, count=%x\n"
  2620. "\t State=%x hWave=%x",
  2621. npMCI,
  2622. pszFilename,
  2623. (npMCI->CmdCritSec).OwningThread, (npMCI->CmdCritSec).RecursionCount,
  2624. (npMCI->WinCritSec).OwningThread, (npMCI->WinCritSec).RecursionCount,
  2625. (npMCI->HDCCritSec).OwningThread, (npMCI->HDCCritSec).RecursionCount,
  2626. npMCI->wTaskState, npMCI->hWave));
  2627. npMCI = npMCI->npMCINext;
  2628. }
  2629. LeaveList();
  2630. }
  2631. if (HeartBeatBreak) {
  2632. DebugBreak();
  2633. }
  2634. }
  2635. return (0);
  2636. }
  2637. #endif