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

2682 lines
65 KiB

  1. //==========================================================================;
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1992 - 1994 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. // aafile.c
  13. //
  14. // Description:
  15. //
  16. //
  17. //
  18. //==========================================================================;
  19. #include <windows.h>
  20. #include <windowsx.h>
  21. #include <mmsystem.h>
  22. #include <memory.h>
  23. #include <mmreg.h>
  24. #include <msacm.h>
  25. #include "appport.h"
  26. #include "waveio.h"
  27. #include "acmapp.h"
  28. #include "debug.h"
  29. //==========================================================================;
  30. //
  31. //
  32. //
  33. //
  34. //==========================================================================;
  35. //--------------------------------------------------------------------------;
  36. //
  37. // DWORD DosGetFileAttributes
  38. //
  39. // Description:
  40. // INT 21 - DOS 2+ - GET FILE ATTRIBUTES
  41. // AX = 4300h
  42. // DS:DX -> ASCIZ file name or directory name without trailing slash
  43. //
  44. // Return: CF set on error
  45. // AX = error code (01h,02h,03h,05h) (see AH=59h)
  46. // CF clear if successful
  47. // CX = file attributes (see AX=4301h)
  48. //
  49. // SeeAlso: AX=4301h, INT 2F/AX=110Fh
  50. //
  51. // --------
  52. // INT 21 - DOS 2+ - PUT FILE ATTRIBUTES (CHMOD)
  53. // AX = 4301h
  54. // CX = file attribute bits
  55. // bit 0 = read only
  56. // 1 = hidden file
  57. // 2 = system file
  58. // 3 = volume label
  59. // 4 = subdirectory
  60. // 5 = written since backup ("archive" bit)
  61. // 8 = shareable (Novell NetWare)
  62. // DS:DX -> ASCIZ file name
  63. //
  64. // Return: CF set on error
  65. // AX = error code (01h,02h,03h,05h) (see AH=59h)
  66. // CF clear if successful
  67. //
  68. // Note: will not change volume label or directory attributes
  69. //
  70. // SeeAlso: AX=4300h, INT 2F/AX=110Eh
  71. //
  72. //
  73. // Arguments:
  74. // LPTSTR pszFilePath:
  75. //
  76. // Return (DWORD):
  77. //
  78. //
  79. //--------------------------------------------------------------------------;
  80. #ifndef WIN32
  81. #pragma optimize("", off)
  82. DWORD FNGLOBAL DosGetFileAttributes
  83. (
  84. LPTSTR pszFilePath
  85. )
  86. {
  87. WORD fwDosAttributes;
  88. _asm
  89. {
  90. push ds
  91. mov ax, 4300h
  92. lds dx, pszFilePath
  93. int 21h
  94. jnc Get_File_Attributes_Continue
  95. xor cx, cx
  96. Get_File_Attributes_Continue:
  97. mov fwDosAttributes, cx
  98. pop ds
  99. }
  100. return ((DWORD)fwDosAttributes);
  101. } // DosGetFileAttributes()
  102. #pragma optimize("", on)
  103. #endif
  104. //--------------------------------------------------------------------------;
  105. //
  106. // DWORD DosGetDateTime
  107. //
  108. // Description:
  109. //
  110. // Arguments:
  111. // HFILE hf:
  112. //
  113. // Return (DWORD):
  114. //
  115. //
  116. //--------------------------------------------------------------------------;
  117. #ifndef WIN32
  118. #pragma optimize("", off)
  119. DWORD FNGLOBAL DosGetDateTime
  120. (
  121. HFILE hf
  122. )
  123. {
  124. WORD wDosDate;
  125. WORD wDosTime;
  126. _asm
  127. {
  128. mov ax, 5700h
  129. mov bx, hf
  130. int 21h
  131. jnc Get_Date_Time_Continue
  132. xor cx, cx
  133. xor dx, dx
  134. Get_Date_Time_Continue:
  135. mov wDosDate, dx
  136. mov wDosTime, cx
  137. }
  138. return ((DWORD)MAKELONG(wDosDate, wDosTime));
  139. } // DosGetDateTime()
  140. #pragma optimize("", on)
  141. #endif
  142. //==========================================================================;
  143. //
  144. //
  145. //
  146. //
  147. //==========================================================================;
  148. //--------------------------------------------------------------------------;
  149. //
  150. // BOOL AcmAppFileSaveModified
  151. //
  152. // Description:
  153. // This function tests if the current file has been modified, and
  154. // if it has it gives the option of saving the file.
  155. //
  156. // NOTE! This function does *NOT* clear the modified bit for the
  157. // file. The calling function must do this if necessary.
  158. //
  159. // Arguments:
  160. // HWND hwnd: Handle to main window.
  161. //
  162. // PACMAPPFILEDESC paafd: Pointer to file descriptor.
  163. //
  164. // Return (BOOL):
  165. // Returns TRUE if the calling function should continue--the file was
  166. // either saved or the user does not wish to save it. Returns FALSE
  167. // if the calling function should cancel its operation--the user
  168. // wants to keep the data, but it has not been saved.
  169. //
  170. //--------------------------------------------------------------------------;
  171. BOOL FNGLOBAL AcmAppFileSaveModified
  172. (
  173. HWND hwnd,
  174. PACMAPPFILEDESC paafd
  175. )
  176. {
  177. BOOL f;
  178. int n;
  179. //
  180. // check if the contents of the file have been modified--if they have
  181. // then ask the user if they want to save the current contents...
  182. //
  183. f = (0 != (ACMAPPFILEDESC_STATEF_MODIFIED & paafd->fdwState));
  184. if (f)
  185. {
  186. //
  187. // display an appropriate message box asking for the user's opinion
  188. //
  189. n = AppMsgBox(hwnd, MB_YESNOCANCEL | MB_ICONQUESTION,
  190. TEXT("The file '%s' has been modified. Do you want to save these changes?"),
  191. (LPSTR)paafd->szFilePath);
  192. switch (n)
  193. {
  194. case IDYES:
  195. f = AppFileSave(hwnd, paafd, FALSE);
  196. if (f)
  197. break;
  198. // -- fall through --
  199. case IDCANCEL:
  200. //
  201. // don't continue!
  202. //
  203. return (FALSE);
  204. case IDNO:
  205. break;
  206. }
  207. }
  208. //
  209. // ok to continue...
  210. //
  211. return (TRUE);
  212. } // AcmAppFileSaveModified()
  213. //--------------------------------------------------------------------------;
  214. //
  215. // BOOL AcmAppFileNew
  216. //
  217. // Description:
  218. //
  219. // Arguments:
  220. // HWND hwnd: Handle to main window.
  221. //
  222. // PACMAPPFILEDESC paafd: Pointer to file descriptor.
  223. //
  224. // Return (BOOL):
  225. //
  226. //--------------------------------------------------------------------------;
  227. BOOL FNGLOBAL AcmAppFileNew
  228. (
  229. HWND hwnd,
  230. PACMAPPFILEDESC paafd
  231. )
  232. {
  233. TCHAR szFilePath[APP_MAX_FILE_PATH_CHARS];
  234. TCHAR szFileTitle[APP_MAX_FILE_TITLE_CHARS];
  235. MMRESULT mmr;
  236. LPWAVEFORMATEX pwfx;
  237. DWORD cbwfx;
  238. BOOL f;
  239. ACMFORMATCHOOSE afc;
  240. HMMIO hmmio;
  241. MMCKINFO ckRIFF;
  242. MMCKINFO ck;
  243. DWORD cSamples;
  244. if (!gfAcmAvailable)
  245. {
  246. AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
  247. TEXT("AcmAppFileNew() called when ACM is not installed!"));
  248. return (FALSE);
  249. }
  250. //
  251. // test for a modified file first...
  252. //
  253. f = AcmAppFileSaveModified(hwnd, paafd);
  254. if (!f)
  255. return (FALSE);
  256. //
  257. // get a filename
  258. //
  259. szFileTitle[0] = '\0';
  260. szFilePath[0] = '\0';
  261. f = AppGetFileName(hwnd, szFilePath, szFileTitle, APP_GETFILENAMEF_SAVE);
  262. if (!f)
  263. return (FALSE);
  264. //
  265. //
  266. //
  267. //
  268. //
  269. //
  270. mmr = acmMetrics(NULL, ACM_METRIC_MAX_SIZE_FORMAT, &cbwfx);
  271. if (MMSYSERR_NOERROR != mmr)
  272. {
  273. AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
  274. TEXT("AcmAppFileNew() acmMetrics failed mmr=%u!"), mmr);
  275. return (FALSE);
  276. }
  277. pwfx = (LPWAVEFORMATEX)GlobalAllocPtr(GHND, cbwfx);
  278. if (NULL == pwfx)
  279. {
  280. AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
  281. TEXT("AcmAppFileNew() GlobalAllocPtr(%lu) failed!"), cbwfx);
  282. return (FALSE);
  283. }
  284. //
  285. //
  286. //
  287. //
  288. f = FALSE;
  289. //
  290. // initialize the ACMFORMATCHOOSE members
  291. //
  292. memset(&afc, 0, sizeof(afc));
  293. afc.cbStruct = sizeof(afc);
  294. afc.fdwStyle = ACMFORMATCHOOSE_STYLEF_SHOWHELP;
  295. afc.hwndOwner = hwnd;
  296. afc.pwfx = pwfx;
  297. afc.cbwfx = cbwfx;
  298. afc.pszTitle = TEXT("ACM App: New Format Choice");
  299. afc.szFormatTag[0] = '\0';
  300. afc.szFormat[0] = '\0';
  301. afc.pszName = NULL;
  302. afc.cchName = 0;
  303. afc.fdwEnum = 0;
  304. afc.pwfxEnum = NULL;
  305. afc.hInstance = NULL;
  306. afc.pszTemplateName = NULL;
  307. afc.lCustData = 0L;
  308. afc.pfnHook = NULL;
  309. //
  310. //
  311. //
  312. mmr = acmFormatChoose(&afc);
  313. if (MMSYSERR_NOERROR != mmr)
  314. {
  315. if (ACMERR_CANCELED != mmr)
  316. {
  317. AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
  318. TEXT("acmFormatChoose() failed with error = %u!"), mmr);
  319. }
  320. GlobalFreePtr(pwfx);
  321. return (FALSE);
  322. }
  323. //
  324. //
  325. //
  326. hmmio = mmioOpen(szFilePath,
  327. NULL,
  328. MMIO_CREATE | MMIO_WRITE | MMIO_EXCLUSIVE | MMIO_ALLOCBUF);
  329. if (NULL == hmmio)
  330. {
  331. AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
  332. TEXT("AcmAppFileNew() cannot create file '%s'!"), (LPSTR)szFilePath);
  333. GlobalFreePtr(pwfx);
  334. return (FALSE);
  335. }
  336. //
  337. // create the RIFF chunk of form type 'WAVE'
  338. //
  339. ckRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E');
  340. ckRIFF.cksize = 0L;
  341. mmioCreateChunk(hmmio, &ckRIFF, MMIO_CREATERIFF);
  342. //
  343. // now create the destination fmt, fact, and data chunks _in that order_
  344. //
  345. // hmmio is now descended into the 'RIFF' chunk--create the format chunk
  346. // and write the format header into it
  347. //
  348. cbwfx = SIZEOF_WAVEFORMATEX(pwfx);
  349. ck.ckid = mmioFOURCC('f', 'm', 't', ' ');
  350. ck.cksize = 0L;
  351. mmioCreateChunk(hmmio, &ck, 0);
  352. mmioWrite(hmmio, (HPSTR)pwfx, cbwfx);
  353. mmioAscend(hmmio, &ck, 0);
  354. //
  355. // create the 'fact' chunk (not necessary for PCM--but is nice to have)
  356. // since we are not writing any data to this file (yet), we set the
  357. // samples contained in the file to 0..
  358. //
  359. ck.ckid = mmioFOURCC('f', 'a', 'c', 't');
  360. ck.cksize = 0L;
  361. mmioCreateChunk(hmmio, &ck, 0);
  362. cSamples = 0L;
  363. mmioWrite(hmmio, (HPSTR)&cSamples, sizeof(DWORD));
  364. mmioAscend(hmmio, &ck, 0);
  365. //
  366. // create the data chunk with no data..
  367. //
  368. ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
  369. ck.cksize = 0L;
  370. mmioCreateChunk(hmmio, &ck, 0);
  371. mmioAscend(hmmio, &ck, 0);
  372. mmioAscend(hmmio, &ckRIFF, 0);
  373. mmioClose(hmmio, 0);
  374. //
  375. //
  376. //
  377. GlobalFreePtr(pwfx);
  378. lstrcpy(paafd->szFilePath, szFilePath);
  379. lstrcpy(paafd->szFileTitle, szFileTitle);
  380. return (AcmAppFileOpen(hwnd, paafd));
  381. //
  382. // success
  383. //
  384. return (TRUE);
  385. } // AcmAppFileNew()
  386. //--------------------------------------------------------------------------;
  387. //
  388. // BOOL AcmAppFileOpen
  389. //
  390. // Description:
  391. // This function opens the specified file and get the important info
  392. // from it.
  393. //
  394. // NOTE! This function does NOT check for a modified file! It is
  395. // assumed that the calling function took care of everything before
  396. // calling this function.
  397. //
  398. // Arguments:
  399. // HWND hwnd: Handle to main window.
  400. //
  401. // PACMAPPFILEDESC paafd: Pointer to file descriptor.
  402. //
  403. // Return (BOOL):
  404. // The return value is TRUE if the function is successful. It is FALSE
  405. // if an error occurred. If an error does occur, then the contents
  406. // of the file descriptor will remain unchanged.
  407. //
  408. //
  409. //--------------------------------------------------------------------------;
  410. BOOL FNGLOBAL AcmAppFileOpen
  411. (
  412. HWND hwnd,
  413. PACMAPPFILEDESC paafd
  414. )
  415. {
  416. WAVEIOCB wio;
  417. WIOERR werr;
  418. #ifdef WIN32
  419. HANDLE hf;
  420. #else
  421. #define SEEK_SET 0 // flags for _lseek
  422. #define SEEK_CUR 1
  423. #define SEEK_END 2
  424. HFILE hf;
  425. OFSTRUCT of;
  426. DWORD dw;
  427. #endif
  428. DWORD cbFileSize;
  429. BOOL fReturn;
  430. //
  431. // blow previous stuff...
  432. //
  433. if (NULL != paafd->pwfx)
  434. {
  435. GlobalFreePtr(paafd->pwfx);
  436. paafd->pwfx = NULL;
  437. paafd->cbwfx = 0;
  438. }
  439. paafd->fdwState = 0L;
  440. paafd->cbFileSize = 0L;
  441. paafd->uDosChangeDate = 0;
  442. paafd->uDosChangeTime = 0;
  443. paafd->fdwFileAttributes = 0L;
  444. paafd->dwDataBytes = 0L;
  445. paafd->dwDataSamples = 0L;
  446. //
  447. // open the file for reading..
  448. //
  449. #ifdef WIN32
  450. hf = CreateFile(paafd->szFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
  451. OPEN_EXISTING, 0, 0);
  452. if (INVALID_HANDLE_VALUE == hf)
  453. return (FALSE);
  454. #else
  455. of.cBytes = sizeof(of);
  456. hf = OpenFile(paafd->szFilePath, &of, OF_READ);
  457. if (HFILE_ERROR == hf)
  458. return (FALSE);
  459. #endif
  460. //
  461. // assume the worst
  462. //
  463. fReturn = FALSE;
  464. //
  465. // determine the length in _bytes_ of the file
  466. //
  467. #ifdef WIN32
  468. cbFileSize = GetFileSize((HANDLE)hf, NULL);
  469. #else
  470. cbFileSize = _llseek(hf, 0L, SEEK_END);
  471. _llseek(hf, 0L, SEEK_SET);
  472. #endif
  473. //
  474. //
  475. //
  476. //
  477. paafd->cbFileSize = cbFileSize;
  478. #ifdef WIN32
  479. {
  480. BY_HANDLE_FILE_INFORMATION bhfi;
  481. WORD wDosChangeDate;
  482. WORD wDosChangeTime;
  483. GetFileInformationByHandle(hf, &bhfi);
  484. paafd->fdwFileAttributes = bhfi.dwFileAttributes;
  485. FileTimeToDosDateTime(&bhfi.ftLastWriteTime,
  486. &wDosChangeDate, &wDosChangeTime);
  487. paafd->uDosChangeDate = (UINT)wDosChangeDate;
  488. paafd->uDosChangeTime = (UINT)wDosChangeTime;
  489. }
  490. #else
  491. paafd->fdwFileAttributes = DosGetFileAttributes(paafd->szFilePath);
  492. dw = DosGetDateTime(hf);
  493. paafd->uDosChangeDate = LOWORD(dw);
  494. paafd->uDosChangeTime = HIWORD(dw);
  495. #endif
  496. //
  497. // now return the fully qualified path and title for the file
  498. //
  499. #ifndef WIN32
  500. lstrcpy(paafd->szFilePath, of.szPathName);
  501. #endif
  502. AppGetFileTitle(paafd->szFilePath, paafd->szFileTitle);
  503. #ifdef WIN32
  504. CloseHandle(hf);
  505. #else
  506. _lclose(hf);
  507. #endif
  508. //
  509. //
  510. //
  511. //
  512. werr = wioFileOpen(&wio, paafd->szFilePath, 0L);
  513. if (WIOERR_NOERROR == werr)
  514. {
  515. UINT cbwfx;
  516. cbwfx = SIZEOF_WAVEFORMATEX(wio.pwfx);
  517. paafd->pwfx = (LPWAVEFORMATEX)GlobalAllocPtr(GHND, cbwfx);
  518. if (NULL != paafd->pwfx)
  519. {
  520. _fmemcpy(paafd->pwfx, wio.pwfx, cbwfx);
  521. paafd->cbwfx = cbwfx;
  522. paafd->dwDataBytes = wio.dwDataBytes;
  523. paafd->dwDataSamples = wio.dwDataSamples;
  524. fReturn = TRUE;
  525. }
  526. wioFileClose(&wio, 0L);
  527. }
  528. else
  529. {
  530. AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL,
  531. TEXT("The file '%s' cannot be loaded as a wave file (wio error=%u)."),
  532. (LPTSTR)paafd->szFilePath, werr);
  533. }
  534. //
  535. // !!! before returning, we really should try to display a error
  536. // message... memory error, etc..
  537. //
  538. return (fReturn);
  539. } // AcmAppFileOpen()
  540. //--------------------------------------------------------------------------;
  541. //
  542. // BOOL AcmAppOpenInstance
  543. //
  544. // Description:
  545. //
  546. //
  547. // Arguments:
  548. // HWND hwnd:
  549. //
  550. // LPCTSTR pszFilePath:
  551. //
  552. // BOOL fForceOpen:
  553. //
  554. // Return (BOOL):
  555. //
  556. //--------------------------------------------------------------------------;
  557. BOOL FNLOCAL AcmAppOpenInstance
  558. (
  559. HWND hwnd,
  560. LPCTSTR pszFilePath,
  561. BOOL fForceOpen
  562. )
  563. {
  564. TCHAR szCmdLine[APP_MAX_FILE_PATH_CHARS * 2];
  565. BOOL f;
  566. UINT uDosErr;
  567. //
  568. //
  569. //
  570. if (!fForceOpen)
  571. {
  572. if (0 == (APP_OPTIONSF_AUTOOPEN * gfuAppOptions))
  573. {
  574. return (TRUE);
  575. }
  576. }
  577. //
  578. //
  579. //
  580. if (0 == GetModuleFileName(ghinst, szCmdLine, SIZEOF(szCmdLine)))
  581. {
  582. //
  583. // this would be fatal
  584. //
  585. AppMsgBox(hwnd, MB_ICONEXCLAMATION | MB_OK,
  586. TEXT("GetModuleFileName() is unable to return self reference!"));
  587. return (FALSE);
  588. }
  589. lstrcat(szCmdLine, TEXT(" "));
  590. lstrcat(szCmdLine, pszFilePath);
  591. #ifdef WIN32
  592. {
  593. STARTUPINFO si;
  594. PROCESS_INFORMATION pi;
  595. //
  596. // perform the equivalent of WinExec in NT, but we use a Unicode string
  597. //
  598. memset(&si, 0, sizeof(si));
  599. si.cb = sizeof(si);
  600. si.dwFlags = STARTF_USESHOWWINDOW;
  601. si.wShowWindow = SW_SHOW;
  602. f = CreateProcess(NULL,
  603. szCmdLine,
  604. NULL,
  605. NULL,
  606. FALSE,
  607. 0,
  608. NULL,
  609. NULL,
  610. &si,
  611. &pi);
  612. if (f)
  613. {
  614. //
  615. // as the docs say.. wait 10 second for process to go idle before
  616. // continuing.
  617. //
  618. WaitForInputIdle(pi.hProcess, 10000);
  619. CloseHandle(pi.hProcess);
  620. CloseHandle(pi.hThread);
  621. }
  622. else
  623. {
  624. uDosErr = GetLastError();
  625. }
  626. }
  627. #else
  628. {
  629. uDosErr = WinExec(szCmdLine, SW_SHOW);
  630. f = (uDosErr >= 32);
  631. }
  632. #endif
  633. if (!f)
  634. {
  635. AppMsgBox(hwnd, MB_ICONEXCLAMATION | MB_OK,
  636. TEXT("WinExec(%s) failed! DOS error=%u."),
  637. (LPTSTR)szCmdLine, uDosErr);
  638. }
  639. return (f);
  640. } // AcmAppOpenInstance()
  641. //--------------------------------------------------------------------------;
  642. //
  643. // BOOL AcmAppFileSave
  644. //
  645. // Description:
  646. // This function saves the file to the specified file.
  647. //
  648. // NOTE! This function does NOT bring up a save file chooser dialog
  649. // if the file path is invalid. The calling function is responsible
  650. // for making sure the file path is valid before calling this function.
  651. //
  652. // This function also does NOT modify the 'modified' bit of the file
  653. // descriptor. This is up to the calling function.
  654. //
  655. // Arguments:
  656. // HWND hwnd: Handle to main window.
  657. //
  658. // PACMAPPFILEDESC paafd: Pointer to file descriptor.
  659. //
  660. // Return (BOOL):
  661. // The return value is TRUE if the function is successful. It is FALSE
  662. // if an error occurred. If an error does occur, then the contents
  663. // of the file descriptor was not saved.
  664. //
  665. //--------------------------------------------------------------------------;
  666. BOOL FNGLOBAL AcmAppFileSave
  667. (
  668. HWND hwnd,
  669. PACMAPPFILEDESC paafd,
  670. PTSTR pszFilePath,
  671. PTSTR pszFileTitle,
  672. UINT fuSave
  673. )
  674. {
  675. return (FALSE);
  676. } // AcmAppFileSave()
  677. //==========================================================================;
  678. //==========================================================================;
  679. //==========================================================================;
  680. //==========================================================================;
  681. //
  682. //
  683. //
  684. #define IDD_INFOLIST 100
  685. #define IDD_INFOINFO 101
  686. #define IDD_INFOTEXT 102
  687. #ifdef RC_INVOKED
  688. #define DLG_INFOEDIT 31
  689. #else
  690. #define DLG_INFOEDIT MAKEINTRESOURCE(31)
  691. #endif
  692. ////////////////////////////////////////////////////////////////////////////
  693. typedef struct tCHUNK
  694. {
  695. FOURCC fcc;
  696. DWORD cksize;
  697. BYTE data[];
  698. } CHUNK, * PCHUNK, far * LPCHUNK;
  699. typedef struct tDISP
  700. {
  701. DWORD cfid; // Clipboard id of data
  702. HANDLE h; // handle to data
  703. struct tDISP * next; // next in list
  704. } DISP;
  705. typedef struct tINFODATA
  706. {
  707. WORD index; // index into aINFO
  708. WORD wFlags; // flags for chunk
  709. DWORD dwINFOOffset; // offset in file to INFO chunk
  710. #define INFOCHUNK_MODIFIED 1
  711. #define INFOCHUNK_REVERT 2 // command to revert to original text
  712. LPCTSTR lpText; // text of modified chunk. None if NULL.
  713. struct tINFODATA near * pnext; // next read sub-chunk
  714. } INFODATA, * PINFODATA, FAR * LPINFODATA;
  715. typedef struct tINFOCHUNK
  716. {
  717. LPTSTR lpChunk; // complete chunk in memory (GlobalPtr)
  718. DWORD cksize; // size of chunk data
  719. PINFODATA pHead; // first sub-chunk data
  720. } INFOCHUNK, * PINFOCHUNK, FAR * LPINFOCHUNK;
  721. ////////////////////////////////////////////////////////////////////////////
  722. //
  723. // error returns from RIFF functions
  724. //
  725. #define RIFFERR_BASE (0)
  726. #define RIFFERR_NOERROR (0)
  727. #define RIFFERR_ERROR (RIFFERR_BASE+1)
  728. #define RIFFERR_BADPARAM (RIFFERR_BASE+2)
  729. #define RIFFERR_FILEERROR (RIFFERR_BASE+3)
  730. #define RIFFERR_NOMEM (RIFFERR_BASE+4)
  731. #define RIFFERR_BADFILE (RIFFERR_BASE+5)
  732. ////////////////////////////////////////////////////////////////////////////
  733. //
  734. // public function prototypes
  735. //
  736. #define RIFFAPI FAR PASCAL
  737. BOOL RIFFAPI riffCopyList(HMMIO hmmioSrc, HMMIO hmmioDst, const LPMMCKINFO lpck);
  738. BOOL RIFFAPI riffCopyChunk(HMMIO hmmioSrc, HMMIO hmmioDst, const LPMMCKINFO lpck);
  739. LRESULT RIFFAPI riffInitINFO(INFOCHUNK FAR * FAR * lplpInfo);
  740. LRESULT RIFFAPI riffReadINFO(HMMIO hmmio, const LPMMCKINFO lpck, LPINFOCHUNK lpInfo);
  741. LRESULT RIFFAPI riffEditINFO(HWND hwnd, LPINFOCHUNK lpInfo, HINSTANCE hInst);
  742. LRESULT RIFFAPI riffFreeINFO(INFOCHUNK FAR * FAR * lpnpInfo);
  743. LRESULT RIFFAPI riffWriteINFO(HMMIO hmmioDst, LPINFOCHUNK lpInfo);
  744. LRESULT RIFFAPI riffReadDISP(HMMIO hmmio, LPMMCKINFO lpck, DISP FAR * FAR * lpnpDisp);
  745. LRESULT RIFFAPI riffFreeDISP(DISP FAR * FAR * lpnpDisp);
  746. LRESULT RIFFAPI riffWriteDISP(HMMIO hmmio, DISP FAR * FAR * lpnpDisp);
  747. LRESULT NEAR PASCAL riffParseINFO(const LPINFOCHUNK lpInfo);
  748. /** BOOL RIFFAPI riffCopyChunk(HMMIO hmmioSrc, HMMIO hmmioDst, const LPMMCKINFO lpck)
  749. *
  750. * DESCRIPTION:
  751. *
  752. *
  753. * ARGUMENTS:
  754. * (LPWAVECONVCB lpwc, LPMMCKINFO lpck)
  755. *
  756. * RETURN (BOOL NEAR PASCAL):
  757. *
  758. *
  759. * NOTES:
  760. *
  761. ** */
  762. BOOL RIFFAPI riffCopyChunk(HMMIO hmmioSrc, HMMIO hmmioDst, const LPMMCKINFO lpck)
  763. {
  764. MMCKINFO ck;
  765. HPSTR hpBuf;
  766. //
  767. //
  768. //
  769. hpBuf = (HPSTR)GlobalAllocPtr(GHND, lpck->cksize);
  770. if (!hpBuf)
  771. return (FALSE);
  772. ck.ckid = lpck->ckid;
  773. ck.cksize = lpck->cksize;
  774. if (mmioCreateChunk(hmmioDst, &ck, 0))
  775. goto rscc_Error;
  776. if (mmioRead(hmmioSrc, hpBuf, lpck->cksize) != (LONG)lpck->cksize)
  777. goto rscc_Error;
  778. if (mmioWrite(hmmioDst, hpBuf, lpck->cksize) != (LONG)lpck->cksize)
  779. goto rscc_Error;
  780. if (mmioAscend(hmmioDst, &ck, 0))
  781. goto rscc_Error;
  782. if (hpBuf)
  783. GlobalFreePtr(hpBuf);
  784. return (TRUE);
  785. rscc_Error:
  786. if (hpBuf)
  787. GlobalFreePtr(hpBuf);
  788. return (FALSE);
  789. } /* RIFFSupCopyChunk() */
  790. /** BOOL RIFFAPI riffCopyList(HMMIO hmmioSrc, HMMIO hmmioDst, const LPMMCKINFO lpck)
  791. *
  792. * DESCRIPTION:
  793. *
  794. *
  795. * ARGUMENTS:
  796. * (HMMIO hmmioSrc, HMMIO hmmioDst, LPMMCKINFO lpck)
  797. *
  798. * RETURN (BOOL NEAR PASCAL):
  799. *
  800. *
  801. * NOTES:
  802. *
  803. ** */
  804. BOOL RIFFAPI riffCopyList(HMMIO hmmioSrc, HMMIO hmmioDst, const LPMMCKINFO lpck)
  805. {
  806. MMCKINFO ck;
  807. HPSTR hpBuf;
  808. DWORD dwCopySize;
  809. hpBuf = (HPSTR)GlobalAllocPtr(GHND, lpck->cksize);
  810. if (!hpBuf)
  811. return (FALSE);
  812. dwCopySize=lpck->cksize;
  813. // mmio leaves us after LIST ID
  814. ck.ckid = lpck->ckid;
  815. ck.cksize = dwCopySize;
  816. ck.fccType= lpck->fccType;
  817. if (mmioCreateChunk(hmmioDst, &ck, MMIO_CREATELIST))
  818. goto rscl_Error;
  819. // we already wrote 'LIST' ID, so reduce byte count
  820. dwCopySize-=sizeof(FOURCC);
  821. if (mmioRead(hmmioSrc, hpBuf, dwCopySize) != (LONG)dwCopySize)
  822. goto rscl_Error;
  823. if (mmioWrite(hmmioDst, hpBuf, dwCopySize) != (LONG)dwCopySize)
  824. goto rscl_Error;
  825. if (mmioAscend(hmmioDst, &ck, 0))
  826. goto rscl_Error;
  827. if (hpBuf)
  828. GlobalFreePtr(hpBuf);
  829. return (TRUE);
  830. rscl_Error:
  831. if (hpBuf)
  832. GlobalFreePtr(hpBuf);
  833. return (FALSE);
  834. } /* RIFFSupCopyList() */
  835. /////////////////////////////////////////////////////////////////////////////
  836. typedef struct tINFO
  837. {
  838. PTSTR pFOURCC;
  839. PTSTR pShort;
  840. PTSTR pLong;
  841. } INFO;
  842. static INFO aINFO[]=
  843. {
  844. TEXT("IARL"), TEXT("Archival Location"), TEXT("Indicates where the subject of the file is archived."),
  845. TEXT("IART"), TEXT("Artist"), TEXT("Lists the artist of the original subject of the file. For example, \"Michaelangelo.\""),
  846. TEXT("ICMS"), TEXT("Commissioned"), TEXT("Lists the name of the person or organization that commissioned the subject of the file. For example, \"Pope Julian II.\""),
  847. TEXT("ICMT"), TEXT("Comments"), TEXT("Provides general comments about the file or the subject of the file. If the comment is several sentences long, end each sentence with a period. Do not include newline characters."),
  848. TEXT("ICOP"), TEXT("Copyright"), TEXT("Records the copyright information for the file. For example, \"Copyright Encyclopedia International 1991.\" If there are multiple copyrights, separate them by a semicolon followed by a space."),
  849. TEXT("ICRD"), TEXT("Creation date"), TEXT("Specifies the date the subject of the file was created. List dates in year-month-day format, padding one-digit months and days with a zero on the left. For example, \"1553-05-03\" for May 3, 1553."),
  850. TEXT("ICRP"), TEXT("Cropped"), TEXT("Describes whether an image has been cropped and, if so, how it was cropped. For example, \"lower right corner.\""),
  851. TEXT("IDIM"), TEXT("Dimensions"), TEXT("Specifies the size of the original subject of the file. For example, \"8.5 in h, 11 in w.\""),
  852. TEXT("IDPI"), TEXT("Dots Per Inch"), TEXT("Stores dots per inch setting of the digitizer used to produce the file, such as \"300.\""),
  853. TEXT("IENG"), TEXT("Engineer"), TEXT("Stores the name of the engineer who worked on the file. If there are multiple engineers, separate the names by a semicolon and a blank. For example, \"Smith, John; Adams, Joe.\""),
  854. TEXT("IGNR"), TEXT("Genre"), TEXT("Describes the original work, such as, \"landscape,\" \"portrait,\" \"still life,\" etc."),
  855. TEXT("IKEY"), TEXT("Keywords"), TEXT("Provides a list of keywords that refer to the file or subject of the file. Separate multiple keywords with a semicolon and a blank. For example, \"Seattle; aerial view; scenery.\""),
  856. TEXT("ILGT"), TEXT("Lightness"), TEXT("Describes the changes in lightness settings on the digitizer required to produce the file. Note that the format of this information depends on hardware used."),
  857. TEXT("IMED"), TEXT("Medium"), TEXT("Describes the original subject of the file, such as, \"computer image,\" \"drawing,\" \"lithograph,\" and so forth."),
  858. TEXT("INAM"), TEXT("Name"), TEXT("Stores the title of the subject of the file, such as, \"Seattle From Above.\""),
  859. TEXT("IPLT"), TEXT("Palette Setting"), TEXT("Specifies the number of colors requested when digitizing an image, such as \"256.\""),
  860. TEXT("IPRD"), TEXT("Product"), TEXT("Specifies the name of the title the file was originally intended for, such as \"Encyclopedia of Pacific Northwest Geography.\""),
  861. TEXT("ISBJ"), TEXT("Subject"), TEXT("Describes the contents of the file, such as \"Aerial view of Seattle.\""),
  862. TEXT("ISFT"), TEXT("Software"), TEXT("Identifies the name of the software package used to create the file, such as \"Microsoft WaveEdit.\""),
  863. TEXT("ISHP"), TEXT("Sharpness"), TEXT("Identifies the changes in sharpness for the digitizer required to produce the file (the format depends on the hardware used)."),
  864. TEXT("ISRC"), TEXT("Source"), TEXT("Identifies the name of the person or organization who supplied the original subject of the file. For example, \"Trey Research.\""),
  865. TEXT("ISRF"), TEXT("Source Form"), TEXT("Identifies the original form of the material that was digitized, such as \"slide,\" \"paper,\" \"map,\" and so forth. This is not necessarily the same as IMED."),
  866. TEXT("ITCH"), TEXT("Technician"), TEXT("Identifies the technician who digitized the subject file. For example, \"Smith, John.\""),
  867. NULL, NULL, NULL
  868. };
  869. void NEAR PASCAL riffInsertINFO(LPINFOCHUNK lpInfo, const PINFODATA pInfo)
  870. {
  871. PINFODATA pI;
  872. if(!lpInfo)
  873. return;
  874. if(!lpInfo->pHead)
  875. {
  876. lpInfo->pHead=pInfo;
  877. return;
  878. }
  879. pI=lpInfo->pHead;
  880. while(pI->pnext)
  881. {
  882. pI=pI->pnext;
  883. }
  884. // insert at end
  885. pI->pnext=pInfo;
  886. return;
  887. }
  888. PINFODATA NEAR PASCAL riffCreateINFO(WORD id, WORD wFlags, DWORD dwInfoOffset, LPCTSTR lpText)
  889. {
  890. PINFODATA pI;
  891. pI=(PINFODATA)LocalAlloc(LPTR,sizeof(INFODATA));
  892. if(!pI)
  893. return NULL;
  894. pI->index=id;
  895. pI->wFlags=wFlags;
  896. pI->dwINFOOffset=dwInfoOffset;
  897. pI->lpText=lpText;
  898. return pI;
  899. }
  900. LRESULT RIFFAPI riffInitINFO(INFOCHUNK FAR * FAR * lplpInfo)
  901. {
  902. LPINFOCHUNK lpInfo;
  903. WORD id;
  904. PINFODATA pI;
  905. lpInfo=(LPINFOCHUNK)GlobalAllocPtr(GHND, sizeof(INFOCHUNK));
  906. if(!lpInfo)
  907. return RIFFERR_NOMEM;
  908. *lplpInfo=lpInfo;
  909. for (id=0;aINFO[id].pFOURCC;id++)
  910. {
  911. pI=riffCreateINFO(id, 0, 0L, NULL); // create empty INFO
  912. riffInsertINFO(lpInfo,pI);
  913. }
  914. return RIFFERR_NOERROR;
  915. }
  916. LRESULT RIFFAPI riffReadINFO(HMMIO hmmio, const LPMMCKINFO lpck, LPINFOCHUNK lpInfo)
  917. {
  918. DWORD dwInfoSize;
  919. dwInfoSize=lpck->cksize - sizeof(FOURCC); // take out 'INFO'
  920. lpInfo->cksize=dwInfoSize;
  921. lpInfo->lpChunk=(LPTSTR)GlobalAllocPtr(GHND, dwInfoSize);
  922. if(!lpInfo->lpChunk)
  923. return RIFFERR_NOMEM;
  924. if (mmioRead(hmmio, (HPSTR)lpInfo->lpChunk, dwInfoSize) != (LONG)dwInfoSize)
  925. return RIFFERR_FILEERROR;
  926. else
  927. return riffParseINFO(lpInfo);
  928. }
  929. PINFODATA NEAR PASCAL riffFindPIINFO(const LPINFOCHUNK lpInfo, FOURCC fcc)
  930. {
  931. PINFODATA pI;
  932. pI=lpInfo->pHead;
  933. while(pI)
  934. {
  935. if(mmioStringToFOURCC(aINFO[pI->index].pFOURCC,0)==fcc)
  936. return(pI);
  937. pI=pI->pnext;
  938. }
  939. return NULL;
  940. }
  941. void NEAR PASCAL riffModifyINFO(const LPINFOCHUNK lpInfo, PINFODATA pI, WORD wFlags, DWORD dw, LPCTSTR lpText)
  942. {
  943. if(!pI)
  944. return;
  945. pI->wFlags=wFlags;
  946. if(!(wFlags&INFOCHUNK_MODIFIED))
  947. pI->dwINFOOffset=dw;
  948. if(pI->lpText)
  949. {
  950. if(lpText)
  951. {
  952. if(!lstrcmp(lpText,pI->lpText))
  953. {
  954. // they are the same, don't bother changing...
  955. GlobalFreePtr(lpText);
  956. }
  957. else
  958. {
  959. GlobalFreePtr(pI->lpText);
  960. pI->lpText=lpText;
  961. }
  962. }
  963. else if(wFlags&INFOCHUNK_REVERT)
  964. {
  965. GlobalFreePtr(pI->lpText);
  966. pI->lpText=NULL;
  967. }
  968. }
  969. else if(lpText)
  970. {
  971. // if no read data, don't bother to check....
  972. if(!lpInfo->lpChunk && *lpText)
  973. {
  974. pI->lpText=lpText;
  975. }
  976. else if(lstrcmp(lpText, (LPTSTR)lpInfo->lpChunk+pI->dwINFOOffset))
  977. { // new text...
  978. if(*lpText)
  979. // NOT the same, set...
  980. pI->lpText=lpText;
  981. else
  982. // new is blank, do nothing...
  983. GlobalFreePtr(lpText);
  984. }
  985. else
  986. // the same, don't bother...
  987. GlobalFreePtr(lpText);
  988. }
  989. }
  990. WORD NEAR PASCAL riffFindaINFO(FOURCC fcc)
  991. {
  992. WORD id;
  993. for (id=0;aINFO[id].pFOURCC;id++)
  994. {
  995. if(mmioStringToFOURCC(aINFO[id].pFOURCC,0)==fcc)
  996. return id;
  997. }
  998. return 0xFFFF;
  999. }
  1000. LRESULT NEAR PASCAL riffParseINFO(const LPINFOCHUNK lpInfo)
  1001. {
  1002. LPTSTR lpBuf;
  1003. DWORD dwCurInfoOffset;
  1004. PINFODATA pI;
  1005. LPCHUNK lpck;
  1006. lpBuf=lpInfo->lpChunk;
  1007. for(dwCurInfoOffset=0;dwCurInfoOffset<lpInfo->cksize;)
  1008. {
  1009. lpck=(LPCHUNK)((LPSTR)(lpBuf+dwCurInfoOffset));
  1010. dwCurInfoOffset+=sizeof(CHUNK); // dwCurInfoOffset is offset of data
  1011. pI=riffFindPIINFO(lpInfo,lpck->fcc);
  1012. if(!pI)
  1013. {
  1014. int n;
  1015. // file contains unknown INFO chunk
  1016. n = AppMsgBox(NULL, MB_YESNO | MB_ICONEXCLAMATION | MB_TASKMODAL,
  1017. TEXT("This wave file contains an unknown item in the INFO chunk: '%4.4s'. Open anyway?"),
  1018. (LPCSTR)(lpck));
  1019. if (n == IDNO)
  1020. {
  1021. return RIFFERR_BADFILE;
  1022. }
  1023. }
  1024. else
  1025. {
  1026. // modify entry to show text (data) from file...
  1027. riffModifyINFO(lpInfo, pI, 0, dwCurInfoOffset, NULL);
  1028. }
  1029. dwCurInfoOffset+=lpck->cksize+(lpck->cksize&1); // skip past data
  1030. }
  1031. return RIFFERR_NOERROR;
  1032. }
  1033. LRESULT RIFFAPI riffFreeINFO(INFOCHUNK FAR * FAR * lplpInfo)
  1034. {
  1035. PINFODATA pI;
  1036. PINFODATA pIT;
  1037. LPINFOCHUNK lpInfo;
  1038. LRESULT lr;
  1039. lr = RIFFERR_BADPARAM;
  1040. if(!lplpInfo)
  1041. goto riff_FI_Error;
  1042. lpInfo=*lplpInfo;
  1043. if(!lpInfo)
  1044. goto riff_FI_Error;
  1045. if(lpInfo->lpChunk)
  1046. GlobalFreePtr(lpInfo->lpChunk);
  1047. pI=lpInfo->pHead;
  1048. while(pI)
  1049. {
  1050. pIT=pI;
  1051. pI=pI->pnext;
  1052. LocalFree((HANDLE)pIT);
  1053. }
  1054. //
  1055. GlobalFreePtr(lpInfo);
  1056. *lplpInfo=NULL;
  1057. return RIFFERR_NOERROR;
  1058. riff_FI_Error:
  1059. return lr;
  1060. }
  1061. TCHAR szBuf[255];
  1062. static BOOL NEAR PASCAL riffSetupEditBoxINFO(HWND hdlg, const LPINFOCHUNK lpInfo, WORD wFlags)
  1063. {
  1064. static PTSTR szFormat = TEXT("%-4s%c %-25s");
  1065. PINFODATA pI;
  1066. WORD iSel;
  1067. HWND hLB;
  1068. hLB=GetDlgItem(hdlg, IDD_INFOLIST);
  1069. if(wFlags&INFOCHUNK_MODIFIED)
  1070. {
  1071. iSel = ComboBox_GetCurSel(hLB);
  1072. }
  1073. else
  1074. iSel = 0;
  1075. ComboBox_ResetContent(hLB);
  1076. pI=lpInfo->pHead;
  1077. while(pI)
  1078. {
  1079. wsprintf(szBuf,szFormat,
  1080. (LPCSTR)aINFO[pI->index].pFOURCC,
  1081. (pI->dwINFOOffset || ( (pI->lpText) && (pI->lpText[0]) ) ) ?
  1082. '*' : ' ',
  1083. (LPCSTR)aINFO[pI->index].pShort
  1084. );
  1085. ComboBox_AddString(hLB, szBuf);
  1086. pI=pI->pnext;
  1087. }
  1088. ComboBox_SetCurSel(hLB, iSel);
  1089. if(!(wFlags&INFOCHUNK_MODIFIED))
  1090. {
  1091. // FIRST time only
  1092. pI=lpInfo->pHead;
  1093. if(pI)
  1094. if(pI->lpText)
  1095. // Modified text
  1096. SetDlgItemText(hdlg, IDD_INFOTEXT, (LPCTSTR)pI->lpText);
  1097. else if(pI->dwINFOOffset)
  1098. // default text
  1099. SetDlgItemText(hdlg, IDD_INFOTEXT, (LPCTSTR)(lpInfo->lpChunk+pI->dwINFOOffset));
  1100. else
  1101. // no text
  1102. SetDlgItemText(hdlg, IDD_INFOTEXT, (LPCTSTR)TEXT(""));
  1103. SetDlgItemText(hdlg, IDD_INFOINFO, (LPCTSTR)aINFO[0].pLong);
  1104. }
  1105. return TRUE;
  1106. }
  1107. static BOOL Cls_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
  1108. {
  1109. LPINFOCHUNK lpInfo;
  1110. HFONT hFont;
  1111. HWND hLB;
  1112. lpInfo = (LPINFOCHUNK)lParam;
  1113. if(!lpInfo)
  1114. return FALSE;
  1115. SetWindowLong(hwnd, DWL_USER, (LONG)lpInfo);
  1116. hFont = GetStockFont(ANSI_FIXED_FONT);
  1117. hLB=GetDlgItem(hwnd, IDD_INFOLIST);
  1118. SetWindowFont(hLB, hFont, FALSE);
  1119. riffSetupEditBoxINFO(hwnd, lpInfo, 0);
  1120. return TRUE;
  1121. }
  1122. static void Cls_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  1123. {
  1124. LPINFOCHUNK lpInfo;
  1125. PINFODATA pI;
  1126. WORD iSel;
  1127. int i;
  1128. LPTSTR lpstr;
  1129. lpInfo=(LPINFOCHUNK)GetWindowLong(hwnd, DWL_USER);
  1130. switch(id)
  1131. {
  1132. case IDOK:
  1133. case IDCANCEL:
  1134. EndDialog(hwnd, (id == IDOK));
  1135. break;
  1136. case IDD_INFOLIST:
  1137. switch(codeNotify)
  1138. {
  1139. case CBN_SELCHANGE:
  1140. iSel = ComboBox_GetCurSel(GetDlgItem(hwnd, id));
  1141. SetDlgItemText(hwnd, IDD_INFOINFO, (LPCTSTR)aINFO[iSel].pLong);
  1142. pI=lpInfo->pHead;
  1143. while(pI)
  1144. {
  1145. if(pI->index==iSel)
  1146. break;
  1147. pI=pI->pnext;
  1148. }
  1149. if(pI)
  1150. {
  1151. if(pI->lpText)
  1152. // Modified text
  1153. SetDlgItemText(hwnd, IDD_INFOTEXT, (LPCTSTR)pI->lpText);
  1154. else if(pI->dwINFOOffset)
  1155. // default text
  1156. SetDlgItemText(hwnd, IDD_INFOTEXT, (LPCTSTR)(lpInfo->lpChunk+pI->dwINFOOffset));
  1157. else
  1158. // no text
  1159. SetDlgItemText(hwnd, IDD_INFOTEXT, (LPCTSTR)TEXT(""));
  1160. }
  1161. else
  1162. SetDlgItemText(hwnd, IDD_INFOINFO, (LPCTSTR)TEXT("Can't FIND iSel"));
  1163. break;
  1164. }
  1165. case IDD_INFOTEXT:
  1166. switch(codeNotify)
  1167. {
  1168. case EN_KILLFOCUS:
  1169. // get text out and give to current id
  1170. iSel=(WORD)SendDlgItemMessage(hwnd,IDD_INFOLIST,CB_GETCURSEL,0,0L);
  1171. pI=lpInfo->pHead;
  1172. while(pI)
  1173. {
  1174. if(pI->index==iSel)
  1175. break;
  1176. pI=pI->pnext;
  1177. }
  1178. if(pI)
  1179. {
  1180. i=GetDlgItemText(hwnd, IDD_INFOTEXT, szBuf,sizeof(szBuf));
  1181. lpstr=(LPTSTR)GlobalAllocPtr(GHND,(DWORD)i+1);
  1182. if(!lpstr)
  1183. break;
  1184. lstrcpy(lpstr,szBuf);
  1185. riffModifyINFO(lpInfo, pI, INFOCHUNK_MODIFIED, 0, lpstr);
  1186. riffSetupEditBoxINFO(hwnd, lpInfo, INFOCHUNK_MODIFIED);
  1187. }
  1188. else
  1189. SetDlgItemText(hwnd, IDD_INFOINFO, (LPCTSTR)TEXT("Can't FIND iSel"));
  1190. break;
  1191. }
  1192. break;
  1193. case IDD_INFOINFO:
  1194. break;
  1195. }
  1196. }
  1197. BOOL FNGLOBAL DlgProcINFOEdit(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1198. {
  1199. switch (uMsg)
  1200. {
  1201. case WM_INITDIALOG:
  1202. return (BOOL)(UINT)(DWORD)(LRESULT)HANDLE_WM_INITDIALOG(hdlg, wParam, lParam, Cls_OnInitDialog);
  1203. case WM_COMMAND:
  1204. HANDLE_WM_COMMAND(hdlg, wParam, lParam, Cls_OnCommand);
  1205. break;
  1206. }
  1207. return FALSE;
  1208. }
  1209. LRESULT RIFFAPI riffEditINFO(HWND hwnd, LPINFOCHUNK lpInfo, HINSTANCE hInst)
  1210. {
  1211. LRESULT lr;
  1212. DLGPROC lpfn;
  1213. #ifdef DEBUG
  1214. int i;
  1215. #endif
  1216. lr = RIFFERR_BADPARAM;
  1217. if(!lpInfo)
  1218. goto riff_EI_Error;
  1219. if (lpfn = (DLGPROC)MakeProcInstance((FARPROC)DlgProcINFOEdit, hInst))
  1220. {
  1221. #ifdef DEBUG
  1222. i=
  1223. #endif
  1224. DialogBoxParam(hInst, DLG_INFOEDIT, hwnd, lpfn, (LPARAM)(LPVOID)lpInfo);
  1225. FreeProcInstance((FARPROC)lpfn);
  1226. lr=RIFFERR_NOERROR;
  1227. #ifdef DEBUG
  1228. if(i==-1)
  1229. {
  1230. MessageBox(hwnd, TEXT("INFO Edit Error: DLG_INFOEDIT not found. Check .RC file."), TEXT("RIFF SUP module"), MB_OK|MB_ICONEXCLAMATION|MB_TASKMODAL);
  1231. lr=RIFFERR_ERROR;
  1232. }
  1233. #endif
  1234. }
  1235. #ifdef DEBUG
  1236. else
  1237. {
  1238. MessageBox(hwnd, TEXT("INFO Edit Error: Can't MakeProcInstace()"), TEXT("RIFF SUP module"), MB_OK|MB_ICONEXCLAMATION|MB_TASKMODAL);
  1239. lr=RIFFERR_ERROR;
  1240. }
  1241. #endif
  1242. riff_EI_Error:
  1243. return lr;
  1244. }
  1245. LRESULT RIFFAPI riffWriteINFO(HMMIO hmmioDst, LPINFOCHUNK lpInfo)
  1246. {
  1247. LRESULT lr;
  1248. MMCKINFO ck;
  1249. MMCKINFO ckINFO;
  1250. PINFODATA pI;
  1251. LPTSTR lpstr;
  1252. BOOL fList=FALSE;
  1253. lr = RIFFERR_BADPARAM;
  1254. if(!hmmioDst || !lpInfo)
  1255. goto riff_SI_Error;
  1256. lr=RIFFERR_FILEERROR;
  1257. ckINFO.ckid = mmioFOURCC('L', 'I', 'S', 'T');
  1258. ckINFO.cksize = 0; // mmio fill fill it in later
  1259. ckINFO.fccType= mmioFOURCC('I', 'N', 'F', 'O');
  1260. pI=lpInfo->pHead;
  1261. while(pI)
  1262. {
  1263. if(pI->lpText)
  1264. // Modified text
  1265. lpstr=(LPTSTR)pI->lpText;
  1266. else if(pI->dwINFOOffset)
  1267. // default text
  1268. lpstr=(lpInfo->lpChunk+pI->dwINFOOffset);
  1269. else
  1270. // no text
  1271. lpstr=NULL;
  1272. if(lpstr)
  1273. {
  1274. if(!fList)
  1275. {
  1276. // only create if needed...
  1277. if (mmioCreateChunk(hmmioDst, &ckINFO, MMIO_CREATELIST))
  1278. goto riff_SI_Error;
  1279. fList=TRUE;
  1280. }
  1281. ck.ckid=mmioStringToFOURCC(aINFO[pI->index].pFOURCC,0);
  1282. ck.cksize=lstrlen(lpstr)+1;
  1283. ck.fccType=0;
  1284. if (mmioCreateChunk(hmmioDst, &ck, 0))
  1285. goto riff_SI_Error;
  1286. if (mmioWrite(hmmioDst, (LPBYTE)lpstr, ck.cksize) != (LONG)(ck.cksize))
  1287. goto riff_SI_Error;
  1288. if (mmioAscend(hmmioDst, &ck, 0))
  1289. goto riff_SI_Error;
  1290. }
  1291. pI=pI->pnext;
  1292. }
  1293. if(fList)
  1294. {
  1295. if (mmioAscend(hmmioDst, &ckINFO, 0))
  1296. goto riff_SI_Error;
  1297. }
  1298. return RIFFERR_NOERROR;
  1299. riff_SI_Error:
  1300. return lr;
  1301. }
  1302. ///////////////////////////////////////////////////////////////////////////////
  1303. LRESULT RIFFAPI riffReadDISP(HMMIO hmmio, LPMMCKINFO lpck, DISP FAR * FAR * lpnpDisp)
  1304. {
  1305. LRESULT lr;
  1306. lr = RIFFERR_ERROR;
  1307. return lr;
  1308. }
  1309. LRESULT RIFFAPI riffFreeDISP(DISP FAR * FAR * lpnpDisp)
  1310. {
  1311. LRESULT lr;
  1312. lr = RIFFERR_ERROR;
  1313. return lr;
  1314. }
  1315. LRESULT RIFFAPI riffWriteDISP(HMMIO hmmio, DISP FAR * FAR * lpnpDisp)
  1316. {
  1317. LRESULT lr;
  1318. lr = RIFFERR_ERROR;
  1319. return lr;
  1320. }
  1321. //==========================================================================;
  1322. //==========================================================================;
  1323. //==========================================================================;
  1324. //==========================================================================;
  1325. BOOL gfCancelConvert;
  1326. #define WM_CONVERT_BEGIN (WM_USER + 100)
  1327. #define WM_CONVERT_END (WM_USER + 101)
  1328. #define BeginConvert(hwnd, paacd) PostMessage(hwnd, WM_CONVERT_BEGIN, 0, (LPARAM)(UINT)paacd)
  1329. #define EndConvert(hwnd, f, paacd) PostMessage(hwnd, WM_CONVERT_END, (WPARAM)f, (LPARAM)(UINT)paacd)
  1330. //--------------------------------------------------------------------------;
  1331. //
  1332. // void AppDlgYield
  1333. //
  1334. // Description:
  1335. //
  1336. //
  1337. // Arguments:
  1338. // HWND hdlg:
  1339. //
  1340. // Return (void):
  1341. //
  1342. //--------------------------------------------------------------------------;
  1343. void FNLOCAL AppDlgYield
  1344. (
  1345. HWND hdlg
  1346. )
  1347. {
  1348. MSG msg;
  1349. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  1350. {
  1351. if ((hdlg == NULL) || !IsDialogMessage(hdlg, &msg))
  1352. {
  1353. TranslateMessage(&msg);
  1354. DispatchMessage(&msg);
  1355. }
  1356. }
  1357. } // AppDlgYield()
  1358. //--------------------------------------------------------------------------;
  1359. //
  1360. // BOOL AcmAppConvertEnd
  1361. //
  1362. // Description:
  1363. //
  1364. //
  1365. // Arguments:
  1366. // HWND hdlg:
  1367. //
  1368. // PAACONVERTDESC paacd:
  1369. //
  1370. // Return (BOOL):
  1371. //
  1372. //
  1373. //--------------------------------------------------------------------------;
  1374. BOOL FNLOCAL AcmAppConvertEnd
  1375. (
  1376. HWND hdlg,
  1377. PAACONVERTDESC paacd
  1378. )
  1379. {
  1380. MMRESULT mmr;
  1381. LPACMSTREAMHEADER pash;
  1382. //
  1383. //
  1384. //
  1385. //
  1386. if (NULL != paacd->hmmioSrc)
  1387. {
  1388. mmioClose(paacd->hmmioSrc, 0);
  1389. paacd->hmmioSrc = NULL;
  1390. }
  1391. if (NULL != paacd->hmmioDst)
  1392. {
  1393. mmioAscend(paacd->hmmioDst, &paacd->ckDst, 0);
  1394. mmioAscend(paacd->hmmioDst, &paacd->ckDstRIFF, 0);
  1395. mmioClose(paacd->hmmioDst, 0);
  1396. paacd->hmmioDst = NULL;
  1397. }
  1398. //
  1399. //
  1400. //
  1401. //
  1402. if (NULL != paacd->has)
  1403. {
  1404. pash = &paacd->ash;
  1405. if (ACMSTREAMHEADER_STATUSF_PREPARED & pash->fdwStatus)
  1406. {
  1407. pash->cbSrcLength = paacd->cbSrcReadSize;
  1408. pash->cbDstLength = paacd->cbDstBufSize;
  1409. mmr = acmStreamUnprepareHeader(paacd->has, &paacd->ash, 0L);
  1410. if (MMSYSERR_NOERROR != mmr)
  1411. {
  1412. AppMsgBox(hdlg, MB_OK | MB_ICONEXCLAMATION,
  1413. TEXT("acmStreamUnprepareHeader() failed with error = %u!"), mmr);
  1414. }
  1415. }
  1416. //
  1417. //
  1418. //
  1419. acmStreamClose(paacd->has, 0L);
  1420. paacd->has = NULL;
  1421. if (NULL != paacd->had)
  1422. {
  1423. acmDriverClose(paacd->had, 0L);
  1424. paacd->had = NULL;
  1425. }
  1426. }
  1427. //
  1428. //
  1429. //
  1430. //
  1431. if (NULL != paacd->pbSrc)
  1432. {
  1433. GlobalFreePtr(paacd->pbSrc);
  1434. paacd->pbSrc = NULL;
  1435. }
  1436. if (NULL != paacd->pbDst)
  1437. {
  1438. GlobalFreePtr(paacd->pbDst);
  1439. paacd->pbDst = NULL;
  1440. }
  1441. return (TRUE);
  1442. } // AcmAppConvertEnd()
  1443. //--------------------------------------------------------------------------;
  1444. //
  1445. // BOOL AcmAppConvertBegin
  1446. //
  1447. // Description:
  1448. //
  1449. //
  1450. // Arguments:
  1451. // HWND hdlg:
  1452. //
  1453. // PAACONVERTDESC paacd:
  1454. //
  1455. // Return (BOOL):
  1456. //
  1457. //
  1458. //--------------------------------------------------------------------------;
  1459. BOOL FNLOCAL AcmAppConvertBegin
  1460. (
  1461. HWND hdlg,
  1462. PAACONVERTDESC paacd
  1463. )
  1464. {
  1465. TCHAR ach[40];
  1466. MMRESULT mmr;
  1467. MMCKINFO ckSrcRIFF;
  1468. MMCKINFO ck;
  1469. DWORD dw;
  1470. LPACMSTREAMHEADER pash;
  1471. LPWAVEFILTER pwfltr;
  1472. //
  1473. //
  1474. //
  1475. if (NULL != paacd->hadid)
  1476. {
  1477. mmr = acmDriverOpen(&paacd->had, paacd->hadid, 0L);
  1478. if (MMSYSERR_NOERROR != mmr)
  1479. {
  1480. AcmAppGetErrorString(mmr, ach);
  1481. AppMsgBox(hdlg, MB_OK | MB_ICONEXCLAMATION,
  1482. TEXT("The selected driver (hadid=%.04Xh) cannot be opened. %s (%u)"),
  1483. paacd->hadid, (LPSTR)ach, mmr);
  1484. return (FALSE);
  1485. }
  1486. }
  1487. //
  1488. //
  1489. //
  1490. //
  1491. pwfltr = paacd->fApplyFilter ? paacd->pwfltr : (LPWAVEFILTER)NULL;
  1492. mmr = acmStreamOpen(&paacd->has,
  1493. paacd->had,
  1494. paacd->pwfxSrc,
  1495. paacd->pwfxDst,
  1496. pwfltr,
  1497. 0L,
  1498. 0L,
  1499. paacd->fdwOpen);
  1500. if (MMSYSERR_NOERROR != mmr)
  1501. {
  1502. AppMsgBox(hdlg, MB_OK | MB_ICONEXCLAMATION,
  1503. TEXT("acmStreamOpen() failed with error = %u!"), mmr);
  1504. return (FALSE);
  1505. }
  1506. //
  1507. //
  1508. //
  1509. mmr = acmStreamSize(paacd->has,
  1510. paacd->cbSrcReadSize,
  1511. &paacd->cbDstBufSize,
  1512. ACM_STREAMSIZEF_SOURCE);
  1513. if (MMSYSERR_NOERROR != mmr)
  1514. {
  1515. AppMsgBox(hdlg, MB_OK | MB_ICONEXCLAMATION,
  1516. TEXT("acmStreamSize() failed with error = %u!"), mmr);
  1517. return (FALSE);
  1518. }
  1519. //
  1520. // first try to open the file, etc.. open the given file for reading
  1521. // using buffered I/O
  1522. //
  1523. paacd->hmmioSrc = mmioOpen(paacd->szFilePathSrc,
  1524. NULL,
  1525. MMIO_READ | MMIO_DENYWRITE | MMIO_ALLOCBUF);
  1526. if (NULL == paacd->hmmioSrc)
  1527. goto aacb_Error;
  1528. //
  1529. //
  1530. //
  1531. paacd->hmmioDst = mmioOpen(paacd->szFilePathDst,
  1532. NULL,
  1533. MMIO_CREATE | MMIO_WRITE | MMIO_EXCLUSIVE | MMIO_ALLOCBUF);
  1534. if (NULL == paacd->hmmioDst)
  1535. goto aacb_Error;
  1536. //
  1537. //
  1538. //
  1539. //
  1540. pash = &paacd->ash;
  1541. pash->fdwStatus = 0L;
  1542. //
  1543. // allocate the src and dst buffers for reading/converting data
  1544. //
  1545. paacd->pbSrc = (HPSTR)GlobalAllocPtr(GHND, paacd->cbSrcReadSize);
  1546. if (NULL == paacd->pbSrc)
  1547. goto aacb_Error;
  1548. paacd->pbDst = (HPSTR)GlobalAllocPtr(GHND, paacd->cbDstBufSize);
  1549. if (NULL == paacd->pbDst)
  1550. goto aacb_Error;
  1551. //
  1552. //
  1553. //
  1554. //
  1555. pash->cbStruct = sizeof(*pash);
  1556. pash->fdwStatus = 0L;
  1557. pash->dwUser = 0L;
  1558. pash->pbSrc = paacd->pbSrc;
  1559. pash->cbSrcLength = paacd->cbSrcReadSize;
  1560. pash->cbSrcLengthUsed = 0L;
  1561. pash->dwSrcUser = paacd->cbSrcReadSize;
  1562. pash->pbDst = paacd->pbDst;
  1563. pash->cbDstLength = paacd->cbDstBufSize;
  1564. pash->cbDstLengthUsed = 0L;
  1565. pash->dwDstUser = paacd->cbDstBufSize;
  1566. mmr = acmStreamPrepareHeader(paacd->has, pash, 0L);
  1567. if (MMSYSERR_NOERROR != mmr)
  1568. {
  1569. AppMsgBox(hdlg, MB_OK | MB_ICONEXCLAMATION,
  1570. TEXT("acmStreamPrepareHeader() failed with error = %u!"), mmr);
  1571. goto aacb_Error;
  1572. }
  1573. //
  1574. // create the RIFF chunk of form type 'WAVE'
  1575. //
  1576. //
  1577. paacd->ckDstRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E');
  1578. paacd->ckDstRIFF.cksize = 0L;
  1579. if (mmioCreateChunk(paacd->hmmioDst, &paacd->ckDstRIFF, MMIO_CREATERIFF))
  1580. goto aacb_Error;
  1581. //
  1582. // locate a 'WAVE' form type in a 'RIFF' thing...
  1583. //
  1584. ckSrcRIFF.fccType = mmioFOURCC('W', 'A', 'V', 'E');
  1585. if (mmioDescend(paacd->hmmioSrc, (LPMMCKINFO)&ckSrcRIFF, NULL, MMIO_FINDRIFF))
  1586. goto aacb_Error;
  1587. //
  1588. // we found a WAVE chunk--now go through and get all subchunks that
  1589. // we know how to deal with...
  1590. //
  1591. while (mmioDescend(paacd->hmmioSrc, &ck, &ckSrcRIFF, 0) == 0)
  1592. {
  1593. //
  1594. // quickly check for corrupt RIFF file--don't ascend past end!
  1595. //
  1596. if ((ck.dwDataOffset + ck.cksize) > (ckSrcRIFF.dwDataOffset + ckSrcRIFF.cksize))
  1597. goto aacb_Error;
  1598. switch (ck.ckid)
  1599. {
  1600. //
  1601. // explicitly skip these...
  1602. //
  1603. //
  1604. //
  1605. case mmioFOURCC('f', 'm', 't', ' '):
  1606. break;
  1607. case mmioFOURCC('d', 'a', 't', 'a'):
  1608. break;
  1609. case mmioFOURCC('f', 'a', 'c', 't'):
  1610. break;
  1611. case mmioFOURCC('J', 'U', 'N', 'K'):
  1612. break;
  1613. case mmioFOURCC('P', 'A', 'D', ' '):
  1614. break;
  1615. case mmioFOURCC('c', 'u', 'e', ' '):
  1616. break;
  1617. //
  1618. // copy chunks that are OK to copy
  1619. //
  1620. //
  1621. //
  1622. case mmioFOURCC('p', 'l', 's', 't'):
  1623. // although without the 'cue' chunk, it doesn't make much sense
  1624. riffCopyChunk(paacd->hmmioSrc, paacd->hmmioDst, &ck);
  1625. break;
  1626. case mmioFOURCC('D', 'I', 'S', 'P'):
  1627. riffCopyChunk(paacd->hmmioSrc, paacd->hmmioDst, &ck);
  1628. break;
  1629. //
  1630. // don't copy unknown chunks
  1631. //
  1632. //
  1633. //
  1634. default:
  1635. break;
  1636. }
  1637. //
  1638. // step up to prepare for next chunk..
  1639. //
  1640. mmioAscend(paacd->hmmioSrc, &ck, 0);
  1641. }
  1642. #if 0
  1643. //
  1644. // now write out possibly editted chunks...
  1645. //
  1646. if (riffWriteINFO(paacd->hmmioDst, (glpwio->pInfo)))
  1647. {
  1648. goto aacb_Error;
  1649. }
  1650. #endif
  1651. //
  1652. // go back to beginning of data portion of WAVE chunk
  1653. //
  1654. if (-1 == mmioSeek(paacd->hmmioSrc, ckSrcRIFF.dwDataOffset + sizeof(FOURCC), SEEK_SET))
  1655. goto aacb_Error;
  1656. ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
  1657. mmioDescend(paacd->hmmioSrc, &ck, &ckSrcRIFF, MMIO_FINDCHUNK);
  1658. //
  1659. // now create the destination fmt, fact, and data chunks _in that order_
  1660. //
  1661. //
  1662. //
  1663. // hmmio is now descended into the 'RIFF' chunk--create the format chunk
  1664. // and write the format header into it
  1665. //
  1666. dw = SIZEOF_WAVEFORMATEX(paacd->pwfxDst);
  1667. paacd->ckDst.ckid = mmioFOURCC('f', 'm', 't', ' ');
  1668. paacd->ckDst.cksize = dw;
  1669. if (mmioCreateChunk(paacd->hmmioDst, &paacd->ckDst, 0))
  1670. goto aacb_Error;
  1671. if (mmioWrite(paacd->hmmioDst, (HPSTR)paacd->pwfxDst, dw) != (LONG)dw)
  1672. goto aacb_Error;
  1673. if (mmioAscend(paacd->hmmioDst, &paacd->ckDst, 0) != 0)
  1674. goto aacb_Error;
  1675. //
  1676. // create the 'fact' chunk (not necessary for PCM--but is nice to have)
  1677. // since we are not writing any data to this file (yet), we set the
  1678. // samples contained in the file to 0..
  1679. //
  1680. paacd->ckDst.ckid = mmioFOURCC('f', 'a', 'c', 't');
  1681. paacd->ckDst.cksize = 0L;
  1682. if (mmioCreateChunk(paacd->hmmioDst, &paacd->ckDst, 0))
  1683. goto aacb_Error;
  1684. if (mmioWrite(paacd->hmmioDst, (HPSTR)&paacd->dwSrcSamples, sizeof(DWORD)) != sizeof(DWORD))
  1685. goto aacb_Error;
  1686. if (mmioAscend(paacd->hmmioDst, &paacd->ckDst, 0) != 0)
  1687. goto aacb_Error;
  1688. //
  1689. // create the data chunk AND STAY DESCENDED... for reasons that will
  1690. // become apparent later..
  1691. //
  1692. paacd->ckDst.ckid = mmioFOURCC('d', 'a', 't', 'a');
  1693. paacd->ckDst.cksize = 0L;
  1694. if (mmioCreateChunk(paacd->hmmioDst, &paacd->ckDst, 0))
  1695. goto aacb_Error;
  1696. //
  1697. // at this point, BOTH the src and dst files are sitting at the very
  1698. // beginning of their data chunks--so we can READ from the source,
  1699. // CONVERT the data, then WRITE it to the destination file...
  1700. //
  1701. return (TRUE);
  1702. //
  1703. //
  1704. //
  1705. //
  1706. aacb_Error:
  1707. AcmAppConvertEnd(hdlg, paacd);
  1708. return (FALSE);
  1709. } // AcmAppConvertBegin()
  1710. //--------------------------------------------------------------------------;
  1711. //
  1712. // BOOL AcmAppConvertConvert
  1713. //
  1714. // Description:
  1715. //
  1716. //
  1717. // Arguments:
  1718. // HWND hdlg:
  1719. //
  1720. // PAACONVERTDESC paacd:
  1721. //
  1722. // Return (BOOL):
  1723. //
  1724. //
  1725. //--------------------------------------------------------------------------;
  1726. BOOL FNLOCAL AcmAppConvertConvert
  1727. (
  1728. HWND hdlg,
  1729. PAACONVERTDESC paacd
  1730. )
  1731. {
  1732. MMRESULT mmr;
  1733. TCHAR ach[40];
  1734. DWORD dw;
  1735. WORD w;
  1736. DWORD dwCurrent;
  1737. WORD wCurPercent;
  1738. LPACMSTREAMHEADER pash;
  1739. DWORD cbRead;
  1740. DWORD dwTime;
  1741. wCurPercent = (WORD)-1;
  1742. paacd->cTotalConverts = 0L;
  1743. paacd->dwTimeTotal = 0L;
  1744. paacd->dwTimeLongest = 0L;
  1745. if (0 == paacd->cbSrcData)
  1746. {
  1747. paacd->dwTimeShortest = 0L;
  1748. paacd->dwShortestConvert = 0L;
  1749. paacd->dwLongestConvert = 0L;
  1750. }
  1751. else
  1752. {
  1753. paacd->dwTimeShortest = (DWORD)-1L;
  1754. paacd->dwShortestConvert = (DWORD)-1L;
  1755. paacd->dwLongestConvert = (DWORD)-1L;
  1756. }
  1757. pash = &paacd->ash;
  1758. for (dwCurrent = 0; dwCurrent < paacd->cbSrcData; )
  1759. {
  1760. w = (WORD)((dwCurrent * 100) / paacd->cbSrcData);
  1761. if (w != wCurPercent)
  1762. {
  1763. wCurPercent = w;
  1764. wsprintf(ach, TEXT("%u%%"), wCurPercent);
  1765. SetDlgItemText(hdlg, IDD_AACONVERT_TXT_STATUS, ach);
  1766. }
  1767. AppDlgYield(hdlg);
  1768. if (gfCancelConvert)
  1769. goto aacc_Error;
  1770. //
  1771. //
  1772. //
  1773. cbRead = min(paacd->cbSrcReadSize, paacd->cbSrcData - dwCurrent);
  1774. dw = mmioRead(paacd->hmmioSrc, paacd->pbSrc, cbRead);
  1775. if (0L == dw)
  1776. break;
  1777. AppDlgYield(hdlg);
  1778. if (gfCancelConvert)
  1779. goto aacc_Error;
  1780. //
  1781. //
  1782. //
  1783. pash->cbSrcLength = dw;
  1784. pash->cbDstLengthUsed = 0L;
  1785. dwTime = timeGetTime();
  1786. mmr = acmStreamConvert(paacd->has,
  1787. &paacd->ash,
  1788. ACM_STREAMCONVERTF_BLOCKALIGN);
  1789. if (MMSYSERR_NOERROR != mmr)
  1790. {
  1791. AppMsgBox(hdlg, MB_OK | MB_ICONEXCLAMATION,
  1792. TEXT("acmStreamConvert() failed with error = %u!"), mmr);
  1793. goto aacc_Error;
  1794. }
  1795. while (0 == (ACMSTREAMHEADER_STATUSF_DONE & ((AACONVERTDESC volatile *)paacd)->ash.fdwStatus))
  1796. ;
  1797. dwTime = timeGetTime() - dwTime;
  1798. paacd->dwTimeTotal += dwTime;
  1799. if (dwTime < paacd->dwTimeShortest)
  1800. {
  1801. paacd->dwTimeShortest = dwTime;
  1802. paacd->dwShortestConvert = paacd->cTotalConverts;
  1803. }
  1804. if (dwTime > paacd->dwTimeLongest)
  1805. {
  1806. paacd->dwTimeLongest = dwTime;
  1807. paacd->dwLongestConvert = paacd->cTotalConverts;
  1808. }
  1809. paacd->cTotalConverts++;
  1810. AppDlgYield(hdlg);
  1811. if (gfCancelConvert)
  1812. goto aacc_Error;
  1813. //
  1814. //
  1815. //
  1816. dw = (cbRead - pash->cbSrcLengthUsed);
  1817. if (0L != dw)
  1818. {
  1819. mmioSeek(paacd->hmmioSrc, -(LONG)dw, SEEK_CUR);
  1820. }
  1821. dwCurrent += pash->cbSrcLengthUsed;
  1822. //
  1823. //
  1824. //
  1825. dw = pash->cbDstLengthUsed;
  1826. if (0L == dw)
  1827. break;
  1828. if (mmioWrite(paacd->hmmioDst, paacd->pbDst, dw) != (LONG)dw)
  1829. goto aacc_Error;
  1830. }
  1831. //
  1832. //
  1833. //
  1834. //
  1835. //
  1836. //
  1837. wCurPercent = (WORD)-1;
  1838. for (;paacd->cbSrcData;)
  1839. {
  1840. w = (WORD)((dwCurrent * 100) / paacd->cbSrcData);
  1841. if (w != wCurPercent)
  1842. {
  1843. wCurPercent = w;
  1844. wsprintf(ach, TEXT("Cleanup Pass -- %u%%"), wCurPercent);
  1845. SetDlgItemText(hdlg, IDD_AACONVERT_TXT_STATUS, ach);
  1846. }
  1847. AppDlgYield(hdlg);
  1848. if (gfCancelConvert)
  1849. goto aacc_Error;
  1850. //
  1851. //
  1852. //
  1853. dw = 0L;
  1854. cbRead = min(paacd->cbSrcReadSize, paacd->cbSrcData - dwCurrent);
  1855. if (0L != cbRead)
  1856. {
  1857. dw = mmioRead(paacd->hmmioSrc, paacd->pbSrc, cbRead);
  1858. if (0L == dw)
  1859. break;
  1860. }
  1861. AppDlgYield(hdlg);
  1862. if (gfCancelConvert)
  1863. goto aacc_Error;
  1864. //
  1865. //
  1866. //
  1867. pash->cbSrcLength = dw;
  1868. pash->cbDstLengthUsed = 0L;
  1869. dwTime = timeGetTime();
  1870. mmr = acmStreamConvert(paacd->has,
  1871. &paacd->ash,
  1872. ACM_STREAMCONVERTF_BLOCKALIGN |
  1873. ACM_STREAMCONVERTF_END);
  1874. if (MMSYSERR_NOERROR != mmr)
  1875. {
  1876. AppMsgBox(hdlg, MB_OK | MB_ICONEXCLAMATION,
  1877. TEXT("acmStreamConvert() failed with error = %u!"), mmr);
  1878. goto aacc_Error;
  1879. }
  1880. while (0 == (ACMSTREAMHEADER_STATUSF_DONE & ((AACONVERTDESC volatile *)paacd)->ash.fdwStatus))
  1881. ;
  1882. dwTime = timeGetTime() - dwTime;
  1883. paacd->dwTimeTotal += dwTime;
  1884. if (dwTime < paacd->dwTimeShortest)
  1885. {
  1886. paacd->dwTimeShortest = dwTime;
  1887. paacd->dwShortestConvert = paacd->cTotalConverts;
  1888. }
  1889. if (dwTime > paacd->dwTimeLongest)
  1890. {
  1891. paacd->dwTimeLongest = dwTime;
  1892. paacd->dwLongestConvert = paacd->cTotalConverts;
  1893. }
  1894. paacd->cTotalConverts++;
  1895. AppDlgYield(hdlg);
  1896. if (gfCancelConvert)
  1897. goto aacc_Error;
  1898. //
  1899. //
  1900. //
  1901. dw = pash->cbDstLengthUsed;
  1902. if (0L == dw)
  1903. {
  1904. pash->cbDstLengthUsed = 0L;
  1905. mmr = acmStreamConvert(paacd->has,
  1906. &paacd->ash,
  1907. ACM_STREAMCONVERTF_END);
  1908. if (MMSYSERR_NOERROR == mmr)
  1909. {
  1910. while (0 == (ACMSTREAMHEADER_STATUSF_DONE & ((AACONVERTDESC volatile *)paacd)->ash.fdwStatus))
  1911. ;
  1912. }
  1913. dw = pash->cbDstLengthUsed;
  1914. if (0L == dw)
  1915. break;
  1916. }
  1917. if (mmioWrite(paacd->hmmioDst, paacd->pbDst, dw) != (LONG)dw)
  1918. goto aacc_Error;
  1919. //
  1920. //
  1921. //
  1922. dw = (cbRead - pash->cbSrcLengthUsed);
  1923. if (0L != dw)
  1924. {
  1925. mmioSeek(paacd->hmmioSrc, -(LONG)dw, SEEK_CUR);
  1926. }
  1927. dwCurrent += pash->cbSrcLengthUsed;
  1928. if (0L == pash->cbDstLengthUsed)
  1929. break;
  1930. }
  1931. EndConvert(hdlg, !gfCancelConvert, paacd);
  1932. return (!gfCancelConvert);
  1933. aacc_Error:
  1934. EndConvert(hdlg, FALSE, paacd);
  1935. return (FALSE);
  1936. } // AcmAppConvertConvert()
  1937. //--------------------------------------------------------------------------;
  1938. //
  1939. // BOOL AcmAppConvertDlgProc
  1940. //
  1941. // Description:
  1942. //
  1943. //
  1944. // Arguments:
  1945. // HWND hdlg:
  1946. //
  1947. // UINT uMsg:
  1948. //
  1949. // WPARAM wParam:
  1950. //
  1951. // LPARAM lParam:
  1952. //
  1953. // Return (BOOL):
  1954. //
  1955. //
  1956. //--------------------------------------------------------------------------;
  1957. BOOL FNEXPORT AcmAppConvertDlgProc
  1958. (
  1959. HWND hwnd,
  1960. UINT uMsg,
  1961. WPARAM wParam,
  1962. LPARAM lParam
  1963. )
  1964. {
  1965. PAACONVERTDESC paacd;
  1966. UINT uId;
  1967. paacd = (PAACONVERTDESC)(UINT)GetWindowLong(hwnd, DWL_USER);
  1968. switch (uMsg)
  1969. {
  1970. case WM_INITDIALOG:
  1971. paacd = (PAACONVERTDESC)(UINT)lParam;
  1972. SetWindowLong(hwnd, DWL_USER, lParam);
  1973. SetWindowFont(GetDlgItem(hwnd, IDD_AACONVERT_TXT_INFILEPATH), ghfontApp, FALSE);
  1974. SetWindowFont(GetDlgItem(hwnd, IDD_AACONVERT_TXT_OUTFILEPATH), ghfontApp, FALSE);
  1975. SetWindowFont(GetDlgItem(hwnd, IDD_AACONVERT_TXT_STATUS), ghfontApp, FALSE);
  1976. SetDlgItemText(hwnd, IDD_AACONVERT_TXT_INFILEPATH, paacd->szFilePathSrc);
  1977. SetDlgItemText(hwnd, IDD_AACONVERT_TXT_OUTFILEPATH, paacd->szFilePathDst);
  1978. BeginConvert(hwnd, paacd);
  1979. return (TRUE);
  1980. case WM_CONVERT_BEGIN:
  1981. gfCancelConvert = FALSE;
  1982. if (AcmAppConvertBegin(hwnd, paacd))
  1983. {
  1984. AcmAppConvertConvert(hwnd, paacd);
  1985. }
  1986. else
  1987. {
  1988. EndConvert(hwnd, FALSE, paacd);
  1989. }
  1990. break;
  1991. case WM_CONVERT_END:
  1992. AcmAppConvertEnd(hwnd, paacd);
  1993. EndDialog(hwnd, !gfCancelConvert);
  1994. break;
  1995. case WM_COMMAND:
  1996. uId = GET_WM_COMMAND_ID(wParam, lParam);
  1997. if (IDCANCEL == uId)
  1998. {
  1999. gfCancelConvert = TRUE;
  2000. }
  2001. break;
  2002. }
  2003. return (FALSE);
  2004. } // AcmAppConvertDlgProc()
  2005. //==========================================================================;
  2006. //
  2007. //
  2008. //
  2009. //
  2010. //==========================================================================;
  2011. //--------------------------------------------------------------------------;
  2012. //
  2013. // BOOL AcmAppFileConvert
  2014. //
  2015. // Description:
  2016. //
  2017. //
  2018. // Arguments:
  2019. // HWND hwnd:
  2020. //
  2021. // PACMAPPFILEDESC paafd:
  2022. //
  2023. // Return (BOOL):
  2024. //
  2025. //--------------------------------------------------------------------------;
  2026. BOOL FNGLOBAL AcmAppFileConvert
  2027. (
  2028. HWND hwnd,
  2029. PACMAPPFILEDESC paafd
  2030. )
  2031. {
  2032. BOOL f;
  2033. DWORD nAvgBytesPerSec;
  2034. DWORD nBlockAlign;
  2035. DWORD dwTimeAverage;
  2036. PAACONVERTDESC paacd;
  2037. paacd = (PAACONVERTDESC)LocalAlloc(LPTR, sizeof(*paacd));
  2038. if (NULL == paacd)
  2039. {
  2040. return (FALSE);
  2041. }
  2042. //
  2043. //
  2044. //
  2045. paacd->hmmioSrc = NULL;
  2046. paacd->hmmioDst = NULL;
  2047. //
  2048. // default to 1 second per convert buffer..
  2049. //
  2050. paacd->uBufferTimePerConvert = 1000;
  2051. paacd->dwSrcSamples = paafd->dwDataSamples;
  2052. //
  2053. // compute source bytes to read (round down to nearest block for
  2054. // one second of data)
  2055. //
  2056. nAvgBytesPerSec = paafd->pwfx->nAvgBytesPerSec;
  2057. nBlockAlign = paafd->pwfx->nBlockAlign;
  2058. paacd->cbSrcReadSize = nAvgBytesPerSec - (nAvgBytesPerSec % nBlockAlign);
  2059. paacd->cbDstBufSize = 0L;
  2060. paacd->fdwOpen = 0L;
  2061. lstrcpy(paacd->szFilePathSrc, paafd->szFilePath);
  2062. paacd->pwfxSrc = paafd->pwfx;
  2063. paacd->pbSrc = NULL;
  2064. paacd->cbSrcData = paafd->dwDataBytes;
  2065. lstrcpy(paacd->szFilePathDst, gszLastSaveFile);
  2066. paacd->pwfxDst = NULL;
  2067. paacd->pbDst = NULL;
  2068. paacd->fApplyFilter = FALSE;
  2069. paacd->pwfltr = NULL;
  2070. paacd->cTotalConverts = 0L;
  2071. paacd->dwTimeTotal = 0L;
  2072. paacd->dwTimeShortest = (DWORD)-1L;
  2073. paacd->dwShortestConvert = (DWORD)-1L;
  2074. paacd->dwTimeLongest = 0L;
  2075. paacd->dwLongestConvert = (DWORD)-1L;
  2076. //
  2077. //
  2078. //
  2079. f = DialogBoxParam(ghinst,
  2080. DLG_AACHOOSER,
  2081. hwnd,
  2082. AcmAppDlgProcChooser,
  2083. (LPARAM)(UINT)paacd);
  2084. if (f)
  2085. {
  2086. lstrcpy(gszLastSaveFile, paacd->szFilePathDst);
  2087. //
  2088. //
  2089. //
  2090. f = DialogBoxParam(ghinst,
  2091. DLG_AACONVERT,
  2092. hwnd,
  2093. AcmAppConvertDlgProc,
  2094. (LPARAM)(UINT)paacd);
  2095. if (!f)
  2096. {
  2097. AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
  2098. TEXT("Conversion aborted--destination file is corrupt!"));
  2099. }
  2100. if (paacd->cTotalConverts > 1)
  2101. {
  2102. dwTimeAverage = paacd->dwTimeTotal;
  2103. dwTimeAverage -= paacd->dwTimeShortest;
  2104. dwTimeAverage /= (paacd->cTotalConverts - 1);
  2105. }
  2106. else
  2107. {
  2108. dwTimeAverage = paacd->dwTimeTotal;
  2109. }
  2110. AppMsgBox(hwnd, MB_OK | MB_ICONEXCLAMATION,
  2111. TEXT("Conversion Statistics:\n\nTotal Time:\t%lu ms\nTotal Converts:\t%lu\nShortest Time:\t%lu ms (on %lu)\nLongest Time:\t%lu ms (on %lu)\n\nAverage Time:\t%lu ms"),
  2112. paacd->dwTimeTotal,
  2113. paacd->cTotalConverts,
  2114. paacd->dwTimeShortest,
  2115. paacd->dwShortestConvert,
  2116. paacd->dwTimeLongest,
  2117. paacd->dwLongestConvert,
  2118. dwTimeAverage);
  2119. if (f)
  2120. {
  2121. AcmAppOpenInstance(hwnd, paacd->szFilePathDst, FALSE);
  2122. }
  2123. }
  2124. //
  2125. //
  2126. //
  2127. if (NULL != paacd->pwfxDst)
  2128. {
  2129. GlobalFreePtr(paacd->pwfxDst);
  2130. paacd->pwfxDst = NULL;
  2131. }
  2132. if (NULL != paacd->pwfltr)
  2133. {
  2134. GlobalFreePtr(paacd->pwfltr);
  2135. paacd->pwfltr = NULL;
  2136. }
  2137. paacd->pwfxSrc = NULL;
  2138. LocalFree((HLOCAL)paacd);
  2139. return (f);
  2140. } // AcmAppFileConvert()