Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4348 lines
100 KiB

  1. /////////////////////////////////////////////////////////////////////
  2. //
  3. // Module: tswave.c
  4. //
  5. // Purpose: User-mode driver for terminal server
  6. // sound redirection
  7. //
  8. // Copyright(C) Microsoft Corporation 2000
  9. //
  10. // History: 4-10-2000 vladimis [created]
  11. //
  12. /////////////////////////////////////////////////////////////////////
  13. #include "rdpsnd.h"
  14. #include <winsta.h>
  15. #define TSSND_NATIVE_XLATERATE ( TSSND_NATIVE_BLOCKALIGN * TSSND_NATIVE_SAMPLERATE )
  16. #define MIXER_OBJECTF_TYPEMASK 0xF0000000L // internal
  17. enum {
  18. RDP_MXDID_MUTE = 0,
  19. RDP_MXDID_VOLUME,
  20. RDP_MXDID_LAST
  21. };
  22. #define ENTER_CRIT EnterCriticalSection(&g_cs);
  23. #define LEAVE_CRIT LeaveCriticalSection(&g_cs);
  24. //
  25. // Global queue containing all queued wave headers
  26. // guarded by ENTER_CRIT LEAVE_CRIT macros
  27. //
  28. PWAVEOUTCTX g_pAllWaveOut = NULL;
  29. HANDLE g_hMixerEvent = NULL;
  30. CRITICAL_SECTION g_cs;
  31. MIXERCTX g_Mixer;
  32. //
  33. // Stream data
  34. //
  35. HANDLE g_hWaitToInitialize = NULL;
  36. HANDLE g_hDataReadyEvent = NULL;
  37. HANDLE g_hStreamIsEmptyEvent = NULL;
  38. HANDLE g_hStreamMutex = NULL;
  39. HANDLE g_hStream = NULL;
  40. PSNDSTREAM g_Stream = NULL;
  41. BOOL g_bMixerRunning = TRUE;
  42. DWORD
  43. waveRestart(
  44. PWAVEOUTCTX pWaveOut
  45. );
  46. BOOL
  47. _waveCheckSoundAlive(
  48. VOID
  49. );
  50. BOOL
  51. _waveAcquireStream(
  52. VOID
  53. );
  54. BOOL
  55. _waveReleaseStream(
  56. VOID
  57. );
  58. VOID Place8kHz8Mono(PVOID pDest, PVOID pSrc, DWORD dwSize);
  59. VOID Place8kHz8Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize);
  60. VOID Place8kHz16Mono(PVOID pDest, PVOID pSrc, DWORD dwSize);
  61. VOID Place8kHz16Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize);
  62. VOID Place11kHz8Mono(PVOID pDest, PVOID pSrc, DWORD dwSize);
  63. VOID Place22kHz8Mono(PVOID pDest, PVOID pSrc, DWORD dwSize);
  64. VOID Place44kHz8Mono(PVOID pDest, PVOID pSrc, DWORD dwSize);
  65. VOID Place11kHz16Mono(PVOID pDest, PVOID pSrc, DWORD dwSize);
  66. VOID Place22kHz16Mono(PVOID pDest, PVOID pSrc, DWORD dwSize);
  67. VOID Place44kHz16Mono(PVOID pDest, PVOID pSrc, DWORD dwSize);
  68. VOID Place11kHz8Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize);
  69. VOID Place22kHz8Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize);
  70. VOID Place44kHz8Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize);
  71. VOID Place11kHz16Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize);
  72. VOID Place22kHz16Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize);
  73. VOID Place44kHz16Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize);
  74. VOID Place48kHz8Mono(PVOID pDest, PVOID pSrc, DWORD dwSize);
  75. VOID Place48kHz8Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize);
  76. VOID Place48kHz16Mono(PVOID pDest, PVOID pSrc, DWORD dwSize);
  77. VOID Place48kHz16Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize);
  78. /*
  79. * Function:
  80. * waveCallback
  81. *
  82. * Description:
  83. * Fire a user specified callback
  84. *
  85. */
  86. VOID
  87. waveCallback(
  88. PWAVEOUTCTX pWaveOut,
  89. DWORD msg,
  90. DWORD_PTR dwParam1
  91. )
  92. {
  93. if (pWaveOut && pWaveOut->dwCallback)
  94. DriverCallback(pWaveOut->dwCallback, // user's callback DWORD
  95. HIWORD(pWaveOut->dwOpenFlags), // callback flags
  96. (HDRVR)pWaveOut->hWave, // wave device handle
  97. msg, // the message
  98. pWaveOut->dwInstance, // user's instance data
  99. dwParam1, // first DWORD
  100. 0L); // second DWORD
  101. }
  102. /*
  103. * Function:
  104. * waveOpen
  105. *
  106. * Description:
  107. * The user request a device open
  108. *
  109. * Parameters:
  110. * ppWaveOut - pointer to a context
  111. * pWaveOpenDesc- requested formats
  112. * dwFlags - and flags ( see MSDN )
  113. *
  114. */
  115. DWORD
  116. waveOpen(
  117. PWAVEOUTCTX *ppWaveOut,
  118. LPWAVEOPENDESC pWaveOpenDesc,
  119. DWORD_PTR dwFlags
  120. )
  121. {
  122. DWORD rv = MMSYSERR_ERROR;
  123. DWORD dwProbe;
  124. PWAVEOUTCTX pWaveOut = NULL;
  125. LPWAVEFORMATEX lpFormat = NULL;
  126. VOID (*pPlaceFn)(PVOID, PVOID, DWORD);
  127. DWORD dwBytesPerXLate;
  128. // Parameters check
  129. //
  130. if (NULL == ppWaveOut || NULL == pWaveOpenDesc)
  131. {
  132. TRC(ERR, "waveOpen: either ppWaveOut or pWaveOpenDesc are NULL\n");
  133. rv = MMSYSERR_INVALPARAM;
  134. goto exitpt;
  135. }
  136. // Check the requested format
  137. //
  138. lpFormat = (LPWAVEFORMATEX)(pWaveOpenDesc->lpFormat);
  139. if (NULL == lpFormat)
  140. {
  141. TRC(ERR, "waveOpen: pWaveOpenDesc->lpFormat is NULL\n");
  142. rv = MMSYSERR_INVALPARAM;
  143. goto exitpt;
  144. }
  145. if (WAVE_FORMAT_PCM != lpFormat->wFormatTag) // PCM format only
  146. {
  147. TRC(ALV, "waveOpen: non PCM format required, tag=%d\n",
  148. lpFormat->wFormatTag);
  149. rv = WAVERR_BADFORMAT;
  150. goto exitpt;
  151. }
  152. // 8kHz 8 bit mono
  153. //
  154. if (1 == lpFormat->nChannels &&
  155. 8000 == lpFormat->nSamplesPerSec &&
  156. 8000 == lpFormat->nAvgBytesPerSec &&
  157. 1 == lpFormat->nBlockAlign &&
  158. 8 == lpFormat->wBitsPerSample)
  159. {
  160. pPlaceFn = Place8kHz8Mono;
  161. dwBytesPerXLate = 8000;
  162. } else
  163. // 8kHz 8 bit stereo
  164. //
  165. if (2 == lpFormat->nChannels &&
  166. 8000 == lpFormat->nSamplesPerSec &&
  167. 16000 == lpFormat->nAvgBytesPerSec &&
  168. 2 == lpFormat->nBlockAlign &&
  169. 8 == lpFormat->wBitsPerSample)
  170. {
  171. pPlaceFn = Place8kHz8Stereo;
  172. dwBytesPerXLate = 2 * 8000;
  173. } else
  174. // 8kHz 16 bit mono
  175. //
  176. if (1 == lpFormat->nChannels &&
  177. 8000 == lpFormat->nSamplesPerSec &&
  178. 16000 == lpFormat->nAvgBytesPerSec &&
  179. 2 == lpFormat->nBlockAlign &&
  180. 16 == lpFormat->wBitsPerSample)
  181. {
  182. pPlaceFn = Place8kHz16Mono;
  183. dwBytesPerXLate = 2 * 8000;
  184. } else
  185. // 8kHz 16 bit stereo
  186. //
  187. if (2 == lpFormat->nChannels &&
  188. 8000 == lpFormat->nSamplesPerSec &&
  189. 32000 == lpFormat->nAvgBytesPerSec &&
  190. 4 == lpFormat->nBlockAlign &&
  191. 16 == lpFormat->wBitsPerSample)
  192. {
  193. pPlaceFn = Place8kHz16Stereo;
  194. dwBytesPerXLate = 4 * 8000;
  195. } else
  196. // 11kHz 8 bit mono
  197. //
  198. if (1 == lpFormat->nChannels && // mono
  199. 11025 == lpFormat->nSamplesPerSec &&
  200. 11025 == lpFormat->nAvgBytesPerSec &&
  201. 1 == lpFormat->nBlockAlign &&
  202. 8 == lpFormat->wBitsPerSample)
  203. {
  204. pPlaceFn = Place11kHz8Mono;
  205. dwBytesPerXLate = 1 * 11025;
  206. }
  207. else
  208. // 22kHz 8 mono
  209. //
  210. if (1 == lpFormat->nChannels &&
  211. 22050 == lpFormat->nSamplesPerSec &&
  212. 22050 == lpFormat->nAvgBytesPerSec &&
  213. 1 == lpFormat->nBlockAlign &&
  214. 8 == lpFormat->wBitsPerSample)
  215. {
  216. pPlaceFn = Place22kHz8Mono;
  217. dwBytesPerXLate = 2 * 11025;
  218. }
  219. else
  220. // 44kHz 8 mono
  221. //
  222. if (1 == lpFormat->nChannels &&
  223. 44100 == lpFormat->nSamplesPerSec &&
  224. 44100 == lpFormat->nAvgBytesPerSec &&
  225. 1 == lpFormat->nBlockAlign &&
  226. 8 == lpFormat->wBitsPerSample)
  227. {
  228. pPlaceFn = Place44kHz8Mono;
  229. dwBytesPerXLate = 4 * 11025;
  230. }
  231. else
  232. // 11kHz 8 bit stereo
  233. //
  234. if (2 == lpFormat->nChannels &&
  235. 11025 == lpFormat->nSamplesPerSec &&
  236. 22050 == lpFormat->nAvgBytesPerSec &&
  237. 2 == lpFormat->nBlockAlign &&
  238. 8 == lpFormat->wBitsPerSample)
  239. {
  240. pPlaceFn = Place11kHz8Stereo;
  241. dwBytesPerXLate = 2 * 11025;
  242. }
  243. else
  244. // 22kHz 8 bit stereo
  245. //
  246. if (2 == lpFormat->nChannels &&
  247. 22050 == lpFormat->nSamplesPerSec &&
  248. 44100 == lpFormat->nAvgBytesPerSec &&
  249. 2 == lpFormat->nBlockAlign &&
  250. 8 == lpFormat->wBitsPerSample)
  251. {
  252. pPlaceFn = Place22kHz8Stereo;
  253. dwBytesPerXLate = 4 * 11025;
  254. }
  255. else
  256. // 44kHz 8 bit stereo
  257. //
  258. if (2 == lpFormat->nChannels &&
  259. 44100 == lpFormat->nSamplesPerSec &&
  260. 88200 == lpFormat->nAvgBytesPerSec &&
  261. 2 == lpFormat->nBlockAlign &&
  262. 8 == lpFormat->wBitsPerSample)
  263. {
  264. pPlaceFn = Place44kHz8Stereo;
  265. dwBytesPerXLate = 8 * 11025;
  266. }
  267. else
  268. // 11kHz 16 bit mono
  269. //
  270. if (1 == lpFormat->nChannels &&
  271. 11025 == lpFormat->nSamplesPerSec &&
  272. 22050 == lpFormat->nAvgBytesPerSec &&
  273. 2 == lpFormat->nBlockAlign &&
  274. 16 == lpFormat->wBitsPerSample)
  275. {
  276. pPlaceFn = Place11kHz16Mono;
  277. dwBytesPerXLate = 2 * 11025;
  278. }
  279. else
  280. // 22kHz 16 bit mono
  281. //
  282. if (1 == lpFormat->nChannels &&
  283. 22050 == lpFormat->nSamplesPerSec &&
  284. 44100 == lpFormat->nAvgBytesPerSec &&
  285. 2 == lpFormat->nBlockAlign &&
  286. 16 == lpFormat->wBitsPerSample)
  287. {
  288. pPlaceFn = Place22kHz16Mono;
  289. dwBytesPerXLate = 4 * 11025;
  290. }
  291. else
  292. // 44kHz 16 bit mono
  293. //
  294. if (1 == lpFormat->nChannels &&
  295. 44100 == lpFormat->nSamplesPerSec &&
  296. 88200 == lpFormat->nAvgBytesPerSec &&
  297. 2 == lpFormat->nBlockAlign &&
  298. 16== lpFormat->wBitsPerSample)
  299. {
  300. pPlaceFn = Place44kHz16Mono;
  301. dwBytesPerXLate = 8 * 11025;
  302. }
  303. else
  304. // 11kHz 16 bit stereo
  305. //
  306. if (2 == lpFormat->nChannels &&
  307. 11025 == lpFormat->nSamplesPerSec &&
  308. 44100 == lpFormat->nAvgBytesPerSec &&
  309. 4 == lpFormat->nBlockAlign &&
  310. 16 == lpFormat->wBitsPerSample)
  311. {
  312. pPlaceFn = Place11kHz16Stereo;
  313. dwBytesPerXLate = 4 * 11025;
  314. }
  315. else
  316. // 22kHz 16 bit stereo
  317. //
  318. if (2 == lpFormat->nChannels &&
  319. 22050 == lpFormat->nSamplesPerSec &&
  320. 88200 == lpFormat->nAvgBytesPerSec &&
  321. 4 == lpFormat->nBlockAlign &&
  322. 16 == lpFormat->wBitsPerSample)
  323. {
  324. pPlaceFn = Place22kHz16Stereo;
  325. dwBytesPerXLate = 8 * 11025;
  326. }
  327. else
  328. // 44kHz 16 bit stereo
  329. //
  330. if (2 == lpFormat->nChannels &&
  331. 44100 == lpFormat->nSamplesPerSec &&
  332. 176400 == lpFormat->nAvgBytesPerSec &&
  333. 4 == lpFormat->nBlockAlign &&
  334. 16 == lpFormat->wBitsPerSample)
  335. {
  336. pPlaceFn = Place44kHz16Stereo;
  337. dwBytesPerXLate = 16 * 11025;
  338. }
  339. else
  340. // 48kHz 8 bit mono
  341. //
  342. if (1 == lpFormat->nChannels &&
  343. 48000 == lpFormat->nSamplesPerSec &&
  344. 48000 == lpFormat->nAvgBytesPerSec &&
  345. 1 == lpFormat->nBlockAlign &&
  346. 8 == lpFormat->wBitsPerSample)
  347. {
  348. pPlaceFn = Place48kHz8Mono;
  349. dwBytesPerXLate = 48000;
  350. } else
  351. // 48kHz 8 bit stereo
  352. //
  353. if (2 == lpFormat->nChannels &&
  354. 48000 == lpFormat->nSamplesPerSec &&
  355. 96000 == lpFormat->nAvgBytesPerSec &&
  356. 2 == lpFormat->nBlockAlign &&
  357. 8 == lpFormat->wBitsPerSample)
  358. {
  359. pPlaceFn = Place48kHz8Stereo;
  360. dwBytesPerXLate = 2 * 48000;
  361. } else
  362. // 48kHz 16 bit mono
  363. //
  364. if (1 == lpFormat->nChannels &&
  365. 48000 == lpFormat->nSamplesPerSec &&
  366. 96000 == lpFormat->nAvgBytesPerSec &&
  367. 2 == lpFormat->nBlockAlign &&
  368. 16 == lpFormat->wBitsPerSample)
  369. {
  370. pPlaceFn = Place48kHz16Mono;
  371. dwBytesPerXLate = 2 * 48000;
  372. } else
  373. // 48kHz 16 bit stereo
  374. //
  375. if (2 == lpFormat->nChannels &&
  376. 48000 == lpFormat->nSamplesPerSec &&
  377. 192000 == lpFormat->nAvgBytesPerSec &&
  378. 4 == lpFormat->nBlockAlign &&
  379. 16 == lpFormat->wBitsPerSample)
  380. {
  381. pPlaceFn = Place48kHz16Stereo;
  382. dwBytesPerXLate = 4 * 48000;
  383. } else
  384. {
  385. // fall in an error
  386. //
  387. TRC(ALV, "waveOpen: unsupported format requested\n");
  388. TRC(ALV, "waveOpen: FormatTag - %d\n", lpFormat->wFormatTag);
  389. TRC(ALV, "waveOpen: Channels - %d\n", lpFormat->nChannels);
  390. TRC(ALV, "waveOpen: SamplesPerSec - %d\n", lpFormat->nSamplesPerSec);
  391. TRC(ALV, "waveOpen: AvgBytesPerSec - %d\n", lpFormat->nAvgBytesPerSec);
  392. TRC(ALV, "waveOpen: BlockAlign - %d\n", lpFormat->nBlockAlign);
  393. TRC(ALV, "waveOpen: BitsPerSample - %d\n", lpFormat->wBitsPerSample);
  394. rv = WAVERR_BADFORMAT;
  395. goto exitpt;
  396. }
  397. // validate the flags
  398. //
  399. if (0 != (dwFlags & WAVE_FORMAT_QUERY))
  400. {
  401. // this was only a query
  402. TRC(ALV, "waveOpen: WAVE_FORMAT_QUERY\n");
  403. rv = MMSYSERR_NOERROR;
  404. goto exitpt;
  405. }
  406. dwProbe = ~(WAVE_ALLOWSYNC |
  407. CALLBACK_EVENT |
  408. CALLBACK_FUNCTION |
  409. CALLBACK_WINDOW
  410. );
  411. if (0 != (dwFlags & dwProbe))
  412. {
  413. TRC(ERR, "waveOpen: unsupported flags required: 0x%x\n",
  414. dwFlags);
  415. rv = MMSYSERR_NOTSUPPORTED;
  416. goto exitpt;
  417. }
  418. // Check that the remote side is there
  419. //
  420. if ( AudioRedirDisabled() ||
  421. ( !_waveCheckSoundAlive() &&
  422. g_hWaitToInitialize == NULL ))
  423. {
  424. TRC(ALV, "waveOpen: No remote sound\n");
  425. rv = MMSYSERR_NODRIVER;
  426. goto exitpt;
  427. }
  428. // Allocate the context structure
  429. //
  430. pWaveOut = TSMALLOC(sizeof(*pWaveOut));
  431. if (NULL == pWaveOut)
  432. {
  433. TRC(ERR, "waveOpen: Can't allocate %d bytes\n", sizeof(*pWaveOut));
  434. rv = MMSYSERR_NOMEM;
  435. goto exitpt;
  436. }
  437. memset(pWaveOut, 0, sizeof(*pWaveOut));
  438. // fill the context
  439. //
  440. pWaveOut->hWave = pWaveOpenDesc->hWave;
  441. pWaveOut->dwOpenFlags = dwFlags;
  442. pWaveOut->dwCallback = pWaveOpenDesc->dwCallback;
  443. pWaveOut->dwInstance = pWaveOpenDesc->dwInstance;
  444. pWaveOut->lpfnPlace = pPlaceFn;
  445. pWaveOut->dwXlateRate = dwBytesPerXLate;
  446. pWaveOut->Format_nBlockAlign = lpFormat->nBlockAlign;
  447. pWaveOut->Format_nAvgBytesPerSec = lpFormat->nAvgBytesPerSec;
  448. pWaveOut->Format_nChannels = lpFormat->nChannels;
  449. if ( NULL != g_Stream )
  450. pWaveOut->cLastStreamPosition = g_Stream->cLastBlockQueued;
  451. else
  452. pWaveOut->cLastStreamPosition = 0;
  453. pWaveOut->hNoDataEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
  454. if (NULL == pWaveOut->hNoDataEvent)
  455. {
  456. TRC(ERR, "waveOpen: can't create event\n");
  457. goto exitpt;
  458. }
  459. *ppWaveOut = pWaveOut;
  460. if ( NULL != g_hWaitToInitialize )
  461. {
  462. pWaveOut->bDelayed = TRUE;
  463. }
  464. // add this context to the global queue
  465. //
  466. ENTER_CRIT;
  467. pWaveOut->lpNext = g_pAllWaveOut;
  468. g_pAllWaveOut = pWaveOut;
  469. LEAVE_CRIT;
  470. waveCallback(pWaveOut, WOM_OPEN, 0);
  471. rv = MMSYSERR_NOERROR;
  472. exitpt:
  473. if (MMSYSERR_NOERROR != rv)
  474. {
  475. if (pWaveOut)
  476. {
  477. if (NULL != pWaveOut->hNoDataEvent)
  478. CloseHandle(pWaveOut->hNoDataEvent);
  479. TSFREE(pWaveOut);
  480. }
  481. }
  482. return rv;
  483. }
  484. /*
  485. * Function:
  486. * waveGetWaveOutDeviceCaps
  487. *
  488. * Description:
  489. * The user requests for device capabilities
  490. *
  491. * Parameters:
  492. * pWaveOut - our context
  493. * pWaveOutCaps- supported capabilites
  494. * dwWaveOutCapsSize - the sizeof the parameter above
  495. *
  496. */
  497. DWORD
  498. waveGetWaveOutDeviceCaps(
  499. PWAVEOUTCTX pWaveOut,
  500. LPWAVEOUTCAPS pWaveOutCaps,
  501. DWORD_PTR dwWaveOutCapsSize
  502. )
  503. {
  504. DWORD rv = MMSYSERR_ERROR;
  505. // Parameters check
  506. //
  507. if (dwWaveOutCapsSize < sizeof(*pWaveOutCaps))
  508. {
  509. TRC(ERR, "waveGetWaveOutDeviceCaps: invalid size of WAVEOUTCAPS, expect %d, received %d\n",
  510. sizeof(*pWaveOutCaps), dwWaveOutCapsSize);
  511. rv = MMSYSERR_INVALPARAM;
  512. goto exitpt;
  513. }
  514. pWaveOutCaps->wMid = MM_MICROSOFT;
  515. pWaveOutCaps->wPid = MM_MSFT_GENERIC_WAVEOUT;
  516. pWaveOutCaps->vDriverVersion = TSSND_DRIVER_VERSION;
  517. LoadString( g_hDllInst,
  518. IDS_DRIVER_NAME,
  519. pWaveOutCaps->szPname,
  520. sizeof( pWaveOutCaps->szPname ) / sizeof( pWaveOutCaps->szPname[0] ));
  521. pWaveOutCaps->dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_1M16 |
  522. WAVE_FORMAT_1S08 | WAVE_FORMAT_1S16 |
  523. WAVE_FORMAT_2M08 | WAVE_FORMAT_2M16 |
  524. WAVE_FORMAT_2S08 | WAVE_FORMAT_2S16 |
  525. WAVE_FORMAT_4M08 | WAVE_FORMAT_4S08 |
  526. WAVE_FORMAT_4M16 | WAVE_FORMAT_4S16;
  527. pWaveOutCaps->wChannels = 2;
  528. pWaveOutCaps->dwSupport = WAVECAPS_SAMPLEACCURATE;
  529. if ( NULL != g_Stream )
  530. {
  531. pWaveOutCaps->dwSupport |= (g_Stream->dwSoundCaps & TSSNDCAPS_VOLUME)?
  532. WAVECAPS_VOLUME : 0;
  533. pWaveOutCaps->dwSupport |= (g_Stream->dwSoundCaps & TSSNDCAPS_PITCH)?
  534. WAVECAPS_PITCH : 0;
  535. }
  536. rv = MMSYSERR_NOERROR;
  537. exitpt:
  538. return rv;
  539. }
  540. /*
  541. * Function:
  542. * waveSetVolume
  543. *
  544. * Description:
  545. * The user requests a new volume
  546. *
  547. * Parameters:
  548. * pWaveOut - context
  549. * dwVolume - new volume
  550. *
  551. */
  552. DWORD
  553. waveSetVolume(
  554. PWAVEOUTCTX pWaveOut,
  555. DWORD dwVolume
  556. )
  557. {
  558. DWORD rv = MMSYSERR_ERROR;
  559. // Parameters check
  560. //
  561. // in case of mono, adjust the volume to stereo
  562. //
  563. if ( NULL != pWaveOut &&
  564. 1 == pWaveOut->Format_nChannels )
  565. {
  566. dwVolume = ( dwVolume & 0xffff ) |
  567. (( dwVolume & 0xffff ) << 16 );
  568. }
  569. // Set the new volume in the sound stream
  570. //
  571. if (!_waveAcquireStream())
  572. {
  573. TRC(ERR, "waveSetVolume: can't acquire stream mutex\n");
  574. goto exitpt;
  575. }
  576. // Check that volume control
  577. // is supported on the remote
  578. //
  579. if (0 != (g_Stream->dwSoundCaps & TSSNDCAPS_VOLUME))
  580. {
  581. g_Stream->dwVolume = dwVolume;
  582. g_Stream->bNewVolume = TRUE;
  583. }
  584. else
  585. rv = MMSYSERR_NOTSUPPORTED;
  586. _waveReleaseStream();
  587. if (MMSYSERR_NOTSUPPORTED == rv)
  588. {
  589. TRC(INF, "waveSetVolume: volume control not supported\n");
  590. goto exitpt;
  591. }
  592. // kick the sndio thread
  593. //
  594. if (g_hDataReadyEvent)
  595. SetEvent(g_hDataReadyEvent);
  596. else
  597. TRC(WRN, "waveSetVolume: g_hDataReadyEvent is NULL\n");
  598. rv = MMSYSERR_NOERROR;
  599. exitpt:
  600. return rv;
  601. }
  602. /*
  603. * Function:
  604. * waveGetVolume
  605. *
  606. * Description:
  607. * The user queries for the current volume level
  608. *
  609. * Parameters:
  610. * pWaveOut - context
  611. * pdwVolume - [out] current volume
  612. *
  613. */
  614. DWORD
  615. waveGetVolume(
  616. PWAVEOUTCTX pWaveOut,
  617. DWORD *pdwVolume
  618. )
  619. {
  620. DWORD rv = MMSYSERR_ERROR;
  621. // Parameters check
  622. //
  623. if (NULL == pdwVolume)
  624. {
  625. TRC(ERR, "pdwVolume is NULL\n");
  626. rv = MMSYSERR_INVALPARAM;
  627. goto exitpt;
  628. }
  629. if (!_waveAcquireStream())
  630. {
  631. TRC(ERR, "waveGetVolume: can't acquire stream mutex\n");
  632. goto exitpt;
  633. }
  634. // Check that volume control
  635. // is supported on the remote
  636. //
  637. if (0 != (g_Stream->dwSoundCaps & TSSNDCAPS_VOLUME))
  638. *pdwVolume = g_Stream->dwVolume;
  639. else
  640. rv = MMSYSERR_NOTSUPPORTED;
  641. _waveReleaseStream();
  642. if (MMSYSERR_NOTSUPPORTED == rv)
  643. {
  644. TRC(INF, "waveGetVolume: volume control not supported\n");
  645. goto exitpt;
  646. }
  647. rv = MMSYSERR_NOERROR;
  648. exitpt:
  649. return rv;
  650. }
  651. DWORD
  652. waveSetMute(
  653. PWAVEOUTCTX pWaveOut,
  654. BOOL fMute
  655. )
  656. {
  657. DWORD rv = MMSYSERR_ERROR;
  658. if ( NULL == g_Stream)
  659. {
  660. TRC(ERR, "waveGetVolume: stream is NULL\n");
  661. goto exitpt;
  662. }
  663. if ( fMute )
  664. {
  665. g_Stream->dwSoundFlags |= TSSNDFLAGS_MUTE;
  666. } else {
  667. g_Stream->dwSoundFlags &= ~TSSNDFLAGS_MUTE;
  668. }
  669. rv = MMSYSERR_NOERROR;
  670. exitpt:
  671. return rv;
  672. }
  673. DWORD
  674. waveGetMute(
  675. PWAVEOUTCTX pWaveOut,
  676. DWORD *pfdwMute
  677. )
  678. {
  679. DWORD rv = MMSYSERR_ERROR;
  680. if ( NULL == g_Stream)
  681. {
  682. TRC(ERR, "waveGetVolume: stream is NULL\n");
  683. goto exitpt;
  684. }
  685. *pfdwMute = ( 0 != ( g_Stream->dwSoundFlags & TSSNDFLAGS_MUTE ));
  686. rv = MMSYSERR_NOERROR;
  687. exitpt:
  688. return rv;
  689. }
  690. /*
  691. * Function:
  692. * waveSetPitch
  693. *
  694. * Description:
  695. * Sets new pitch level
  696. *
  697. * Parameters:
  698. * pWaveOut - context
  699. * dwPitch - new pitch level
  700. *
  701. */
  702. DWORD
  703. waveSetPitch(
  704. PWAVEOUTCTX pWaveOut,
  705. DWORD dwPitch
  706. )
  707. {
  708. DWORD rv = MMSYSERR_ERROR;
  709. // Parameters check
  710. //
  711. // Set the new volume in the sound stream
  712. //
  713. if (!_waveAcquireStream())
  714. {
  715. TRC(ERR, "waveSetPitch: can't acquire stream mutex\n");
  716. goto exitpt;
  717. }
  718. // Check that pitch control
  719. // is supported on the remote
  720. //
  721. if (0 != (g_Stream->dwSoundCaps & TSSNDCAPS_PITCH))
  722. {
  723. g_Stream->dwPitch = dwPitch;
  724. g_Stream->bNewPitch = TRUE;
  725. }
  726. else
  727. rv = MMSYSERR_NOTSUPPORTED;
  728. _waveReleaseStream();
  729. if (MMSYSERR_NOTSUPPORTED == rv)
  730. {
  731. TRC(INF, "waveSetPitch: pitch control not supported\n");
  732. goto exitpt;
  733. }
  734. // kick the sndio thread
  735. //
  736. if (g_hDataReadyEvent)
  737. SetEvent(g_hDataReadyEvent);
  738. else
  739. TRC(WRN, "waveSetPitch: g_hDataReadyEvent is NULL\n");
  740. rv = MMSYSERR_NOERROR;
  741. exitpt:
  742. return rv;
  743. }
  744. /*
  745. * Function:
  746. * waveGetPitch
  747. *
  748. * Description:
  749. * Queries for the current pitch level
  750. *
  751. * Parameters:
  752. * pWaveOut - context
  753. * pdwPitch - [out] current pitch level
  754. *
  755. */
  756. DWORD
  757. waveGetPitch(
  758. PWAVEOUTCTX pWaveOut,
  759. DWORD *pdwPitch
  760. )
  761. {
  762. DWORD rv = MMSYSERR_ERROR;
  763. // Parameters check
  764. //
  765. if (NULL == pdwPitch)
  766. {
  767. TRC(ERR, "pdwPitch is NULL\n");
  768. rv = MMSYSERR_INVALPARAM;
  769. goto exitpt;
  770. }
  771. if (!_waveAcquireStream())
  772. {
  773. TRC(ERR, "waveGetPitch: can't acquire stream mutex\n");
  774. goto exitpt;
  775. }
  776. // Check that pitch control
  777. // is supported on the remote
  778. //
  779. if (0 != (g_Stream->dwSoundCaps & TSSNDCAPS_PITCH))
  780. *pdwPitch = g_Stream->dwPitch;
  781. else
  782. rv = MMSYSERR_NOTSUPPORTED;
  783. _waveReleaseStream();
  784. if (MMSYSERR_NOTSUPPORTED == rv)
  785. {
  786. TRC(INF, "waveGetPitch: pitch control not supported\n");
  787. goto exitpt;
  788. }
  789. rv = MMSYSERR_NOERROR;
  790. exitpt:
  791. return rv;
  792. }
  793. /*
  794. * Function:
  795. * waveGetNumDevs
  796. *
  797. * Description:
  798. * we have only one device
  799. *
  800. */
  801. DWORD
  802. waveGetNumDevs(
  803. VOID
  804. )
  805. {
  806. return 1;
  807. }
  808. /*
  809. * Function:
  810. * waveClose
  811. *
  812. * Description:
  813. * Wait for all blocks to complete and then close
  814. *
  815. * Parameters:
  816. * pWaveOut - context
  817. *
  818. */
  819. DWORD
  820. waveClose(
  821. PWAVEOUTCTX pWaveOut
  822. )
  823. {
  824. DWORD rv = MMSYSERR_ERROR;
  825. DWORD syserr;
  826. PWAVEOUTCTX pPrevWaveOut;
  827. PWAVEOUTCTX pWaveOutIter;
  828. if (NULL == pWaveOut)
  829. {
  830. TRC(ERR, "waveClose: invalid device handle\n");
  831. rv = MMSYSERR_INVALHANDLE;
  832. goto exitpt;
  833. }
  834. //
  835. // test if we are still playing
  836. //
  837. if ( pWaveOut->bPaused && 0 != pWaveOut->lNumberOfBlocksPlaying )
  838. {
  839. TRC(INF, "waveClose: WAVERR_STILLPLAYING\n");
  840. rv = WAVERR_STILLPLAYING;
  841. goto exitpt;
  842. }
  843. if ( NULL != pWaveOut->hNoDataEvent)
  844. {
  845. DWORD dwTimeout;
  846. if ( pWaveOut->bDelayed )
  847. {
  848. TRC( INF, "waveClose: delaying 15 seconds\n" );
  849. dwTimeout = 15000;
  850. } else {
  851. dwTimeout = 0;
  852. }
  853. syserr = WaitForSingleObject(pWaveOut->hNoDataEvent, dwTimeout);
  854. if ( WAIT_TIMEOUT == syserr )
  855. {
  856. TRC(INF, "waveClose: WAVERR_STILLPLAYING\n");
  857. rv = WAVERR_STILLPLAYING;
  858. goto exitpt;
  859. }
  860. }
  861. //
  862. // we may end with some data in the last block in the stream
  863. // if the "queued" mark hasn't change, increment it and kick the io
  864. // thread to play this block
  865. // to test this play very-very short files
  866. // shorter than TSSND_BLOCKSIZE / (TSSND_NATIVE_BLOCKALIGN *
  867. // TSSND_NATIVE_SAMPLERATE) seconds
  868. //
  869. //
  870. //
  871. if (_waveAcquireStream())
  872. {
  873. if (g_Stream->cLastBlockQueued == pWaveOut->cLastStreamPosition &&
  874. 0 != pWaveOut->dwLastStreamOffset)
  875. {
  876. g_Stream->cLastBlockQueued ++;
  877. //
  878. // kick the io thread
  879. //
  880. if (g_hDataReadyEvent)
  881. SetEvent(g_hDataReadyEvent);
  882. else
  883. TRC(WRN, "waveClose: g_hDataReadyEvent is NULL\n");
  884. }
  885. _waveReleaseStream();
  886. }
  887. if (NULL != pWaveOut->hNoDataEvent)
  888. CloseHandle(pWaveOut->hNoDataEvent);
  889. // remove this context from the global queue
  890. //
  891. ENTER_CRIT;
  892. pPrevWaveOut = NULL;
  893. pWaveOutIter = g_pAllWaveOut;
  894. while ( NULL != pWaveOutIter &&
  895. pWaveOutIter != pWaveOut)
  896. {
  897. pPrevWaveOut = pWaveOutIter;
  898. pWaveOutIter = pWaveOutIter->lpNext;
  899. }
  900. ASSERT(pWaveOut == pWaveOutIter);
  901. if (pWaveOut == pWaveOutIter)
  902. {
  903. if (pPrevWaveOut)
  904. pPrevWaveOut->lpNext = pWaveOut->lpNext;
  905. else
  906. g_pAllWaveOut = pWaveOut->lpNext;
  907. }
  908. LEAVE_CRIT;
  909. waveCallback(pWaveOut, WOM_CLOSE, 0);
  910. TSFREE(pWaveOut);
  911. rv = MMSYSERR_NOERROR;
  912. exitpt:
  913. return rv;
  914. }
  915. /*
  916. * Function:
  917. * waveWrite
  918. *
  919. * Description:
  920. * Play a block of data
  921. *
  922. * Parameters:
  923. * pWaveOut - context
  924. * pWaveHdr - the block
  925. * dwWaveHdrSize - size of the above parameter
  926. *
  927. */
  928. DWORD
  929. waveWrite(
  930. PWAVEOUTCTX pWaveOut,
  931. PWAVEHDR pWaveHdr,
  932. DWORD_PTR dwWaveHdrSize
  933. )
  934. {
  935. SNDWAVE WaveData;
  936. DWORD rv = MMSYSERR_ERROR;
  937. PWAVEHDR pPrevHdr;
  938. PWAVEHDR pLastHdr;
  939. // Parameters check
  940. //
  941. if (NULL == pWaveOut)
  942. {
  943. TRC(ERR, "waveWrite: invalid device handle\n");
  944. rv = MMSYSERR_INVALHANDLE;
  945. goto exitpt;
  946. }
  947. if (sizeof(*pWaveHdr) != dwWaveHdrSize)
  948. {
  949. TRC(ERR, "waveWrite: invalid size for dwWaveHdrSize\n");
  950. rv = MMSYSERR_INVALPARAM;
  951. goto exitpt;
  952. }
  953. //
  954. // check the buffer size alignment
  955. //
  956. if ( 0 != pWaveOut->Format_nBlockAlign &&
  957. 0 != pWaveHdr->dwBufferLength % pWaveOut->Format_nBlockAlign )
  958. {
  959. TRC( ERR, "wavePrepare: size unaligned\n" );
  960. rv = MMSYSERR_INVALPARAM;
  961. goto exitpt;
  962. }
  963. if (IsBadReadPtr( pWaveHdr->lpData, pWaveHdr->dwBufferLength ))
  964. {
  965. TRC( ERR, "wavePrepare: buffer unreadable\n" );
  966. rv = MMSYSERR_INVALPARAM;
  967. goto exitpt;
  968. }
  969. #ifdef _WIN64
  970. //
  971. // check for proper alignment
  972. //
  973. if ( 0 != pWaveOut->Format_nBlockAlign &&
  974. 2 == pWaveOut->Format_nBlockAlign / pWaveOut->Format_nChannels &&
  975. 0 != (( (LONG_PTR)pWaveHdr->lpData ) & 1 ))
  976. {
  977. TRC( ERR, "wavePrepare: buffer unaligned\n" );
  978. rv = MMSYSERR_INVALPARAM;
  979. goto exitpt;
  980. }
  981. #endif
  982. // pass this header to the mixer thread
  983. //
  984. if (NULL == g_hMixerEvent)
  985. {
  986. TRC(ERR, "waveWrite: g_hMixerEvent is NULL\n");
  987. // confirm that the block is done
  988. //
  989. waveCallback(pWaveOut, WOM_DONE, (DWORD_PTR)pWaveHdr);
  990. goto exitpt;
  991. }
  992. // add the header to the queue
  993. //
  994. ENTER_CRIT;
  995. // find the last header
  996. //
  997. pPrevHdr = NULL;
  998. pLastHdr = pWaveOut->pFirstWaveHdr;
  999. while (pLastHdr)
  1000. {
  1001. //
  1002. // VERY VERY VERY IMAPORTANT !!!
  1003. // check if the app trys to add a header twice
  1004. // (WINAMP does)
  1005. //
  1006. if (pLastHdr == pWaveHdr)
  1007. {
  1008. TRC(ERR, "waveWrite: equal headers found, aborting\n");
  1009. goto abort_waveWrite;
  1010. }
  1011. pPrevHdr = pLastHdr;
  1012. pLastHdr = pLastHdr->lpNext;
  1013. }
  1014. pWaveHdr->lpNext = NULL;
  1015. pWaveHdr->reserved = (DWORD_PTR)pWaveOut;
  1016. pWaveHdr->dwFlags &= ~(WHDR_DONE);
  1017. pWaveHdr->dwFlags |= WHDR_INQUEUE;
  1018. // add the new header
  1019. //
  1020. if (NULL == pPrevHdr)
  1021. {
  1022. pWaveOut->pFirstWaveHdr = pWaveHdr;
  1023. } else {
  1024. pPrevHdr->lpNext = pWaveHdr;
  1025. }
  1026. InterlockedIncrement(&pWaveOut->lNumberOfBlocksPlaying);
  1027. ResetEvent(pWaveOut->hNoDataEvent);
  1028. //
  1029. // kick the mixer thread
  1030. //
  1031. SetEvent(g_hMixerEvent);
  1032. abort_waveWrite:
  1033. LEAVE_CRIT;
  1034. rv = MMSYSERR_NOERROR;
  1035. exitpt:
  1036. return rv;
  1037. }
  1038. /*
  1039. * Function:
  1040. * _waveAcquireStream
  1041. *
  1042. * Description:
  1043. * Locks down the stream using mutex
  1044. *
  1045. */
  1046. BOOL
  1047. _waveAcquireStream(
  1048. VOID
  1049. )
  1050. {
  1051. BOOL rv = FALSE;
  1052. DWORD dwres;
  1053. if (NULL == g_hStream ||
  1054. NULL == g_Stream)
  1055. {
  1056. TRC(ALV, "_waveAcquireStream: the stream handle is NULL\n");
  1057. goto exitpt;
  1058. }
  1059. if (NULL == g_hStreamMutex)
  1060. {
  1061. TRC(FATAL, "_waveAcquireStreamMutex: the stream mutex is NULL\n");
  1062. goto exitpt;
  1063. }
  1064. dwres = WaitForSingleObject(g_hStreamMutex, DEFAULT_VC_TIMEOUT);
  1065. if (WAIT_TIMEOUT == dwres ||
  1066. WAIT_ABANDONED == dwres )
  1067. {
  1068. TRC(ERR, "_waveAcquireStreamMutex: "
  1069. "timed out waiting for the stream mutex or owner crashed=%d\n", dwres );
  1070. //
  1071. // possible app crash
  1072. //
  1073. ASSERT(0);
  1074. goto exitpt;
  1075. }
  1076. rv = TRUE;
  1077. exitpt:
  1078. return rv;
  1079. }
  1080. BOOL
  1081. _waveReleaseStream(
  1082. VOID
  1083. )
  1084. {
  1085. BOOL rv = TRUE;
  1086. ASSERT(NULL != g_hStream);
  1087. ASSERT(NULL != g_Stream);
  1088. ASSERT(NULL != g_hStreamMutex);
  1089. if (!ReleaseMutex(g_hStreamMutex))
  1090. rv = FALSE;
  1091. return rv;
  1092. }
  1093. /*
  1094. * Function:
  1095. * _waveCheckSoundAlive
  1096. *
  1097. * Description:
  1098. * Chacks if the client can play audio
  1099. *
  1100. */
  1101. BOOL
  1102. _waveCheckSoundAlive(
  1103. VOID
  1104. )
  1105. {
  1106. BOOL rv = FALSE;
  1107. rv = ( NULL != g_Stream && 0 != (g_Stream->dwSoundCaps & TSSNDCAPS_ALIVE));
  1108. return rv;
  1109. }
  1110. BOOL
  1111. AudioRedirDisabled(
  1112. VOID
  1113. )
  1114. {
  1115. BOOL fSuccess = FALSE;
  1116. static BOOL s_fChecked = FALSE;
  1117. static HANDLE s_hRDPEvent = NULL;
  1118. static WINSTATIONCONFIG s_config;
  1119. ULONG returnedLength;
  1120. if ( s_fChecked )
  1121. {
  1122. return s_config.User.fDisableCam;
  1123. }
  1124. //
  1125. // we need special case for session 0
  1126. // because winlogon never exits there
  1127. //
  1128. if ( 0 == NtCurrentPeb()->SessionId )
  1129. {
  1130. DWORD dw;
  1131. if ( NULL == s_hRDPEvent )
  1132. {
  1133. s_hRDPEvent = OpenEvent( SYNCHRONIZE, FALSE, L"Global\\RDPAudioDisabledEvent" );
  1134. if ( NULL == s_hRDPEvent )
  1135. {
  1136. TRC( ERR, "failed to open Global\\RDPAudioDisabledEvent [%d]\n", GetLastError());
  1137. return FALSE;
  1138. }
  1139. }
  1140. dw = WaitForSingleObject( s_hRDPEvent, 0 );
  1141. return ( WAIT_OBJECT_0 == dw );
  1142. }
  1143. //
  1144. // check if the loader lock is held
  1145. // if true, we'll fail to do the RPC call
  1146. //
  1147. if ( NtCurrentTeb()->ClientId.UniqueThread !=
  1148. ((PRTL_CRITICAL_SECTION)(NtCurrentPeb()->LoaderLock))->OwningThread )
  1149. {
  1150. fSuccess = WinStationQueryInformation(NULL, LOGONID_CURRENT,
  1151. WinStationConfiguration, &s_config,
  1152. sizeof(s_config), &returnedLength);
  1153. if ( fSuccess )
  1154. {
  1155. s_fChecked = TRUE;
  1156. }
  1157. }
  1158. return ( !fSuccess || s_config.User.fDisableCam );
  1159. }
  1160. /*
  1161. * Create the mixer thread
  1162. *
  1163. *
  1164. */
  1165. BOOL
  1166. _EnableMixerThread(
  1167. VOID
  1168. )
  1169. {
  1170. DWORD dwThreadId;
  1171. ENTER_CRIT;
  1172. if ( AudioRedirDisabled() )
  1173. {
  1174. TRC( ALV, "TS Audio redirection is disabled\n" );
  1175. goto exitpt;
  1176. }
  1177. if ( !g_bPersonalTS && 0 != NtCurrentPeb()->SessionId )
  1178. {
  1179. if ( NULL == g_pAllWaveOut )
  1180. {
  1181. //
  1182. // not yet
  1183. //
  1184. goto exitpt;
  1185. }
  1186. }
  1187. if ( NULL != g_hMixerThread )
  1188. {
  1189. DWORD dw = WaitForSingleObject( g_hMixerThread, 0 );
  1190. if ( WAIT_OBJECT_0 == dw )
  1191. {
  1192. CloseHandle( g_hMixerThread );
  1193. g_hMixerThread = NULL;
  1194. }
  1195. }
  1196. if ( NULL == g_hMixerThread )
  1197. {
  1198. g_bMixerRunning = TRUE;
  1199. g_hMixerThread = CreateThread(
  1200. NULL,
  1201. 0,
  1202. waveMixerThread,
  1203. NULL,
  1204. 0,
  1205. &dwThreadId
  1206. );
  1207. }
  1208. if (NULL == g_hMixerThread)
  1209. {
  1210. TRC(FATAL, "DriverProc: can't start mixer thread\n");
  1211. }
  1212. exitpt:
  1213. LEAVE_CRIT;
  1214. return ( NULL != g_hMixerThread );
  1215. }
  1216. /*
  1217. * called on waveOutClose, if there are no more workers to play, close the mixer thread
  1218. *
  1219. */
  1220. VOID
  1221. _DerefMixerThread(
  1222. VOID
  1223. )
  1224. {
  1225. HANDLE hMixerThread;
  1226. //
  1227. // don't close the mixer thread on Pro and on session 0 on servers
  1228. //
  1229. if (g_bPersonalTS || 0 == NtCurrentPeb()->SessionId)
  1230. {
  1231. goto exitpt;
  1232. }
  1233. if ( NULL == g_hMixerEvent )
  1234. {
  1235. TRC( ERR, "_DerefMixerThread: no mixer event\n" );
  1236. goto exitpt;
  1237. }
  1238. ENTER_CRIT;
  1239. if ( NULL != g_pAllWaveOut )
  1240. {
  1241. //
  1242. // not yet
  1243. //
  1244. LEAVE_CRIT;
  1245. goto exitpt;
  1246. }
  1247. hMixerThread = g_hMixerThread;
  1248. g_hMixerThread = NULL;
  1249. g_bMixerRunning = FALSE;
  1250. LEAVE_CRIT;
  1251. SetEvent( g_hMixerEvent );
  1252. WaitForSingleObject(hMixerThread, INFINITE);
  1253. CloseHandle( hMixerThread );
  1254. exitpt:
  1255. ;
  1256. }
  1257. /*
  1258. * Function:
  1259. * _waveMixerWriteData
  1260. *
  1261. * Description:
  1262. * Mixes blocks of data to the stream
  1263. *
  1264. */
  1265. VOID
  1266. _waveMixerWriteData(
  1267. VOID
  1268. )
  1269. {
  1270. // this call is made within the mixer
  1271. // thread context
  1272. //
  1273. UINT uiEmptyBlocks;
  1274. PWAVEHDR pWaveHdr;
  1275. PWAVEHDR pPrevHdr;
  1276. PWAVEOUTCTX pWaveOut;
  1277. DWORD dwStartPos;
  1278. DWORD dwSize1;
  1279. DWORD dwSize2;
  1280. DWORD dwFitBufferLength;
  1281. DWORD dwFitDest;
  1282. DWORD dwBuffDisp;
  1283. BOOL bKickStream = FALSE;
  1284. ENTER_CRIT;
  1285. if (NULL == g_pAllWaveOut)
  1286. {
  1287. TRC(ALV, "_waveWriteData: WaveOut queue is empty\n");
  1288. goto exitpt;
  1289. }
  1290. if (NULL == g_hDataReadyEvent)
  1291. {
  1292. TRC(ERR, "_waveWriteData: g_hStreamDataReady is NULL\n");
  1293. goto exitpt;
  1294. }
  1295. if (!_waveAcquireStream())
  1296. {
  1297. TRC(ERR, "_waveWriteData: can't acquire the stream mutex\n");
  1298. goto exitpt;
  1299. }
  1300. if ( 0 == (g_Stream->dwSoundCaps & TSSNDCAPS_ALIVE) ||
  1301. 0 != ( g_Stream->dwSoundFlags & TSSNDFLAGS_MUTE ))
  1302. {
  1303. // no play here
  1304. _waveReleaseStream();
  1305. goto exitpt;
  1306. }
  1307. for (
  1308. pWaveOut = g_pAllWaveOut;
  1309. NULL != pWaveOut;
  1310. pWaveOut = pWaveOut->lpNext
  1311. )
  1312. {
  1313. for(
  1314. pPrevHdr = NULL, pWaveHdr = pWaveOut->pFirstWaveHdr;
  1315. NULL != pWaveHdr;
  1316. /* nothing */
  1317. )
  1318. {
  1319. // if this stream is paused advance to the next one
  1320. //
  1321. if (pWaveOut->bPaused)
  1322. break;
  1323. // check if we have to append data to a buffer
  1324. // from previous call
  1325. //
  1326. if ((BYTE)(pWaveOut->cLastStreamPosition - g_Stream->cLastBlockSent) >
  1327. TSSND_MAX_BLOCKS ||
  1328. (BYTE)(g_Stream->cLastBlockQueued -
  1329. pWaveOut->cLastStreamPosition) >
  1330. TSSND_MAX_BLOCKS)
  1331. {
  1332. pWaveOut->cLastStreamPosition = g_Stream->cLastBlockSent;
  1333. pWaveOut->dwLastStreamOffset = 0;
  1334. TRC(ALV, "_waveWriteData: reseting the stream position\n");
  1335. }
  1336. // the empty blocks are from "LastStreamPosition" to "Confirmed"
  1337. // ( "Confirmed" to "LastStreamPosition" are preserved )
  1338. //
  1339. uiEmptyBlocks = (BYTE)
  1340. (g_Stream->cLastBlockSent + TSSND_MAX_BLOCKS -
  1341. pWaveOut->cLastStreamPosition);
  1342. if (uiEmptyBlocks > TSSND_MAX_BLOCKS)
  1343. {
  1344. TRC(FATAL, "too many empty blocks:\n");
  1345. TRC(FATAL, "cLastBlockQueued=%d\n", g_Stream->cLastBlockQueued);
  1346. TRC(FATAL, "cLastBlockSent =%d\n", g_Stream->cLastBlockSent);
  1347. TRC(FATAL, "cLastBlockConfirmed%d\n", g_Stream->cLastBlockConfirmed);
  1348. TRC(FATAL, "cLastStreamPosition=%d\n", pWaveOut->cLastStreamPosition);
  1349. ASSERT(0);
  1350. break;
  1351. }
  1352. // if everything is full, go to bed
  1353. //
  1354. if (0 == uiEmptyBlocks)
  1355. {
  1356. TRC(ALV, "_waveMixerWriteData: stream is full\n");
  1357. break;
  1358. }
  1359. // WHAT IF THE EMPTY SPACE IS SMALLER THAN THE DATA IN THE HEADER
  1360. //
  1361. dwFitBufferLength = (uiEmptyBlocks * TSSND_BLOCKSIZE -
  1362. pWaveOut->dwLastStreamOffset);
  1363. dwFitDest = MulDiv(
  1364. pWaveHdr->dwBufferLength -
  1365. pWaveOut->dwLastHeaderOffset,
  1366. TSSND_NATIVE_XLATERATE,
  1367. pWaveOut->dwXlateRate
  1368. );
  1369. dwFitDest &= ~( TSSND_NATIVE_BLOCKALIGN - 1 );
  1370. if ( dwFitBufferLength < dwFitDest )
  1371. {
  1372. dwFitDest = MulDiv(
  1373. dwFitBufferLength,
  1374. pWaveOut->dwXlateRate,
  1375. TSSND_NATIVE_XLATERATE
  1376. );
  1377. dwFitDest &= ~( pWaveOut->Format_nBlockAlign - 1 );
  1378. } else {
  1379. dwFitBufferLength = dwFitDest;
  1380. dwFitDest = pWaveHdr->dwBufferLength - pWaveOut->dwLastHeaderOffset;
  1381. }
  1382. // place the data, because of the round buffer,
  1383. // this could be a two step process
  1384. //
  1385. // TRC( INF, "Filling block # %d, offset=0x%x\n", pWaveOut->cLastStreamPosition, pWaveOut->dwLastStreamOffset );
  1386. dwStartPos = (pWaveOut->cLastStreamPosition
  1387. % TSSND_MAX_BLOCKS) *
  1388. TSSND_BLOCKSIZE +
  1389. pWaveOut->dwLastStreamOffset;
  1390. if ( dwStartPos + dwFitBufferLength >
  1391. TSSND_TOTALSTREAMSIZE)
  1392. {
  1393. dwSize1 = (TSSND_TOTALSTREAMSIZE - dwStartPos) /
  1394. TSSND_NATIVE_BLOCKALIGN;
  1395. dwSize2 = dwFitBufferLength / TSSND_NATIVE_BLOCKALIGN -
  1396. dwSize1;
  1397. } else {
  1398. dwSize1 = dwFitBufferLength / TSSND_NATIVE_BLOCKALIGN;
  1399. dwSize2 = 0;
  1400. }
  1401. pWaveOut->lpfnPlace(g_Stream->pSndData +
  1402. dwStartPos,
  1403. ((LPSTR)pWaveHdr->lpData) + pWaveOut->dwLastHeaderOffset,
  1404. dwSize1);
  1405. dwBuffDisp = MulDiv(
  1406. dwSize1 * TSSND_NATIVE_BLOCKALIGN,
  1407. pWaveOut->dwXlateRate,
  1408. TSSND_NATIVE_XLATERATE
  1409. );
  1410. dwBuffDisp &= ~( pWaveOut->Format_nBlockAlign - 1 );
  1411. pWaveOut->lpfnPlace(g_Stream->pSndData,
  1412. ((LPSTR)pWaveHdr->lpData) + pWaveOut->dwLastHeaderOffset +
  1413. dwBuffDisp,
  1414. dwSize2);
  1415. // Calculate the new position
  1416. //
  1417. pWaveOut->dwLastStreamOffset += dwFitBufferLength;
  1418. pWaveOut->cLastStreamPosition += (BYTE)(pWaveOut->dwLastStreamOffset /
  1419. TSSND_BLOCKSIZE);
  1420. pWaveOut->dwLastStreamOffset %= TSSND_BLOCKSIZE;
  1421. pWaveOut->dwLastHeaderOffset += dwFitDest;
  1422. ASSERT(pWaveOut->dwLastHeaderOffset <= pWaveHdr->dwBufferLength);
  1423. //
  1424. // check if the buffer is completed
  1425. //
  1426. if ( 0 == MulDiv(
  1427. ( pWaveHdr->dwBufferLength - pWaveOut->dwLastHeaderOffset ),
  1428. TSSND_NATIVE_XLATERATE,
  1429. pWaveOut->dwXlateRate))
  1430. {
  1431. pWaveOut->dwLastHeaderOffset = 0;
  1432. // remove this header from the queue
  1433. //
  1434. if (NULL == pPrevHdr)
  1435. pWaveOut->pFirstWaveHdr = pWaveHdr->lpNext;
  1436. else
  1437. pPrevHdr->lpNext = pWaveHdr->lpNext;
  1438. pWaveHdr->lpNext = NULL;
  1439. //
  1440. // save the current stream mark
  1441. //
  1442. pWaveHdr->reserved = g_Stream->cLastBlockQueued;
  1443. // add it to the ready queue
  1444. //
  1445. if (NULL == pWaveOut->pLastReadyHdr)
  1446. {
  1447. pWaveOut->pFirstReadyHdr = pWaveHdr;
  1448. pWaveOut->pLastReadyHdr = pWaveHdr;
  1449. } else {
  1450. pWaveOut->pLastReadyHdr->lpNext = pWaveHdr;
  1451. pWaveOut->pLastReadyHdr = pWaveHdr;
  1452. }
  1453. // reset pPrevHdr and pWaveHdr
  1454. //
  1455. pPrevHdr = NULL;
  1456. pWaveHdr = pWaveOut->pFirstWaveHdr;
  1457. } else {
  1458. //
  1459. // Advance to the next header
  1460. //
  1461. pPrevHdr = pWaveHdr;
  1462. pWaveHdr = pWaveHdr->lpNext;
  1463. }
  1464. //
  1465. // kick the stream thread
  1466. //
  1467. if ((BYTE)(pWaveOut->cLastStreamPosition - g_Stream->cLastBlockQueued) <
  1468. _NEG_IDX)
  1469. {
  1470. bKickStream = TRUE;
  1471. //
  1472. // move the "queued" mark
  1473. //
  1474. g_Stream->cLastBlockQueued = pWaveOut->cLastStreamPosition;
  1475. }
  1476. }
  1477. }
  1478. if (bKickStream)
  1479. {
  1480. //
  1481. // kick the io
  1482. //
  1483. SetEvent(g_hDataReadyEvent);
  1484. }
  1485. _waveReleaseStream();
  1486. exitpt:
  1487. // Now for all "done" buffers, send the callback
  1488. //
  1489. for (pWaveOut = g_pAllWaveOut;
  1490. NULL != pWaveOut;
  1491. pWaveOut = pWaveOut->lpNext)
  1492. {
  1493. for (pPrevHdr = NULL, pWaveHdr = pWaveOut->pFirstReadyHdr;
  1494. NULL != pWaveHdr;
  1495. /* nothing */ )
  1496. {
  1497. if ( (INT)((CHAR)(g_Stream->cLastBlockQueued -
  1498. PtrToLong((PVOID)pWaveHdr->reserved))) >= 0)
  1499. {
  1500. // this block was confirmed, proceed with
  1501. // extracting it and notification
  1502. //
  1503. if (NULL != pPrevHdr)
  1504. pPrevHdr->lpNext = pWaveHdr->lpNext;
  1505. else
  1506. pWaveOut->pFirstReadyHdr = pWaveHdr->lpNext;
  1507. if (pWaveHdr == pWaveOut->pLastReadyHdr)
  1508. pWaveOut->pLastReadyHdr = pPrevHdr;
  1509. //
  1510. // advance the number of samples.
  1511. // also, remember a time stamp and this block size
  1512. // in samples, for sample accuracy
  1513. //
  1514. pWaveOut->dwSamples += pWaveHdr->dwBufferLength /
  1515. pWaveOut->Format_nBlockAlign;
  1516. //
  1517. // clear this buffer from the pending list
  1518. //
  1519. if (0 == InterlockedDecrement(&pWaveOut->lNumberOfBlocksPlaying))
  1520. {
  1521. SetEvent(pWaveOut->hNoDataEvent);
  1522. }
  1523. // notify the app
  1524. //
  1525. // mark the buffer as ready
  1526. //
  1527. pWaveHdr->dwFlags |= WHDR_DONE;
  1528. pWaveHdr->dwFlags &= ~(WHDR_INQUEUE);
  1529. pWaveHdr->lpNext = NULL;
  1530. pWaveHdr->reserved = 0;
  1531. // confirm that the block is done
  1532. //
  1533. waveCallback(pWaveOut, WOM_DONE, (DWORD_PTR)pWaveHdr);
  1534. // reinitialize the iterators
  1535. //
  1536. if ( NULL == g_pAllWaveOut )
  1537. goto leave_crit;
  1538. pWaveOut = g_pAllWaveOut;
  1539. pPrevHdr = NULL, pWaveHdr = pWaveOut->pFirstReadyHdr;
  1540. if ( NULL == pWaveHdr )
  1541. goto leave_crit;
  1542. } else {
  1543. // advance the iterators
  1544. //
  1545. pPrevHdr = pWaveHdr;
  1546. pWaveHdr = pWaveHdr->lpNext;
  1547. }
  1548. }
  1549. }
  1550. leave_crit:
  1551. LEAVE_CRIT;
  1552. }
  1553. /*
  1554. * Function:
  1555. * _waveMixerPlaySilence
  1556. *
  1557. * Description:
  1558. * Simulates play by using sleep
  1559. *
  1560. */
  1561. BOOL
  1562. _waveMixerPlaySilence(
  1563. VOID
  1564. )
  1565. {
  1566. BOOL rv = FALSE;
  1567. DWORD dwMinTime;
  1568. DWORD dwTime;
  1569. DWORD dwLength;
  1570. PWAVEHDR pWaveHdr;
  1571. PWAVEOUTCTX pWaveOut;
  1572. //
  1573. // simulate silent play
  1574. //
  1575. dwMinTime = (DWORD)-1;
  1576. //
  1577. // find the smallest block waiting and sleep
  1578. // for the time it has to play
  1579. //
  1580. ENTER_CRIT;
  1581. for (
  1582. pWaveOut = g_pAllWaveOut;
  1583. NULL != pWaveOut;
  1584. pWaveOut = pWaveOut->lpNext
  1585. )
  1586. {
  1587. pWaveHdr = pWaveOut->pFirstWaveHdr;
  1588. if ( NULL == pWaveHdr )
  1589. continue;
  1590. dwLength = pWaveHdr->dwBufferLength - pWaveOut->dwLastHeaderOffset;
  1591. //
  1592. // time is in miliseconds
  1593. //
  1594. dwTime = dwLength * 1000 /
  1595. pWaveOut->Format_nAvgBytesPerSec;
  1596. if ( dwMinTime > dwTime )
  1597. dwMinTime = dwTime;
  1598. }
  1599. LEAVE_CRIT;
  1600. //
  1601. // exit if no block is found
  1602. //
  1603. if ( (DWORD)-1 == dwMinTime )
  1604. goto exitpt;
  1605. if ( 0 == dwMinTime )
  1606. dwMinTime = 1;
  1607. Sleep( dwMinTime );
  1608. //
  1609. // start confirming
  1610. //
  1611. ENTER_CRIT;
  1612. for (
  1613. pWaveOut = g_pAllWaveOut;
  1614. NULL != pWaveOut;
  1615. pWaveOut = pWaveOut->lpNext
  1616. )
  1617. {
  1618. pWaveHdr = pWaveOut->pFirstWaveHdr;
  1619. if ( NULL == pWaveHdr )
  1620. continue;
  1621. dwLength = pWaveOut->dwLastHeaderOffset;
  1622. dwLength += dwMinTime * pWaveOut->Format_nAvgBytesPerSec / 1000;
  1623. //
  1624. // align to a block
  1625. //
  1626. dwLength += pWaveOut->Format_nBlockAlign - 1;
  1627. dwLength /= pWaveOut->Format_nBlockAlign;
  1628. dwLength *= pWaveOut->Format_nBlockAlign;
  1629. pWaveOut->dwLastHeaderOffset = dwLength;
  1630. if ( dwLength >= pWaveHdr->dwBufferLength )
  1631. {
  1632. pWaveOut->dwLastHeaderOffset = 0;
  1633. pWaveOut->pFirstWaveHdr = pWaveHdr->lpNext;
  1634. //
  1635. // this block is "done"
  1636. // mark the buffer as ready
  1637. //
  1638. pWaveHdr->dwFlags |= WHDR_DONE;
  1639. pWaveHdr->dwFlags &= ~(WHDR_INQUEUE);
  1640. pWaveHdr->lpNext = NULL;
  1641. pWaveHdr->reserved = 0;
  1642. // increment the position
  1643. //
  1644. pWaveOut->dwSamples += pWaveHdr->dwBufferLength /
  1645. pWaveOut->Format_nBlockAlign;
  1646. if (0 == InterlockedDecrement(&pWaveOut->lNumberOfBlocksPlaying))
  1647. {
  1648. SetEvent(pWaveOut->hNoDataEvent);
  1649. }
  1650. // confirm that the block is done
  1651. //
  1652. waveCallback(pWaveOut, WOM_DONE, (DWORD_PTR)pWaveHdr);
  1653. }
  1654. }
  1655. LEAVE_CRIT;
  1656. rv = TRUE;
  1657. exitpt:
  1658. return rv;
  1659. }
  1660. /*
  1661. * Function:
  1662. * waveMixerThread
  1663. *
  1664. * Description:
  1665. * Mixer thread main entry point
  1666. *
  1667. * Parameters:
  1668. * pParam - unused
  1669. *
  1670. */
  1671. DWORD
  1672. WINAPI
  1673. waveMixerThread(
  1674. PVOID pParam
  1675. )
  1676. {
  1677. HANDLE ahEvents[3];
  1678. PWAVEOUTCTX pWaveOut;
  1679. HANDLE hCleanupEvent = NULL;
  1680. DWORD numEvents;
  1681. //
  1682. // wait for the sound process to initialize
  1683. //
  1684. if (( NULL == g_Stream ||
  1685. 0 == ( g_Stream->dwSoundCaps & TSSNDCAPS_INITIALIZED)) &&
  1686. NULL != g_hWaitToInitialize )
  1687. {
  1688. DWORD dw = WaitForSingleObject( g_hWaitToInitialize,
  1689. 10 * DEFAULT_VC_TIMEOUT );
  1690. if ( WAIT_OBJECT_0 != dw )
  1691. TRC( ERR, "WaitToInitialize failed\n" );
  1692. else
  1693. TRC( INF, "WaitToInitialize succeeded\n" );
  1694. hCleanupEvent = g_hWaitToInitialize;
  1695. g_hWaitToInitialize = NULL;
  1696. drvEnable();
  1697. } else {
  1698. hCleanupEvent = _CreateInitEvent();
  1699. }
  1700. if (NULL == g_hMixerEvent ||
  1701. NULL == g_hDataReadyEvent)
  1702. {
  1703. TRC(FATAL, "waveMixerThread: no events\n");
  1704. goto exitpt;
  1705. }
  1706. if ( NULL != hCleanupEvent )
  1707. {
  1708. ahEvents[0] = hCleanupEvent;
  1709. ahEvents[1] = g_hMixerEvent;
  1710. ahEvents[2] = g_hStreamIsEmptyEvent;
  1711. numEvents = 3;
  1712. } else {
  1713. ahEvents[0] = g_hMixerEvent;
  1714. ahEvents[1] = g_hStreamIsEmptyEvent;
  1715. numEvents = 2;
  1716. }
  1717. while (g_bMixerRunning)
  1718. {
  1719. DWORD dwres;
  1720. DWORD bHdrsPending = FALSE;
  1721. // check if there are headers pending
  1722. //
  1723. ENTER_CRIT;
  1724. for (pWaveOut = g_pAllWaveOut;
  1725. NULL != pWaveOut && !bHdrsPending;
  1726. pWaveOut = pWaveOut->lpNext
  1727. )
  1728. bHdrsPending = (NULL != pWaveOut->pFirstWaveHdr ||
  1729. NULL != pWaveOut->pFirstReadyHdr) &&
  1730. !pWaveOut->bPaused;
  1731. LEAVE_CRIT;
  1732. if ( bHdrsPending &&
  1733. NULL != g_Stream &&
  1734. ( 0 == (g_Stream->dwSoundCaps & TSSNDCAPS_ALIVE) ||
  1735. ( 0 != (g_Stream->dwSoundCaps & TSSNDCAPS_VOLUME) &&
  1736. 0 == g_Stream->dwVolume
  1737. ) ||
  1738. ( 0 != ( g_Stream->dwSoundFlags & TSSNDFLAGS_MUTE ))
  1739. )
  1740. )
  1741. {
  1742. //
  1743. // play silence in case of disconnected on "mute" mode
  1744. //
  1745. while( ( 0 == (g_Stream->dwSoundCaps & TSSNDCAPS_ALIVE) ||
  1746. ( 0 != (g_Stream->dwSoundCaps & TSSNDCAPS_VOLUME) &&
  1747. 0 == g_Stream->dwVolume
  1748. ) ||
  1749. ( 0 != ( g_Stream->dwSoundFlags & TSSNDFLAGS_MUTE ))
  1750. ) &&
  1751. _waveMixerPlaySilence() )
  1752. ;
  1753. } else {
  1754. Sleep( 30 ); // give some time to the DSound emulator thread to wake up
  1755. //
  1756. dwres = WaitForMultipleObjects(
  1757. (!bHdrsPending) ? numEvents - 1 : numEvents,
  1758. ahEvents,
  1759. FALSE,
  1760. INFINITE
  1761. );
  1762. //
  1763. // check for termination
  1764. //
  1765. if ( WAIT_OBJECT_0 == dwres && NULL != hCleanupEvent )
  1766. {
  1767. TRC( INF, "Cleanup detected (rdpclip disappeared ?!)\n" );
  1768. // check for termination
  1769. if ( _waveAcquireStream() )
  1770. {
  1771. if ( TSSNDCAPS_TERMINATED == g_Stream->dwSoundCaps )
  1772. {
  1773. TRC( INF, "Cleaning up global data\n" );
  1774. CloseHandle( g_hMixerThread );
  1775. g_hMixerThread = NULL;
  1776. _waveReleaseStream();
  1777. drvDisable();
  1778. goto exitpt;
  1779. }
  1780. _waveReleaseStream();
  1781. }
  1782. }
  1783. _waveMixerWriteData();
  1784. }
  1785. }
  1786. exitpt:
  1787. TRC(INF, "waveMixerThread exited\n");
  1788. if ( NULL != hCleanupEvent )
  1789. CloseHandle( hCleanupEvent );
  1790. return 0;
  1791. }
  1792. /*
  1793. * Function:
  1794. * wavePrepare
  1795. *
  1796. * Description:
  1797. * Prepares a block, i.e. only sets it's flags
  1798. *
  1799. */
  1800. DWORD
  1801. wavePrepare(
  1802. PVOID pWaveCtx,
  1803. PWAVEHDR pWaveHdr,
  1804. DWORD_PTR dwWaveHdrSize,
  1805. BOOL bPrepare)
  1806. {
  1807. PWAVEOUTCTX pWaveOut = pWaveCtx;
  1808. BOOL rv = MMSYSERR_NOTSUPPORTED;
  1809. // Parameters check
  1810. //
  1811. if (NULL == pWaveCtx)
  1812. {
  1813. TRC(ERR, "wavePrepare: invalid device handle\n");
  1814. rv = MMSYSERR_INVALHANDLE;
  1815. goto exitpt;
  1816. }
  1817. if (sizeof(*pWaveHdr) != dwWaveHdrSize)
  1818. {
  1819. TRC(ERR, "wavePrepare: invalid size for dwWaveHdrSize\n");
  1820. rv = MMSYSERR_INVALPARAM;
  1821. goto exitpt;
  1822. }
  1823. //
  1824. // check the buffer size alignment
  1825. //
  1826. if ( 0 != pWaveOut->Format_nBlockAlign &&
  1827. 0 != pWaveHdr->dwBufferLength % pWaveOut->Format_nBlockAlign )
  1828. {
  1829. TRC( ERR, "wavePrepare: size unaligned\n" );
  1830. rv = MMSYSERR_INVALPARAM;
  1831. goto exitpt;
  1832. }
  1833. if (IsBadReadPtr( pWaveHdr->lpData, pWaveHdr->dwBufferLength ))
  1834. {
  1835. TRC( ERR, "wavePrepare: buffer unreadable\n" );
  1836. rv = MMSYSERR_INVALPARAM;
  1837. goto exitpt;
  1838. }
  1839. #ifdef _WIN64
  1840. //
  1841. // check for proper alignment
  1842. //
  1843. if ( 0 != pWaveOut->Format_nChannels &&
  1844. 2 == pWaveOut->Format_nBlockAlign / pWaveOut->Format_nChannels &&
  1845. 0 != (( (LONG_PTR)pWaveHdr->lpData ) & 1 ))
  1846. {
  1847. TRC( ERR, "wavePrepare: buffer unaligned\n" );
  1848. rv = MMSYSERR_INVALPARAM;
  1849. goto exitpt;
  1850. }
  1851. #endif
  1852. if (bPrepare)
  1853. pWaveHdr->dwFlags |= WHDR_PREPARED;
  1854. else
  1855. pWaveHdr->dwFlags &= ~WHDR_PREPARED;
  1856. rv = MMSYSERR_NOERROR;
  1857. exitpt:
  1858. return rv;
  1859. }
  1860. /*
  1861. * Function:
  1862. * waveReset
  1863. *
  1864. * Description:
  1865. * Resets all current queued blocks
  1866. *
  1867. */
  1868. DWORD
  1869. waveReset(
  1870. PWAVEOUTCTX pWaveOut
  1871. )
  1872. {
  1873. BOOL rv = MMSYSERR_NOTSUPPORTED;
  1874. LPWAVEHDR pWaveHdr;
  1875. LPWAVEHDR pFoundPrevHdr;
  1876. ENTER_CRIT;
  1877. // Parameters check
  1878. //
  1879. if (NULL == pWaveOut)
  1880. {
  1881. TRC(ERR, "waveReset: invalid device handle\n");
  1882. rv = MMSYSERR_INVALHANDLE;
  1883. goto exitpt;
  1884. }
  1885. // dismiss all headers pending confirmation
  1886. //
  1887. while ( NULL != pWaveOut->pFirstReadyHdr )
  1888. {
  1889. pWaveHdr = pWaveOut->pFirstReadyHdr;
  1890. pWaveOut->pFirstReadyHdr = pWaveOut->pFirstReadyHdr->lpNext;
  1891. if (NULL == pWaveOut->pFirstReadyHdr)
  1892. pWaveOut->pLastReadyHdr = NULL;
  1893. pWaveHdr->reserved = 0;
  1894. pWaveHdr->lpNext = NULL;
  1895. pWaveHdr->dwFlags |= WHDR_DONE;
  1896. pWaveHdr->dwFlags &= ~(WHDR_INQUEUE);
  1897. // confirm that the block is done
  1898. //
  1899. LEAVE_CRIT;
  1900. waveCallback(pWaveOut, WOM_DONE, (DWORD_PTR)pWaveHdr);
  1901. ENTER_CRIT;
  1902. if (0 == InterlockedDecrement(&pWaveOut->lNumberOfBlocksPlaying))
  1903. {
  1904. SetEvent(pWaveOut->hNoDataEvent);
  1905. }
  1906. }
  1907. // Clean all headers in the queue
  1908. //
  1909. while(NULL != pWaveOut->pFirstWaveHdr)
  1910. {
  1911. pWaveHdr = pWaveOut->pFirstWaveHdr;
  1912. pWaveOut->pFirstWaveHdr = pWaveHdr->lpNext;
  1913. pWaveHdr->reserved = 0;
  1914. pWaveHdr->lpNext = NULL;
  1915. pWaveHdr->dwFlags |= WHDR_DONE;
  1916. pWaveHdr->dwFlags &= ~(WHDR_INQUEUE);
  1917. // confirm that the block is done
  1918. //
  1919. LEAVE_CRIT;
  1920. waveCallback(pWaveOut, WOM_DONE, (DWORD_PTR)pWaveHdr);
  1921. ENTER_CRIT;
  1922. if (0 == InterlockedDecrement(&pWaveOut->lNumberOfBlocksPlaying))
  1923. {
  1924. SetEvent(pWaveOut->hNoDataEvent);
  1925. }
  1926. }
  1927. //
  1928. // we may end with some data in the last block in the stream
  1929. // if the "queued" mark hasn't change, increment it and kick the io
  1930. // thread to play this block
  1931. // to test this play very-very short files
  1932. // shorter than TSSND_BLOCKSIZE / (TSSND_NATIVE_BLOCKALIGN *
  1933. // TSSND_NATIVE_SAMPLERATE) seconds
  1934. //
  1935. //
  1936. //
  1937. if (_waveAcquireStream())
  1938. {
  1939. if (g_Stream->cLastBlockQueued == pWaveOut->cLastStreamPosition &&
  1940. 0 != pWaveOut->dwLastStreamOffset)
  1941. {
  1942. g_Stream->cLastBlockQueued ++;
  1943. //
  1944. // kick the io thread
  1945. //
  1946. if (g_hDataReadyEvent)
  1947. SetEvent(g_hDataReadyEvent);
  1948. else
  1949. TRC(WRN, "waveClose: g_hDataReadyEvent is NULL\n");
  1950. }
  1951. _waveReleaseStream();
  1952. }
  1953. pWaveOut->dwLastHeaderOffset = 0;
  1954. pWaveOut->dwSamples = 0;
  1955. rv = MMSYSERR_NOERROR;
  1956. exitpt:
  1957. LEAVE_CRIT;
  1958. return rv;
  1959. }
  1960. /*
  1961. * Function:
  1962. * waveGetPos
  1963. *
  1964. * Description:
  1965. * Gets current position in the current stream
  1966. *
  1967. */
  1968. DWORD
  1969. waveGetPos(
  1970. PWAVEOUTCTX pWaveOut,
  1971. MMTIME *pMMTime,
  1972. DWORD_PTR dwMMTimeSize
  1973. )
  1974. {
  1975. DWORD rv = MMSYSERR_ERROR;
  1976. DWORD dwSamples;
  1977. DWORD ms;
  1978. if (NULL == pWaveOut)
  1979. {
  1980. TRC(ERR, "waveGetPos: invalid device handle\n");
  1981. rv = MMSYSERR_INVALHANDLE;
  1982. goto exitpt;
  1983. }
  1984. if (NULL == pMMTime || sizeof(*pMMTime) != dwMMTimeSize)
  1985. {
  1986. TRC(ERR, "waveGetPos: pMMTime is invalid\n");
  1987. rv = MMSYSERR_INVALPARAM;
  1988. goto exitpt;
  1989. }
  1990. //
  1991. // update the played position
  1992. //
  1993. dwSamples = pWaveOut->dwSamples;
  1994. switch ( pMMTime->wType )
  1995. {
  1996. case TIME_SAMPLES:
  1997. pMMTime->u.sample = dwSamples;
  1998. break;
  1999. case TIME_BYTES:
  2000. pMMTime->u.cb = dwSamples * pWaveOut->Format_nBlockAlign;
  2001. break;
  2002. case TIME_MS:
  2003. pMMTime->u.ms = MulDiv( dwSamples, pWaveOut->Format_nBlockAlign * 1000,
  2004. pWaveOut->Format_nAvgBytesPerSec );
  2005. break;
  2006. case TIME_SMPTE:
  2007. ms = MulDiv( dwSamples, pWaveOut->Format_nBlockAlign * 1000,
  2008. pWaveOut->Format_nAvgBytesPerSec );
  2009. pMMTime->u.smpte.frame = (BYTE)((ms % 1000) * 24 / 1000);
  2010. ms /= 1000;
  2011. pMMTime->u.smpte.sec = (BYTE)(ms % 60);
  2012. ms /= 60;
  2013. pMMTime->u.smpte.min = (BYTE)(ms % 60);
  2014. ms /= 60;
  2015. pMMTime->u.smpte.hour = (BYTE)ms;
  2016. pMMTime->u.smpte.fps = 24;
  2017. break;
  2018. default:
  2019. rv = MMSYSERR_NOTSUPPORTED;
  2020. }
  2021. rv = MMSYSERR_NOERROR;
  2022. exitpt:
  2023. return rv;
  2024. }
  2025. /*
  2026. * Function:
  2027. * wavePause
  2028. *
  2029. * Description:
  2030. * Pauses the current play
  2031. *
  2032. */
  2033. DWORD
  2034. wavePause(
  2035. PWAVEOUTCTX pWaveOut
  2036. )
  2037. {
  2038. DWORD rv = MMSYSERR_ERROR;
  2039. if (NULL == pWaveOut)
  2040. {
  2041. TRC(ERR, "wavePause: invalid device handle\n");
  2042. rv = MMSYSERR_INVALHANDLE;
  2043. goto exitpt;
  2044. }
  2045. pWaveOut->bPaused = TRUE;
  2046. rv = MMSYSERR_NOERROR;
  2047. exitpt:
  2048. return rv;
  2049. }
  2050. /*
  2051. * Function:
  2052. * waveRestart
  2053. *
  2054. * Description:
  2055. * Restarts a paused play
  2056. *
  2057. */
  2058. DWORD
  2059. waveRestart(
  2060. PWAVEOUTCTX pWaveOut
  2061. )
  2062. {
  2063. DWORD rv = MMSYSERR_ERROR;
  2064. if (NULL == pWaveOut)
  2065. {
  2066. TRC(ERR, "waveRestart: invalid device handle\n");
  2067. rv = MMSYSERR_INVALHANDLE;
  2068. goto exitpt;
  2069. }
  2070. pWaveOut->bPaused = FALSE;
  2071. //
  2072. // Kick the mixer thread
  2073. //
  2074. if (NULL == g_hMixerEvent)
  2075. {
  2076. TRC(WRN, "waveRestart: g_hMixerEvent is NULL\n");
  2077. } else
  2078. SetEvent(g_hMixerEvent);
  2079. rv = MMSYSERR_NOERROR;
  2080. exitpt:
  2081. return rv;
  2082. }
  2083. /*
  2084. * Function:
  2085. * wodMessage
  2086. *
  2087. * Description:
  2088. * Main entry point for WaveOut device
  2089. *
  2090. * Parameters:
  2091. *
  2092. *
  2093. */
  2094. DWORD
  2095. APIENTRY
  2096. wodMessage(
  2097. UINT uDeviceID,
  2098. UINT uMessage,
  2099. DWORD_PTR dwUser,
  2100. DWORD_PTR dwParam1,
  2101. DWORD_PTR dwParam2
  2102. )
  2103. {
  2104. DWORD rv = MMSYSERR_ERROR;
  2105. PWAVEOUTCTX pWaveOut = (PWAVEOUTCTX)dwUser;
  2106. switch ( uMessage )
  2107. {
  2108. case WODM_GETNUMDEVS:
  2109. TRC(ALV, "WODM_GETNUMDEVS\n");
  2110. rv = waveGetNumDevs();
  2111. break;
  2112. case WODM_GETDEVCAPS:
  2113. drvEnable();
  2114. TRC( ALV, "WODM_GETDEVCAPS\n");
  2115. rv = waveGetWaveOutDeviceCaps(
  2116. pWaveOut,
  2117. (LPWAVEOUTCAPS)dwParam1,
  2118. dwParam2
  2119. );
  2120. break;
  2121. case WODM_OPEN:
  2122. drvEnable();
  2123. TRC(ALV, "WODM_OPEN\n");
  2124. rv = waveOpen( (PWAVEOUTCTX *)dwUser,
  2125. (LPWAVEOPENDESC)dwParam1,
  2126. dwParam2);
  2127. _EnableMixerThread();
  2128. break;
  2129. case WODM_CLOSE:
  2130. TRC(ALV, "WODM_CLOSE\n");
  2131. rv = waveClose(pWaveOut);
  2132. _DerefMixerThread();
  2133. break;
  2134. case WODM_WRITE:
  2135. TRC(ALV, "WODM_WRITE\n");
  2136. rv = waveWrite(pWaveOut, (PWAVEHDR)dwParam1, dwParam2);
  2137. break;
  2138. case WODM_PAUSE:
  2139. TRC(ALV, "WODM_PAUSE\n");
  2140. rv = wavePause(pWaveOut);
  2141. break;
  2142. case WODM_RESTART:
  2143. TRC(ALV, "WODM_RESTART\n");
  2144. rv = waveRestart(pWaveOut);
  2145. break;
  2146. case WODM_RESET:
  2147. TRC(ALV, "WODM_RESET\n");
  2148. rv = waveReset(pWaveOut);
  2149. break;
  2150. case WODM_BREAKLOOP:
  2151. TRC(ALV, "WODM_BREAKLOOP\n");
  2152. // rv = waveBreakLoop(pWaveOut);
  2153. rv = MMSYSERR_NOERROR;
  2154. break;
  2155. case WODM_GETPOS:
  2156. TRC(ALV, "WODM_GETPOS\n");
  2157. rv = waveGetPos(pWaveOut, (MMTIME *)dwParam1, dwParam2);
  2158. break;
  2159. case WODM_SETPITCH:
  2160. TRC(ALV, "WODM_SETPITCH\n");
  2161. rv = waveSetPitch(pWaveOut, PtrToLong((PVOID)dwParam1));
  2162. break;
  2163. case WODM_SETVOLUME:
  2164. TRC(ALV, "WODM_SETVOLUME\n");
  2165. rv = waveSetVolume(pWaveOut, PtrToLong((PVOID)dwParam1));
  2166. break;
  2167. case WODM_SETPLAYBACKRATE:
  2168. TRC(ALV, "WODM_SETPLAYBACKRATE\n");
  2169. // rv = waveSetPlaybackRate(pWaveOut, dwParam1);
  2170. rv = MMSYSERR_NOTSUPPORTED;
  2171. break;
  2172. case WODM_GETPITCH:
  2173. TRC(ALV, "WODM_GETVOLUME\n");
  2174. rv = waveGetPitch(pWaveOut, (DWORD *)dwParam1);
  2175. break;
  2176. case WODM_GETVOLUME:
  2177. TRC(ALV, "WODM_GETVOLUME\n");
  2178. rv = waveGetVolume(pWaveOut, (DWORD *)dwParam1);
  2179. break;
  2180. case WODM_GETPLAYBACKRATE:
  2181. TRC(ALV, "WODM_GETPLAYBACKRATE\n");
  2182. // rv = waveGetPlaybackRate(pWaveOut, (DWORD *)dwParam1);
  2183. rv = MMSYSERR_NOTSUPPORTED;
  2184. break;
  2185. case WODM_PREPARE:
  2186. TRC(ALV, "WODM_PREPARE\n");
  2187. rv = wavePrepare(pWaveOut, (PWAVEHDR)dwParam1, dwParam2, TRUE);
  2188. break;
  2189. case WODM_UNPREPARE:
  2190. TRC(ALV, "WODM_UNPREPARE\n");
  2191. rv = wavePrepare(pWaveOut, (PWAVEHDR)dwParam1, dwParam2, FALSE);
  2192. break;
  2193. default:
  2194. TRC(ERR, "Unsupported message: 0x%x\n", uMessage);
  2195. rv = MMSYSERR_NOTSUPPORTED;
  2196. }
  2197. return rv;
  2198. }
  2199. /*
  2200. * Function:
  2201. * widMessage
  2202. *
  2203. * Description:
  2204. * Main entry point for WaveIn device ( unsupported
  2205. */
  2206. DWORD
  2207. APIENTRY
  2208. widMessage(
  2209. UINT uDeviceID,
  2210. UINT uMessage,
  2211. DWORD_PTR dwUser,
  2212. DWORD_PTR dwParam1,
  2213. DWORD_PTR dwParam2
  2214. )
  2215. {
  2216. if ( WIDM_GETNUMDEVS == uMessage )
  2217. return 0;
  2218. return MMSYSERR_NODRIVER;
  2219. }
  2220. //
  2221. // Common PCM format -> 22 kHz 16 bit stereo
  2222. //
  2223. // THE SIZE IS IN NUMBER OF SAMPLES IN NATIVE FORMAT
  2224. //
  2225. #define PLACE_DATA(_pdst_, _srcv_) \
  2226. sum = _pdst_[0] + _srcv_; \
  2227. \
  2228. if (sum > 0x7FFF) \
  2229. sum = 0x7FFF; \
  2230. if (sum < -0x8000) \
  2231. sum = -0x8000; \
  2232. \
  2233. _pdst_[0] = (INT16)sum; \
  2234. _pdst_ ++;
  2235. VOID
  2236. Place8kHz8Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2237. {
  2238. BYTE *psrc;
  2239. INT16 *pdst;
  2240. DWORD dwLeap;
  2241. if ( NULL == pDest || NULL == pSrc )
  2242. goto exitpt;
  2243. for (psrc = pSrc,
  2244. pdst = pDest,
  2245. dwLeap = 0;
  2246. dwSize;
  2247. dwSize--)
  2248. {
  2249. INT src;
  2250. INT sum;
  2251. src = ((INT)(psrc[0] - 0x80)) << 8;
  2252. PLACE_DATA( pdst, src );
  2253. PLACE_DATA( pdst, src );
  2254. dwLeap += 8000;
  2255. psrc += ( dwLeap / TSSND_NATIVE_SAMPLERATE );
  2256. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2257. }
  2258. exitpt:
  2259. ;
  2260. }
  2261. VOID
  2262. Place8kHz8Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2263. {
  2264. BYTE *psrc;
  2265. INT16 *pdst;
  2266. DWORD dwLeap;
  2267. if ( NULL == pDest || NULL == pSrc )
  2268. goto exitpt;
  2269. for (psrc = pSrc,
  2270. pdst = pDest,
  2271. dwLeap = 0;
  2272. dwSize;
  2273. dwSize--)
  2274. {
  2275. INT src;
  2276. INT sum;
  2277. src = ((INT)(psrc[0] - 0x80)) << 8;
  2278. PLACE_DATA( pdst, src );
  2279. src = ((INT)(psrc[1] - 0x80)) << 8;
  2280. PLACE_DATA( pdst, src );
  2281. dwLeap += 8000;
  2282. psrc += 2 * ( dwLeap / TSSND_NATIVE_SAMPLERATE );
  2283. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2284. }
  2285. exitpt:
  2286. ;
  2287. }
  2288. VOID
  2289. Place8kHz16Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2290. {
  2291. INT16 *psrc;
  2292. INT16 *pdst;
  2293. DWORD dwLeap;
  2294. if ( NULL == pDest || NULL == pSrc )
  2295. goto exitpt;
  2296. for (psrc = pSrc,
  2297. pdst = pDest,
  2298. dwLeap = 0;
  2299. dwSize;
  2300. dwSize--)
  2301. {
  2302. INT src;
  2303. INT sum;
  2304. src = psrc[0];
  2305. PLACE_DATA( pdst, src );
  2306. PLACE_DATA( pdst, src );
  2307. dwLeap += 8000;
  2308. psrc += (dwLeap / TSSND_NATIVE_SAMPLERATE);
  2309. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2310. }
  2311. exitpt:
  2312. ;
  2313. }
  2314. VOID
  2315. Place8kHz16Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2316. {
  2317. INT16 *psrc;
  2318. INT16 *pdst;
  2319. DWORD dwLeap;
  2320. if ( NULL == pDest || NULL == pSrc )
  2321. goto exitpt;
  2322. for (psrc = pSrc,
  2323. pdst = pDest,
  2324. dwLeap = 0;
  2325. dwSize;
  2326. dwSize--)
  2327. {
  2328. INT src;
  2329. INT sum;
  2330. src = psrc[0];
  2331. PLACE_DATA( pdst, src );
  2332. src = psrc[1];
  2333. PLACE_DATA( pdst, src );
  2334. dwLeap += 8000;
  2335. psrc += 2 * (dwLeap / TSSND_NATIVE_SAMPLERATE);
  2336. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2337. }
  2338. exitpt:
  2339. ;
  2340. }
  2341. VOID
  2342. Place11kHz8Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2343. {
  2344. BYTE *psrc;
  2345. INT16 *pdst;
  2346. if (NULL == pDest || NULL == pSrc)
  2347. goto exitpt;
  2348. for (psrc = pSrc,
  2349. pdst = pDest;
  2350. dwSize;
  2351. dwSize--)
  2352. {
  2353. INT sum;
  2354. INT src;
  2355. src = ((INT)(psrc[0] - 0x80)) << 8;
  2356. PLACE_DATA(pdst, src);
  2357. PLACE_DATA(pdst, src);
  2358. psrc += (dwSize & 1); // advance on every odd step
  2359. }
  2360. exitpt:
  2361. ;
  2362. }
  2363. VOID
  2364. Place22kHz8Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2365. {
  2366. BYTE *psrc;
  2367. INT16 *pdst;
  2368. if (NULL == pDest || NULL == pSrc)
  2369. goto exitpt;
  2370. for (pdst = pDest, psrc = pSrc;
  2371. dwSize;
  2372. dwSize--)
  2373. {
  2374. INT sum;
  2375. INT src;
  2376. src = ((INT)(psrc[0] - 0x80)) << 8;
  2377. PLACE_DATA(pdst, src);
  2378. PLACE_DATA(pdst, src);
  2379. psrc ++;
  2380. }
  2381. exitpt:
  2382. ;
  2383. }
  2384. VOID
  2385. Place44kHz8Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2386. {
  2387. BYTE *psrc;
  2388. INT16 *pdst;
  2389. if (NULL == pDest || NULL == pSrc)
  2390. goto exitpt;
  2391. for (pdst = pDest, psrc = pSrc;
  2392. dwSize;
  2393. dwSize--)
  2394. {
  2395. INT sum;
  2396. INT src;
  2397. src = (((INT)(psrc[0] + psrc[1] - 2 * 0x80)) / 2) << 8;
  2398. PLACE_DATA(pdst, src);
  2399. PLACE_DATA(pdst, src);
  2400. psrc += 2;
  2401. }
  2402. exitpt:
  2403. ;
  2404. }
  2405. VOID
  2406. Place11kHz16Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2407. {
  2408. INT16 *psrc;
  2409. INT16 *pdst;
  2410. if (NULL == pDest || NULL == pSrc)
  2411. goto exitpt;
  2412. for (pdst = pDest, psrc = pSrc;
  2413. dwSize;
  2414. dwSize --)
  2415. {
  2416. INT sum;
  2417. INT src;
  2418. src = psrc[0];
  2419. PLACE_DATA(pdst, src);
  2420. PLACE_DATA(pdst, src);
  2421. psrc += (dwSize & 1); // advance on every odd step
  2422. }
  2423. exitpt:
  2424. ;
  2425. }
  2426. VOID
  2427. Place22kHz16Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2428. {
  2429. INT16 *pdst;
  2430. INT16 *psrc;
  2431. if (NULL == pDest || NULL == pSrc)
  2432. goto exitpt;
  2433. for (pdst = pDest, psrc = pSrc;
  2434. dwSize;
  2435. dwSize--)
  2436. {
  2437. INT sum;
  2438. INT src;
  2439. src = psrc[0];
  2440. PLACE_DATA(pdst, src);
  2441. PLACE_DATA(pdst, src);
  2442. psrc ++;
  2443. }
  2444. exitpt:
  2445. ;
  2446. }
  2447. VOID
  2448. Place44kHz16Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2449. {
  2450. INT16 *pdst;
  2451. INT16 *psrc;
  2452. if (NULL == pDest || NULL == pSrc)
  2453. goto exitpt;
  2454. for (pdst = pDest, psrc = pSrc;
  2455. dwSize;
  2456. dwSize--)
  2457. {
  2458. INT sum;
  2459. INT src;
  2460. src = (psrc[0] + psrc[1]) / 2;
  2461. PLACE_DATA(pdst, src);
  2462. PLACE_DATA(pdst, src);
  2463. psrc += 2;
  2464. }
  2465. exitpt:
  2466. ;
  2467. }
  2468. VOID
  2469. Place11kHz8Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2470. {
  2471. INT16 *pdst;
  2472. BYTE *psrc;
  2473. if (NULL == pDest || NULL == pSrc)
  2474. goto exitpt;
  2475. for (pdst = pDest, psrc = pSrc;
  2476. dwSize;
  2477. dwSize --)
  2478. {
  2479. INT sum;
  2480. INT srcl, srcr;
  2481. srcl = (((INT)(psrc[0] - 0x80)) << 8);
  2482. srcr = (((INT)(psrc[1] - 0x80)) << 8);
  2483. PLACE_DATA(pdst, srcl);
  2484. PLACE_DATA(pdst, srcr);
  2485. psrc += 2 * (dwSize & 1); // advance on every odd step
  2486. }
  2487. exitpt:
  2488. ;
  2489. }
  2490. VOID
  2491. Place22kHz8Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2492. {
  2493. INT16 *pdst;
  2494. BYTE *psrc;
  2495. if (NULL == pDest || NULL == pSrc)
  2496. goto exitpt;
  2497. for (pdst = pDest, psrc = pSrc;
  2498. dwSize;
  2499. dwSize--)
  2500. {
  2501. INT sum;
  2502. INT srcl, srcr;
  2503. srcl = (((INT)(psrc[0] - 0x80)) << 8);
  2504. srcr = (((INT)(psrc[1] - 0x80)) << 8);
  2505. PLACE_DATA(pdst, srcl);
  2506. PLACE_DATA(pdst, srcr);
  2507. psrc += 2;
  2508. }
  2509. exitpt:
  2510. ;
  2511. }
  2512. VOID
  2513. Place44kHz8Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2514. {
  2515. INT16 *pdst;
  2516. BYTE *psrc;
  2517. if (NULL == pDest || NULL == pSrc)
  2518. goto exitpt;
  2519. for (pdst = pDest, psrc = pSrc;
  2520. dwSize;
  2521. dwSize--)
  2522. {
  2523. INT sum;
  2524. INT srcl, srcr;
  2525. srcl = (((INT)(psrc[0] + psrc[2] - 2 * 0x80) / 2) << 8);
  2526. srcr = (((INT)(psrc[1] + psrc[3] - 2 * 0x80) / 2) << 8);
  2527. PLACE_DATA(pdst, srcl);
  2528. PLACE_DATA(pdst, srcr);
  2529. psrc += 4;
  2530. }
  2531. exitpt:
  2532. ;
  2533. }
  2534. VOID
  2535. Place11kHz16Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2536. {
  2537. INT16 *pdst;
  2538. INT16 *psrc;
  2539. if (NULL == pDest || NULL == pSrc)
  2540. goto exitpt;
  2541. for (pdst = pDest, psrc = pSrc;
  2542. dwSize;
  2543. dwSize --)
  2544. {
  2545. INT sum;
  2546. INT srcl, srcr;
  2547. srcl = (INT)psrc[0];
  2548. srcr = (INT)psrc[1];
  2549. PLACE_DATA(pdst, srcl);
  2550. PLACE_DATA(pdst, srcr);
  2551. psrc += 2 * (dwSize & 1); // advance on every odd step
  2552. }
  2553. exitpt:
  2554. ;
  2555. }
  2556. VOID
  2557. Place22kHz16Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2558. {
  2559. INT16 *pdst;
  2560. INT16 *psrc;
  2561. if (NULL == pDest || NULL == pSrc)
  2562. goto exitpt;
  2563. for (pdst = pDest, psrc = pSrc;
  2564. dwSize;
  2565. dwSize--)
  2566. {
  2567. INT sum;
  2568. INT srcl, srcr;
  2569. srcl = (INT)psrc[0];
  2570. srcr = (INT)psrc[1];
  2571. PLACE_DATA(pdst, srcl);
  2572. PLACE_DATA(pdst, srcr);
  2573. psrc += 2;
  2574. }
  2575. exitpt:
  2576. ;
  2577. }
  2578. VOID
  2579. Place44kHz16Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2580. {
  2581. INT16 *pdst;
  2582. INT16 *psrc;
  2583. if (NULL == pDest || NULL == pSrc)
  2584. goto exitpt;
  2585. for (pdst = pDest, psrc = pSrc;
  2586. dwSize;
  2587. dwSize--)
  2588. {
  2589. INT sum;
  2590. INT srcl, srcr;
  2591. srcl = (INT)(psrc[0] + psrc[2]) / 2;
  2592. srcr = (INT)(psrc[1] + psrc[3]) / 2;
  2593. PLACE_DATA(pdst, srcl);
  2594. PLACE_DATA(pdst, srcr);
  2595. psrc += 4;
  2596. }
  2597. exitpt:
  2598. ;
  2599. }
  2600. VOID
  2601. Place12kHz8Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2602. {
  2603. BYTE *psrc;
  2604. INT16 *pdst;
  2605. DWORD dwLeap;
  2606. if ( NULL == pDest || NULL == pSrc )
  2607. goto exitpt;
  2608. for (psrc = pSrc,
  2609. pdst = pDest,
  2610. dwLeap = 0;
  2611. dwSize;
  2612. dwSize--)
  2613. {
  2614. INT src;
  2615. INT sum;
  2616. src = ((INT)(psrc[0] - 0x80)) << 8;
  2617. PLACE_DATA( pdst, src );
  2618. PLACE_DATA( pdst, src );
  2619. dwLeap += 12000;
  2620. psrc += ( dwLeap / TSSND_NATIVE_SAMPLERATE );
  2621. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2622. }
  2623. exitpt:
  2624. ;
  2625. }
  2626. VOID
  2627. Place12kHz8Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2628. {
  2629. BYTE *psrc;
  2630. INT16 *pdst;
  2631. DWORD dwLeap;
  2632. if ( NULL == pDest || NULL == pSrc )
  2633. goto exitpt;
  2634. for (psrc = pSrc,
  2635. pdst = pDest,
  2636. dwLeap = 0;
  2637. dwSize;
  2638. dwSize--)
  2639. {
  2640. INT src;
  2641. INT sum;
  2642. src = ((INT)(psrc[0] - 0x80)) << 8;
  2643. PLACE_DATA( pdst, src );
  2644. src = ((INT)(psrc[1] - 0x80)) << 8;
  2645. PLACE_DATA( pdst, src );
  2646. dwLeap += 12000;
  2647. psrc += 2 * ( dwLeap / TSSND_NATIVE_SAMPLERATE );
  2648. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2649. }
  2650. exitpt:
  2651. ;
  2652. }
  2653. VOID
  2654. Place12kHz16Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2655. {
  2656. INT16 *psrc;
  2657. INT16 *pdst;
  2658. DWORD dwLeap;
  2659. if ( NULL == pDest || NULL == pSrc )
  2660. goto exitpt;
  2661. for (psrc = pSrc,
  2662. pdst = pDest,
  2663. dwLeap = 0;
  2664. dwSize;
  2665. dwSize--)
  2666. {
  2667. INT src;
  2668. INT sum;
  2669. src = psrc[0];
  2670. PLACE_DATA( pdst, src );
  2671. PLACE_DATA( pdst, src );
  2672. dwLeap += 12000;
  2673. psrc += (dwLeap / TSSND_NATIVE_SAMPLERATE);
  2674. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2675. }
  2676. exitpt:
  2677. ;
  2678. }
  2679. VOID
  2680. Place12kHz16Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2681. {
  2682. INT16 *psrc;
  2683. INT16 *pdst;
  2684. DWORD dwLeap;
  2685. if ( NULL == pDest || NULL == pSrc )
  2686. goto exitpt;
  2687. for (psrc = pSrc,
  2688. pdst = pDest,
  2689. dwLeap = 0;
  2690. dwSize;
  2691. dwSize--)
  2692. {
  2693. INT src;
  2694. INT sum;
  2695. src = psrc[0];
  2696. PLACE_DATA( pdst, src );
  2697. src = psrc[1];
  2698. PLACE_DATA( pdst, src );
  2699. dwLeap += 12000;
  2700. psrc += 2 * (dwLeap / TSSND_NATIVE_SAMPLERATE);
  2701. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2702. }
  2703. exitpt:
  2704. ;
  2705. }
  2706. VOID
  2707. Place16kHz8Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2708. {
  2709. BYTE *psrc;
  2710. INT16 *pdst;
  2711. DWORD dwLeap;
  2712. if ( NULL == pDest || NULL == pSrc )
  2713. goto exitpt;
  2714. for (psrc = pSrc,
  2715. pdst = pDest,
  2716. dwLeap = 0;
  2717. dwSize;
  2718. dwSize--)
  2719. {
  2720. INT src;
  2721. INT sum;
  2722. src = ((INT)(psrc[0] - 0x80)) << 8;
  2723. PLACE_DATA( pdst, src );
  2724. PLACE_DATA( pdst, src );
  2725. dwLeap += 16000;
  2726. psrc += ( dwLeap / TSSND_NATIVE_SAMPLERATE );
  2727. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2728. }
  2729. exitpt:
  2730. ;
  2731. }
  2732. VOID
  2733. Place16kHz8Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2734. {
  2735. BYTE *psrc;
  2736. INT16 *pdst;
  2737. DWORD dwLeap;
  2738. if ( NULL == pDest || NULL == pSrc )
  2739. goto exitpt;
  2740. for (psrc = pSrc,
  2741. pdst = pDest,
  2742. dwLeap = 0;
  2743. dwSize;
  2744. dwSize--)
  2745. {
  2746. INT src;
  2747. INT sum;
  2748. src = ((INT)(psrc[0] - 0x80)) << 8;
  2749. PLACE_DATA( pdst, src );
  2750. src = ((INT)(psrc[1] - 0x80)) << 8;
  2751. PLACE_DATA( pdst, src );
  2752. dwLeap += 16000;
  2753. psrc += 2 * ( dwLeap / TSSND_NATIVE_SAMPLERATE );
  2754. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2755. }
  2756. exitpt:
  2757. ;
  2758. }
  2759. VOID
  2760. Place16kHz16Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2761. {
  2762. INT16 *psrc;
  2763. INT16 *pdst;
  2764. DWORD dwLeap;
  2765. if ( NULL == pDest || NULL == pSrc )
  2766. goto exitpt;
  2767. for (psrc = pSrc,
  2768. pdst = pDest,
  2769. dwLeap = 0;
  2770. dwSize;
  2771. dwSize--)
  2772. {
  2773. INT src;
  2774. INT sum;
  2775. src = psrc[0];
  2776. PLACE_DATA( pdst, src );
  2777. PLACE_DATA( pdst, src );
  2778. dwLeap += 16000;
  2779. psrc += (dwLeap / TSSND_NATIVE_SAMPLERATE);
  2780. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2781. }
  2782. exitpt:
  2783. ;
  2784. }
  2785. VOID
  2786. Place16kHz16Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2787. {
  2788. INT16 *psrc;
  2789. INT16 *pdst;
  2790. DWORD dwLeap;
  2791. if ( NULL == pDest || NULL == pSrc )
  2792. goto exitpt;
  2793. for (psrc = pSrc,
  2794. pdst = pDest,
  2795. dwLeap = 0;
  2796. dwSize;
  2797. dwSize--)
  2798. {
  2799. INT src;
  2800. INT sum;
  2801. src = psrc[0];
  2802. PLACE_DATA( pdst, src );
  2803. src = psrc[1];
  2804. PLACE_DATA( pdst, src );
  2805. dwLeap += 16000;
  2806. psrc += 2 * (dwLeap / TSSND_NATIVE_SAMPLERATE);
  2807. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2808. }
  2809. exitpt:
  2810. ;
  2811. }
  2812. VOID
  2813. Place24kHz8Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2814. {
  2815. BYTE *psrc;
  2816. INT16 *pdst;
  2817. DWORD dwLeap;
  2818. if ( NULL == pDest || NULL == pSrc )
  2819. goto exitpt;
  2820. for (psrc = pSrc,
  2821. pdst = pDest,
  2822. dwLeap = 0;
  2823. dwSize;
  2824. dwSize--)
  2825. {
  2826. INT src;
  2827. INT sum;
  2828. src = ((INT)(psrc[0] - 0x80)) << 8;
  2829. PLACE_DATA( pdst, src );
  2830. PLACE_DATA( pdst, src );
  2831. dwLeap += 24000;
  2832. psrc += ( dwLeap / TSSND_NATIVE_SAMPLERATE );
  2833. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2834. }
  2835. exitpt:
  2836. ;
  2837. }
  2838. VOID
  2839. Place24kHz8Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2840. {
  2841. BYTE *psrc;
  2842. INT16 *pdst;
  2843. DWORD dwLeap;
  2844. if ( NULL == pDest || NULL == pSrc )
  2845. goto exitpt;
  2846. for (psrc = pSrc,
  2847. pdst = pDest,
  2848. dwLeap = 0;
  2849. dwSize;
  2850. dwSize--)
  2851. {
  2852. INT src;
  2853. INT sum;
  2854. src = ((INT)(psrc[0] - 0x80)) << 8;
  2855. PLACE_DATA( pdst, src );
  2856. src = ((INT)(psrc[1] - 0x80)) << 8;
  2857. PLACE_DATA( pdst, src );
  2858. dwLeap += 24000;
  2859. psrc += 2 * ( dwLeap / TSSND_NATIVE_SAMPLERATE );
  2860. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2861. }
  2862. exitpt:
  2863. ;
  2864. }
  2865. VOID
  2866. Place24kHz16Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2867. {
  2868. INT16 *psrc;
  2869. INT16 *pdst;
  2870. DWORD dwLeap;
  2871. if ( NULL == pDest || NULL == pSrc )
  2872. goto exitpt;
  2873. for (psrc = pSrc,
  2874. pdst = pDest,
  2875. dwLeap = 0;
  2876. dwSize;
  2877. dwSize--)
  2878. {
  2879. INT src;
  2880. INT sum;
  2881. src = psrc[0];
  2882. PLACE_DATA( pdst, src );
  2883. PLACE_DATA( pdst, src );
  2884. dwLeap += 24000;
  2885. psrc += (dwLeap / TSSND_NATIVE_SAMPLERATE);
  2886. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2887. }
  2888. exitpt:
  2889. ;
  2890. }
  2891. VOID
  2892. Place24kHz16Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2893. {
  2894. INT16 *psrc;
  2895. INT16 *pdst;
  2896. DWORD dwLeap;
  2897. if ( NULL == pDest || NULL == pSrc )
  2898. goto exitpt;
  2899. for (psrc = pSrc,
  2900. pdst = pDest,
  2901. dwLeap = 0;
  2902. dwSize;
  2903. dwSize--)
  2904. {
  2905. INT src;
  2906. INT sum;
  2907. src = psrc[0];
  2908. PLACE_DATA( pdst, src );
  2909. src = psrc[1];
  2910. PLACE_DATA( pdst, src );
  2911. dwLeap += 24000;
  2912. psrc += 2 * (dwLeap / TSSND_NATIVE_SAMPLERATE);
  2913. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2914. }
  2915. exitpt:
  2916. ;
  2917. }
  2918. VOID
  2919. Place32kHz8Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2920. {
  2921. BYTE *psrc;
  2922. INT16 *pdst;
  2923. DWORD dwLeap;
  2924. if ( NULL == pDest || NULL == pSrc )
  2925. goto exitpt;
  2926. for (psrc = pSrc,
  2927. pdst = pDest,
  2928. dwLeap = 0;
  2929. dwSize;
  2930. dwSize--)
  2931. {
  2932. INT src;
  2933. INT sum;
  2934. src = ((INT)(psrc[0] - 0x80)) << 8;
  2935. PLACE_DATA( pdst, src );
  2936. PLACE_DATA( pdst, src );
  2937. dwLeap += 32000;
  2938. psrc += ( dwLeap / TSSND_NATIVE_SAMPLERATE );
  2939. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2940. }
  2941. exitpt:
  2942. ;
  2943. }
  2944. VOID
  2945. Place32kHz8Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2946. {
  2947. BYTE *psrc;
  2948. INT16 *pdst;
  2949. DWORD dwLeap;
  2950. if ( NULL == pDest || NULL == pSrc )
  2951. goto exitpt;
  2952. for (psrc = pSrc,
  2953. pdst = pDest,
  2954. dwLeap = 0;
  2955. dwSize;
  2956. dwSize--)
  2957. {
  2958. INT src;
  2959. INT sum;
  2960. src = ((INT)(psrc[0] - 0x80)) << 8;
  2961. PLACE_DATA( pdst, src );
  2962. src = ((INT)(psrc[1] - 0x80)) << 8;
  2963. PLACE_DATA( pdst, src );
  2964. dwLeap += 32000;
  2965. psrc += 2 * ( dwLeap / TSSND_NATIVE_SAMPLERATE );
  2966. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2967. }
  2968. exitpt:
  2969. ;
  2970. }
  2971. VOID
  2972. Place32kHz16Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2973. {
  2974. INT16 *psrc;
  2975. INT16 *pdst;
  2976. DWORD dwLeap;
  2977. if ( NULL == pDest || NULL == pSrc )
  2978. goto exitpt;
  2979. for (psrc = pSrc,
  2980. pdst = pDest,
  2981. dwLeap = 0;
  2982. dwSize;
  2983. dwSize--)
  2984. {
  2985. INT src;
  2986. INT sum;
  2987. src = psrc[0];
  2988. PLACE_DATA( pdst, src );
  2989. PLACE_DATA( pdst, src );
  2990. dwLeap += 32000;
  2991. psrc += (dwLeap / TSSND_NATIVE_SAMPLERATE);
  2992. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  2993. }
  2994. exitpt:
  2995. ;
  2996. }
  2997. VOID
  2998. Place32kHz16Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  2999. {
  3000. INT16 *psrc;
  3001. INT16 *pdst;
  3002. DWORD dwLeap;
  3003. if ( NULL == pDest || NULL == pSrc )
  3004. goto exitpt;
  3005. for (psrc = pSrc,
  3006. pdst = pDest,
  3007. dwLeap = 0;
  3008. dwSize;
  3009. dwSize--)
  3010. {
  3011. INT src;
  3012. INT sum;
  3013. src = psrc[0];
  3014. PLACE_DATA( pdst, src );
  3015. src = psrc[1];
  3016. PLACE_DATA( pdst, src );
  3017. dwLeap += 32000;
  3018. psrc += 2 * (dwLeap / TSSND_NATIVE_SAMPLERATE);
  3019. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  3020. }
  3021. exitpt:
  3022. ;
  3023. }
  3024. VOID
  3025. Place48kHz8Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  3026. {
  3027. BYTE *psrc;
  3028. INT16 *pdst;
  3029. DWORD dwLeap;
  3030. if ( NULL == pDest || NULL == pSrc )
  3031. goto exitpt;
  3032. for (psrc = pSrc,
  3033. pdst = pDest,
  3034. dwLeap = 0;
  3035. dwSize;
  3036. dwSize--)
  3037. {
  3038. INT src;
  3039. INT sum;
  3040. src = ((INT)(psrc[0] - 0x80)) << 8;
  3041. PLACE_DATA( pdst, src );
  3042. PLACE_DATA( pdst, src );
  3043. dwLeap += 48000;
  3044. psrc += ( dwLeap / TSSND_NATIVE_SAMPLERATE );
  3045. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  3046. }
  3047. exitpt:
  3048. ;
  3049. }
  3050. VOID
  3051. Place48kHz8Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  3052. {
  3053. BYTE *psrc;
  3054. INT16 *pdst;
  3055. DWORD dwLeap;
  3056. if ( NULL == pDest || NULL == pSrc )
  3057. goto exitpt;
  3058. for (psrc = pSrc,
  3059. pdst = pDest,
  3060. dwLeap = 0;
  3061. dwSize;
  3062. dwSize--)
  3063. {
  3064. INT src;
  3065. INT sum;
  3066. src = ((INT)(psrc[0] - 0x80)) << 8;
  3067. PLACE_DATA( pdst, src );
  3068. src = ((INT)(psrc[1] - 0x80)) << 8;
  3069. PLACE_DATA( pdst, src );
  3070. dwLeap += 48000;
  3071. psrc += 2 * ( dwLeap / TSSND_NATIVE_SAMPLERATE );
  3072. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  3073. }
  3074. exitpt:
  3075. ;
  3076. }
  3077. VOID
  3078. Place48kHz16Mono(PVOID pDest, PVOID pSrc, DWORD dwSize)
  3079. {
  3080. INT16 *psrc;
  3081. INT16 *pdst;
  3082. DWORD dwLeap;
  3083. if ( NULL == pDest || NULL == pSrc )
  3084. goto exitpt;
  3085. for (psrc = pSrc,
  3086. pdst = pDest,
  3087. dwLeap = 0;
  3088. dwSize;
  3089. dwSize--)
  3090. {
  3091. INT src;
  3092. INT sum;
  3093. src = psrc[0];
  3094. PLACE_DATA( pdst, src );
  3095. PLACE_DATA( pdst, src );
  3096. dwLeap += 48000;
  3097. psrc += (dwLeap / TSSND_NATIVE_SAMPLERATE);
  3098. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  3099. }
  3100. exitpt:
  3101. ;
  3102. }
  3103. VOID
  3104. Place48kHz16Stereo(PVOID pDest, PVOID pSrc, DWORD dwSize)
  3105. {
  3106. INT16 *psrc;
  3107. INT16 *pdst;
  3108. DWORD dwLeap;
  3109. if ( NULL == pDest || NULL == pSrc )
  3110. goto exitpt;
  3111. for (psrc = pSrc,
  3112. pdst = pDest,
  3113. dwLeap = 0;
  3114. dwSize;
  3115. dwSize--)
  3116. {
  3117. INT src;
  3118. INT sum;
  3119. src = psrc[0];
  3120. PLACE_DATA( pdst, src );
  3121. src = psrc[1];
  3122. PLACE_DATA( pdst, src );
  3123. dwLeap += 48000;
  3124. psrc += 2 * (dwLeap / TSSND_NATIVE_SAMPLERATE);
  3125. dwLeap %= TSSND_NATIVE_SAMPLERATE;
  3126. }
  3127. exitpt:
  3128. ;
  3129. }
  3130. ////////////////////////////////////////////////////////////////////////
  3131. //
  3132. // Unsupported entries
  3133. //
  3134. ////////////////////////////////////////////////////////////////////////
  3135. DWORD
  3136. APIENTRY
  3137. modMessage(
  3138. UINT uDeviceID,
  3139. UINT uMessage,
  3140. DWORD_PTR dwUser,
  3141. DWORD_PTR dwParam1,
  3142. DWORD_PTR dwParam2
  3143. )
  3144. {
  3145. if ( MODM_GETNUMDEVS == uMessage )
  3146. return 0;
  3147. return MMSYSERR_NODRIVER;
  3148. }
  3149. DWORD
  3150. APIENTRY
  3151. midMessage(
  3152. UINT uDeviceID,
  3153. UINT uMessage,
  3154. DWORD_PTR dwUser,
  3155. DWORD_PTR dwParam1,
  3156. DWORD_PTR dwParam2
  3157. )
  3158. {
  3159. if ( MIDM_GETNUMDEVS == uMessage )
  3160. return 0;
  3161. return MMSYSERR_NODRIVER;
  3162. }
  3163. DWORD
  3164. APIENTRY
  3165. auxMessage(
  3166. UINT uDeviceID,
  3167. UINT uMessage,
  3168. DWORD_PTR dwUser,
  3169. DWORD_PTR dwParam1,
  3170. DWORD_PTR dwParam2
  3171. )
  3172. {
  3173. if ( AUXDM_GETNUMDEVS == uMessage )
  3174. return 0;
  3175. return MMSYSERR_NODRIVER;
  3176. }
  3177. ////////////////////////////////////////////////////////////////////////
  3178. //
  3179. // Mixer implementation
  3180. //
  3181. DWORD
  3182. RDPMixerOpen(
  3183. PMIXERCTX *ppMixer,
  3184. PMIXEROPENDESC pMixerDesc,
  3185. DWORD_PTR dwFlags
  3186. )
  3187. {
  3188. DWORD rv = MMSYSERR_ERROR;
  3189. PMIXERCTX pMix = NULL;
  3190. ASSERT( CALLBACK_FUNCTION == dwFlags );
  3191. pMix = &g_Mixer;
  3192. rv = MMSYSERR_NOERROR;
  3193. return rv;
  3194. }
  3195. DWORD
  3196. RDPMixerClose(
  3197. PMIXERCTX pMixer
  3198. )
  3199. {
  3200. return MMSYSERR_NOERROR;
  3201. }
  3202. DWORD
  3203. RDPMixerGetDevCaps(
  3204. PMIXERCTX pMixer,
  3205. PMIXERCAPS pCaps,
  3206. DWORD_PTR dwCapsSize
  3207. )
  3208. {
  3209. DWORD rv = MMSYSERR_ERROR;
  3210. // Parameters check
  3211. //
  3212. if (dwCapsSize < sizeof(*pCaps))
  3213. {
  3214. TRC(ERR, "RDPMixerGetDevCaps: invalid size of MIXERCAPS, expect %d, received %d\n",
  3215. sizeof(*pCaps), dwCapsSize);
  3216. rv = MMSYSERR_INVALPARAM;
  3217. goto exitpt;
  3218. }
  3219. pCaps->wMid = MM_MICROSOFT;
  3220. pCaps->wPid = MM_MSFT_GENERIC_WAVEOUT;
  3221. pCaps->vDriverVersion = TSSND_DRIVER_VERSION;
  3222. LoadString( g_hDllInst,
  3223. IDS_DRIVER_NAME,
  3224. pCaps->szPname,
  3225. sizeof( pCaps->szPname ) / sizeof( pCaps->szPname[0] ));
  3226. pCaps->fdwSupport = 0; // no flags defined
  3227. pCaps->cDestinations = 1;
  3228. rv = MMSYSERR_NOERROR;
  3229. exitpt:
  3230. return rv;
  3231. }
  3232. DWORD
  3233. _FillMixerLineInfo( PMIXERLINE pLine )
  3234. {
  3235. DWORD dw;
  3236. pLine->dwDestination = 0; // just one destination
  3237. pLine->dwLineID = 0; // just one line
  3238. pLine->fdwLine = MIXERLINE_LINEF_ACTIVE;
  3239. pLine->dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
  3240. pLine->cChannels = 2;
  3241. pLine->cConnections = 0;
  3242. pLine->cControls = 2;
  3243. LoadString( g_hDllInst,
  3244. IDS_VOLUME_NAME,
  3245. pLine->szShortName,
  3246. RTL_NUMBER_OF( pLine->szShortName ));
  3247. LoadString( g_hDllInst,
  3248. IDS_VOLUME_NAME,
  3249. pLine->szName,
  3250. RTL_NUMBER_OF( pLine->szName ));
  3251. pLine->Target.dwType = MIXERLINE_TARGETTYPE_WAVEOUT;
  3252. pLine->Target.dwDeviceID = WAVE_MAPPER;
  3253. pLine->Target.wMid = MM_MICROSOFT;
  3254. pLine->Target.wPid = MM_MSFT_GENERIC_WAVEOUT;
  3255. pLine->Target.vDriverVersion = TSSND_DRIVER_VERSION;
  3256. LoadString( g_hDllInst,
  3257. IDS_DRIVER_NAME,
  3258. pLine->Target.szPname,
  3259. RTL_NUMBER_OF( pLine->Target.szPname ));
  3260. return MMSYSERR_NOERROR;
  3261. }
  3262. DWORD
  3263. RDPMixerGetLineInfo(
  3264. PMIXERCTX pMixer,
  3265. PMIXERLINE pLine,
  3266. DWORD_PTR dwFlags
  3267. )
  3268. {
  3269. DWORD rv = MMSYSERR_ERROR;
  3270. if ( pLine->cbStruct < sizeof( *pLine ))
  3271. {
  3272. TRC(ERR, "MixerGetLineInfo: invalid lineinfo size: %d\n", pLine->cbStruct );
  3273. rv = MMSYSERR_INVALPARAM;
  3274. goto exitpt;
  3275. }
  3276. switch( dwFlags & MIXER_GETLINEINFOF_QUERYMASK )
  3277. {
  3278. case MIXER_GETLINEINFOF_DESTINATION:
  3279. TRC( ALV, "MixerGetLineInfo: MIXER_GETLINEINFOF_DESTINATION\n" );
  3280. if ( 0 != pLine->dwDestination )
  3281. {
  3282. //
  3283. // there's just one destination
  3284. //
  3285. TRC( ERR, "MixerGetLineInfo: invalid destination: %d\n", pLine->dwDestination );
  3286. rv = MMSYSERR_INVALPARAM;
  3287. goto exitpt;
  3288. }
  3289. rv = _FillMixerLineInfo( pLine );
  3290. break;
  3291. case MIXER_GETLINEINFOF_TARGETTYPE:
  3292. TRC( ALV, "MixerGetLineInfo: MIXER_GETLINEINFOF_TARGETTYPE\n" );
  3293. if ( MIXERLINE_TARGETTYPE_WAVEOUT != pLine->Target.dwType )
  3294. {
  3295. TRC( ERR, "MIXER_GETLINEINFOF_TARGETTYPE for unsupported type=0x%x\n", pLine->Target.dwType );
  3296. rv = MMSYSERR_NOTSUPPORTED;
  3297. goto exitpt;
  3298. }
  3299. rv = _FillMixerLineInfo( pLine );
  3300. break;
  3301. case MIXER_GETLINEINFOF_COMPONENTTYPE:
  3302. TRC( ALV, "MixerGetLineInfo: MIXER_GETLINEINFOF_COMPONENTTYPE\n" );
  3303. if ( MIXERLINE_COMPONENTTYPE_DST_SPEAKERS != pLine->dwComponentType )
  3304. {
  3305. TRC( ERR, "MIXER_GETLINEINFOF_COMPONENTTYPE for unsupported type=0x%x\n", pLine->dwComponentType );
  3306. rv = MMSYSERR_NOTSUPPORTED;
  3307. goto exitpt;
  3308. }
  3309. rv = _FillMixerLineInfo( pLine );
  3310. break;
  3311. case MIXER_GETLINEINFOF_LINEID:
  3312. TRC( ALV, "MIXER_GETLINEINFOF_LINEID\n" );
  3313. if ( 0 != pLine->dwLineID )
  3314. {
  3315. TRC( ERR, "MIXER_GETLINEINFOF_LINEID for invalid line ID: %d\n", pLine->dwLineID );
  3316. rv = MIXERR_INVALLINE;
  3317. goto exitpt;
  3318. }
  3319. rv = _FillMixerLineInfo( pLine );
  3320. break;
  3321. }
  3322. exitpt:
  3323. return rv;
  3324. }
  3325. DWORD
  3326. _FillLineControl(
  3327. PMIXERLINECONTROLS pc,
  3328. DWORD dwControlId
  3329. )
  3330. {
  3331. DWORD rv = MMSYSERR_ERROR;
  3332. PMIXERCONTROL pmc;
  3333. DWORD dwMax = (DWORD)-1;
  3334. if ( pc->cbmxctrl < sizeof( *(pc->pamxctrl )))
  3335. {
  3336. TRC( ERR, "_FillLineControl: no enough space\n" );
  3337. rv = MMSYSERR_INVALPARAM;
  3338. goto exitpt;
  3339. }
  3340. pc->dwLineID = 0;
  3341. pmc = pc->pamxctrl;
  3342. pmc->cbStruct = sizeof( *pmc );
  3343. pmc->dwControlID = dwControlId;
  3344. switch( dwControlId )
  3345. {
  3346. // case RDP_MXDID_MIXER: pmc->dwControlType = MIXERCONTROL_CONTROLTYPE_MIXER; break;
  3347. case RDP_MXDID_VOLUME: pmc->dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; dwMax = (WORD)-1; break;
  3348. case RDP_MXDID_MUTE: pmc->dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE; dwMax = 1; break;
  3349. }
  3350. pmc->fdwControl = 0;
  3351. pmc->cMultipleItems = 0;
  3352. LoadString( g_hDllInst,
  3353. IDS_VOLUME_NAME,
  3354. pmc->szShortName,
  3355. RTL_NUMBER_OF( pmc->szShortName ));
  3356. LoadString( g_hDllInst,
  3357. IDS_VOLUME_NAME,
  3358. pmc->szName,
  3359. RTL_NUMBER_OF( pmc->szName ));
  3360. pmc->Bounds.dwMinimum = 0;
  3361. pmc->Bounds.dwMaximum = dwMax;
  3362. pmc->Metrics.cSteps = 1;
  3363. rv = MMSYSERR_NOERROR;
  3364. exitpt:
  3365. return rv;
  3366. }
  3367. DWORD
  3368. _FillLineControlAll(
  3369. PMIXERLINECONTROLS pc
  3370. )
  3371. {
  3372. DWORD rv = MMSYSERR_ERROR;
  3373. PMIXERCONTROL pmc;
  3374. PMIXERCONTROL pnextmc;
  3375. if ( pc->cbmxctrl < sizeof( *(pc->pamxctrl )))
  3376. {
  3377. TRC( ERR, "_FillLineControl: no enough space\n" );
  3378. rv = MMSYSERR_INVALPARAM;
  3379. goto exitpt;
  3380. }
  3381. if ( 2 != pc->cControls )
  3382. {
  3383. TRC( ERR, "_FillLineControl: invalid number of lines\n" );
  3384. rv = MMSYSERR_INVALPARAM;
  3385. goto exitpt;
  3386. }
  3387. pc->dwLineID = 0;
  3388. pmc = pc->pamxctrl;
  3389. pmc->cbStruct = sizeof( *pmc );
  3390. pmc->dwControlID = RDP_MXDID_MUTE;
  3391. pmc->dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
  3392. pmc->fdwControl = 0;
  3393. pmc->cMultipleItems = 0;
  3394. LoadString( g_hDllInst,
  3395. IDS_VOLUME_NAME,
  3396. pmc->szShortName,
  3397. RTL_NUMBER_OF( pmc->szShortName ));
  3398. LoadString( g_hDllInst,
  3399. IDS_VOLUME_NAME,
  3400. pmc->szName,
  3401. RTL_NUMBER_OF( pmc->szName ));
  3402. pmc->Bounds.dwMinimum = 0;
  3403. pmc->Bounds.dwMaximum = 1;
  3404. pmc->Metrics.cSteps = 1;
  3405. //
  3406. // copy the volume struct
  3407. //
  3408. pnextmc = (PMIXERCONTROL)(((PBYTE)pmc) + pc->cbmxctrl);
  3409. RtlCopyMemory( pnextmc, pmc, sizeof( *pmc ));
  3410. pmc = pnextmc;
  3411. pmc->dwControlID = RDP_MXDID_VOLUME;
  3412. pmc->dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
  3413. pmc->Bounds.dwMinimum = 0;
  3414. pmc->Bounds.dwMaximum = (WORD)(-1);
  3415. rv = MMSYSERR_NOERROR;
  3416. exitpt:
  3417. return rv;
  3418. }
  3419. DWORD
  3420. RDPMixerGetLineControls(
  3421. PMIXERCTX pMixer,
  3422. PMIXERLINECONTROLS pControls,
  3423. DWORD_PTR fdwControls
  3424. )
  3425. {
  3426. DWORD rv = MMSYSERR_ERROR;
  3427. DWORD dwControlId;
  3428. if ( pControls->cbStruct < sizeof( *pControls ))
  3429. {
  3430. TRC(ERR, "MixerGetLineControls: invalid linecontrols size: %d\n", pControls->cbStruct );
  3431. rv = MMSYSERR_INVALPARAM;
  3432. goto exitpt;
  3433. }
  3434. switch( fdwControls )
  3435. {
  3436. case MIXER_GETLINECONTROLSF_ONEBYTYPE:
  3437. TRC( ALV, "MixerGetLineControls: MIXER_GETLINECONTROLSF_ONEBYTYPE\n",
  3438. pControls->dwControlType );
  3439. if ( 0 != pControls->dwLineID )
  3440. {
  3441. rv = MIXERR_INVALLINE;
  3442. goto exitpt;
  3443. }
  3444. switch( pControls->dwControlType )
  3445. {
  3446. // case MIXERCONTROL_CONTROLTYPE_MIXER: dwControlId = RDP_MXDID_MIXER; break;
  3447. case MIXERCONTROL_CONTROLTYPE_VOLUME: dwControlId = RDP_MXDID_VOLUME; break;
  3448. case MIXERCONTROL_CONTROLTYPE_MUTE: dwControlId = RDP_MXDID_MUTE; break;
  3449. default:
  3450. rv = MMSYSERR_NOTSUPPORTED;
  3451. goto exitpt;
  3452. }
  3453. rv = _FillLineControl( pControls, dwControlId );
  3454. break;
  3455. case MIXER_GETLINECONTROLSF_ONEBYID:
  3456. TRC( ALV, "MixerGetLineControls: MIXER_GETLINECONTROLSF_ONEBYID\n" );
  3457. if ( RDP_MXDID_LAST <= pControls->dwControlID )
  3458. {
  3459. TRC( ERR, "MixerGetLineControls: invalid line id: %d\n", pControls->dwControlID );
  3460. rv = MIXERR_INVALCONTROL;
  3461. goto exitpt;
  3462. }
  3463. rv = _FillLineControl( pControls, pControls->dwControlID );
  3464. break;
  3465. case MIXER_GETLINECONTROLSF_ALL:
  3466. TRC( ALV, "MixerGetLineControls: MIXER_GETLINECONTROLSF_ALL\n" );
  3467. if ( 0 != pControls->dwLineID )
  3468. {
  3469. rv = MIXERR_INVALLINE;
  3470. goto exitpt;
  3471. }
  3472. if ( 2 > pControls->cControls )
  3473. {
  3474. TRC( ERR, "MixerGetLineControls: invalid cControls=%d\n", pControls->cControls );
  3475. rv = MIXERR_INVALCONTROL;
  3476. goto exitpt;
  3477. }
  3478. rv = _FillLineControlAll( pControls );
  3479. break;
  3480. }
  3481. exitpt:
  3482. return rv;
  3483. }
  3484. DWORD
  3485. RDPMixerGetSetControlDetails(
  3486. PMIXERCTX pMixer,
  3487. PMIXERCONTROLDETAILS pDetails,
  3488. DWORD_PTR fdwDetails,
  3489. BOOL bGet
  3490. )
  3491. {
  3492. DWORD rv = MMSYSERR_ERROR;
  3493. DWORD fdw;
  3494. if ( pDetails->cbStruct < sizeof( *pDetails ))
  3495. {
  3496. TRC( ERR, "Mixer%sControlDetails: invalid details size\n", (bGet)?"Get":"Set" );
  3497. rv = MMSYSERR_INVALPARAM;
  3498. goto exitpt;
  3499. }
  3500. if ( 0 != pDetails->cMultipleItems &&
  3501. 1 != pDetails->cMultipleItems )
  3502. {
  3503. rv = MMSYSERR_INVALPARAM;
  3504. goto exitpt;
  3505. }
  3506. if ( RDP_MXDID_LAST <= pDetails->dwControlID )
  3507. {
  3508. TRC( ERR, "Mixer%sControlDetails: invalid control id: %d\n", (bGet)?"Get":"Set", pDetails->dwControlID );
  3509. rv = MIXERR_INVALCONTROL;
  3510. goto exitpt;
  3511. }
  3512. fdw = PtrToLong( (PVOID)(MIXER_GETCONTROLDETAILSF_QUERYMASK & fdwDetails));
  3513. if ( MIXER_GETCONTROLDETAILSF_VALUE == fdw )
  3514. {
  3515. TRC( ALV, "Mixer%sControlDetails: read VALUE, cbDetail=%d, cChannels=%d, controlId=%d\n",
  3516. (bGet)?"Get":"Set",
  3517. pDetails->cbDetails, pDetails->cChannels,
  3518. pDetails->dwControlID
  3519. );
  3520. ASSERT( pDetails->cbDetails == sizeof( DWORD ));
  3521. if ( pDetails->cbDetails == sizeof( DWORD ))
  3522. {
  3523. DWORD dwVal = *(DWORD *)pDetails->paDetails;
  3524. if ( !bGet )
  3525. {
  3526. if ( 2 != pDetails->cChannels &&
  3527. 1 != pDetails->cChannels )
  3528. {
  3529. TRC( ERR, "Unexpected # channels\n" );
  3530. rv = MMSYSERR_INVALPARAM;
  3531. goto exitpt;
  3532. }
  3533. //
  3534. // the mute has different control id
  3535. //
  3536. if ( RDP_MXDID_MUTE == pDetails->dwControlID )
  3537. {
  3538. rv = waveSetMute( NULL, (dwVal != 0) );
  3539. } else {
  3540. //
  3541. // this will set the volume
  3542. // there should be 2 channels for stereo
  3543. //
  3544. if ( pDetails->cChannels == 2 )
  3545. {
  3546. DWORD dwChanLeft, dwChanRight;
  3547. dwChanRight = ((DWORD *)pDetails->paDetails)[0];
  3548. dwChanLeft = ((DWORD *)pDetails->paDetails)[1];
  3549. dwVal = ((dwChanLeft & 0xffff) << 16) | ( dwChanRight & 0xffff );
  3550. } else {
  3551. dwVal = ((DWORD *)pDetails->paDetails)[0];
  3552. dwVal |= dwVal << 16;
  3553. }
  3554. rv = waveSetVolume( NULL, dwVal );
  3555. }
  3556. } else {
  3557. if ( 2 != pDetails->cChannels &&
  3558. 1 != pDetails->cChannels )
  3559. {
  3560. TRC( ERR, "Unexpected # channels\n" );
  3561. rv = MMSYSERR_INVALPARAM;
  3562. goto exitpt;
  3563. }
  3564. //
  3565. // get the new volume value
  3566. //
  3567. if ( RDP_MXDID_MUTE == pDetails->dwControlID )
  3568. {
  3569. rv = waveGetMute( NULL, &dwVal );
  3570. ((DWORD *)(pDetails->paDetails))[0] = dwVal;
  3571. if ( 2 == pDetails->cChannels )
  3572. {
  3573. ((DWORD *)(pDetails->paDetails))[1] = dwVal;
  3574. }
  3575. } else {
  3576. //
  3577. // get the volume
  3578. //
  3579. rv = waveGetVolume( NULL, &dwVal );
  3580. TRC( ALV, "GET Volume=0x%x\n", dwVal );
  3581. if ( 2 == pDetails->cChannels )
  3582. {
  3583. ((DWORD *)(pDetails->paDetails))[0] = dwVal & 0xffff; // right
  3584. ((DWORD *)(pDetails->paDetails))[1] = dwVal >> 16; // left
  3585. } else
  3586. {
  3587. // get an average
  3588. //
  3589. ((DWORD *)(pDetails->paDetails))[0] =
  3590. (( dwVal & 0xffff ) + ( dwVal >> 16 )) / 2;
  3591. }
  3592. }
  3593. }
  3594. }
  3595. } else {
  3596. TRC( ERR, "Mixer%sControlDetails fdwDetails=0x%x\n",
  3597. (bGet)?"Get":"Set", fdwDetails );
  3598. }
  3599. exitpt:
  3600. return rv;
  3601. }
  3602. DWORD
  3603. APIENTRY
  3604. mxdMessage(
  3605. UINT uDeviceID,
  3606. UINT uMessage,
  3607. DWORD_PTR dwUser,
  3608. DWORD_PTR dwParam1,
  3609. DWORD_PTR dwParam2
  3610. )
  3611. {
  3612. DWORD rv = MMSYSERR_ERROR;
  3613. PMIXERCTX pMixer = (PMIXERCTX)dwUser;
  3614. switch ( uMessage )
  3615. {
  3616. case MXDM_GETNUMDEVS:
  3617. TRC( ALV, "WXDM_GETNUMDEVS\n");
  3618. return 1;
  3619. case MXDM_GETDEVCAPS:
  3620. TRC( ALV, "MXDM_GETDEVCAPS\n" );
  3621. rv = RDPMixerGetDevCaps( pMixer, (PMIXERCAPS)dwParam1, dwParam2 );
  3622. break;
  3623. case MXDM_OPEN:
  3624. TRC( ALV, "MXDM_OPEN\n" );
  3625. rv = RDPMixerOpen( (PMIXERCTX *)dwUser,
  3626. (PMIXEROPENDESC)dwParam1,
  3627. dwParam2 );
  3628. break;
  3629. case MXDM_CLOSE:
  3630. TRC( ALV, "MXDM_CLOSE\n" );
  3631. rv = RDPMixerClose( pMixer );
  3632. break;
  3633. case MXDM_GETLINEINFO:
  3634. TRC( ALV, "MXDM_GETLINEINFO\n" );
  3635. rv = RDPMixerGetLineInfo( pMixer, (PMIXERLINE)dwParam1, dwParam2 );
  3636. break;
  3637. case MXDM_GETLINECONTROLS:
  3638. TRC( ALV, "MXDM_GETLINECONTROLS\n" );
  3639. rv = RDPMixerGetLineControls( pMixer, (PMIXERLINECONTROLS)dwParam1, dwParam2 );
  3640. break;
  3641. case MXDM_GETCONTROLDETAILS:
  3642. TRC( ALV, "MXDM_GETCONTROLDETAILS\n" );
  3643. rv = RDPMixerGetSetControlDetails( pMixer, (PMIXERCONTROLDETAILS)dwParam1, dwParam2, TRUE );
  3644. break;
  3645. case MXDM_SETCONTROLDETAILS:
  3646. TRC( ALV, "MXDM_SETCONTROLDETAILS\n" );
  3647. rv = RDPMixerGetSetControlDetails( pMixer, (PMIXERCONTROLDETAILS)dwParam1, dwParam2, FALSE );
  3648. break;
  3649. default:
  3650. TRC( ALV, "Message id=%d\n", uMessage );
  3651. }
  3652. return rv;
  3653. }