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.

799 lines
18 KiB

  1. //
  2. // Copyright (c) 1995-2000 Microsoft Corporation
  3. //
  4. // Waves.cpp
  5. //
  6. #include "stdafx.h"
  7. BOOL DSParseWaveResource(void *pvRes, WAVEFORMATEX **ppWaveHeader, BYTE ** ppbWaveData, DWORD *pdwWaveSize);
  8. static const char c_szWAV[] = "WAVE";
  9. ///////////////////////////////////////////////////////////////////////////////
  10. //
  11. // DSGetWaveResource
  12. //
  13. ///////////////////////////////////////////////////////////////////////////////
  14. BOOL DSGetWaveResource(HMODULE hModule, LPCTSTR lpName,
  15. WAVEFORMATEX **ppWaveHeader, BYTE **ppbWaveData, DWORD *pcbWaveSize)
  16. {
  17. HRSRC hResInfo;
  18. HGLOBAL hResData;
  19. void *pvRes;
  20. if (((hResInfo = FindResource(hModule, lpName, c_szWAV)) != NULL) &&
  21. ((hResData = LoadResource(hModule, hResInfo)) != NULL) &&
  22. ((pvRes = LockResource(hResData)) != NULL) &&
  23. DSParseWaveResource(pvRes, ppWaveHeader, ppbWaveData, pcbWaveSize))
  24. {
  25. return TRUE;
  26. }
  27. return FALSE;
  28. }
  29. ///////////////////////////////////////////////////////////////////////////////
  30. ///////////////////////////////////////////////////////////////////////////////
  31. BOOL DSParseWaveResource(void *pvRes, WAVEFORMATEX **ppWaveHeader, BYTE **
  32. ppbWaveData,DWORD *pcbWaveSize)
  33. {
  34. DWORD *pdw;
  35. DWORD *pdwEnd;
  36. DWORD dwRiff;
  37. DWORD dwType;
  38. DWORD dwLength;
  39. if (ppWaveHeader)
  40. {
  41. *ppWaveHeader = NULL;
  42. }
  43. if (ppbWaveData)
  44. {
  45. *ppbWaveData = NULL;
  46. }
  47. if (pcbWaveSize)
  48. {
  49. *pcbWaveSize = 0;
  50. }
  51. pdw = (DWORD *)pvRes;
  52. dwRiff = *pdw++;
  53. dwLength = *pdw++;
  54. dwType = *pdw++;
  55. if (dwRiff != mmioFOURCC('R', 'I', 'F', 'F'))
  56. goto exit; // not even RIFF
  57. if (dwType != mmioFOURCC('W', 'A', 'V', 'E'))
  58. goto exit; // not a WAV
  59. pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4);
  60. while (pdw < pdwEnd)
  61. {
  62. dwType = *pdw++;
  63. dwLength = *pdw++;
  64. switch (dwType)
  65. {
  66. case mmioFOURCC('f', 'm', 't', ' '):
  67. if (ppWaveHeader && !*ppWaveHeader)
  68. {
  69. if (dwLength < sizeof(WAVEFORMAT))
  70. {
  71. goto exit; // not a WAV
  72. }
  73. *ppWaveHeader = (WAVEFORMATEX *)pdw;
  74. if ((!ppbWaveData || *ppbWaveData) &&
  75. (!pcbWaveSize || *pcbWaveSize))
  76. {
  77. return TRUE;
  78. }
  79. }
  80. break;
  81. case mmioFOURCC('d', 'a', 't', 'a'):
  82. if ((ppbWaveData && !*ppbWaveData) ||
  83. (pcbWaveSize && !*pcbWaveSize))
  84. {
  85. if (ppbWaveData)
  86. {
  87. *ppbWaveData = (LPBYTE)pdw;
  88. }
  89. if (pcbWaveSize)
  90. {
  91. *pcbWaveSize = dwLength;
  92. }
  93. if (!ppWaveHeader || *ppWaveHeader)
  94. {
  95. return TRUE;
  96. }
  97. }
  98. break;
  99. }
  100. pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1));
  101. }
  102. exit:
  103. return FALSE;
  104. }
  105. //////////////////////////////////////////////////////////////////////////////
  106. //
  107. CWavePlayer::CWavePlayer()
  108. {
  109. m_hWaveOutTone = NULL;
  110. m_hWaveOutRing = NULL;
  111. m_hMixer = NULL;
  112. m_fInitialized = FALSE;
  113. memset(m_fPlaying, 0, NUM_TONES * sizeof(BOOL));
  114. m_lCurrentTone = -1;
  115. }
  116. //////////////////////////////////////////////////////////////////////////////
  117. //
  118. CWavePlayer::~CWavePlayer()
  119. {
  120. //
  121. // We should have closed the wave device by now.
  122. //
  123. if ( m_fInitialized == TRUE )
  124. {
  125. _ASSERTE( m_hWaveOutTone == NULL );
  126. _ASSERTE( m_hWaveOutRing == NULL );
  127. _ASSERTE( m_hMixer == NULL );
  128. }
  129. }
  130. //////////////////////////////////////////////////////////////////////////////
  131. //
  132. HRESULT CWavePlayer::Initialize(void)
  133. {
  134. int i;
  135. //
  136. // It's wasteful to initialize twice, but it won't break anything.
  137. //
  138. _ASSERTE( m_fInitialized == FALSE );
  139. //
  140. // Read all wave data resources.
  141. // We ignore the size and the wave header -- since these are our own
  142. // resources, we do not expect any surprises.
  143. //
  144. BOOL fResult;
  145. //
  146. // For each wave
  147. //
  148. for ( i = 0; i < NUM_WAVES; i ++ )
  149. {
  150. //
  151. // Read the wave resource for this tone.
  152. //
  153. fResult = DSGetWaveResource(
  154. _Module.GetModuleInstance(), // HMODULE hModule,
  155. (LPCTSTR)IDR_WAV_DTMF0 + i, // LPCTSTR lpName,
  156. NULL, // WAVEFORMATEX **ppWaveHeader,
  157. &m_lpWaveform[i], // BYTE **ppbWaveData,
  158. &m_dwWaveformSize[i] // DWORD *pcbWaveSize
  159. );
  160. if ( fResult == FALSE )
  161. {
  162. return E_FAIL;
  163. }
  164. }
  165. //
  166. // We can now go ahead with the other methods.
  167. //
  168. m_fInitialized = TRUE;
  169. return S_OK;
  170. }
  171. //////////////////////////////////////////////////////////////////////////////
  172. //
  173. HRESULT CWavePlayer::StartTone(
  174. long lTone
  175. )
  176. {
  177. MMRESULT mmresult;
  178. HRESULT hr;
  179. if ( lTone < 0 )
  180. {
  181. _ASSERTE( FALSE );
  182. return E_UNEXPECTED;
  183. }
  184. if ( lTone > NUM_TONES )
  185. {
  186. _ASSERTE( FALSE );
  187. return E_UNEXPECTED;
  188. }
  189. if ( m_fInitialized == FALSE )
  190. {
  191. _ASSERTE( FALSE );
  192. return E_UNEXPECTED;
  193. }
  194. if ( m_hWaveOutTone == NULL )
  195. {
  196. _ASSERTE( FALSE );
  197. return E_UNEXPECTED;
  198. }
  199. m_fPlaying[lTone] = TRUE;
  200. hr = ChangeTone();
  201. if ( FAILED( hr ) )
  202. {
  203. m_fPlaying[lTone] = FALSE;
  204. }
  205. return hr;
  206. }
  207. //////////////////////////////////////////////////////////////////////////////
  208. //
  209. HRESULT CWavePlayer::StopTone(
  210. long lTone
  211. )
  212. {
  213. if ( lTone < 0 )
  214. {
  215. _ASSERTE( FALSE );
  216. return E_UNEXPECTED;
  217. }
  218. if ( lTone > NUM_TONES )
  219. {
  220. _ASSERTE( FALSE );
  221. return E_UNEXPECTED;
  222. }
  223. if ( m_fInitialized == FALSE )
  224. {
  225. _ASSERTE( FALSE );
  226. return E_UNEXPECTED;
  227. }
  228. if ( m_hWaveOutTone == NULL )
  229. {
  230. _ASSERTE( FALSE );
  231. return E_UNEXPECTED;
  232. }
  233. m_fPlaying[lTone] = FALSE;
  234. return ChangeTone();
  235. }
  236. //////////////////////////////////////////////////////////////////////////////
  237. //
  238. HRESULT CWavePlayer::ChangeTone()
  239. {
  240. MMRESULT mmresult;
  241. for (int i=0; i < NUM_TONES; i++)
  242. {
  243. if (m_fPlaying[i])
  244. {
  245. //
  246. // If already playing it, just return
  247. //
  248. if (m_lCurrentTone == i)
  249. {
  250. return S_OK;
  251. }
  252. //
  253. // Reset the wave device to flush out any pending buffers.
  254. //
  255. mmresult = waveOutReset( m_hWaveOutTone );
  256. if ( mmresult != MMSYSERR_NOERROR )
  257. {
  258. return E_FAIL;
  259. }
  260. //
  261. // Construct a wave header structure that will indicate what to play
  262. // in waveOutWrite.
  263. //
  264. ZeroMemory( & m_WaveHeaderTone, sizeof( m_WaveHeaderTone ) );
  265. m_WaveHeaderTone.lpData = (LPSTR)m_lpWaveform[i];
  266. m_WaveHeaderTone.dwBufferLength = m_dwWaveformSize[i];
  267. m_WaveHeaderTone.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
  268. m_WaveHeaderTone.dwLoops = (DWORD) -1;
  269. //
  270. // Submit the data to the wave device. The wave header indicated that
  271. // we want to loop. Need to prepare the header first, but it can
  272. // only be prepared after the device has been opened.
  273. //
  274. mmresult = waveOutPrepareHeader(m_hWaveOutTone,
  275. & m_WaveHeaderTone,
  276. sizeof(WAVEHDR)
  277. );
  278. if ( mmresult != MMSYSERR_NOERROR )
  279. {
  280. m_lCurrentTone = -1;
  281. return E_FAIL;
  282. }
  283. mmresult = waveOutWrite(m_hWaveOutTone,
  284. & m_WaveHeaderTone,
  285. sizeof(WAVEHDR)
  286. );
  287. if ( mmresult != MMSYSERR_NOERROR )
  288. {
  289. m_lCurrentTone = -1;
  290. return E_FAIL;
  291. }
  292. m_lCurrentTone = i;
  293. return S_OK;
  294. }
  295. }
  296. //
  297. // Stop the tone
  298. //
  299. if ( m_lCurrentTone != -1 )
  300. {
  301. mmresult = waveOutReset( m_hWaveOutTone );
  302. if ( mmresult != MMSYSERR_NOERROR )
  303. {
  304. return E_FAIL;
  305. }
  306. m_lCurrentTone = -1;
  307. }
  308. return S_OK;
  309. }
  310. //////////////////////////////////////////////////////////////////////////////
  311. //
  312. BOOL CWavePlayer::PlayingTone(
  313. long lTone
  314. )
  315. {
  316. if ( lTone < 0 )
  317. {
  318. _ASSERTE( FALSE );
  319. return FALSE;
  320. }
  321. if ( lTone > NUM_TONES )
  322. {
  323. _ASSERTE( FALSE );
  324. return FALSE;
  325. }
  326. return m_fPlaying[lTone];
  327. }
  328. //////////////////////////////////////////////////////////////////////////////
  329. //
  330. HRESULT CWavePlayer::StartRing()
  331. {
  332. MMRESULT mmresult;
  333. if ( m_fInitialized == FALSE )
  334. {
  335. _ASSERTE( FALSE );
  336. return E_UNEXPECTED;
  337. }
  338. if ( m_hWaveOutRing == NULL )
  339. {
  340. _ASSERTE( FALSE );
  341. return E_UNEXPECTED;
  342. }
  343. //
  344. // Reset the wave device to flush out any pending buffers.
  345. //
  346. mmresult = waveOutReset( m_hWaveOutRing );
  347. if ( mmresult != MMSYSERR_NOERROR )
  348. {
  349. return E_FAIL;
  350. }
  351. //
  352. // Construct a wave header structure that will indicate what to play
  353. // in waveOutWrite.
  354. //
  355. ZeroMemory( & m_WaveHeaderRing, sizeof( m_WaveHeaderRing ) );
  356. m_WaveHeaderRing.lpData = (LPSTR)m_lpWaveform[NUM_WAVES-1];
  357. m_WaveHeaderRing.dwBufferLength = m_dwWaveformSize[NUM_WAVES-1];
  358. m_WaveHeaderRing.dwFlags = 0;
  359. m_WaveHeaderRing.dwLoops = (DWORD) 0;
  360. //
  361. // Submit the data to the wave device. The wave header indicated that
  362. // we want to loop. Need to prepare the header first, but it can
  363. // only be prepared after the device has been opened.
  364. //
  365. mmresult = waveOutPrepareHeader(m_hWaveOutRing,
  366. & m_WaveHeaderRing,
  367. sizeof(WAVEHDR)
  368. );
  369. if ( mmresult != MMSYSERR_NOERROR )
  370. {
  371. return E_FAIL;
  372. }
  373. mmresult = waveOutWrite(m_hWaveOutRing,
  374. & m_WaveHeaderRing,
  375. sizeof(WAVEHDR)
  376. );
  377. if ( mmresult != MMSYSERR_NOERROR )
  378. {
  379. return E_FAIL;
  380. }
  381. return S_OK;
  382. }
  383. //////////////////////////////////////////////////////////////////////////////
  384. //
  385. HRESULT CWavePlayer::StopRing( void )
  386. {
  387. MMRESULT mmresult;
  388. if ( m_fInitialized == FALSE )
  389. {
  390. _ASSERTE( FALSE );
  391. return E_UNEXPECTED;
  392. }
  393. if ( m_hWaveOutRing == NULL )
  394. {
  395. _ASSERTE( FALSE );
  396. return E_UNEXPECTED;
  397. }
  398. mmresult = waveOutReset( m_hWaveOutRing );
  399. if ( mmresult != MMSYSERR_NOERROR )
  400. {
  401. return E_FAIL;
  402. }
  403. return S_OK;
  404. }
  405. //////////////////////////////////////////////////////////////////////////////
  406. //
  407. HRESULT CWavePlayer::OpenWaveDeviceForTone(
  408. long lWaveID
  409. )
  410. {
  411. MMRESULT mmresult;
  412. if ( m_fInitialized == FALSE )
  413. {
  414. _ASSERTE( FALSE );
  415. return E_UNEXPECTED;
  416. }
  417. //
  418. // We expect that the wave device will not be opened twice. This is
  419. // dependent on the calling code.
  420. //
  421. _ASSERTE( m_hWaveOutTone == NULL );
  422. //
  423. // Open the wave device. Here we specify a hard-coded audio format.
  424. //
  425. WAVEFORMATEX waveFormat;
  426. waveFormat.wFormatTag = WAVE_FORMAT_PCM; // linear PCM
  427. waveFormat.nChannels = 1; // mono
  428. waveFormat.nSamplesPerSec = 8000; // 8 KHz
  429. waveFormat.wBitsPerSample = 16; // 16-bit samples
  430. waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
  431. waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
  432. waveFormat.cbSize = 0; // no extra format info
  433. mmresult = waveOutOpen(& m_hWaveOutTone, // returned handle
  434. lWaveID, // which device to use
  435. &waveFormat, // wave format to use
  436. 0, // callback function pointer
  437. 0, // callback instance data
  438. WAVE_FORMAT_DIRECT // we don't want ACM
  439. );
  440. if ( mmresult != MMSYSERR_NOERROR )
  441. {
  442. m_hWaveOutTone = NULL;
  443. return E_FAIL;
  444. }
  445. return S_OK;
  446. }
  447. //////////////////////////////////////////////////////////////////////////////
  448. //
  449. HRESULT CWavePlayer::OpenWaveDeviceForRing(
  450. long lWaveID
  451. )
  452. {
  453. MMRESULT mmresult;
  454. if ( m_fInitialized == FALSE )
  455. {
  456. _ASSERTE( FALSE );
  457. return E_UNEXPECTED;
  458. }
  459. //
  460. // We expect that the wave device will not be opened twice. This is
  461. // dependent on the calling code.
  462. //
  463. _ASSERTE( m_hWaveOutRing == NULL );
  464. //
  465. // Open the wave device. Here we specify a hard-coded audio format.
  466. //
  467. WAVEFORMATEX waveFormat;
  468. waveFormat.wFormatTag = WAVE_FORMAT_PCM; // linear PCM
  469. waveFormat.nChannels = 1; // mono
  470. waveFormat.nSamplesPerSec = 8000; // 8 KHz
  471. waveFormat.wBitsPerSample = 16; // 16-bit samples
  472. waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8;
  473. waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
  474. waveFormat.cbSize = 0; // no extra format info
  475. mmresult = waveOutOpen(& m_hWaveOutRing, // returned handle
  476. lWaveID, // which device to use
  477. &waveFormat, // wave format to use
  478. 0, // callback function pointer
  479. 0, // callback instance data
  480. WAVE_FORMAT_DIRECT // we don't want ACM
  481. );
  482. if ( mmresult != MMSYSERR_NOERROR )
  483. {
  484. m_hWaveOutRing = NULL;
  485. return E_FAIL;
  486. }
  487. return S_OK;
  488. }
  489. //////////////////////////////////////////////////////////////////////////////
  490. //
  491. void CWavePlayer::CloseWaveDeviceForTone(void)
  492. {
  493. if ( m_fInitialized == FALSE )
  494. {
  495. _ASSERTE( FALSE );
  496. }
  497. if ( m_hWaveOutTone != NULL )
  498. {
  499. waveOutReset( m_hWaveOutTone );
  500. memset(m_fPlaying, 0, NUM_TONES * sizeof(BOOL));
  501. m_lCurrentTone = -1;
  502. waveOutClose( m_hWaveOutTone );
  503. m_hWaveOutTone = NULL;
  504. }
  505. }
  506. //////////////////////////////////////////////////////////////////////////////
  507. //
  508. void CWavePlayer::CloseWaveDeviceForRing(void)
  509. {
  510. if ( m_fInitialized == FALSE )
  511. {
  512. _ASSERTE( FALSE );
  513. }
  514. if ( m_hWaveOutRing != NULL )
  515. {
  516. waveOutReset( m_hWaveOutRing );
  517. waveOutClose( m_hWaveOutRing );
  518. m_hWaveOutRing = NULL;
  519. }
  520. }
  521. //////////////////////////////////////////////////////////////////////////////
  522. //
  523. HRESULT CWavePlayer::OpenMixerDevice(
  524. long lWaveID
  525. )
  526. {
  527. MMRESULT mmresult;
  528. MIXERLINECONTROLS mxlc;
  529. mmresult = mixerOpen( &m_hMixer, lWaveID, 0, 0, MIXER_OBJECTF_WAVEOUT);
  530. if ( mmresult != MMSYSERR_NOERROR )
  531. {
  532. m_hMixer = NULL;
  533. return E_FAIL;
  534. }
  535. mxlc.cbStruct = sizeof(MIXERLINECONTROLS);
  536. mxlc.dwLineID = 0;
  537. mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
  538. mxlc.pamxctrl = &m_mxctrl;
  539. mxlc.cbmxctrl = sizeof(m_mxctrl);
  540. mmresult = mixerGetLineControls( (HMIXEROBJ)m_hMixer, &mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE );
  541. if ( mmresult != MMSYSERR_NOERROR )
  542. {
  543. //
  544. // Close the mixer
  545. //
  546. mixerClose( m_hMixer );
  547. m_hMixer = NULL;
  548. return E_FAIL;
  549. }
  550. return S_OK;
  551. }
  552. //////////////////////////////////////////////////////////////////////////////
  553. //
  554. void CWavePlayer::CloseMixerDevice(void)
  555. {
  556. if ( m_hMixer != NULL )
  557. {
  558. mixerClose( m_hMixer );
  559. m_hMixer = NULL;
  560. }
  561. }
  562. //////////////////////////////////////////////////////////////////////////////
  563. //
  564. HRESULT CWavePlayer::SetVolume( DWORD dwVolume )
  565. {
  566. MIXERCONTROLDETAILS mxcd;
  567. MIXERCONTROLDETAILS_UNSIGNED mxcd_u;
  568. MMRESULT mmresult;
  569. if ( m_fInitialized == FALSE )
  570. {
  571. _ASSERTE( FALSE );
  572. return E_UNEXPECTED;
  573. }
  574. if ( m_hMixer == NULL )
  575. {
  576. _ASSERTE( FALSE );
  577. return E_UNEXPECTED;
  578. }
  579. mxcd_u.dwValue = dwVolume;
  580. mxcd.cbStruct = sizeof(mxcd);
  581. mxcd.dwControlID = m_mxctrl.dwControlID;
  582. mxcd.cChannels = 1;
  583. mxcd.cMultipleItems = 0;
  584. mxcd.cbDetails = sizeof(mxcd_u);
  585. mxcd.paDetails = &mxcd_u;
  586. mmresult = mixerSetControlDetails( (HMIXEROBJ)m_hMixer, &mxcd, MIXER_SETCONTROLDETAILSF_VALUE);
  587. if ( mmresult != MMSYSERR_NOERROR )
  588. {
  589. return E_FAIL;
  590. }
  591. return S_OK;
  592. }
  593. //////////////////////////////////////////////////////////////////////////////
  594. //
  595. HRESULT CWavePlayer::GetVolume( DWORD * pdwVolume )
  596. {
  597. MIXERCONTROLDETAILS mxcd;
  598. MIXERCONTROLDETAILS_UNSIGNED mxcd_u;
  599. MMRESULT mmresult;
  600. if ( m_fInitialized == FALSE )
  601. {
  602. _ASSERTE( FALSE );
  603. return E_UNEXPECTED;
  604. }
  605. if ( m_hMixer == NULL )
  606. {
  607. _ASSERTE( FALSE );
  608. return E_UNEXPECTED;
  609. }
  610. mxcd.cbStruct = sizeof(mxcd);
  611. mxcd.dwControlID = m_mxctrl.dwControlID;
  612. mxcd.cChannels = 1;
  613. mxcd.cMultipleItems = 0;
  614. mxcd.cbDetails = sizeof(mxcd_u);
  615. mxcd.paDetails = &mxcd_u;
  616. mmresult = mixerGetControlDetails( (HMIXEROBJ)m_hMixer, &mxcd, MIXER_GETCONTROLDETAILSF_VALUE);
  617. if ( mmresult != MMSYSERR_NOERROR )
  618. {
  619. return E_FAIL;
  620. }
  621. *pdwVolume = mxcd_u.dwValue;
  622. return S_OK;
  623. }