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.

2108 lines
64 KiB

  1. /****************************************************************************
  2. *
  3. * AVILIB.CPP
  4. *
  5. * routines for reading a AVIStream
  6. *
  7. * Copyright (c) 1992 Microsoft Corporation. All Rights Reserved.
  8. *
  9. * You have a royalty-free right to use, modify, reproduce and
  10. * distribute the Sample Files (and/or any modified version) in
  11. * any way you find useful, provided that you agree that
  12. * Microsoft has no warranty obligations or liability for any
  13. * Sample Application Files which are modified.
  14. *
  15. ***************************************************************************/
  16. #include <win32.h>
  17. #include <compobj.h>
  18. #include <compman.h>
  19. #include <shellapi.h>
  20. #include <memory.h> // for _fmemset
  21. #include "avifile.h"
  22. #include "aviopts.h" // string resources
  23. #include "avireg.h"
  24. #include "debug.h"
  25. #ifndef WIN32
  26. #undef HKEY_CLASSES_ROOT
  27. #define HKEY_CLASSES_ROOT 0x00000001
  28. #endif
  29. #define ValidPAVI(pavi) (pavi != NULL)
  30. #define V_PAVI(pavi, err) \
  31. if (!ValidPAVI(pavi)) \
  32. return err;
  33. /****************************************************************************
  34. strings
  35. ****************************************************************************/
  36. #define SZCODE char _based(_segname("_CODE"))
  37. ///////////////////////////////////////////////////////////////////////////
  38. ///////////////////////////////////////////////////////////////////////////
  39. EXTERN_C HINSTANCE ghMod;
  40. static int iInit = 0;
  41. ///////////////////////////////////////////////////////////////////////////
  42. ///////////////////////////////////////////////////////////////////////////
  43. /**************************************************************************
  44. * @doc INTERNAL InitRegistry()
  45. *
  46. * @api void | write all the default AVIFile/AVIStream handlers to the
  47. * registry.
  48. *
  49. * @comm This function should be enhanced so that some of the key values
  50. * can be loaded from resources, instead of a static string table....
  51. *
  52. * @xref AVIStreamInit
  53. *
  54. *************************************************************************/
  55. static void InitRegistry()
  56. {
  57. char **ppch = aszReg;
  58. char ach[80];
  59. #ifndef DEBUG
  60. LONG cb;
  61. // !!! This should have a version number or something in it....
  62. if (RegQueryValue(HKEY_CLASSES_ROOT, ppch[0], ach, (cb = sizeof(ach),&cb)) == ERROR_SUCCESS &&
  63. lstrcmpi(ach, ppch[1]) == 0)
  64. return;
  65. #endif
  66. while (ppch[0])
  67. {
  68. if (((UINT) ppch[1]) < MAX_RC_CONSTANT) {
  69. LoadString(ghMod, (UINT) ppch[1], ach, sizeof(ach));
  70. RegSetValue(HKEY_CLASSES_ROOT, ppch[0], REG_SZ, ach, 0L);
  71. } else
  72. RegSetValue(HKEY_CLASSES_ROOT, ppch[0], REG_SZ, ppch[1], 0L);
  73. ppch += 2;
  74. }
  75. }
  76. /**************************************************************************
  77. * @doc EXTERNAL AVIFileInit
  78. *
  79. * @api void | AVIFileInit | This function initalizes the AVIFILE library.
  80. *
  81. * @comm Call this function before using any other AVIFILE functions.
  82. *
  83. * @xref <f AVIFileExit>
  84. *
  85. *************************************************************************/
  86. STDAPI_(void) AVIFileInit()
  87. {
  88. iInit++;
  89. CoInitialize(NULL);
  90. if (iInit == 1) {
  91. InitRegistry();
  92. }
  93. }
  94. /**************************************************************************
  95. * @doc EXTERNAL AVIFileExit
  96. *
  97. * @api void | AVIFileExit | This function exits the AVIFILE library.
  98. *
  99. * @comm Call this function after using any other AVIFILE functions.
  100. *
  101. * @xref <f AVIFileInit>
  102. *
  103. *************************************************************************/
  104. STDAPI_(void) AVIFileExit()
  105. {
  106. extern HINSTANCE ghOLE2;
  107. iInit--;
  108. CoFreeUnusedLibraries();
  109. CoUninitialize();
  110. if (iInit == 0){
  111. if (ghOLE2) {
  112. DPF("Freeing OLE2.DLL\n");
  113. FreeLibrary(ghOLE2);
  114. ghOLE2 = NULL;
  115. }
  116. }
  117. }
  118. /**************************************************************************
  119. * @doc INTERNAL AVIFileCreate
  120. *
  121. * @api LONG | AVIFileCreate | Initializes an empty AVI File interface
  122. * pointer.
  123. *
  124. * @parm PAVIFILE FAR * | ppfile | Pointer to where the new <t PAVIFILE>
  125. * should be returned.
  126. *
  127. * @parm LONG | lParam | Specifies a parameter passed to the handler.
  128. *
  129. * @parm CLSID FAR * | pclsidHandler | Specifies a pointer to a
  130. * class ID used to create the file.
  131. *
  132. * @devnote Nobody should have to call this function, because AVIFileOpen
  133. * does it. In fact, why do we even have this?
  134. *
  135. * @rdesc Returns zero if successful; otherwise it returns an error code.
  136. *
  137. * @xref AVIFileOpen
  138. *
  139. *************************************************************************/
  140. STDAPI AVIFileCreate (PAVIFILE FAR *ppfile, LONG lParam,
  141. CLSID FAR *pclsidHandler)
  142. {
  143. CLSID clsid;
  144. HRESULT hr;
  145. if (!iInit) {
  146. return ResultFromScode(CO_E_NOTINITIALIZED);
  147. }
  148. // AVIStreamInit();
  149. if (pclsidHandler)
  150. clsid = *pclsidHandler;
  151. else {
  152. // if (pfh == NULL)
  153. // pfh = &AVIFFileHandler;
  154. }
  155. if (FAILED(GetScode(hr = CoCreateInstance((REFCLSID) clsid,
  156. NULL, CLSCTX_INPROC,
  157. (REFIID) IID_IAVIFile,
  158. (void FAR* FAR*)ppfile))))
  159. return hr; // !!! PropagateHResult?
  160. return AVIERR_OK;
  161. }
  162. // Remove trailing spaces after a file...
  163. void FixFourCC(LPSTR lp)
  164. {
  165. int i;
  166. for (i = 3; i >= 0; i--) {
  167. if (lp[i] == ' ')
  168. lp[i] = '\0';
  169. else
  170. break;
  171. }
  172. }
  173. // Returns a pointer to the extension of a filename....
  174. LPCSTR FindExtension(LPCSTR lp)
  175. {
  176. LPCSTR lpExt = lp;
  177. int i;
  178. // Goto end of string
  179. while (*lpExt != '\0')
  180. {
  181. ++lpExt;
  182. }
  183. // Must be at least 2 characters in string
  184. if (lpExt - lp < 2)
  185. return NULL;
  186. lpExt -= 1;
  187. // Does not count if last character is '.'
  188. if (*lpExt == '.')
  189. return NULL;
  190. lpExt -= 1;
  191. // Now looking at second to the last character. Check this and the two
  192. // previous characters for a '.'
  193. for (i=1; i<=3; ++i)
  194. {
  195. // Cannot have path separator here
  196. if (*lpExt == '/' || *lpExt == '\\')
  197. return NULL;
  198. if (*lpExt == '.')
  199. {
  200. ++lpExt;
  201. return lpExt;
  202. }
  203. if (lpExt == lp)
  204. return NULL;
  205. --lpExt;
  206. }
  207. return NULL;
  208. }
  209. /**************************************************************************
  210. * @doc INTERNAL GetHandlerFromFile
  211. *
  212. * @api PAVIFILEHANDLER | GetHandlerFromFile | Figure out what handler
  213. * to use for a file by looking at its extension, its RIFF type,
  214. * and possibly other things.
  215. *
  216. * @parm LPCSTR | szFile | The file to look at.
  217. *
  218. * @parm CLSID FAR * | pclsidHandler | Pointer to a classID.
  219. *
  220. * @comm We don't look at the extensions yet. We need a better way to
  221. * add handlers.
  222. *
  223. * @rdesc Returns the <PAVIFILEHANDLER> to use, or NULL if it can't find
  224. * one.
  225. *
  226. * @xref AVIFileOpen AVIRegisterLoader
  227. *
  228. *************************************************************************/
  229. #define HKEY_AVIFILE_ROOT HKEY_CLASSES_ROOT
  230. static SZCODE aszRegRIFF[] = "AVIFile\\RIFFHandlers\\%.4s";
  231. static SZCODE aszRegExt[] = "AVIFile\\Extensions";
  232. static SZCODE aszRegClsid[] = "Clsid";
  233. static SZCODE aszRegExtTmpl[] = "%s\\%.3s";
  234. BOOL GetHandlerFromFile(LPCSTR szFile, CLSID FAR *pclsid)
  235. {
  236. DWORD dw[3];
  237. HMMIO hmmio;
  238. LPCSTR lpExt;
  239. char achKey[100];
  240. char achClass[100];
  241. LONG lcbClass;
  242. // I hate share
  243. hmmio = mmioOpen((LPSTR) szFile, NULL, MMIO_READ | MMIO_DENYWRITE);
  244. if (hmmio == NULL)
  245. hmmio = mmioOpen((LPSTR) szFile, NULL, MMIO_READ | MMIO_DENYNONE);
  246. if (hmmio == NULL)
  247. hmmio = mmioOpen((LPSTR) szFile, NULL, MMIO_READ);
  248. if (hmmio == NULL)
  249. goto UseExtension;
  250. if (mmioRead(hmmio, (HPSTR) dw, sizeof(dw)) != sizeof(dw)) {
  251. mmioClose(hmmio, 0);
  252. goto UseExtension;
  253. }
  254. mmioClose(hmmio, 0);
  255. if (dw[0] != FOURCC_RIFF)
  256. goto UseExtension;
  257. FixFourCC((LPSTR) &dw[2]);
  258. // Look up the RIFF type in the registration database....
  259. wsprintf(achKey, aszRegRIFF, (LPSTR) &dw[2]);
  260. lcbClass = sizeof(achClass);
  261. RegQueryValue(HKEY_CLASSES_ROOT, achKey, achClass, &lcbClass);
  262. if (!FAILED(GetScode(CLSIDFromString(achClass, pclsid))))
  263. return TRUE;
  264. UseExtension:
  265. lpExt = FindExtension(szFile);
  266. if (lpExt) {
  267. // Look up the extension in the registration database....
  268. wsprintf(achKey, aszRegExtTmpl, (LPSTR) aszRegExt, lpExt);
  269. lcbClass = sizeof(achClass);
  270. RegQueryValue(HKEY_CLASSES_ROOT, achKey, achClass, &lcbClass);
  271. if (!FAILED(GetScode(CLSIDFromString(achClass, pclsid))))
  272. return TRUE;
  273. }
  274. // !!! Use IStorage?
  275. return FALSE;
  276. }
  277. /**************************************************************************
  278. * @doc EXTERNAL AVIFileOpen
  279. *
  280. * @api LONG | AVIFileOpen | Opens an AVI file and returns a file interface
  281. * pointer used to access it.
  282. *
  283. * @parm PAVIFILE FAR * | ppfile | Pointer to the location used to return
  284. * the new <t PAVIFILE> file pointer.
  285. *
  286. * @parm LPCSTR | szFile | Specifies a zero-terminated string
  287. * containing the name of the file to open.
  288. *
  289. * @parm UINT | mode | Specifies the mode to use when opening the file.
  290. *
  291. *
  292. * @flag OF_READ | Opens the file for reading only. This is the
  293. * default, if OF_WRITE and OF_READWRITE are not specified.
  294. *
  295. * @flag OF_WRITE | Opens the file for writing. You should not
  296. * read from a file opened in this mode.
  297. *
  298. * @flag OF_READWRITE | Opens the file for both reading and writing.
  299. *
  300. * @flag OF_CREATE | Creates a new file.
  301. * If the file already exists, it is truncated to zero length.
  302. *
  303. * @flag OF_DENYWRITE | Opens the file and denies other
  304. * processes write access to the file. <f AVIFileOpen> fails
  305. * if the file has been opened in compatibility or for write
  306. * access by any other process.
  307. *
  308. * @flag OF_DENYREAD | Opens the file and denies other
  309. * processes read access to the file. <f AVIFileOpen> fails if the
  310. * file has been opened in compatibility mode or for read access
  311. * by any other process.
  312. *
  313. * @flag OF_DENYNONE | Opens the file without denying other
  314. * processes read or write access to the file. <f AVIFileOpen>
  315. * fails if the file has been opened in compatibility mode
  316. * by any other process.
  317. *
  318. * @flag OF_EXCLUSIVE | Opens the file and denies other processes
  319. * any access to the file. <f AVIFileOpen> will fail if any
  320. * other process has opened the file.
  321. *
  322. * See <f OpenFile> for more information about these flags.
  323. *
  324. * @parm CLSID FAR * | pclsidHandler | Specifies a pointer to a class ID
  325. * identifying the handler you want to use. If NULL, the system
  326. * chooses one from the registration database based on the file
  327. * extension or the file's RIFF type.
  328. *
  329. * @comm In general, the mode specified is used to open
  330. * the file.
  331. *
  332. * Be sure to call <f AVIFileInit> at least once in your
  333. * application before calling this function, and to balance each
  334. * call to <f AVIFileInit> with a call to <f AVIFileExit>.
  335. *
  336. * @rdesc Returns zero if successful; otherwise returns an error code.
  337. * Possible error returns include:
  338. *
  339. * @flag AVIERR_BADFORMAT | The file was corrupted or not in the
  340. * proper format, and could not be read.
  341. *
  342. * @flag AVIERR_MEMORY | The file could not be opened because
  343. * there was not enough memory.
  344. *
  345. * @flag AVIERR_FILEREAD | A disk error occurred while reading the
  346. * file.
  347. *
  348. * @flag AVIERR_FILEOPEN | A disk error occurred while opening the
  349. * file.
  350. *
  351. * @flag REGDB_E_CLASSNOTREG | No handler could be found to open
  352. * this type of file.
  353. *
  354. * @xref <f AVIFileRelease> <f AVIFileInit>
  355. *
  356. *************************************************************************/
  357. STDAPI AVIFileOpen (PAVIFILE FAR *ppfile,
  358. LPCSTR szFile,
  359. UINT mode,
  360. CLSID FAR *pclsidHandler)
  361. {
  362. CLSID clsid;
  363. HRESULT hr;
  364. // We used to just fail if AVIFileInit wasn't called
  365. #if 0
  366. if (!iInit) {
  367. return ResultFromScode(E_UNEXPECTED);
  368. }
  369. #endif
  370. // Now we do it for them
  371. hr = CoInitialize(NULL);
  372. // Let them know what they did wrong
  373. if (GetScode(hr) == NOERROR) {
  374. #ifdef DEBUG
  375. MessageBox(NULL, "You didn't call AVIFileInit!", "Bad dog!",
  376. MB_OK | MB_ICONHAND);
  377. #endif
  378. } else
  379. CoUninitialize();
  380. *ppfile = 0;
  381. if (pclsidHandler)
  382. clsid = *pclsidHandler;
  383. else {
  384. if (!GetHandlerFromFile(szFile, &clsid)) {
  385. DPF("Couldn't find handler for %s\n", (LPSTR) szFile);
  386. return ResultFromScode(REGDB_E_CLASSNOTREG);
  387. }
  388. }
  389. if (FAILED(GetScode(hr = CoCreateInstance((RCLSID) clsid,
  390. NULL, CLSCTX_INPROC,
  391. (REFIID) IID_IAVIFile,
  392. (void FAR* FAR*)ppfile)))) {
  393. DPF("CoCreateInstance returns %08lx\n", (DWORD) hr);
  394. return hr;
  395. }
  396. //
  397. // Let's simplify things for the handlers. They will only see...
  398. // OF_CREATE | OF_READWRITE or...
  399. // OF_READWRITE or...
  400. // OF_READ
  401. //
  402. if (mode & OF_READWRITE)
  403. mode &= ~(OF_WRITE | OF_READ);
  404. if (mode & OF_CREATE) {
  405. mode &= ~(OF_WRITE | OF_READ);
  406. mode |= OF_READWRITE;
  407. }
  408. if (mode & OF_WRITE) {
  409. mode &= ~(OF_WRITE | OF_READ);
  410. mode |= OF_READWRITE;
  411. }
  412. if (FAILED(GetScode(hr = (*ppfile)->Open(szFile, mode)))) {
  413. DPF("Open method returns %08lx\n", (DWORD) hr);
  414. (*ppfile)->Release();
  415. *ppfile = NULL;
  416. }
  417. return hr;
  418. }
  419. /**************************************************************************
  420. * @doc EXTERNAL AVIFileAddRef
  421. *
  422. * @api LONG | AVIFileAddRef | Increases the reference count of an AVI file.
  423. *
  424. * @parm PAVIFILE | pfile | Specifies the handle for an open AVI file.
  425. *
  426. * @rdesc Returns zero on success; otherwise returns an error code.
  427. *
  428. * @comm Balance each call to <f AVIFileAddRef> with a call to
  429. * <f AVIFileRelease>.
  430. *
  431. * @xref <f AVIFileRelease>
  432. *
  433. *************************************************************************/
  434. STDAPI_(ULONG) AVIFileAddRef(PAVIFILE pfile)
  435. {
  436. return pfile->AddRef();
  437. }
  438. /**************************************************************************
  439. * @doc EXTERNAL AVIFileRelease
  440. *
  441. * @api LONG | AVIFileRelease | Reduces the reference count of an AVI file
  442. * interface handle by one, and closes the file if the count reaches
  443. * zero.
  444. *
  445. * @parm PAVIFILE | pfile | Specifies a handle to an open AVI file.
  446. *
  447. * @comm Balance each call to <f AVIFileAddRef> or <f AVIFileOpen>
  448. * a call to <f AVIFileRelease>.
  449. *
  450. * @devnote Currently, this saves all changes to the file. Should a separate
  451. * Save command be needed to do this?
  452. *
  453. * @rdesc Returns the reference count of the file. This return value
  454. * should be used only for debugging purposes.
  455. *
  456. * @xref AVIFileOpen AVIFileAddRef
  457. *
  458. *************************************************************************/
  459. STDAPI_(ULONG) AVIFileRelease(PAVIFILE pfile)
  460. {
  461. return pfile->Release();
  462. }
  463. /**************************************************************************
  464. * @doc EXTERNAL AVIFileInfo
  465. *
  466. * @api LONG | AVIFileInfo | Obtains information about an AVI file.
  467. *
  468. * @parm PAVIFILE | pfile | Specifies a handle to an open AVI file.
  469. *
  470. * @parm AVIFILEINFO FAR * | pfi | Pointer to the structure used to
  471. * return file information.
  472. *
  473. * @parm LONG | lSize | Specifies the size of the structure. This value
  474. * should be at least sizeof(AVIFILEINFO), obviously.
  475. *
  476. * @rdesc Returns zero if successful; otherwise it returns an error code.
  477. *
  478. *************************************************************************/
  479. STDAPI AVIFileInfo (PAVIFILE pfile, AVIFILEINFO FAR * pfi,
  480. LONG lSize)
  481. {
  482. _fmemset(pfi, 0, (int)lSize);
  483. return pfile->Info(pfi, lSize);
  484. }
  485. /**************************************************************************
  486. * @doc EXTERNAL AVIFileGetStream
  487. *
  488. * @api LONG | AVIFileGetStream | Returns a pointer to a stream interface
  489. * that is a component of a file.
  490. *
  491. * @parm PAVIFILE | pfile | Specifies a handle to an open AVI file.
  492. *
  493. * @parm PAVISTREAM FAR * | ppavi | Pointer to the return location
  494. * for the new stream interface pointer.
  495. *
  496. * @parm DWORD | fccType | Specifies a four-character code
  497. * indicating the type of stream to be opened.
  498. * Zero indicates that any stream can be opened. The following
  499. * definitions apply to the data commonly
  500. * found in AVI streams:
  501. *
  502. * @flag streamtypeAUDIO | Indicates an audio stream.
  503. * @flag streamtypeMIDI | Indicates a MIDI stream.
  504. * @flag streamtypeTEXT | Indicates a text stream.
  505. * @flag streamtypeVIDEO | Indicates a video stream.
  506. *
  507. * @parm LONG | lParam | Specifies an integer indicating which stream
  508. * of the type defined by <p fccType> should actually be accessed.
  509. *
  510. * @comm Balance each call to <f AVIFileGetStream> with a call to
  511. * <f AVIStreamRelease> using the stream handle returned.
  512. *
  513. * @rdesc Returns zero if successful; otherwise it returns an error code.
  514. * Possible error codes include:
  515. *
  516. * @flag AVIERR_NODATA | There is no stream in the file corresponding
  517. * to the values passed in for <p fccType> and <p lParam>.
  518. * @flag AVIERR_MEMORY | Not enough memory.
  519. *
  520. * @xref <f AVIStreamRelease>
  521. *
  522. *************************************************************************/
  523. STDAPI AVIFileGetStream (PAVIFILE pfile, PAVISTREAM FAR * ppavi, DWORD fccType, LONG lParam)
  524. {
  525. return pfile->GetStream(ppavi, fccType, lParam);
  526. }
  527. #if 0
  528. // !!! This would be used to save changes, if AVIFileRelease didn't do that.
  529. STDAPI AVIFileSave (PAVIFILE pfile,
  530. LPCSTR szFile,
  531. AVISAVEOPTIONS FAR *lpOptions,
  532. AVISAVECALLBACK lpfnCallback,
  533. PAVIFILEHANDLER pfh)
  534. {
  535. if (pfile->FileSave == NULL)
  536. return -1;
  537. return pfile->FileSave(pfile, szFile, lpOptions, lpfnCallback);
  538. }
  539. #endif
  540. /**************************************************************************
  541. * @doc EXTERNAL AVIFileCreateStream
  542. *
  543. * @api LONG | AVIFileCreateStream | Creates a new stream in an existing file,
  544. * and returns a stream interface pointer for it.
  545. *
  546. * @parm PAVIFILE | pfile | Specifies a handle to an open AVI file.
  547. *
  548. * @parm PAVISTREAM FAR * | ppavi | Specifies a pointer used to return the new
  549. * stream interface pointer.
  550. *
  551. * @parm AVISTREAMINFO FAR * | psi | Specifies a pointer to a structure
  552. * containing information about the new stream. This structure
  553. * contains the type of the new stream and its sample rate.
  554. *
  555. * @comm Balance each call to <f AVIFileCreateStream> with a call to
  556. * <f AVIStreamRelease> using the returned stream handle.
  557. *
  558. * This function fails with a return value of AVIERR_READONLY unless
  559. * the file was opened with write permission.
  560. *
  561. * After creating the stream, call <f AVIStreamSetFormat>
  562. * before using <f AVIStreamWrite> to write to the stream.
  563. *
  564. * @rdesc Returns zero if successful; otherwise it returns an error code.
  565. *
  566. * @xref <f AVIStreamRelease> <f AVIFileGetStream> <f AVIStreamSetFormat>
  567. *
  568. *************************************************************************/
  569. STDAPI AVIFileCreateStream (PAVIFILE pfile,
  570. PAVISTREAM FAR *ppavi,
  571. AVISTREAMINFO FAR *psi)
  572. {
  573. *ppavi = NULL;
  574. return pfile->CreateStream(ppavi, psi);
  575. }
  576. /**************************************************************************
  577. * @doc INTERNAL AVIFileAddStream
  578. *
  579. * @api LONG | AVIFileAddStream | Adds an existing stream into
  580. * an existing file, and returns a stream interface pointer for it.
  581. *
  582. * @parm PAVIFILE | pfile | Specifies a handle to an open AVI file.
  583. *
  584. * @parm PAVISTREAM | pavi | Specifies a stream interface pointer
  585. * for the stream being added.
  586. *
  587. * @parm PAVISTREAM FAR * | ppaviNew | Pointer to a buffer used
  588. * to return the new stream interface pointer.
  589. *
  590. * @comm Balance each call to <f AVIFileAddStream> with a call to
  591. * <f AVIStreamRelease> using the returned stream handle.
  592. *
  593. * This call fails with a return value of AVIERR_READONLY unless
  594. * the file was opened with write permission.
  595. *
  596. * @devnote This function still doesn't really work. Perhaps it should just
  597. * be a helper function that gets data from the stream and calls
  598. * AVIFileCreateStream, then copies the data from one stream to another.
  599. *
  600. * @rdesc Returns zero if successful; otherwise it returns an error code.
  601. *
  602. * @xref AVIStreamRelease AVIFileGetStream AVIFileCreateStream
  603. *
  604. *************************************************************************/
  605. #if 0
  606. STDAPI AVIFileAddStream (PAVIFILE pfile,
  607. PAVISTREAM pavi,
  608. PAVISTREAM FAR * ppaviNew)
  609. {
  610. // if (pfile->FileAddStream == NULL)
  611. // return -1;
  612. return pfile->AddStream(pavi, ppaviNew);
  613. }
  614. #endif
  615. /**************************************************************************
  616. * @doc EXTERNAL AVIFileWriteData
  617. *
  618. * @api LONG | AVIFileWriteData | Writes some additional data to the file.
  619. *
  620. * @parm PAVIFILE | pfile | Specifies a handle to an open AVI file.
  621. *
  622. * @parm DWORD | ckid | Specifies a four-character code identifying the data.
  623. *
  624. * @parm LPVOID | lpData | Specifies a pointer to the data to write.
  625. *
  626. * @parm LONG | cbData | Specifies the size of the memory block
  627. * referenced by <p lpData>.
  628. *
  629. * @comm This function fails with a return value of AVIERR_READONLY unless
  630. * the file was opened with write permission.
  631. *
  632. * Use <f AVIStreamWriteData> instead of this function to write
  633. * data that applies to an individual stream.
  634. *
  635. * @devnote !!! Somewhere, we should specify some types.
  636. * !!! Should the data block contain the ckid and cksize?
  637. *
  638. * @rdesc Returns zero if successful; otherwise it returns an error code.
  639. *
  640. * @xref <f AVIStreamWriteData> <f AVIFileReadData>
  641. *
  642. *************************************************************************/
  643. STDAPI AVIFileWriteData (PAVIFILE pfile,
  644. DWORD ckid,
  645. LPVOID lpData,
  646. LONG cbData)
  647. {
  648. // if (pfile->FileWriteData == NULL)
  649. // return -1;
  650. return pfile->WriteData(ckid, lpData, cbData);
  651. }
  652. /**************************************************************************
  653. * @doc EXTERNAL AVIFileReadData
  654. *
  655. * @api LONG | AVIFileReadData | Reads optional header data from the file.
  656. *
  657. * @parm PAVIFILE | pfile | Specifies a handle to an open AVI file.
  658. *
  659. * @parm DWORD | ckid | Specifies a four-character code identifying the data.
  660. *
  661. * @parm LPVOID | lpData | Specifies a pointer to a buffer used to return
  662. * the data read.
  663. *
  664. * @parm LONG FAR * | lpcbData | Specifies a pointer to a location indicating
  665. * the size of the memory block referred to by <p lpData>. If
  666. * the read is successful, the value is changed to indicate the
  667. * amount of data read.
  668. *
  669. * @devnote !!! Somewhere, we should specify some types.
  670. * !!! Should the data block contain the ckid and cksize?
  671. *
  672. * @comm Do not use this function to read video and audio data. Use it
  673. * only to read additional information such as author
  674. * information or copyright information that applies to the file
  675. * as a whole. Information that applies to a single stream should
  676. * be read using <f AVIStreamReadData>.
  677. *
  678. * @rdesc Returns zero if successful; otherwise it returns an error code.
  679. * The return value AVIERR_NODATA indicates that data with the
  680. * requested chunk ID does not exist.
  681. *
  682. * @xref <f AVIStreamReadData> <f AVIFileWriteData>
  683. *
  684. *************************************************************************/
  685. STDAPI AVIFileReadData (PAVIFILE pfile,
  686. DWORD ckid,
  687. LPVOID lpData,
  688. LONG FAR * lpcbData)
  689. {
  690. return pfile->ReadData(ckid, lpData, lpcbData);
  691. }
  692. /**************************************************************************
  693. * @doc EXTERNAL AVIFileEndRecord
  694. *
  695. * @api LONG | AVIFileEndRecord | Marks the end of a record, if writing out
  696. * a strictly interleaved file.
  697. *
  698. * @parm PAVIFILE | pfile | Specifies a handle to a currently open AVI file.
  699. *
  700. * @comm <f AVIFileSave> uses this function when writing files that are
  701. * have audio interleaved every frame. In general, applications
  702. * should not need to use this function.
  703. *
  704. * @rdesc Returns zero if successful; otherwise it returns an error code.
  705. *
  706. * @xref <f AVIFileSave> <f AVIStreamWrite>
  707. *
  708. *************************************************************************/
  709. STDAPI AVIFileEndRecord (PAVIFILE pfile)
  710. {
  711. // if (pfile->FileEndRecord == NULL)
  712. // return -1;
  713. return pfile->EndRecord();
  714. }
  715. /**************************************************************************
  716. * @doc EXTERNAL AVIStreamAddRef
  717. *
  718. * @api LONG | AVIStreamAddRef | Increases the reference count of an AVI stream.
  719. *
  720. * @parm PAVISTREAM | pavi | Specifies a handle to an open AVI stream.
  721. *
  722. * @comm Balance each call to <f AVIStreamAddRef> with a call to
  723. * <f AVIStreamRelease>.
  724. *
  725. * @rdesc Returns the current reference count of the stream. This value
  726. * should only be used for debugging purposes.
  727. *
  728. * @xref <f AVIStreamRelease>
  729. *
  730. *************************************************************************/
  731. STDAPI_(ULONG) AVIStreamAddRef (PAVISTREAM pavi)
  732. {
  733. return pavi->AddRef();
  734. }
  735. /**************************************************************************
  736. * @doc EXTERNAL AVIStreamRelease
  737. *
  738. * @api LONG | AVIStreamRelease | Reduces the reference count of an AVI stream
  739. * interface handle by one, and closes the stream if the count reaches
  740. * zero.
  741. *
  742. * @parm PAVISTREAM | pavi | Specifies a handle to an open stream.
  743. *
  744. * @comm Balance each call to <f AVIStreamAddRef> or <f AVIFileGetStream>
  745. * with a call to <f AVIStreamRelease>.
  746. *
  747. * @rdesc Returns the current reference count of the stream. This value
  748. * should only be used for debugging purposes.
  749. *
  750. * @xref <f AVIFileGetStream> <f AVIStreamAddRef>
  751. *
  752. *************************************************************************/
  753. STDAPI_(ULONG) AVIStreamRelease (PAVISTREAM pavi)
  754. {
  755. return pavi->Release();
  756. }
  757. /**************************************************************************
  758. * @doc EXTERNAL AVIStreamInfo
  759. *
  760. * @api LONG | AVIStreamInfo | Obtains stream header information.
  761. *
  762. * @parm PAVISTREAM | pavi | Specifies a handle to an open stream.
  763. *
  764. * @parm AVISTREAMINFO FAR * | psi | Specifies a pointer to a structure
  765. * used to return stream information.
  766. *
  767. * @parm LONG | lSize | Specifies the size of the structure used for
  768. * <p psi>.
  769. *
  770. * @rdesc Returns zero if successful; otherwise it returns an error code.
  771. *
  772. *************************************************************************/
  773. STDAPI AVIStreamInfo (PAVISTREAM pavi, AVISTREAMINFO FAR * psi, LONG lSize)
  774. {
  775. _fmemset(psi, 0, (int)lSize);
  776. return pavi->Info(psi, lSize);
  777. }
  778. /**************************************************************************
  779. * @doc EXTERNAL AVIStreamFindSample
  780. *
  781. * @api LONG | AVIStreamFindSample | Returns the position of
  782. * a key frames or non-empty frame relative to the specified position.
  783. *
  784. * @parm PAVISTREAM | pavi | Specifies a handle to an open stream.
  785. *
  786. * @parm LONG | lPos | Specifies the starting position
  787. * for the search.
  788. *
  789. * @parm LONG | lFlags | The following flags are defined:
  790. *
  791. * @flag FIND_KEY | Finds a key frame.
  792. * @flag FIND_ANY | Finds a non-empty sample.
  793. * @flag FIND_FORMAT | Finds a format change.
  794. *
  795. * @flag FIND_NEXT | Finds nearest sample, frame, or format change
  796. * searching forward. The current sample is
  797. * included in the search. Use this flag with the
  798. * FIND_ANY, FIND_KEY, or FIND_FORMAT flag.
  799. *
  800. * @flag FIND_PREV | Finds nearest sample, frame, or format change
  801. * searching backwards. The current sample is
  802. * included in the search. Use this flag with the
  803. * FIND_ANY, FIND_KEY, or FIND_FORMAT flag.
  804. *
  805. *
  806. * @comm The FIND_KEY, FIND_ANY, and FIND_FORMAT flags are mutually exclusive.
  807. * The FIND_NEXT and FIND_PREV flags are also mutually exclusive.
  808. * For example:
  809. *
  810. * @ex FIND_PREV|FIND_KEY Returns the first key sample prior to or at
  811. * <p lPos>.
  812. *
  813. * FIND_PREV|FIND_ANY Returns the first non-empty sample prior to
  814. * or at <p lPos>.
  815. *
  816. * FIND_NEXT|FIND_KEY Returns the first key sample after <p lPos>,
  817. * or -1 if a key sample does not follow <p lPos>.
  818. *
  819. * FIND_NEXT|FIND_ANY Returns the first non-empty sample after <p lPos>,
  820. * or -1 if a sample does not exist after <p lPos>.
  821. *
  822. * FIND_NEXT|FIND_FORMAT Returns the first format change after or
  823. * at <p lPos>, or -1 if the stream does not
  824. * have format changes.
  825. *
  826. * FIND_PREV|FIND_FORMAT Returns the first format change prior to
  827. * or at <p lPos>. If the stream does not
  828. * have format changes, it returns the first sample
  829. *
  830. * @rdesc Returns the position found. In many boundary cases, this
  831. * function will return -1; see the example above for details.
  832. *
  833. *************************************************************************/
  834. STDAPI_(LONG) AVIStreamFindSample(PAVISTREAM pavi, LONG lPos, LONG lFlags)
  835. {
  836. // Default to Find Previous Key Frame
  837. if ((lFlags & FIND_TYPE) == 0)
  838. lFlags |= FIND_KEY;
  839. if ((lFlags & FIND_DIR) == 0)
  840. lFlags |= FIND_PREV;
  841. return pavi->FindSample(lPos, lFlags);
  842. }
  843. /**************************************************************************
  844. * @doc EXTERNAL AVIStreamReadFormat
  845. *
  846. * @api LONG | AVIStreamReadFormat | Reads the stream format data.
  847. *
  848. * @parm PAVISTREAM | pavi | Specifies a handle to an open stream.
  849. *
  850. * @parm LONG | lPos | Specifies the position in the stream
  851. * used to obtain the format data.
  852. *
  853. * @parm LPVOID | lpFormat | Specifies a pointer to a buffer
  854. * used to return the format data.
  855. *
  856. * @parm LONG FAR * | lpcbFormat | Specifies a pointer to a
  857. * location indicating the size of the memory block
  858. * referred to by <p lpFormat>. On return, the value is
  859. * changed to indicate the amount of data read. If
  860. * <p lpFormat> is NULL, this parameter can be used
  861. * to obtain the amount of memory needed to return the format.
  862. *
  863. * @comm This function will return part of the format even if the buffer
  864. * provided is not large enough to hold the entire format. In this case
  865. * the return value will be AVIERR_BUFFERTOOSMALL, and the location
  866. * referenced by <p lpcbFormat> will be filled in with the size
  867. * of the entire format.
  868. *
  869. * This is useful because it allows you to use a buffer the
  870. * size of a <t BITMAPINFOHEADER> structure and
  871. * retrieve just the common part of the video format if you are not
  872. * interested in extended format information or palette information.
  873. *
  874. * @rdesc Returns zero if successful, otherwise it returns an error code.
  875. *
  876. *************************************************************************/
  877. STDAPI AVIStreamReadFormat (PAVISTREAM pavi, LONG lPos,
  878. LPVOID lpFormat, LONG FAR *lpcbFormat)
  879. {
  880. // if (pavi->StreamReadFormat == NULL)
  881. // return -1;
  882. return pavi->ReadFormat(lPos, lpFormat, lpcbFormat);
  883. }
  884. /**************************************************************************
  885. * @doc EXTERNAL AVIStreamSetFormat
  886. *
  887. * @api LONG | AVIStreamSetFormat | Sets the format of a stream at the
  888. * specified position.
  889. *
  890. * @parm PAVISTREAM | pavi | Specifies a handle to open stream.
  891. *
  892. * @parm LONG | lPos | Specifies the position in the stream to
  893. * receive the format.
  894. *
  895. * @parm LPVOID | lpFormat | Specifies a pointer to a structure
  896. * containing the new format.
  897. *
  898. * @parm LONG | cbFormat | Specifies the size of the block of memory
  899. * referred to by <p lpFormat> in bytes.
  900. *
  901. * @comm After creating a new stream with <f AVIFileCreateStream>,
  902. * call this function to set the stream's format.
  903. *
  904. * The handler for writing AVI files does not, in general, accept
  905. * format changes. Aside from setting the initial format for a
  906. * stream, only changes in the palette of a video stream are allowed
  907. * in an AVI file. The palette change must be after
  908. * any frames already written to the AVI file. Other handlers may
  909. * impose different restrictions.
  910. *
  911. * @rdesc Returns zero if successful, otherwise it returns an error code.
  912. *
  913. * @xref <f AVIFileCreateStream> <f AVIStreamReadFormat>
  914. *
  915. *************************************************************************/
  916. STDAPI AVIStreamSetFormat (PAVISTREAM pavi, LONG lPos,
  917. LPVOID lpFormat, LONG cbFormat)
  918. {
  919. // if (pavi->StreamSetFormat == NULL)
  920. // return -1;
  921. return pavi->SetFormat(lPos, lpFormat, cbFormat);
  922. }
  923. /**************************************************************************
  924. * @doc EXTERNAL AVIStreamReadData
  925. *
  926. * @api LONG | AVIStreamReadData | Reads optional header data from a stream.
  927. *
  928. * @parm PAVISTREAM | pavi | Specifies a handle to an open stream.
  929. *
  930. * @parm DWORD | ckid | Specifies a four-character code identifying the data.
  931. *
  932. * @parm LPVOID | lpData | Specifies a pointer to used to return
  933. * the data read.
  934. *
  935. * @parm LONG FAR * | lpcbData | Points to a location which
  936. * specifies the buffer size used for <p lpData>.
  937. * If the read is successful, AVIFile changes this value
  938. * to indicate the amount of data written into the buffer for
  939. * <p lpData>.
  940. *
  941. * @comm This function only retrieves header information
  942. * from the stream. To read the actual multimedia content of the
  943. * stream, use <f AVIStreamRead>.
  944. *
  945. * @devnote !!! Somewhere, we should specify some types.
  946. * !!! Should the data block contain the ckid and cksize?
  947. *
  948. * @rdesc Returns zero if successful; otherwise it returns an error code.
  949. * The return value AVIERR_NODATA indicates the system could not
  950. * find any data with the specified chunk ID.
  951. *
  952. * @xref <f AVIFileReadData> <f AVIStreamWriteData> <f AVIStreamWrite>
  953. *
  954. *************************************************************************/
  955. STDAPI AVIStreamReadData (PAVISTREAM pavi, DWORD ckid, LPVOID lpData, LONG FAR *lpcbData)
  956. {
  957. // if (pavi->StreamReadData == NULL)
  958. // return -1;
  959. return pavi->ReadData(ckid, lpData, lpcbData);
  960. }
  961. /**************************************************************************
  962. * @doc EXTERNAL AVIStreamWriteData
  963. *
  964. * @api LONG | AVIStreamWriteData | Writes optional data to the stream.
  965. *
  966. * @parm PAVISTREAM | pavi | Specifies a handle to an open stream.
  967. *
  968. * @parm DWORD | ckid | Specifies a four-character code identifying the data.
  969. *
  970. * @parm LPVOID | lpData | Specifies a pointer to a buffer containing
  971. * the data to write.
  972. *
  973. * @parm LONG | cbData | Indicates the number of bytes of data to be copied
  974. * from <p lpData> into the stream.
  975. *
  976. * @comm This function only writes header information to the stream.
  977. * To write the actual multimedia content of the stream, use
  978. * <f AVIStreamWrite>. Use <f AVIFileWriteData> to write
  979. * data that applies to an entire file.
  980. *
  981. * This call fails with a return value of AVIERR_READONLY unless
  982. * the file was opened with write permission.
  983. *
  984. * @devnote !!! Somewhere, we should specify some types.
  985. * !!! Should the data block contain the ckid and cksize?
  986. *
  987. * @rdesc Returns zero if successful; otherwise it returns an error code.
  988. *
  989. * @xref <f AVIFileWriteData> <f AVIStreamReadData> <f AVIStreamWrite>
  990. *
  991. *************************************************************************/
  992. STDAPI AVIStreamWriteData (PAVISTREAM pavi, DWORD ckid, LPVOID lpData, LONG cbData)
  993. {
  994. return pavi->WriteData(ckid, lpData, cbData);
  995. }
  996. /**************************************************************************
  997. * @doc EXTERNAL AVIStreamRead
  998. *
  999. * @api LONG | AVIStreamRead | Reads audio or video data from a stream.
  1000. *
  1001. * @parm PAVISTREAM | pavi | Specifies a handle to an open stream.
  1002. *
  1003. * @parm LONG | lStart | Specifies the starting sample to read.
  1004. *
  1005. * @parm LONG | lSamples | Specifies the number of samples to read.
  1006. *
  1007. * @parm LPVOID | lpBuffer | Specifies a pointer to a buffer used to
  1008. * return the data.
  1009. *
  1010. * @parm LONG | cbBuffer | Specifies the size of buffer pointed to by <p lpBuffer>.
  1011. *
  1012. * @parm LONG FAR * | plBytes | Specifies a pointer to the location
  1013. * used to return number of bytes of data written into the
  1014. * buffer for <p lpBuffer>. <p plBytes> can be NULL.
  1015. *
  1016. * @parm LONG FAR * | plSamples | Specifies a pointer to the location
  1017. * used to return the number of samples written into the buffer for
  1018. * for <p lpBuffer>. <p plSamples> can be NULL.
  1019. *
  1020. * @comm If <p lpBuffer> is NULL, this function does not read
  1021. * any data; it returns information about the size of data
  1022. * that would be read.
  1023. *
  1024. * See <f AVIStreamLength> for a discussion of how sample numbers
  1025. * correspond to the data you want to read.
  1026. *
  1027. * @rdesc Returns zero if successful, or an error code. Use <p plBytes>
  1028. * and <p plSamples> to find out how much was actually read.
  1029. *
  1030. * Possible errors include:
  1031. *
  1032. * @flag AVIERR_BUFFERTOOSMALL | The buffer size <p cbBuffer> was
  1033. * too small to read in even a single sample of data.
  1034. *
  1035. * @flag AVIERR_MEMORY | There was not enough memory for some
  1036. * reason to complete the read operation.
  1037. *
  1038. * @flag AVIERR_FILEREAD | A disk error occurred while reading the
  1039. * file.
  1040. *
  1041. * @xref <f AVIFileGetStream> <f AVIStreamFindSample> <f AVIStreamWrite>
  1042. *
  1043. *************************************************************************/
  1044. STDAPI AVIStreamRead (PAVISTREAM pavi,
  1045. LONG lStart, LONG lSamples,
  1046. LPVOID lpBuffer, LONG cbBuffer,
  1047. LONG FAR * plBytes, LONG FAR * plSamples)
  1048. {
  1049. // if (pavi->StreamRead == NULL)
  1050. // return -1;
  1051. return pavi->Read(lStart, lSamples, lpBuffer, cbBuffer, plBytes, plSamples);
  1052. }
  1053. /**************************************************************************
  1054. * @doc EXTERNAL AVIStreamWrite
  1055. *
  1056. * @api LONG | AVIStreamWrite | Writes data to a stream.
  1057. *
  1058. * @parm PAVISTREAM | pavi | Specifies a handle to an open stream.
  1059. *
  1060. * @parm LONG | lStart | Specifies the starting sample to write.
  1061. *
  1062. * @parm LONG | lSamples | Specifies the number of samples to write.
  1063. *
  1064. * @parm LPVOID | lpBuffer | Specifies a pointer to buffer
  1065. * containing the data to write.
  1066. *
  1067. * @parm LONG | cbBuffer | Specifies the size of buffer used by <p lpBuffer>.
  1068. *
  1069. * @parm DWORD | dwFlags | Specifies any flags associated with this data.
  1070. * The following flags are defined:
  1071. *
  1072. * @flag AVIIF_KEYFRAME | Indicates this data does not rely on preceding
  1073. * data in the file.
  1074. *
  1075. * @parm LONG FAR * | plSampWritten | Specifies a pointer to a location
  1076. * used to return the number of samples written. This can be set
  1077. * to NULL.
  1078. *
  1079. * @parm LONG FAR * | plBytesWritten | Specifies a pointer to a location
  1080. * used to return the number of bytes written. This can be set
  1081. * to NULL.
  1082. *
  1083. * @comm The default AVI file handler only supports writing to the end
  1084. * of a stream. The WAVE file handler supports writing anywhere.
  1085. *
  1086. * This function overwrites existing data, rather than inserting
  1087. * new data.
  1088. *
  1089. * See <f AVIStreamLength> for a discussion of how sample numbers
  1090. * correspond to the data you want to read.
  1091. *
  1092. * @rdesc Returns zero if successful; otherwise it returns an error code.
  1093. *
  1094. * @xref <f AVIFileGetStream> <f AVIFileCreateStream> <f AVIStreamRead>
  1095. *
  1096. *************************************************************************/
  1097. STDAPI AVIStreamWrite (PAVISTREAM pavi,
  1098. LONG lStart, LONG lSamples,
  1099. LPVOID lpBuffer, LONG cbBuffer,
  1100. DWORD dwFlags,
  1101. LONG FAR *plSampWritten,
  1102. LONG FAR *plBytesWritten)
  1103. {
  1104. // if (pavi->StreamWrite == NULL)
  1105. // return -1;
  1106. return pavi->Write(lStart, lSamples, lpBuffer, cbBuffer,
  1107. dwFlags, plSampWritten, plBytesWritten);
  1108. }
  1109. /**************************************************************************
  1110. * @doc INTERNAL AVIStreamDelete
  1111. *
  1112. * @api LONG | AVIStreamDelete | Deletes data from a stream.
  1113. *
  1114. * @parm PAVISTREAM | pavi | Specifies a handle to an open stream.
  1115. *
  1116. * @parm LONG | lStart | Specifies the starting sample to delete.
  1117. *
  1118. * @parm LONG | lSamples | Specifies the number of samples to delete.
  1119. *
  1120. * @devnote This isn't implemented by anybody yet. Should it be? Wave files,
  1121. * for instance, would have to copy lots of data around....
  1122. *
  1123. * @rdesc Returns zero if successful; otherwise it returns an error code.
  1124. *
  1125. * @xref
  1126. *
  1127. *************************************************************************/
  1128. STDAPI AVIStreamDelete (PAVISTREAM pavi, LONG lStart, LONG lSamples)
  1129. {
  1130. // if (pavi->StreamDelete == NULL)
  1131. // return -1;
  1132. return pavi->Delete(lStart, lSamples);
  1133. }
  1134. #if 0
  1135. // !!! should this exist?
  1136. STDAPI AVIStreamClone (PAVISTREAM pavi, PAVISTREAM FAR *ppaviNew)
  1137. {
  1138. // if (pavi->StreamClone == NULL)
  1139. // return -1;
  1140. return pavi->Clone(ppaviNew);
  1141. }
  1142. #endif
  1143. /**************************************************************************
  1144. * @doc EXTERNAL AVIStreamStart
  1145. *
  1146. * @api LONG | AVIStreamStart | Returns the starting sample of the stream.
  1147. *
  1148. * @parm PAVISTREAM | pavi | Specifies a handle to an open stream.
  1149. *
  1150. * @rdesc Returns the starting sample number for the stream, or -1 on error.
  1151. *
  1152. * @comm See <f AVIStreamLength> for a discussion of how sample numbers
  1153. * correspond to the data you want to read.
  1154. *
  1155. * @xref <f AVIStreamSampleToTime> <f AVIStreamLength>
  1156. *
  1157. *************************************************************************/
  1158. STDAPI_(LONG) AVIStreamStart (PAVISTREAM pavi)
  1159. {
  1160. AVISTREAMINFO avistream;
  1161. pavi->Info(&avistream, sizeof(avistream));
  1162. return (LONG) avistream.dwStart;
  1163. }
  1164. /**************************************************************************
  1165. * @doc EXTERNAL AVIStreamLength
  1166. *
  1167. * @api LONG | AVIStreamLength | Returns the length of the stream in samples.
  1168. *
  1169. * @parm PAVISTREAM | pavi | Specifies a handle to an open stream.
  1170. *
  1171. * @devnote Currently, this doesn't call a handler function at all.
  1172. *
  1173. * @rdesc Returns the stream's length in samples, or -1 on error.
  1174. *
  1175. * @comm Values in samples can be converted to milliseconds using
  1176. * the <f AVIStreamSampleToTime> function.
  1177. *
  1178. * For video streams, each sample generally corresponds to a
  1179. * frame of video. There may, however, be sample numbers for
  1180. * which no video data is actually present: If <f AVIStreamRead>
  1181. * is called at those positions, it will return a data length
  1182. * of zero bytes. You can use <f AVIStreamFindSample> with the
  1183. * FIND_ANY flag to find sample numbers which actually have data.
  1184. *
  1185. * For audio streams, each sample corresponds to one "block"
  1186. * of data. Note the conflicting terminology here: if you're
  1187. * working with 22KHz ADPCM data, each block of audio data is
  1188. * 256 bytes, corresponding to about 500 "audio samples" which
  1189. * will be presented to the speaker each 22000th of a second.
  1190. * From the point of view of the AVIFile APIs, however, each 256-byte
  1191. * block is a single sample, because they cannot be subdivided.
  1192. *
  1193. * Note that the stream's starting position may not be zero; see
  1194. * <f AVIStreamStart>. Valid positions within a stream range from
  1195. * start to start+length; there is no actual data present at position
  1196. * start+length, but that corresponds to a time after the last data
  1197. * has been rendered.
  1198. *
  1199. * @xref <f AVIStreamInfo>
  1200. *
  1201. *************************************************************************/
  1202. STDAPI_(LONG) AVIStreamLength (PAVISTREAM pavi)
  1203. {
  1204. AVISTREAMINFO avistream;
  1205. HRESULT hr;
  1206. hr = pavi->Info(&avistream, sizeof(avistream));
  1207. if (hr != NOERROR) {
  1208. DPF("Error in AVIStreamLength!\n");
  1209. return 1;
  1210. }
  1211. return (LONG) avistream.dwLength;
  1212. }
  1213. /**************************************************************************
  1214. * @doc EXTERNAL AVIStreamTimeToSample
  1215. *
  1216. * @api LONG | AVIStreamTimeToSample | Converts from milliseconds to samples.
  1217. *
  1218. * @parm PAVISTREAM | pavi | Specifies a handle to an open stream.
  1219. *
  1220. * @parm LONG | lTime | Specifies the time in milliseconds.
  1221. *
  1222. * @devnote Currently, this doesn't call a handler function at all.
  1223. *
  1224. * @comm Samples typically correspond to audio samples or video frames.
  1225. * Other stream types might support different formats than these.
  1226. * @rdesc Returns the converted time, or -1 on error.
  1227. *
  1228. * @xref AVIStreamSampleToTime
  1229. *
  1230. *************************************************************************/
  1231. STDAPI_(LONG) AVIStreamTimeToSample (PAVISTREAM pavi, LONG lTime)
  1232. {
  1233. AVISTREAMINFO avistream;
  1234. HRESULT hr;
  1235. LONG lSample;
  1236. // Invalid time
  1237. if (lTime < 0)
  1238. return -1;
  1239. hr = pavi->Info(&avistream, sizeof(avistream));
  1240. if (hr != NOERROR || avistream.dwScale == 0) {
  1241. DPF("Error in AVIStreamTimeToSample!\n");
  1242. return lTime;
  1243. }
  1244. // This is likely to overflow if we're not careful for long AVIs
  1245. // so keep the 1000 inside the brackets.
  1246. if (avistream.dwRate / avistream.dwScale < 1000)
  1247. lSample = muldivrd32(lTime, avistream.dwRate, avistream.dwScale * 1000);
  1248. else
  1249. lSample = muldivru32(lTime, avistream.dwRate, avistream.dwScale * 1000);
  1250. lSample = min(max(lSample, (LONG) avistream.dwStart),
  1251. (LONG) (avistream.dwStart + avistream.dwLength));
  1252. return lSample;
  1253. }
  1254. /**************************************************************************
  1255. * @doc EXTERNAL AVIStreamSampleToTime
  1256. *
  1257. * @api LONG | AVIStreamSampleToTime | Converts from samples to milliseconds.
  1258. * Samples can correspond to blocks of audio samples, video frames, or other format
  1259. * depending on the stream type.
  1260. *
  1261. * @parm PAVISTREAM | pavi | Specifies a handle to an open stream.
  1262. *
  1263. * @parm LONG | lSample | Specifies the position information.
  1264. *
  1265. * @rdesc Returns the converted time, or -1 on error.
  1266. *
  1267. * @xref <f AVIStreamTimeToSample>
  1268. *
  1269. *************************************************************************/
  1270. STDAPI_(LONG) AVIStreamSampleToTime (PAVISTREAM pavi, LONG lSample)
  1271. {
  1272. AVISTREAMINFO avistream;
  1273. HRESULT hr;
  1274. hr = pavi->Info(&avistream, sizeof(avistream));
  1275. if (hr != NOERROR || avistream.dwRate == 0) {
  1276. DPF("Error in AVIStreamSampleToTime!\n");
  1277. return lSample;
  1278. }
  1279. lSample = min(max(lSample, (LONG) avistream.dwStart),
  1280. (LONG) (avistream.dwStart + avistream.dwLength));
  1281. // lSample * 1000 would overflow too easily
  1282. if (avistream.dwRate / avistream.dwScale < 1000)
  1283. return muldivrd32(lSample, avistream.dwScale * 1000, avistream.dwRate);
  1284. else
  1285. return muldivru32(lSample, avistream.dwScale * 1000, avistream.dwRate);
  1286. }
  1287. /**************************************************************************
  1288. * @doc EXTERNAL AVIStreamOpenFromFile
  1289. *
  1290. * @api LONG | AVIStreamOpenFromFile | This function provides a convenient
  1291. * way to open a single stream from a file.
  1292. *
  1293. * @parm PAVISTREAM FAR * | ppavi | Specifies a pointer to the location
  1294. * used to return the new stream handle.
  1295. *
  1296. * @parm LPCSTR | szFile | Specifies a zero-terminated string containing
  1297. * the name of the file to open.
  1298. *
  1299. * @parm DWORD | fccType | Specifies a four-character code
  1300. * indicating the type of stream to be opened.
  1301. * Zero indicates that any stream can be opened. The following
  1302. * definitions apply to the data commonly
  1303. * found in AVI streams:
  1304. *
  1305. * @flag streamtypeAUDIO | Indicates an audio stream.
  1306. * @flag streamtypeMIDI | Indicates a MIDI stream.
  1307. * @flag streamtypeTEXT | Indicates a text stream.
  1308. * @flag streamtypeVIDEO | Indicates a video stream.
  1309. *
  1310. * @parm LONG | lParam | Indicates which stream of the type specified in
  1311. * <p fccType> should actually be accessed.
  1312. *
  1313. * @parm UINT | mode | Specifies the mode to use when opening the file.
  1314. * This function can only open existing streams so the OF_CREATE
  1315. * mode flag cannot be used. See
  1316. * <f OpenFile> for more information about the available flags.
  1317. *
  1318. * @parm CLSID FAR * | pclsidHandler | Specifies a pointer to a class ID
  1319. * identifying the handler you want to use. If NULL, the system
  1320. * chooses one from the registration database based on the file
  1321. * extension or the file's RIFF type.
  1322. *
  1323. * @comm Balance each call to <f AVIStreamOpenFromFile> with a
  1324. * call to <f AVIStreamRelease> using the stream handle returned.
  1325. *
  1326. * This function calls <f AVIFileOpen>, <f AVIFileGetStream>, and
  1327. * <f AVIFileRelease>.
  1328. *
  1329. * @rdesc Returns zero if successful; otherwise it returns an error code.
  1330. *
  1331. * @xref <f AVIFileOpen> <f AVIFileGetStream>
  1332. *
  1333. *************************************************************************/
  1334. STDAPI AVIStreamOpenFromFile(PAVISTREAM FAR *ppavi,
  1335. LPCSTR szFile,
  1336. DWORD fccType, LONG lParam,
  1337. UINT mode, CLSID FAR *pclsidHandler)
  1338. {
  1339. PAVIFILE pfile;
  1340. HRESULT hr;
  1341. hr = AVIFileOpen(&pfile, szFile, mode, pclsidHandler);
  1342. if (!FAILED(GetScode(hr))) {
  1343. hr = AVIFileGetStream(pfile, ppavi, fccType, lParam);
  1344. AVIFileRelease(pfile); // the stream still has a reference to the file
  1345. }
  1346. return hr;
  1347. }
  1348. /**************************************************************************
  1349. * @doc EXTERNAL AVIStreamCreate
  1350. *
  1351. * @api LONG | AVIStreamCreate | Creates a stream not associated with any
  1352. * file.
  1353. *
  1354. * @parm PAVISTREAM FAR * | ppavi | Pointer to a location to return the
  1355. * new stream handle.
  1356. *
  1357. * @parm LONG | lParam1 | Specifies stream-handler specific information.
  1358. *
  1359. * @parm LONG | lParam2 | Specifies stream-handler specific information.
  1360. *
  1361. * @parm CLSID FAR * | pclsidHandler | Pointer to the class ID used
  1362. * for the stream.
  1363. *
  1364. * @comm Balance each call to <f AVIStreamCreate> with a
  1365. * call to <f AVIStreamRelease>.
  1366. *
  1367. * You should not need to call this function; functions like
  1368. * <f CreateEditableStream> and <f AVIMakeCompressedStream>
  1369. * use it internally.
  1370. *
  1371. * @rdesc Returns zero if successful; otherwise returns an error code.
  1372. *
  1373. * @xref <f AVIFileOpen> <f AVIFileGetStream>
  1374. *
  1375. *************************************************************************/
  1376. STDAPI AVIStreamCreate (PAVISTREAM FAR *ppavi, LONG lParam1, LONG lParam2,
  1377. CLSID FAR *pclsidHandler)
  1378. {
  1379. CLSID clsid;
  1380. HRESULT hr;
  1381. if (!iInit) {
  1382. return ResultFromScode(E_UNEXPECTED);
  1383. }
  1384. if (pclsidHandler)
  1385. clsid = *pclsidHandler;
  1386. else {
  1387. return ResultFromScode(REGDB_E_CLASSNOTREG);
  1388. }
  1389. if (FAILED(GetScode(hr = CoCreateInstance((REFCLSID) clsid,
  1390. NULL, CLSCTX_INPROC,
  1391. (REFIID) IID_IAVIStream,
  1392. (void FAR* FAR*)ppavi))))
  1393. return hr;
  1394. if (FAILED(GetScode(hr = (*ppavi)->Create(lParam1, lParam2)))) {
  1395. (*ppavi)->Release();
  1396. // AVIStreamExit();
  1397. }
  1398. return AVIERR_OK;
  1399. }
  1400. /**************************************************************************
  1401. * @doc EXTERNAL AVIStreamBeginStreaming
  1402. *
  1403. * @api LONG | AVIStreamBeginStreaming | Specifies the parameters for
  1404. * streaming and lets a stream handler prepare for streaming.
  1405. *
  1406. * @parm PAVISTREAM | pavi | Specifies a pointer to a stream.
  1407. *
  1408. * @parm LONG | lStart | Specifies the starting point for streaming.
  1409. *
  1410. * @parm LONG | lEnd | Specifies the ending point for streaming.
  1411. *
  1412. * @parm LONG | lRate | Specifies the speed at which the file will be
  1413. * read relative to its natural speed. Specify 1000 for the normal speed.
  1414. *
  1415. * @comm Many stream implementations ignore this function.
  1416. *
  1417. * @rdesc Returns zero if successful; otherwise returns an error code.
  1418. *
  1419. * @xref <f AVIStreamEndStreaming>
  1420. *
  1421. *************************************************************************/
  1422. STDAPI AVIStreamBeginStreaming(PAVISTREAM pavi,
  1423. LONG lStart,
  1424. LONG lEnd,
  1425. LONG lRate)
  1426. {
  1427. IAVIStreaming FAR * pi;
  1428. HRESULT hr;
  1429. if (FAILED(GetScode(pavi->QueryInterface(IID_IAVIStreaming,
  1430. (void FAR* FAR*) &pi))))
  1431. return AVIERR_OK;
  1432. hr = pi->Begin(lStart, lEnd, lRate);
  1433. pi->Release();
  1434. return hr;
  1435. }
  1436. /**************************************************************************
  1437. * @doc EXTERNAL AVIStreamEndStreaming
  1438. *
  1439. * @api LONG | AVIStreamEndStreaming | Ends streaming.
  1440. *
  1441. * @parm PAVISTREAM | pavi | Specifies a pointer to a stream.
  1442. *
  1443. * @comm Many stream implementations ignore this function.
  1444. *
  1445. * @rdesc Returns zero if successful; otherwise it returns an error code.
  1446. *
  1447. * @xref AVIStreamBeginStreaming
  1448. *
  1449. *************************************************************************/
  1450. STDAPI AVIStreamEndStreaming(PAVISTREAM pavi)
  1451. {
  1452. IAVIStreaming FAR * pi;
  1453. HRESULT hr;
  1454. if (FAILED(GetScode(pavi->QueryInterface(IID_IAVIStreaming, (LPVOID FAR *) &pi))))
  1455. return AVIERR_OK;
  1456. hr = pi->End();
  1457. pi->Release();
  1458. return hr;
  1459. }
  1460. #if 0
  1461. /*******************************************************************
  1462. * @doc INTERNAL AVIStreamHasChanged
  1463. *
  1464. * @api LONG | AVIStreamHasChanged | This function forces an update
  1465. * of the strem information for the specified stream.
  1466. *
  1467. * @parm PAVISTREAM | pavi | Interface pointer for an AVI stream instance.
  1468. *
  1469. * @rdesc Returns AVIERR_OK on success.
  1470. *
  1471. ****************************************************************/
  1472. STDAPI AVIStreamHasChanged(PAVISTREAM pavi)
  1473. {
  1474. pavi->lFrame = -4224; // bogus value
  1475. AVIStreamInfo(pavi, &pavi->avistream, sizeof(pavi->avistream));
  1476. // !!! Only need to do this if format changes?
  1477. AVIReleaseCachedData(pavi);
  1478. return AVIERR_OK;
  1479. }
  1480. #endif
  1481. static SZCODE aszRegCompressors[] = "AVIFile\\Compressors\\%.4ls";
  1482. /*******************************************************************
  1483. * @doc EXTERNAL AVIMakeCompressedStream
  1484. *
  1485. * @api HRESULT | AVIMakeCompressedStream | Returns a pointer to a
  1486. * compressed stream created from an uncompressed stream.
  1487. * The uncompressed stream is compressed using
  1488. * the compression options specified.
  1489. *
  1490. * @parm PAVISTREAM FAR * | ppsCompressed | Specifies a pointer to
  1491. * the location used to return the compressed stream pointer.
  1492. *
  1493. * @parm PAVISTREAM | psSource | Specifies a pointer to the stream to be compressed.
  1494. *
  1495. * @parm AVICOMPRESSOPTIONS FAR * | lpOptions | Specifies a pointer to a
  1496. * structure indicating the type compression to use and the options
  1497. * to apply.
  1498. *
  1499. * @parm CLSID FAR * | pclsidHandler | Specifies a pointer to a
  1500. * class ID used to create the stream.
  1501. *
  1502. * @comm This supports both audio and video compression. Applications
  1503. * can use the created stream for reading or writing.
  1504. *
  1505. * For video compression, either specify a handler to use or specify
  1506. * the format for the compressed data.
  1507. *
  1508. * For audio compression, you can only specify a format for the compressed
  1509. * data.
  1510. *
  1511. * @rdesc Returns AVIERR_OK on success, or an error code.
  1512. * Possible errors include:
  1513. *
  1514. * @flag AVIERR_NOCOMPRESSOR | No suitable compressor can be found.
  1515. *
  1516. * @flag AVIERR_MEMORY | There was not enough memory to complete the operation.
  1517. *
  1518. * @flag AVIERR_UNSUPPORTED | Compression is not supported for this type
  1519. * of data. This error may be returned if you try to compress
  1520. * data that is not audio or video.
  1521. *
  1522. *
  1523. *
  1524. ****************************************************************/
  1525. STDAPI AVIMakeCompressedStream(
  1526. PAVISTREAM FAR * ppsCompressed,
  1527. PAVISTREAM psSource,
  1528. AVICOMPRESSOPTIONS FAR * lpOptions,
  1529. CLSID FAR *pclsidHandler)
  1530. {
  1531. CLSID clsid;
  1532. char achKey[100];
  1533. char achClass[100];
  1534. LONG lcbClass;
  1535. AVISTREAMINFO strhdr;
  1536. HRESULT hr;
  1537. *ppsCompressed = NULL;
  1538. if (pclsidHandler) {
  1539. clsid = *pclsidHandler;
  1540. } else {
  1541. if (FAILED(GetScode(hr = AVIStreamInfo(psSource,
  1542. &strhdr,
  1543. sizeof(strhdr)))))
  1544. return hr;
  1545. // Look up the stream type in the registration database to find
  1546. // the appropriate compressor....
  1547. wsprintf(achKey, aszRegCompressors, (LPSTR) &strhdr.fccType);
  1548. lcbClass = sizeof(achClass);
  1549. RegQueryValue(HKEY_CLASSES_ROOT, achKey, achClass, &lcbClass);
  1550. if (FAILED(GetScode(CLSIDFromString(achClass, &clsid))))
  1551. return ResultFromScode(AVIERR_UNSUPPORTED);
  1552. }
  1553. if (FAILED(GetScode(hr = CoCreateInstance((REFCLSID) clsid,
  1554. NULL, CLSCTX_INPROC,
  1555. (REFIID) IID_IAVIStream,
  1556. (void FAR* FAR*)ppsCompressed))))
  1557. return hr; // !!! PropagateHResult?
  1558. if (FAILED(GetScode(hr = (*ppsCompressed)->Create((LONG) psSource,
  1559. (LONG) lpOptions)))) {
  1560. (*ppsCompressed)->Release();
  1561. *ppsCompressed = NULL;
  1562. return hr;
  1563. }
  1564. return AVIERR_OK;
  1565. }
  1566. typedef struct {
  1567. char achClsid[64];
  1568. char achExtString[128];
  1569. } TEMPFILTER, FAR * LPTEMPFILTER;
  1570. SZCODE aszAnotherExtension[] = ";*.%s";
  1571. /***************************************************************************
  1572. *
  1573. * @doc INTERNAL MCIAVI
  1574. *
  1575. * @api LONG | atol | local version of atol
  1576. *
  1577. ***************************************************************************/
  1578. static LONG NEAR PASCAL atol(char FAR *sz)
  1579. {
  1580. LONG l = 0;
  1581. while (*sz)
  1582. l = l*10 + *sz++ - '0';
  1583. return l;
  1584. }
  1585. /*******************************************************************
  1586. * @doc EXTERNAL AVIBuildFilter
  1587. *
  1588. * @api HRESULT | AVIBuildFilter | Builds a filter specification for passing
  1589. * to <f GetOpenFileName> or <f GetSaveFileName>.
  1590. *
  1591. * @parm LPSTR | lpszFilter | Pointer to buffer where the filter string
  1592. * should be returned.
  1593. *
  1594. * @parm LONG | cbFilter | Size of buffer pointed to by <p lpszFilter>.
  1595. *
  1596. * @parm BOOL | fSaving | Indicates whether the filter should include only
  1597. * formats that can be written, or all formats that can be read.
  1598. *
  1599. * @rdesc Returns AVIERR_OK on success.
  1600. *
  1601. * @comm This function does not check if the DLLs referenced
  1602. * in the registration database actually exist.
  1603. *
  1604. ****************************************************************/
  1605. STDAPI AVIBuildFilter(LPSTR lpszFilter, LONG cbFilter, BOOL fSaving)
  1606. {
  1607. #define MAXFILTERS 256
  1608. LPTEMPFILTER lpf;
  1609. int i;
  1610. int cf = 0;
  1611. HKEY hkey;
  1612. LONG lRet;
  1613. DWORD dwSubKey;
  1614. char ach[128];
  1615. char ach2[128];
  1616. char achExt[10];
  1617. LONG cb;
  1618. char achAllFiles[40];
  1619. int cbAllFiles;
  1620. // This string has a NULL in it, so remember its length for real....
  1621. cbAllFiles = LoadString(ghMod,
  1622. IDS_ALLFILES,
  1623. achAllFiles,
  1624. sizeof(achAllFiles));
  1625. for (i = 0; i < cbAllFiles; i++)
  1626. if (achAllFiles[i] == '@')
  1627. achAllFiles[i] = '\0';
  1628. lpf = (LPTEMPFILTER) GlobalAllocPtr(GHND, sizeof(TEMPFILTER) * MAXFILTERS);
  1629. if (!lpf) {
  1630. return ResultFromScode(AVIERR_MEMORY);
  1631. }
  1632. lRet = RegOpenKey(HKEY_CLASSES_ROOT, aszRegExt, &hkey);
  1633. if (lRet != ERROR_SUCCESS) {
  1634. }
  1635. // Make sure that AVI files come first in the list....
  1636. // !!! Should use StringFromClsid here!
  1637. _fstrcpy(lpf[1].achClsid, "{00020000-0000-0000-C000-000000000046}");
  1638. cf = 1;
  1639. //
  1640. // First, scan through the Extensions list looking for all of the
  1641. // handlers that are installed
  1642. //
  1643. for (dwSubKey = 0; ; dwSubKey++) {
  1644. lRet = RegEnumKey(hkey, dwSubKey, achExt, sizeof(achExt));
  1645. if (lRet != ERROR_SUCCESS) {
  1646. break;
  1647. }
  1648. cb = sizeof(ach);
  1649. lRet = RegQueryValue(hkey, achExt, ach, &cb);
  1650. if (lRet != ERROR_SUCCESS) {
  1651. break;
  1652. }
  1653. //
  1654. // See if we've seen this handler before
  1655. //
  1656. for (i = 1; i <= cf; i++) {
  1657. if (_fstrcmp(ach, lpf[i].achClsid) == 0) {
  1658. break;
  1659. }
  1660. }
  1661. //
  1662. // If not, add it to our list of handlers
  1663. //
  1664. if (i == cf + 1) {
  1665. if (cf == MAXFILTERS) {
  1666. DPF("Too many filters!\n");
  1667. continue;
  1668. }
  1669. _fstrcpy(lpf[i].achClsid, ach);
  1670. cb = sizeof(ach);
  1671. wsprintf(ach2, "%s\\AVIFile", (LPSTR) ach);
  1672. lRet = RegQueryValue(hkey, ach2, ach, &cb);
  1673. if (lRet == 0) {
  1674. lRet = atol(ach);
  1675. if (fSaving) {
  1676. if (!(lRet & AVIFILEHANDLER_CANWRITE))
  1677. continue;
  1678. } else {
  1679. if (!(lRet & AVIFILEHANDLER_CANREAD))
  1680. continue;
  1681. }
  1682. }
  1683. cf++;
  1684. }
  1685. wsprintf(ach, aszAnotherExtension, (LPSTR) achExt);
  1686. _fstrcat(lpf[i].achExtString, lpf[i].achExtString[0] ?
  1687. ach : ach + 1);
  1688. _fstrcat(lpf[0].achExtString, lpf[0].achExtString[0] ?
  1689. ach : ach + 1);
  1690. }
  1691. RegCloseKey(hkey);
  1692. lRet = RegOpenKey(HKEY_CLASSES_ROOT, aszRegClsid, &hkey);
  1693. if (lRet != ERROR_SUCCESS) {
  1694. }
  1695. //
  1696. // Now, scan through our list of handlers and build up the
  1697. // filter to use....
  1698. //
  1699. for (i = 0; i <= cf; i++) {
  1700. if (i == 0) {
  1701. cb = wsprintf(lpszFilter, "All multimedia files") + 1; // !!!
  1702. } else {
  1703. cb = sizeof(ach);
  1704. lRet = RegQueryValue(hkey, lpf[i].achClsid, ach, &cb);
  1705. if (cbFilter < (LONG)(_fstrlen(lpf[i].achExtString) +
  1706. (LONG)_fstrlen(ach) + 10)) {
  1707. break; // !!!
  1708. }
  1709. cb = wsprintf(lpszFilter, "%s", // "%s (%s)", Todd doesn't like this
  1710. (LPSTR) ach, (LPSTR) lpf[i].achExtString) + 1;
  1711. }
  1712. cbFilter -= cb;
  1713. lpszFilter += cb;
  1714. _fstrncpy(lpszFilter, lpf[i].achExtString, (int) cbFilter);
  1715. cbFilter -= _fstrlen(lpf[i].achExtString) + 1;
  1716. lpszFilter += _fstrlen(lpf[i].achExtString) + 1;
  1717. if (cbFilter <= 0) {
  1718. GlobalFreePtr(lpf);
  1719. return ResultFromScode(AVIERR_BUFFERTOOSMALL);
  1720. }
  1721. }
  1722. if (cbFilter > cbAllFiles) {
  1723. _fmemcpy(lpszFilter, achAllFiles, cbAllFiles);
  1724. cbFilter -= cbAllFiles;
  1725. lpszFilter += cbAllFiles;
  1726. }
  1727. RegCloseKey(hkey);
  1728. *lpszFilter++ = '\0';
  1729. --cbFilter;
  1730. GlobalFreePtr(lpf);
  1731. return AVIERR_OK;
  1732. }
  1733. /*****************************************************************************
  1734. *
  1735. * dprintf() is called by the DPF macro if DEBUG is defined at compile time.
  1736. *
  1737. * The messages will be send to COM1: like any debug message. To
  1738. * enable debug output, add the following to WIN.INI :
  1739. *
  1740. * [debug]
  1741. * ICSAMPLE=1
  1742. *
  1743. ****************************************************************************/
  1744. #ifdef DEBUG
  1745. //
  1746. // I wish languages would make up their mind about defines!!!!!
  1747. //
  1748. #ifndef WINDLL
  1749. #define WINDLL
  1750. #endif
  1751. #ifndef _WINDLL
  1752. #define _WINDLL
  1753. #endif
  1754. #ifndef __WINDLL
  1755. #define __WINDLL
  1756. #endif
  1757. #include <stdarg.h>
  1758. #define MODNAME "AVIFILE"
  1759. static int iDebug = -1;
  1760. void cdecl dprintf(LPSTR szFormat, ...)
  1761. {
  1762. char ach[128];
  1763. if (iDebug == -1)
  1764. iDebug = GetProfileIntA("Debug", MODNAME, 0);
  1765. if (iDebug < 1)
  1766. return;
  1767. va_list va;
  1768. va_start(va, szFormat);
  1769. if (szFormat[0] == '!')
  1770. ach[0]=0, szFormat++;
  1771. else
  1772. lstrcpyA(ach, MODNAME ": ");
  1773. wvsprintfA(ach+lstrlenA(ach),szFormat,(LPSTR)va);
  1774. va_end(va);
  1775. // lstrcatA(ach, "\r\r\n");
  1776. OutputDebugStringA(ach);
  1777. }
  1778. void cdecl dprintf2(LPSTR szFormat, ...)
  1779. {
  1780. char ach[128];
  1781. if (iDebug == -1)
  1782. iDebug = GetProfileIntA("Debug", MODNAME, 0);
  1783. if (iDebug < 2)
  1784. return;
  1785. va_list va;
  1786. va_start(va, szFormat);
  1787. if (szFormat[0] == '!')
  1788. ach[0]=0, szFormat++;
  1789. else
  1790. lstrcpyA(ach, MODNAME ": ");
  1791. wvsprintfA(ach+lstrlenA(ach),szFormat,(LPSTR)va);
  1792. va_end(va);
  1793. // lstrcatA(ach, "\r\r\n");
  1794. OutputDebugStringA(ach);
  1795. }
  1796. void cdecl dprintf3(LPSTR szFormat, ...)
  1797. {
  1798. char ach[128];
  1799. if (iDebug == -1)
  1800. iDebug = GetProfileIntA("Debug", MODNAME, 0);
  1801. if (iDebug < 3)
  1802. return;
  1803. va_list va;
  1804. va_start(va, szFormat);
  1805. if (szFormat[0] == '!')
  1806. ach[0]=0, szFormat++;
  1807. else
  1808. lstrcpyA(ach, MODNAME ": ");
  1809. wvsprintfA(ach+lstrlenA(ach),szFormat,(LPSTR)va);
  1810. va_end(va);
  1811. // lstrcatA(ach, "\r\r\n");
  1812. OutputDebugStringA(ach);
  1813. }
  1814. #endif
  1815. #ifdef DEBUG
  1816. /* _Assert(szExpr, szFile, iLine)
  1817. *
  1818. * If <fExpr> is TRUE, then do nothing. If <fExpr> is FALSE, then display
  1819. * an "assertion failed" message box allowing the user to abort the program,
  1820. * enter the debugger (the "Retry" button), or igore the error.
  1821. *
  1822. * <szFile> is the name of the source file; <iLine> is the line number
  1823. * containing the _Assert() call.
  1824. */
  1825. void FAR PASCAL
  1826. _Assert(char *szExp, char *szFile, int iLine)
  1827. {
  1828. static char ach[300]; // debug output (avoid stack overflow)
  1829. int id;
  1830. void FAR PASCAL DebugBreak(void);
  1831. /* display error message */
  1832. if (szExp)
  1833. wsprintfA(ach, "(%s)\nFile %s, line %d", (LPSTR)szExp, (LPSTR)szFile, iLine);
  1834. else
  1835. wsprintfA(ach, "File %s, line %d", (LPSTR)szFile, iLine);
  1836. MessageBeep(MB_ICONHAND);
  1837. id = MessageBoxA(NULL, ach, "Assertion Failed",
  1838. #ifdef BIDI
  1839. MB_RTL_READING |
  1840. #endif
  1841. MB_SYSTEMMODAL | MB_ICONHAND | MB_ABORTRETRYIGNORE);
  1842. /* abort, debug, or ignore */
  1843. switch (id)
  1844. {
  1845. case IDABORT:
  1846. FatalAppExit(0, "Good Bye");
  1847. break;
  1848. case IDRETRY:
  1849. /* break into the debugger */
  1850. DebugBreak();
  1851. break;
  1852. case IDIGNORE:
  1853. /* ignore the assertion failure */
  1854. break;
  1855. }
  1856. }
  1857. #endif