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.

1310 lines
31 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. // aaplyrec.c
  13. //
  14. // Description:
  15. // An play/record dialog based on MCI Wave.
  16. //
  17. //
  18. // Known Bugs In MCIWAVE for Windows 3.1:
  19. // ======================================
  20. //
  21. // o If you are running SHARE (or the equivelant) and attempt to open
  22. // a file that is open by another application, you will receive the
  23. // following error:
  24. //
  25. // "Cannot find the specified file. Make sure the path and
  26. // filename are correct..."
  27. //
  28. // This is of course wrong. The problem is the file cannot be opened
  29. // read/write by multiple applications.
  30. //
  31. // o Opening a wave file that is more than about three seconds long and
  32. // issueing the following commands will hang Windows:
  33. //
  34. // open xxx.wav alias zyz ; open > 3 second file
  35. // delete zyz from 1000 to 2000 ; remove some data
  36. // delete zyz from 1000 to 2000 ; do it again and you hang
  37. //
  38. // I think this will also happen with the following commands:
  39. //
  40. // open c:\win31\ding.wav alias zyz
  41. // delete zyz to 100
  42. //
  43. // o You cannot play or record data with a synchronous wave device. This
  44. // is due to MCIWAVE relying on the ability to 'stream' data. This is
  45. // not really a bug, just a limitation.
  46. //
  47. // o Block alignment is not correctly handled for non-PCM wave files
  48. // when editing (includes recording). It is illegal to start recording
  49. // in the middle of a block. The result if this happens is garbage
  50. // data. This occurs if you insert data with a partial block at the
  51. // end also...
  52. //
  53. // o It is possible to kill Windows by issueing the following commands
  54. // without yielding between sending the commands:
  55. //
  56. // capability <file> inputs
  57. // close <file>
  58. // open <file>
  59. //
  60. // Should be able to fix the problem by Yield'ing.
  61. //
  62. // o Saving to the same wave file twice without closing the device deletes
  63. // the existing file. Don't save twice.
  64. //
  65. // o Saving an 'empty' wave file does not work. Issueing the following
  66. // commands demonstrates the problem:
  67. //
  68. // open new type waveaudio alias zyz
  69. // save zyz as c:\zyz.wav
  70. //
  71. // You will receive an 'out of memory error' which is completely bogus.
  72. // Just don't save empty files.
  73. //
  74. // o Setting the time format to bytes doesn't work with compressed files.
  75. // Sigh...
  76. //
  77. // o And there are others with less frequently used commands.
  78. //
  79. //==========================================================================;
  80. #include <windows.h>
  81. #include <windowsx.h>
  82. #include <mmsystem.h>
  83. #include <stdlib.h>
  84. #include <memory.h>
  85. #include <mmreg.h>
  86. #include <msacm.h>
  87. #include "muldiv32.h"
  88. #include "appport.h"
  89. #include "acmapp.h"
  90. #include "debug.h"
  91. #ifndef _MCIERROR_
  92. #define _MCIERROR_
  93. typedef DWORD MCIERROR; // error return code, 0 means no error
  94. #endif
  95. TCHAR gszAlias[] = TEXT("zyzthing");
  96. BOOL gfFileOpen;
  97. BOOL gfDirty;
  98. BOOL gfTimerGoing;
  99. UINT guPlayRecordStatus;
  100. #define AAPLAYRECORD_TIMER_RESOLUTION 54
  101. #define AAPLAYRECORD_MAX_MCI_COMMAND_CHARS 255
  102. #define AAPLAYRECORD_STATUS_NOT_READY 0
  103. #define AAPLAYRECORD_STATUS_PAUSED 1
  104. #define AAPLAYRECORD_STATUS_PLAYING 2
  105. #define AAPLAYRECORD_STATUS_STOPPED 3
  106. #define AAPLAYRECORD_STATUS_RECORDING 4
  107. #define AAPLAYRECORD_STATUS_SEEKING 5
  108. #define AAPLAYRECORD_STATUS_NOT_OPEN (UINT)-1
  109. //--------------------------------------------------------------------------;
  110. //
  111. // MCIERROR AcmPlayRecordSendCommand
  112. //
  113. // Description:
  114. // The string is of the form "verb params" our device name is inserted
  115. // after the verb and send to the device.
  116. //
  117. // Arguments:
  118. // HWND hwnd:
  119. //
  120. // PSTR pszCommand:
  121. //
  122. // PSTR pszReturn:
  123. //
  124. // UINT cbReturn:
  125. //
  126. // BOOL fErrorBox:
  127. //
  128. // Return (MCIERROR):
  129. //
  130. //
  131. //--------------------------------------------------------------------------;
  132. MCIERROR FNLOCAL AcmPlayRecordSendCommand
  133. (
  134. HWND hwnd,
  135. PTSTR pszCommand,
  136. PTSTR pszReturn,
  137. UINT cbReturn,
  138. BOOL fErrorBox
  139. )
  140. {
  141. MCIERROR mcierr;
  142. TCHAR ach[AAPLAYRECORD_MAX_MCI_COMMAND_CHARS * 2];
  143. TCHAR *pch;
  144. PTSTR psz;
  145. pch = pszCommand;
  146. while (('\t' == *pch) || (' ' == *pch))
  147. {
  148. pch++;
  149. }
  150. if (0 == lstrlen(pch))
  151. {
  152. return (MMSYSERR_NOERROR);
  153. }
  154. pch = ach;
  155. psz = pszCommand;
  156. while (('\0' != *psz) && (' ' != *psz))
  157. {
  158. *pch++ = *psz++;
  159. }
  160. *pch++ = ' ';
  161. lstrcpy(pch, gszAlias);
  162. lstrcat(pch, psz);
  163. mcierr = mciSendString(ach, pszReturn, cbReturn, hwnd);
  164. if (MMSYSERR_NOERROR != mcierr)
  165. {
  166. if (fErrorBox)
  167. {
  168. int n;
  169. n = wsprintf(ach, TEXT("Command: '%s'\n\nMCI Wave Error (%lu): "),
  170. (LPTSTR)pszCommand, mcierr);
  171. mciGetErrorString(mcierr, &ach[n], SIZEOF(ach) - n);
  172. MessageBox(hwnd, ach, TEXT("MCI Wave Error"), MB_ICONEXCLAMATION | MB_OK);
  173. }
  174. }
  175. return (mcierr);
  176. } // AcmPlayRecordSendCommand()
  177. //--------------------------------------------------------------------------;
  178. //
  179. // BOOL AcmAppPlayRecordCommand
  180. //
  181. // Description:
  182. //
  183. //
  184. // Arguments:
  185. // HWND hwnd:
  186. //
  187. // Return (BOOL):
  188. //
  189. //
  190. //--------------------------------------------------------------------------;
  191. BOOL FNLOCAL AcmAppPlayRecordCommand
  192. (
  193. HWND hwnd
  194. )
  195. {
  196. TCHAR ach[AAPLAYRECORD_MAX_MCI_COMMAND_CHARS * 2];
  197. HWND hedit;
  198. MCIERROR mcierr;
  199. //
  200. //
  201. //
  202. hedit = GetDlgItem(hwnd, IDD_AAPLAYRECORD_EDIT_COMMAND);
  203. Edit_SetSel(hedit, 0, -1);
  204. Edit_GetText(hedit, ach, SIZEOF(ach));
  205. mcierr = AcmPlayRecordSendCommand(hwnd, ach, ach, SIZEOF(ach), FALSE);
  206. if (MMSYSERR_NOERROR != mcierr)
  207. {
  208. mciGetErrorString(mcierr, ach, SIZEOF(ach));
  209. }
  210. hedit = GetDlgItem(hwnd, IDD_AAPLAYRECORD_EDIT_RESULT);
  211. Edit_SetText(hedit, ach);
  212. return (TRUE);
  213. } // AcmAppPlayRecordCommand()
  214. //--------------------------------------------------------------------------;
  215. //
  216. // BOOL AcmAppPlayRecordSetPosition
  217. //
  218. // Description:
  219. //
  220. //
  221. // Arguments:
  222. // HWND hwnd:
  223. //
  224. // HWND hsb:
  225. //
  226. // UINT uCode:
  227. //
  228. // int nPos:
  229. //
  230. // Return (BOOL):
  231. //
  232. //
  233. //--------------------------------------------------------------------------;
  234. BOOL FNLOCAL AcmAppPlayRecordSetPosition
  235. (
  236. HWND hwnd,
  237. HWND hsb,
  238. UINT uCode,
  239. int nPos
  240. )
  241. {
  242. MCIERROR mcierr;
  243. TCHAR szPosition[40];
  244. TCHAR szLength[40];
  245. LONG lLength;
  246. LONG lPosition;
  247. LONG lPageInc;
  248. int nRange;
  249. int nMinPos;
  250. //
  251. //
  252. //
  253. //
  254. if (AAPLAYRECORD_STATUS_NOT_OPEN == guPlayRecordStatus)
  255. {
  256. return (FALSE);
  257. }
  258. //
  259. //
  260. //
  261. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("status length"), szLength, SIZEOF(szLength), FALSE);
  262. if (MMSYSERR_NOERROR != mcierr)
  263. {
  264. return (FALSE);
  265. }
  266. lLength = _tcstol(szLength, NULL, 10);
  267. if (0L == lLength)
  268. {
  269. return (FALSE);
  270. }
  271. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("status position"), szPosition, SIZEOF(szPosition), FALSE);
  272. if (MMSYSERR_NOERROR != mcierr)
  273. {
  274. return (FALSE);
  275. }
  276. lPosition = _tcstol(szPosition, NULL, 10);
  277. lPageInc = (lLength / 10);
  278. if (0L == lPageInc)
  279. {
  280. lPageInc = 1;
  281. }
  282. //
  283. //
  284. //
  285. switch (uCode)
  286. {
  287. case SB_PAGEDOWN:
  288. lPosition = min(lLength, lPosition + lPageInc);
  289. break;
  290. case SB_LINEDOWN:
  291. lPosition = min(lLength, lPosition + 1);
  292. break;
  293. case SB_PAGEUP:
  294. lPosition -= lPageInc;
  295. //-- fall through --//
  296. case SB_LINEUP:
  297. lPosition = (lPosition < 1) ? 0 : (lPosition - 1);
  298. break;
  299. case SB_TOP:
  300. lPosition = 0;
  301. break;
  302. case SB_BOTTOM:
  303. lPosition = lLength;
  304. break;
  305. case SB_THUMBPOSITION:
  306. case SB_THUMBTRACK:
  307. GetScrollRange(hsb, SB_CTL, &nMinPos, &nRange);
  308. lPosition = (DWORD)MulDivRN((DWORD)nPos, (DWORD)lLength, (DWORD)nRange);
  309. break;
  310. default:
  311. return (FALSE);
  312. }
  313. //
  314. //
  315. //
  316. wsprintf(szPosition, TEXT("seek to %lu"), lPosition);
  317. AcmPlayRecordSendCommand(hwnd, szPosition, NULL, 0, FALSE);
  318. return (TRUE);
  319. } // AcmAppPlayRecordSetPosition()
  320. //--------------------------------------------------------------------------;
  321. //
  322. // BOOL AcmAppPlayRecordStatus
  323. //
  324. // Description:
  325. //
  326. //
  327. // Arguments:
  328. // HWND hwnd:
  329. //
  330. // PACMAPPFILEDESC paafd:
  331. //
  332. // Return (BOOL):
  333. //
  334. //
  335. //--------------------------------------------------------------------------;
  336. BOOL FNLOCAL AcmAppPlayRecordStatus
  337. (
  338. HWND hwnd,
  339. PACMAPPFILEDESC paafd
  340. )
  341. {
  342. TCHAR ach[AAPLAYRECORD_MAX_MCI_COMMAND_CHARS];
  343. TCHAR szMode[40];
  344. TCHAR szPosition[40];
  345. TCHAR szLength[40];
  346. TCHAR szFormat[40];
  347. MCIERROR mcierr;
  348. UINT uStatus;
  349. BOOL fStartTimer;
  350. BOOL fPlay;
  351. BOOL fPause;
  352. BOOL fStop;
  353. BOOL fStart;
  354. BOOL fEnd;
  355. BOOL fRecord;
  356. BOOL fCommand;
  357. UINT uIdFocus;
  358. DWORD dwLength;
  359. DWORD dwPosition;
  360. HWND hsb;
  361. //
  362. //
  363. //
  364. if (AAPLAYRECORD_STATUS_NOT_OPEN != guPlayRecordStatus)
  365. {
  366. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("status mode"), szMode, SIZEOF(szMode), FALSE);
  367. if (MMSYSERR_NOERROR != mcierr)
  368. {
  369. guPlayRecordStatus = AAPLAYRECORD_STATUS_NOT_OPEN;
  370. }
  371. }
  372. //
  373. // assume all buttons disabled
  374. //
  375. fStartTimer = FALSE;
  376. fPlay = FALSE;
  377. fPause = FALSE;
  378. fStop = FALSE;
  379. fStart = FALSE;
  380. fEnd = FALSE;
  381. fRecord = FALSE;
  382. fCommand = TRUE;
  383. uIdFocus = IDOK;
  384. dwPosition = 0L;
  385. dwLength = 0L;
  386. lstrcpy(szFormat, TEXT("???"));
  387. hsb = GetDlgItem(hwnd, IDD_AAPLAYRECORD_SCROLL_POSITION);
  388. //
  389. //
  390. //
  391. if (AAPLAYRECORD_STATUS_NOT_OPEN == guPlayRecordStatus)
  392. {
  393. lstrcpy(szMode, TEXT("not open"));
  394. }
  395. else if (0 == lstrcmpi(TEXT("not ready"), szMode))
  396. {
  397. uStatus = AAPLAYRECORD_STATUS_NOT_READY;
  398. fStartTimer = TRUE;
  399. }
  400. else if (0 == lstrcmpi(TEXT("paused"), szMode))
  401. {
  402. uStatus = AAPLAYRECORD_STATUS_PAUSED;
  403. fPause = TRUE;
  404. fStop = TRUE;
  405. }
  406. else if (0 == lstrcmpi(TEXT("playing"), szMode))
  407. {
  408. uStatus = AAPLAYRECORD_STATUS_PLAYING;
  409. fStartTimer = TRUE;
  410. fPause = TRUE;
  411. fStop = TRUE;
  412. }
  413. else if (0 == lstrcmpi(TEXT("stopped"), szMode))
  414. {
  415. uStatus = AAPLAYRECORD_STATUS_STOPPED;
  416. fPlay = TRUE;
  417. fStart = TRUE;
  418. fEnd = TRUE;
  419. fRecord = TRUE;
  420. }
  421. else if (0 == lstrcmpi(TEXT("recording"), szMode))
  422. {
  423. uStatus = AAPLAYRECORD_STATUS_RECORDING;
  424. fStartTimer = TRUE;
  425. fPause = TRUE;
  426. fStop = TRUE;
  427. }
  428. else if (0 == lstrcmpi(TEXT("seeking"), szMode))
  429. {
  430. uStatus = AAPLAYRECORD_STATUS_SEEKING;
  431. fStartTimer = TRUE;
  432. fStop = TRUE;
  433. }
  434. //
  435. //
  436. //
  437. //
  438. //
  439. if (fStartTimer)
  440. {
  441. if (!gfTimerGoing)
  442. {
  443. SetTimer(hwnd, 1, AAPLAYRECORD_TIMER_RESOLUTION, NULL);
  444. gfTimerGoing = TRUE;
  445. }
  446. }
  447. else if (gfTimerGoing)
  448. {
  449. KillTimer(hwnd, 1);
  450. gfTimerGoing = FALSE;
  451. }
  452. //
  453. //
  454. //
  455. //
  456. if (AAPLAYRECORD_STATUS_NOT_OPEN != guPlayRecordStatus)
  457. {
  458. //
  459. //
  460. //
  461. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("status position"), szPosition, SIZEOF(szPosition), FALSE);
  462. if (MMSYSERR_NOERROR == mcierr)
  463. {
  464. dwPosition = _tcstoul(szPosition, NULL, 10);
  465. }
  466. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("status length"), szLength, SIZEOF(szLength), FALSE);
  467. if (MMSYSERR_NOERROR == mcierr)
  468. {
  469. dwLength = _tcstoul(szLength, NULL, 10);
  470. }
  471. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("status time format"), szFormat, SIZEOF(szFormat), FALSE);
  472. }
  473. //
  474. //
  475. //
  476. //
  477. if (uStatus != guPlayRecordStatus)
  478. {
  479. if (GetFocus() != hsb)
  480. {
  481. LRESULT lr;
  482. lr = SendMessage(hwnd, DM_GETDEFID, 0, 0L);
  483. if (DC_HASDEFID == HIWORD(lr))
  484. {
  485. UINT uIdDefId;
  486. uIdDefId = LOWORD(lr);
  487. if (IDOK != uIdDefId)
  488. {
  489. HWND hwndDefId;
  490. hwndDefId = GetDlgItem(hwnd, uIdDefId);
  491. Button_SetStyle(hwndDefId, BS_PUSHBUTTON, TRUE);
  492. }
  493. }
  494. SendMessage(hwnd, DM_SETDEFID, IDOK, 0L);
  495. SetFocus(GetDlgItem(hwnd, IDD_AAPLAYRECORD_EDIT_COMMAND));
  496. }
  497. EnableWindow(GetDlgItem(hwnd, IDD_AAPLAYRECORD_BTN_PLAY), fPlay );
  498. EnableWindow(GetDlgItem(hwnd, IDD_AAPLAYRECORD_BTN_PAUSE), fPause );
  499. EnableWindow(GetDlgItem(hwnd, IDD_AAPLAYRECORD_BTN_STOP), fStop );
  500. EnableWindow(GetDlgItem(hwnd, IDD_AAPLAYRECORD_BTN_START), fStart );
  501. EnableWindow(GetDlgItem(hwnd, IDD_AAPLAYRECORD_BTN_END), fEnd );
  502. EnableWindow(GetDlgItem(hwnd, IDD_AAPLAYRECORD_BTN_RECORD), fRecord);
  503. EnableWindow(GetDlgItem(hwnd, IDD_AAPLAYRECORD_EDIT_COMMAND), fCommand);
  504. EnableWindow(GetDlgItem(hwnd, IDOK), fCommand);
  505. if (AAPLAYRECORD_STATUS_PAUSED == uStatus)
  506. SetDlgItemText(hwnd, IDD_AAPLAYRECORD_BTN_PAUSE, TEXT("Resum&e"));
  507. else
  508. SetDlgItemText(hwnd, IDD_AAPLAYRECORD_BTN_PAUSE, TEXT("Paus&e"));
  509. guPlayRecordStatus = uStatus;
  510. }
  511. //
  512. //
  513. //
  514. AppFormatBigNumber(szPosition, dwPosition);
  515. AppFormatBigNumber(szLength, dwLength);
  516. wsprintf(ach, TEXT("%s: %14s (%s) %s"),
  517. (LPSTR)szMode,
  518. (LPSTR)szPosition,
  519. (LPSTR)szLength,
  520. (LPSTR)szFormat);
  521. SetDlgItemText(hwnd, IDD_AAPLAYRECORD_TXT_POSITION, ach);
  522. //
  523. //
  524. //
  525. //
  526. {
  527. int nRange;
  528. int nValue;
  529. int nMinPos;
  530. int nMaxPos;
  531. GetScrollRange(hsb, SB_CTL, &nMinPos, &nMaxPos);
  532. nRange = (int)min(dwLength, 32767L);
  533. if (nMaxPos != nRange)
  534. {
  535. SetScrollRange(hsb, SB_CTL, 0, nRange, FALSE);
  536. }
  537. //
  538. //
  539. //
  540. nValue = 0;
  541. if (0L != dwLength)
  542. {
  543. nValue = (int)MulDivRN(dwPosition, nRange, dwLength);
  544. }
  545. if (nValue != GetScrollPos(hsb, SB_CTL))
  546. {
  547. SetScrollPos(hsb, SB_CTL, nValue, TRUE);
  548. }
  549. }
  550. return (TRUE);
  551. } // AcmAppPlayRecordStatus()
  552. //--------------------------------------------------------------------------;
  553. //
  554. // BOOL AcmAppPlayRecordRecord
  555. //
  556. // Description:
  557. //
  558. //
  559. // Arguments:
  560. // HWND hwnd:
  561. //
  562. // PACMAPPFILEDESC paafd:
  563. //
  564. // Return (BOOL):
  565. //
  566. //
  567. //--------------------------------------------------------------------------;
  568. BOOL FNLOCAL AcmAppPlayRecordRecord
  569. (
  570. HWND hwnd,
  571. PACMAPPFILEDESC paafd
  572. )
  573. {
  574. MCIERROR mcierr;
  575. //
  576. //
  577. //
  578. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("record insert"), NULL, 0, TRUE);
  579. if (MMSYSERR_NOERROR == mcierr)
  580. {
  581. gfDirty = TRUE;
  582. }
  583. return (MMSYSERR_NOERROR == mcierr);
  584. } // AcmAppPlayRecordRecord()
  585. //--------------------------------------------------------------------------;
  586. //
  587. // BOOL AcmAppPlayRecordStart
  588. //
  589. // Description:
  590. //
  591. //
  592. // Arguments:
  593. // HWND hwnd:
  594. //
  595. // PACMAPPFILEDESC paafd:
  596. //
  597. // Return (BOOL):
  598. //
  599. //
  600. //--------------------------------------------------------------------------;
  601. BOOL FNLOCAL AcmAppPlayRecordStart
  602. (
  603. HWND hwnd,
  604. PACMAPPFILEDESC paafd
  605. )
  606. {
  607. MCIERROR mcierr;
  608. //
  609. //
  610. //
  611. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("seek to start"), NULL, 0, TRUE);
  612. return (MMSYSERR_NOERROR == mcierr);
  613. } // AcmAppPlayRecordStart()
  614. //--------------------------------------------------------------------------;
  615. //
  616. // BOOL AcmAppPlayRecordEnd
  617. //
  618. // Description:
  619. //
  620. //
  621. // Arguments:
  622. // HWND hwnd:
  623. //
  624. // PACMAPPFILEDESC paafd:
  625. //
  626. // Return (BOOL):
  627. //
  628. //
  629. //--------------------------------------------------------------------------;
  630. BOOL FNLOCAL AcmAppPlayRecordEnd
  631. (
  632. HWND hwnd,
  633. PACMAPPFILEDESC paafd
  634. )
  635. {
  636. MCIERROR mcierr;
  637. //
  638. //
  639. //
  640. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("seek to end"), NULL, 0, TRUE);
  641. return (MMSYSERR_NOERROR == mcierr);
  642. } // AcmAppPlayRecordEnd()
  643. //--------------------------------------------------------------------------;
  644. //
  645. // BOOL AcmAppPlayRecordStop
  646. //
  647. // Description:
  648. //
  649. //
  650. // Arguments:
  651. // HWND hwnd:
  652. //
  653. // PACMAPPFILEDESC paafd:
  654. //
  655. // Return (BOOL):
  656. //
  657. //
  658. //--------------------------------------------------------------------------;
  659. BOOL FNLOCAL AcmAppPlayRecordStop
  660. (
  661. HWND hwnd,
  662. PACMAPPFILEDESC paafd
  663. )
  664. {
  665. MCIERROR mcierr;
  666. //
  667. //
  668. //
  669. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("stop"), NULL, 0, TRUE);
  670. return (MMSYSERR_NOERROR == mcierr);
  671. } // AcmAppPlayRecordStop()
  672. //--------------------------------------------------------------------------;
  673. //
  674. // BOOL AcmAppPlayRecordPause
  675. //
  676. // Description:
  677. //
  678. //
  679. // Arguments:
  680. // HWND hwnd:
  681. //
  682. // PACMAPPFILEDESC paafd:
  683. //
  684. // Return (BOOL):
  685. //
  686. //
  687. //--------------------------------------------------------------------------;
  688. BOOL FNLOCAL AcmAppPlayRecordPause
  689. (
  690. HWND hwnd,
  691. PACMAPPFILEDESC paafd
  692. )
  693. {
  694. MCIERROR mcierr;
  695. PTSTR psz;
  696. //
  697. //
  698. //
  699. if (AAPLAYRECORD_STATUS_PAUSED == guPlayRecordStatus)
  700. psz = TEXT("resume");
  701. else
  702. psz = TEXT("pause");
  703. mcierr = AcmPlayRecordSendCommand(hwnd, psz, NULL, 0, TRUE);
  704. return (MMSYSERR_NOERROR == mcierr);
  705. } // AcmAppPlayRecordPause()
  706. //--------------------------------------------------------------------------;
  707. //
  708. // BOOL AcmAppPlayRecordPlay
  709. //
  710. // Description:
  711. //
  712. //
  713. // Arguments:
  714. // HWND hwnd:
  715. //
  716. // PACMAPPFILEDESC paafd:
  717. //
  718. // Return (BOOL):
  719. //
  720. //
  721. //--------------------------------------------------------------------------;
  722. BOOL FNLOCAL AcmAppPlayRecordPlay
  723. (
  724. HWND hwnd,
  725. PACMAPPFILEDESC paafd
  726. )
  727. {
  728. MCIERROR mcierr;
  729. TCHAR szPosition[40];
  730. TCHAR szLength[40];
  731. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("status position"), szPosition, SIZEOF(szPosition), TRUE);
  732. if (MMSYSERR_NOERROR != mcierr)
  733. {
  734. return (FALSE);
  735. }
  736. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("status length"), szLength, SIZEOF(szLength), TRUE);
  737. if (MMSYSERR_NOERROR != mcierr)
  738. {
  739. return (FALSE);
  740. }
  741. if (0 == lstrcmp(szPosition, szLength))
  742. {
  743. AcmPlayRecordSendCommand(hwnd, TEXT("seek to start"), NULL, 0, TRUE);
  744. }
  745. //
  746. //
  747. //
  748. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("play"), NULL, 0, TRUE);
  749. return (MMSYSERR_NOERROR == mcierr);
  750. } // AcmAppPlayRecordPlay()
  751. //--------------------------------------------------------------------------;
  752. //
  753. // BOOL AcmAppPlayRecordClose
  754. //
  755. // Description:
  756. //
  757. //
  758. // Arguments:
  759. // HWND hwnd:
  760. //
  761. // PACMAPPFILEDESC paafd:
  762. //
  763. // Return (BOOL):
  764. //
  765. //
  766. //--------------------------------------------------------------------------;
  767. BOOL FNLOCAL AcmAppPlayRecordClose
  768. (
  769. HWND hwnd,
  770. PACMAPPFILEDESC paafd
  771. )
  772. {
  773. MCIERROR mcierr;
  774. if (gfDirty)
  775. {
  776. UINT u;
  777. u = MessageBox(hwnd, TEXT("Save newly recorded data?"), TEXT("Save"),
  778. MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2);
  779. if (IDYES == u)
  780. {
  781. AppHourGlass(TRUE);
  782. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("save"), NULL, 0, TRUE);
  783. AppHourGlass(FALSE);
  784. }
  785. else
  786. {
  787. gfDirty = FALSE;
  788. }
  789. }
  790. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("close"), NULL, 0, TRUE);
  791. return (MMSYSERR_NOERROR == mcierr);
  792. } // AcmAppPlayRecordClose()
  793. //--------------------------------------------------------------------------;
  794. //
  795. // BOOL AcmAppPlayRecordOpen
  796. //
  797. // Description:
  798. //
  799. //
  800. // Arguments:
  801. // HWND hwnd:
  802. //
  803. // PACMAPPFILEDESC paafd:
  804. //
  805. // Return (BOOL):
  806. //
  807. //
  808. //--------------------------------------------------------------------------;
  809. BOOL FNLOCAL AcmAppPlayRecordOpen
  810. (
  811. HWND hwnd,
  812. PACMAPPFILEDESC paafd,
  813. UINT uWaveInId,
  814. UINT uWaveOutId
  815. )
  816. {
  817. TCHAR ach[AAPLAYRECORD_MAX_MCI_COMMAND_CHARS];
  818. MCIERROR mcierr;
  819. guPlayRecordStatus = AAPLAYRECORD_STATUS_NOT_OPEN;
  820. gfTimerGoing = FALSE;
  821. gfFileOpen = FALSE;
  822. gfDirty = FALSE;
  823. if (NULL == paafd->pwfx)
  824. {
  825. MessageBox(hwnd, TEXT("No wave file currently selected."),
  826. TEXT("Open Error"), MB_ICONEXCLAMATION | MB_OK);
  827. return (FALSE);
  828. }
  829. wsprintf(ach, TEXT("open %s alias %s"), (LPSTR)paafd->szFilePath, (LPSTR)gszAlias);
  830. mcierr = mciSendString(ach, NULL, 0, NULL);
  831. if (MMSYSERR_NOERROR != mcierr)
  832. {
  833. mciGetErrorString(mcierr, ach, SIZEOF(ach));
  834. MessageBox(hwnd, ach, TEXT("Open Error"), MB_ICONEXCLAMATION | MB_OK);
  835. return (FALSE);
  836. }
  837. gfFileOpen = TRUE;
  838. guPlayRecordStatus = AAPLAYRECORD_STATUS_NOT_READY;
  839. mcierr = AcmPlayRecordSendCommand(hwnd, TEXT("set time format samples"), NULL, 0, TRUE);
  840. if (WAVE_MAPPER != uWaveInId)
  841. {
  842. wsprintf(ach, TEXT("set input %u"), uWaveInId);
  843. mcierr = AcmPlayRecordSendCommand(hwnd, ach, NULL, 0, TRUE);
  844. }
  845. if (WAVE_MAPPER != uWaveOutId)
  846. {
  847. wsprintf(ach, TEXT("set output %u"), uWaveOutId);
  848. mcierr = AcmPlayRecordSendCommand(hwnd, ach, NULL, 0, TRUE);
  849. }
  850. return (TRUE);
  851. } // AcmAppPlayRecordOpen()
  852. //--------------------------------------------------------------------------;
  853. //
  854. // BOOL AcmAppPlayRecordInitCommands
  855. //
  856. // Description:
  857. //
  858. //
  859. // Arguments:
  860. // HWND hwnd:
  861. //
  862. // PACMAPPFILEDESC paafd:
  863. //
  864. // Return (BOOL):
  865. //
  866. //
  867. //--------------------------------------------------------------------------;
  868. BOOL FNLOCAL AcmAppPlayRecordInitCommands
  869. (
  870. HWND hwnd,
  871. PACMAPPFILEDESC paafd
  872. )
  873. {
  874. static PTSTR pszCommands[] =
  875. {
  876. TEXT("play"),
  877. TEXT("play to Y"),
  878. TEXT("play from X to Y"),
  879. TEXT(""),
  880. TEXT("capability can eject"),
  881. TEXT("capability can play"),
  882. TEXT("capability can record"),
  883. TEXT("capability can save"),
  884. TEXT("capability compound device"),
  885. TEXT("capability device type"),
  886. TEXT("capability has audio"),
  887. TEXT("capability has video"),
  888. TEXT("capability inputs"),
  889. TEXT("capability outputs"),
  890. TEXT("capability uses files"),
  891. TEXT(""),
  892. TEXT("cue input !"),
  893. TEXT("cue output !"),
  894. TEXT(""),
  895. TEXT("delete to Y !"),
  896. TEXT("delete from X to Y !"),
  897. TEXT(""),
  898. TEXT("info input"),
  899. TEXT("info file"),
  900. TEXT("info output"),
  901. TEXT("info product"),
  902. TEXT(""),
  903. TEXT("pause"),
  904. TEXT(""),
  905. TEXT("record insert !"),
  906. TEXT("record overwrite !"),
  907. TEXT("record to Y !"),
  908. TEXT("record from X to Y !"),
  909. TEXT(""),
  910. TEXT("resume"),
  911. TEXT(""),
  912. TEXT("save"),
  913. TEXT("save FILENAME"),
  914. TEXT(""),
  915. TEXT("seek to Y"),
  916. TEXT("seek to start"),
  917. TEXT("seek to end"),
  918. TEXT(""),
  919. TEXT("set alignment X"),
  920. TEXT("set any input"),
  921. TEXT("set any output"),
  922. TEXT("set audio all off"),
  923. TEXT("set audio all on"),
  924. TEXT("set audio left off"),
  925. TEXT("set audio left on"),
  926. TEXT("set audio right off"),
  927. TEXT("set audio right on"),
  928. TEXT("set bitspersample X"),
  929. TEXT("set bytespersec X"),
  930. TEXT("set channels X"),
  931. TEXT("set format tag X"),
  932. TEXT("set format tag pcm"),
  933. TEXT("set input X"),
  934. TEXT("set output X"),
  935. TEXT("set samplespersec X"),
  936. TEXT("set time format bytes"),
  937. TEXT("set time format milliseconds"),
  938. TEXT("set time format samples"),
  939. TEXT(""),
  940. TEXT("status alignment"),
  941. TEXT("status bitspersample"),
  942. TEXT("status bytespersec"),
  943. TEXT("status channels"),
  944. TEXT("status current track"),
  945. TEXT("status format tag"),
  946. TEXT("status input"),
  947. TEXT("status length"),
  948. TEXT("status length track X"),
  949. TEXT("status level"),
  950. TEXT("status media present"),
  951. TEXT("status mode"),
  952. TEXT("status number of tracks"),
  953. TEXT("status output"),
  954. TEXT("status position"),
  955. TEXT("status position track X"),
  956. TEXT("status ready"),
  957. TEXT("status samplespersec"),
  958. TEXT("status start position"),
  959. TEXT("status time format"),
  960. TEXT(""),
  961. TEXT("stop"),
  962. NULL
  963. };
  964. HWND hcb;
  965. UINT u;
  966. PTSTR psz;
  967. //
  968. //
  969. //
  970. hcb = GetDlgItem(hwnd, IDD_AAPLAYRECORD_EDIT_COMMAND);
  971. for (u = 0; psz = pszCommands[u]; u++)
  972. {
  973. ComboBox_AddString(hcb, psz);
  974. }
  975. ComboBox_SetCurSel(hcb, 0);
  976. return (TRUE);
  977. } // AcmAppPlayRecordInitCommands()
  978. //--------------------------------------------------------------------------;
  979. //
  980. // BOOL AcmAppPlayRecord
  981. //
  982. // Description:
  983. //
  984. //
  985. // Arguments:
  986. // HWND hwnd: Handle to window.
  987. //
  988. // UINT uMsg: Message being sent to the window.
  989. //
  990. // WPARAM wParam: Specific argument to message.
  991. //
  992. // LPARAM lParam: Specific argument to message.
  993. //
  994. // Return (BOOL):
  995. // The return value is specific to the message that was received. For
  996. // the most part, it is FALSE if this dialog procedure does not handle
  997. // a message.
  998. //
  999. //
  1000. //--------------------------------------------------------------------------;
  1001. BOOL FNEXPORT AcmAppPlayRecord
  1002. (
  1003. HWND hwnd,
  1004. UINT uMsg,
  1005. WPARAM wParam,
  1006. LPARAM lParam
  1007. )
  1008. {
  1009. PACMAPPFILEDESC paafd;
  1010. UINT uId;
  1011. HWND hedit;
  1012. HFONT hfont;
  1013. paafd = (PACMAPPFILEDESC)(UINT)GetWindowLong(hwnd, DWL_USER);
  1014. switch (uMsg)
  1015. {
  1016. case WM_INITDIALOG:
  1017. paafd = (PACMAPPFILEDESC)(UINT)lParam;
  1018. SetWindowLong(hwnd, DWL_USER, lParam);
  1019. // hfont = GetStockFont(ANSI_FIXED_FONT);
  1020. hfont = ghfontApp;
  1021. hedit = GetDlgItem(hwnd, IDD_AAPLAYRECORD_TXT_POSITION);
  1022. SetWindowFont(hedit, hfont, FALSE);
  1023. hedit = GetDlgItem(hwnd, IDD_AAPLAYRECORD_EDIT_COMMAND);
  1024. SetWindowFont(hedit, hfont, FALSE);
  1025. hedit = GetDlgItem(hwnd, IDD_AAPLAYRECORD_EDIT_RESULT);
  1026. SetWindowFont(hedit, hfont, FALSE);
  1027. AcmAppPlayRecordInitCommands(hwnd, paafd);
  1028. AcmAppPlayRecordOpen(hwnd, paafd, guWaveInId, guWaveOutId);
  1029. AcmAppPlayRecordStatus(hwnd, paafd);
  1030. //
  1031. // if the format is non-PCM, display a little warning so the
  1032. // user knows that not everything may work correctly when
  1033. // dealing working with MCI Wave..
  1034. //
  1035. if ((NULL != paafd->pwfx) &&
  1036. (WAVE_FORMAT_PCM != paafd->pwfx->wFormatTag))
  1037. {
  1038. hedit = GetDlgItem(hwnd, IDD_AAPLAYRECORD_EDIT_RESULT);
  1039. Edit_SetText(hedit, TEXT("WARNING! There are known bugs with MCI Wave EDITING operations on non-PCM formats--see the README.TXT with this application. (end)\r\n\r\nRemember, DON'T PANIC!\r\n\r\n\r\n\r\n\r\n\r\n- zYz -"));
  1040. }
  1041. return (TRUE);
  1042. case WM_TIMER:
  1043. AcmAppPlayRecordStatus(hwnd, paafd);
  1044. break;
  1045. case WM_HSCROLL:
  1046. HANDLE_WM_HSCROLL(hwnd, wParam, lParam, AcmAppPlayRecordSetPosition);
  1047. guPlayRecordStatus = AAPLAYRECORD_STATUS_SEEKING;
  1048. AcmAppPlayRecordStatus(hwnd, paafd);
  1049. return (TRUE);
  1050. case WM_COMMAND:
  1051. uId = GET_WM_COMMAND_ID(wParam, lParam);
  1052. switch (uId)
  1053. {
  1054. case IDD_AAPLAYRECORD_BTN_PLAY:
  1055. AcmAppPlayRecordPlay(hwnd, paafd);
  1056. AcmAppPlayRecordStatus(hwnd, paafd);
  1057. break;
  1058. case IDD_AAPLAYRECORD_BTN_PAUSE:
  1059. AcmAppPlayRecordPause(hwnd, paafd);
  1060. AcmAppPlayRecordStatus(hwnd, paafd);
  1061. break;
  1062. case IDD_AAPLAYRECORD_BTN_STOP:
  1063. AcmAppPlayRecordStop(hwnd, paafd);
  1064. AcmAppPlayRecordStatus(hwnd, paafd);
  1065. break;
  1066. case IDD_AAPLAYRECORD_BTN_START:
  1067. AcmAppPlayRecordStart(hwnd, paafd);
  1068. AcmAppPlayRecordStatus(hwnd, paafd);
  1069. break;
  1070. case IDD_AAPLAYRECORD_BTN_END:
  1071. AcmAppPlayRecordEnd(hwnd, paafd);
  1072. AcmAppPlayRecordStatus(hwnd, paafd);
  1073. break;
  1074. case IDD_AAPLAYRECORD_BTN_RECORD:
  1075. AcmAppPlayRecordRecord(hwnd, paafd);
  1076. AcmAppPlayRecordStatus(hwnd, paafd);
  1077. break;
  1078. case IDOK:
  1079. AcmAppPlayRecordCommand(hwnd);
  1080. guPlayRecordStatus = AAPLAYRECORD_STATUS_SEEKING;
  1081. AcmAppPlayRecordStatus(hwnd, paafd);
  1082. break;
  1083. case IDCANCEL:
  1084. if (gfFileOpen)
  1085. {
  1086. AcmAppPlayRecordStop(hwnd, paafd);
  1087. AcmAppPlayRecordStatus(hwnd, paafd);
  1088. AcmAppPlayRecordClose(hwnd, paafd);
  1089. }
  1090. EndDialog(hwnd, gfDirty);
  1091. break;
  1092. }
  1093. break;
  1094. }
  1095. return (FALSE);
  1096. } // AcmAppPlayRecord()