Leaked source code of windows server 2003
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.

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