Windows NT 4.0 source code leak
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.

3702 lines
104 KiB

4 years ago
  1. //--------------------------------------------------------------------------;
  2. //
  3. // File: DsBuffHW.c
  4. //
  5. // Copyright (c) 1995 Microsoft Corporation. All Rights Reserved.
  6. //
  7. // Abstract:
  8. //
  9. //
  10. // Contents:
  11. // IDSHWBufferQueryInterface()
  12. // IDSHWBufferAddRef()
  13. // IDSHWBufferRelease()
  14. // IDSHWBufferGetCaps()
  15. // IDSHWBufferGetCurrentPosition()
  16. // IDSHWBufferGetFormat()
  17. // IDSHWBufferGetVolume()
  18. // IDSHWBufferGetPan()
  19. // IDSHWBufferGetFrequency()
  20. // IDSHWBufferGetStatus()
  21. // IDSHWBufferInitialize()
  22. // IDSHWBufferLock()
  23. // IDSHWBufferPlay()
  24. // IDSHWBufferSetCurrentPosition()
  25. // IDSHWBufferSetFormat()
  26. // IDSHWBufferSetVolume()
  27. // IDSHWBufferSetPan()
  28. // IDSHWBufferSetFrequency()
  29. // IDSHWBufferStop()
  30. // IDSHWBufferRestore()
  31. // IDSHWBufferUnlock()
  32. // IDSHWBufferWaveBlt()
  33. // DSBufferCreateTable()
  34. // DSBufferActivate()
  35. // DSBufferDeactivate()
  36. //
  37. // History:
  38. //
  39. //--------------------------------------------------------------------------;
  40. #include "dsoundpr.h"
  41. #include "grace.h"
  42. __inline BOOL CircularBufferRegionsIntersect
  43. (
  44. int cbBuffer,
  45. int iStart1,
  46. int iLen1,
  47. int iStart2,
  48. int iLen2
  49. )
  50. {
  51. int iEnd1;
  52. int iEnd2;
  53. ASSERT(iStart1 >= 0);
  54. ASSERT(iStart2 >= 0);
  55. ASSERT(iStart1 + iLen1 >= 0);
  56. ASSERT(iStart2 + iLen2 >= 0);
  57. iEnd1 = iStart1 + iLen1;
  58. iEnd2 = iStart2 + iLen2;
  59. if ((0 == iLen1) || (0 == iLen2)) return FALSE;
  60. if (iStart1 == iStart2) return TRUE;
  61. // Handle r1 does not wrap
  62. if ((iStart1 < iStart2) && (iEnd1 > iStart2)) return TRUE;
  63. // Handle r2 does not wrap
  64. if ((iStart2 < iStart1) && (iEnd2 > iStart1)) return TRUE;
  65. // Handle r1 wraps
  66. if (iEnd1 >= cbBuffer) {
  67. iEnd1 -= cbBuffer;
  68. ASSERT(iEnd1 < cbBuffer);
  69. if (iEnd1 > iStart2) return TRUE;
  70. }
  71. // Handle r2 wraps
  72. if (iEnd2 >= cbBuffer) {
  73. iEnd2 -= cbBuffer;
  74. ASSERT(iEnd2 < cbBuffer);
  75. if (iEnd2 > iStart1) return TRUE;
  76. }
  77. return FALSE;
  78. }
  79. HRESULT FAR PASCAL IDSHWBufferQueryInterface
  80. (
  81. LPDIRECTSOUNDBUFFER pidsb,
  82. REFIID riid,
  83. LPVOID FAR* ppvObj
  84. )
  85. {
  86. LPDSOUND pds;
  87. LPDSBUFFER pdsb;
  88. LPDSBUFFEREXTERNAL pdsbe;
  89. DPF(4,"Entering Buffer Query Interface method");
  90. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  91. RPF("IDirectSoundBuffer::QueryInterface - Invalid Object or ref count");
  92. return DSERR_INVALIDPARAM;
  93. }
  94. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  95. pdsb = pdsbe->pdsb;
  96. pds = pdsb->pds;
  97. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  98. RPF("IDirectSoundBuffer::QueryInterface - Invalid Object or ref count");
  99. return DSERR_INVALIDPARAM;
  100. }
  101. ASSERT( DSBUFFSIG == pdsb->dwSig );
  102. if( riid == NULL ) {
  103. RPF("IDirectSoundBuffer::QueryInterface - NULL riid");
  104. return DSERR_INVALIDPARAM;
  105. }
  106. if( ppvObj == NULL ) {
  107. RPF("IDirectSoundBuffer::QueryInterface - NULL ppvObj");
  108. return DSERR_INVALIDPARAM;
  109. }
  110. if( pdsbe->dwPID == DWBUFFER_INTERNAL_PID ) {
  111. DPF(0,"Query Internface on INTERNAL external obj");
  112. DPF(0,"**************ERROR****************");
  113. return DSERR_INVALIDPARAM;
  114. }
  115. ENTER_DLL_CSECT();
  116. *ppvObj = NULL;
  117. if( IsEqualGUID(riid,&IID_IDirectSoundBuffer) ||
  118. IsEqualGUID(riid,&IID_IUnknown) ) {
  119. *ppvObj = pdsbe;
  120. pidsb->lpVtbl->AddRef( pidsb );
  121. LEAVE_DLL_CSECT();
  122. return DS_OK;
  123. } else {
  124. LEAVE_DLL_CSECT();
  125. return DSERR_NOINTERFACE;
  126. }
  127. LEAVE_DLL_CSECT();
  128. return DSERR_GENERIC;
  129. } // IDSHWBufferQueryInterface()
  130. ULONG FAR PASCAL IDSHWBufferAddRef
  131. (
  132. LPDIRECTSOUNDBUFFER pidsb
  133. )
  134. {
  135. LPDSOUND pds;
  136. LPDSBUFFER pdsb;
  137. LPDSBUFFEREXTERNAL pdsbe;
  138. DPF(4,"Entering Buffer add ref method");
  139. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  140. RPF("IDirectSoundBuffer::AddRef - Invalid Object or ref count");
  141. return 0;
  142. }
  143. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  144. pdsb = pdsbe->pdsb;
  145. pds = pdsb->pds;
  146. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  147. RPF("IDirectSoundBuffer::AddRef - Invalid Object or ref count");
  148. return 0;
  149. }
  150. ASSERT( DSBUFFSIG == pdsb->dwSig );
  151. if( pdsbe->dwPID == DWBUFFER_INTERNAL_PID ) {
  152. DPF(0,"AddRef on INTERNAL external obj");
  153. DPF(0,"**************ERROR****************");
  154. return 0;
  155. }
  156. ENTER_DLL_CSECT();
  157. pdsb->uRefCount++;
  158. pdsbe->uRefCount++;
  159. if( DSBIncAccess( pdsb ) != DS_OK ) {
  160. DPF(0,"Increment access error");
  161. LEAVE_DLL_CSECT();
  162. return 0;
  163. }
  164. DPF(4,"Exiting buffer add ref method");
  165. LEAVE_DLL_CSECT();
  166. return (pdsbe->uRefCount);
  167. } // IDSHWBufferAddRef()
  168. ULONG FAR PASCAL IDSHWBufferRelease
  169. (
  170. LPDIRECTSOUNDBUFFER pidsb
  171. )
  172. {
  173. LPDSOUND pds;
  174. LPDSOUNDEXTERNAL pdse;
  175. LPDSBUFFER pdsb;
  176. LPDSBUFFEREXTERNAL pdsbe;
  177. LPDSBUFFEREXTERNAL pdsbe1;
  178. LPDSBUFFER pdsb1,pdsbPrimary;
  179. DPF(3,"Entering Buffer release method %X", pidsb);
  180. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  181. RPF("IDirectSoundBuffer::Release - Invalid Object or ref count");
  182. return 0;
  183. }
  184. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  185. pdsb = pdsbe->pdsb;
  186. pds = pdsb->pds;
  187. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  188. RPF("IDirectSoundBuffer::Release - Invalid Object or ref count");
  189. return 0;
  190. }
  191. ASSERT( DSBUFFSIG == pdsb->dwSig );
  192. if( pdsbe->dwPID == DWBUFFER_INTERNAL_PID ) {
  193. DPF(0,"Release on INTERNAL external obj");
  194. DPF(0,"************RELASE PRIMARY PROBLEM*********");
  195. return 0;
  196. }
  197. ENTER_DLL_CSECT();
  198. if( pdsbe->dwPID == DWPRIMARY_INTERNAL_PID ) {
  199. // FORCE A RELEASE our common DS object is going away
  200. DPF(0,"Release on PRIMARY INTERNAL external obj ");
  201. if( pdsbe->uRefCount != 1 ) {
  202. DPF(0,"************RELASE PRIMARY PROBLEM*********");
  203. }
  204. }
  205. DPF(0," BUFFER RELEASE ext %X core %X, PID %X",
  206. pdsbe, pdsbe->pdsb, pdsbe->dwPID );
  207. // If this is last ref make sure it is stopped....
  208. if(pdsb->uRefCount == 1) {
  209. IDsbStopI( pdsb, FALSE );
  210. }
  211. pdsb->uRefCount--;
  212. pdsbe->uRefCount--;
  213. if( (pdsbe->uRefCount == 0) &&
  214. (pdsbe->dwPID == DWPRIMARY_INTERNAL_PID) ) {
  215. // This will have process ID different from task
  216. DPF(0," RELEASE ORIGINAL PRIMARY " );
  217. MemFree( pdsb->plProcess );
  218. pdsb->plProcess = NULL;
  219. } else {
  220. if( DSBDecAccess( pdsb ) != DS_OK ) {
  221. DPF(0,"Decrement access error");
  222. LEAVE_DLL_CSECT();
  223. return 0;
  224. }
  225. }
  226. // If this is the freeing of the last access this process had
  227. // on this object, then free any locks that this process may have had
  228. // and release exclusive access as well
  229. if( DSBAccessCount( pdsb ) == 0 ) {
  230. // This process is not longer accessing this DS obj
  231. // Now release any buffers this process may have accessed.
  232. // Release all buffers for this process for this object
  233. FreeLocksOnBufferForProcess( pdsb );
  234. } else {
  235. if( pdsbe->uRefCount == 0 ) {
  236. DPF(0,"******** external ref count 0 but access > 0" );
  237. }
  238. }
  239. if( pdsbe->uRefCount > 0) {
  240. // This object is still refrenced
  241. DPF(3," Object still accessed %X", pdsbe->uRefCount );
  242. LEAVE_DLL_CSECT();
  243. return (pdsbe->uRefCount);
  244. }
  245. // Kill off the external object
  246. DPF(2,"Destroying DirectSoundBuffer External object");
  247. pdse = pdsbe->pdse;
  248. // Remove it from list
  249. if( pdse ) {
  250. // pdse will be null for Primary created by DS obj creation
  251. if(pdse->pdsbe == pdsbe)
  252. {
  253. pdse->pdsbe = pdsbe->pNext;
  254. } else {
  255. for(pdsbe1 = pdse->pdsbe; pdsbe1 != NULL; pdsbe1 = pdsbe1->pNext)
  256. {
  257. if(pdsbe1->pNext == pdsbe) {
  258. pdsbe1->pNext = pdsbe->pNext;
  259. pdsbe->pNext = NULL;
  260. break;
  261. }
  262. }
  263. }
  264. }
  265. // For non-waveemulated primary buffers free the alias pointer
  266. // to the data buffer.
  267. if (pdsbe->pDSBufferAlias) {
  268. ASSERT((DSB_INTERNALF_PRIMARY & pdsb->fdwDsbI) &&
  269. !(DS_INTERNALF_WAVEEMULATED & pds->fdwInternal));
  270. vxdMemFreeAlias(pdsbe->pDSBufferAlias, pdsb->cbBufferSize);
  271. } else {
  272. ASSERT(!(DSB_INTERNALF_PRIMARY & pdsb->fdwDsbI) ||
  273. (DS_INTERNALF_WAVEEMULATED & pds->fdwInternal));
  274. }
  275. MemFree( pdsbe );
  276. if(pdsb->uRefCount) {
  277. // If object is still accessed
  278. DPF(2,"External Object Destroyed, core remains");
  279. LEAVE_DLL_CSECT();
  280. return 0;
  281. }
  282. // Core object has no ref left - destroy it.
  283. DPF(2,"Destroying DirectSound Buffer object");
  284. // Check to see if we are freeing the primary.....
  285. if(pds->pdsbPrimary == pdsb) {
  286. DPF(3,"Destroying Primary %X", pdsb);
  287. // Check to see if we are on the WAVE apis
  288. if( pdsb->fdwDsbI & DSB_INTERNALF_WAVEEMULATED ) {
  289. DSShutdownEmulator(pds);
  290. }
  291. pdsbPrimary = pds->pdsbPrimary;
  292. pds->pdsbPrimary = NULL;
  293. pds->pdsbePrimary = NULL;
  294. }
  295. // Remove it from list
  296. if(pds->pdsb == pdsb)
  297. {
  298. pds->pdsb = pdsb->pNext;
  299. } else {
  300. for(pdsb1 = pds->pdsb; pdsb1 != NULL; pdsb1 = pdsb1->pNext)
  301. {
  302. if(pdsb1->pNext == pdsb) {
  303. pdsb1->pNext = pdsb->pNext;
  304. break;
  305. }
  306. }
  307. }
  308. if( pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE ) {
  309. // This is a HW buffer - do not free it normally
  310. DPF(3,"Release HW buffer %X", pdsb);
  311. vxdBufferRelease(pdsb->hBuffer);
  312. pdsb->hBuffer = NULL;
  313. }
  314. DPF(3,"Free memory for this buffer");
  315. if( pdsb->pMixBuffer != NULL ) {
  316. MemFree(pdsb->pMixBuffer);
  317. }
  318. // If this buffer has been duplicated then do not free memory, but erase
  319. // this buffer from dup list.
  320. if( pdsb->pdsbDuplicateNext == pdsb ) {
  321. // No duplicate Just free
  322. DPF(3,"NO Duplicate exists" );
  323. if( pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE ) {
  324. // This is a HW buffer - handle card and system mem snd buffer
  325. if (0 != pdsb->dwCardAddress) {
  326. DPF(3,"Freeing card memory at %08Xh", pdsb->dwCardAddress);
  327. ASSERT(NULL != pdsb->pds->pDriverHeap);
  328. VidMemFree(pdsb->pds->pDriverHeap, pdsb->dwCardAddress);
  329. }
  330. if( (DSDDESC_USESYSTEMMEMORY & pdsb->pds->fdwDriverDesc) &&
  331. !(pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) ) {
  332. DPF(3,"Freeing system memory at %08Xh", pdsb->pDSBuffer);
  333. MemFree(pdsb->pDSBuffer);
  334. }
  335. } else {
  336. // This is a SW buffer - free system mem snd buffer
  337. if( pdsb->pDSBuffer != NULL ) {
  338. MemFree(pdsb->pDSBuffer);
  339. }
  340. }
  341. } else {
  342. // There is a duplicate. Just remove this one from the list
  343. DPF(3,"Duplicate exists, do not free main memory" );
  344. pdsb->pdsbDuplicateNext->pdsbDuplicatePrev = pdsb->pdsbDuplicatePrev;
  345. pdsb->pdsbDuplicatePrev->pdsbDuplicateNext = pdsb->pdsbDuplicateNext;
  346. pdsb->pdsbDuplicateNext = NULL;
  347. pdsb->pdsbDuplicatePrev = NULL;
  348. }
  349. MemFree(pdsb->pwfx);
  350. DPF(1, "Freeing DSBUFFER obj 0x%8x",pdsb);
  351. pdsb->dwSig = 0xdeaddead;
  352. MemFree(pdsb);
  353. ASSERT(mxListIsValid(pds));
  354. DPF(3,"Exiting buffer release method");
  355. LEAVE_DLL_CSECT();
  356. return 0;
  357. } // IDSHWBufferRelease()
  358. HRESULT FAR PASCAL IDSHWBufferGetCaps
  359. (
  360. LPDIRECTSOUNDBUFFER pidsb,
  361. LPDSBCAPS pBufferCaps
  362. )
  363. {
  364. LPDSOUND pds;
  365. LPDSBUFFER pdsb;
  366. LPDSOUNDEXTERNAL pdse;
  367. LPDSBUFFEREXTERNAL pdsbe;
  368. DPF(4,"Entering Get Caps method");
  369. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  370. RPF("IDirectSoundBuffer::GetCaps - Invalid Object or ref count");
  371. return DSERR_INVALIDPARAM;
  372. }
  373. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  374. pdsb = pdsbe->pdsb;
  375. pds = pdsb->pds;
  376. pdse = pdsbe->pdse;
  377. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  378. RPF("IDirectSoundBuffer::GetCaps - Invalid Object or ref count");
  379. return DSERR_INVALIDPARAM;
  380. }
  381. ASSERT( DSBUFFSIG == pdsb->dwSig );
  382. if( !VALID_DSBCAPS_PTR( pBufferCaps ) ) {
  383. RPF("IDirectSoundBuffer::GetCaps - Invalid DSBCAPS pointer or dwSize member.");
  384. return DSERR_INVALIDPARAM;
  385. }
  386. ENTER_DLL_CSECT();
  387. pBufferCaps->dwFlags = pdsb->fdwBufferDesc;
  388. if( pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE ) {
  389. pBufferCaps->dwFlags |= DSBCAPS_LOCHARDWARE;
  390. pBufferCaps->dwFlags |= (DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLDEFAULT);
  391. }
  392. else if( pdsb->fdwDsbI & DSB_INTERNALF_EMULATED ) {
  393. pBufferCaps->dwFlags &= (~DSBCAPS_LOCHARDWARE);
  394. pBufferCaps->dwFlags |= DSBCAPS_LOCSOFTWARE;
  395. pBufferCaps->dwFlags |= (DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLDEFAULT);
  396. }
  397. pBufferCaps->dwBufferBytes = pdsb->cbBufferSize;
  398. pBufferCaps->dwUnlockTransferRate = 0;
  399. pBufferCaps->dwPlayCpuOverhead = 0;
  400. DPF(4,"Exiting get buffer caps method");
  401. LEAVE_DLL_CSECT();
  402. return DS_OK;
  403. } // IDSHWBufferGetCaps()
  404. HRESULT FAR PASCAL IDSHWBufferGetCurrentPosition
  405. (
  406. LPDIRECTSOUNDBUFFER pidsb,
  407. LPDWORD pdwPlay,
  408. LPDWORD pdwWrite
  409. )
  410. {
  411. LPDSOUND pds;
  412. LPDSBUFFER pdsb;
  413. LPDSBUFFEREXTERNAL pdsbe;
  414. DWORD cbSample;
  415. DSVAL dsv;
  416. DPF(4,"Entering HW Get Position method");
  417. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  418. RPF("IDirectSoundBuffer::GetCurrentPosition - Invalid Object or ref count");
  419. return DSERR_INVALIDPARAM;
  420. }
  421. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  422. pdsb = pdsbe->pdsb;
  423. pds = pdsb->pds;
  424. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  425. RPF("IDirectSoundBuffer::GetCurrentPosition - Invalid Object or ref count");
  426. return DSERR_INVALIDPARAM;
  427. }
  428. ASSERT( DSBUFFSIG == pdsb->dwSig );
  429. if( !VALID_DWORD_PTR(pdwPlay) ) {
  430. RPF("IDirectSoundBuffer::GetCurrentPosition - Invalid Play pointer");
  431. return DSERR_INVALIDPARAM;
  432. }
  433. if( !VALID_DWORD_PTR(pdwWrite) ) {
  434. RPF("IDirectSoundBuffer::GetCurrentPosition - Invalid Write pointer");
  435. return DSERR_INVALIDPARAM;
  436. }
  437. *pdwPlay = 0;
  438. *pdwWrite = 0;
  439. ENTER_DLL_CSECT();
  440. if( pdsbe != pds->pdsbePrimary ) {
  441. if( (pdsbe->dwPriority < DSSCL_NORMAL)
  442. || (pdsbe->dwPriority > DSSCL_WRITEPRIMARY)) {
  443. RPF("IDirectSoundBuffer::GetCurrentPosition - Invalid priority level or buffer owner");
  444. LEAVE_DLL_CSECT();
  445. return DSERR_PRIOLEVELNEEDED;
  446. }
  447. }
  448. // If called on a primary buffer, caller must be WRITEPRIMARY
  449. if( (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) &&
  450. (pdsbe->dwPriority < DSSCL_WRITEPRIMARY) )
  451. {
  452. RPF("IDirectSoundBuffer::GetCurrentPosition - Caller isn't WRITEPRIMARY");
  453. LEAVE_DLL_CSECT();
  454. return DSERR_PRIOLEVELNEEDED;
  455. }
  456. //
  457. //
  458. //
  459. if( (pdsb->pwfx) && (pdsb->pwfx->nBlockAlign) ) {
  460. cbSample = pdsb->pwfx->nBlockAlign;
  461. } else {
  462. cbSample = 4;
  463. }
  464. // If called on a primary buffer and the buffer is lost, return its
  465. // position as 0.
  466. if( (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) &&
  467. (pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) )
  468. {
  469. RPF("IDirectSoundBuffer::GetCurrentPosition - Buffer is lost");
  470. LEAVE_DLL_CSECT();
  471. *pdwPlay = 0;
  472. *pdwWrite = 0;
  473. return DS_OK;
  474. }
  475. if ((pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) &&
  476. (pdsb->fdwDsbI & DSB_INTERNALF_SETPOS_WHILE_LOST)) {
  477. // Buffer is lost, they've set the position since... just use that
  478. //
  479. *pdwPlay = pdsb->dwSavePosition;
  480. *pdwWrite = pdsb->dwSavePosition;
  481. } else if( pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE ) {
  482. // We are a HW buffer - get position from HW
  483. dsv = vxdBufferGetPosition(pdsb->hBuffer, pdwPlay, pdwWrite);
  484. if (DS_OK != dsv) {
  485. RPF("IDirectSoundBuffer::GetCurrentPosition - Hardware returned error.");
  486. LEAVE_DLL_CSECT();
  487. return dsv;
  488. }
  489. //
  490. // REMIND: really this should only be true for HW buffers, which return
  491. // dwPlay==cbBufferSize when a non-looping buffer reaches the end.
  492. // We should stop those buffers as we do below.
  493. //
  494. if( (*pdwPlay >= pdsb->cbBufferSize) ) {
  495. ASSERT(!(pdsb->fdwDsbI & DSB_INTERNALF_LOOPING));
  496. // We are past end of buffer and not looping stop the buffer
  497. DPF(0,"Play postion is past end - Stop it.");
  498. IDsbStopI( pdsb, FALSE );
  499. // Now set position back to beginning
  500. IDsbSetCurrentPositionI(pdsb, 0);
  501. *pdwPlay = 0;
  502. *pdwWrite = 0;
  503. }
  504. // If the buffer is not stopped then we need to pad the write cursor
  505. if (!(pdsb->fdwDsbI & DSB_INTERNALF_STOP)) {
  506. *pdwWrite += pdsb->helInfo.dwSampleRate * MIXER_WRITEPAD / 1000;
  507. if (*pdwWrite >= pdsb->cbBufferSize) *pdwWrite -= pdsb->cbBufferSize;
  508. }
  509. ASSERT(*pdwPlay >= 0 && *pdwPlay < pdsb->cbBufferSize);
  510. ASSERT(*pdwWrite >= 0 && *pdwWrite < pdsb->cbBufferSize);
  511. } else {
  512. // We are not a HW buffer
  513. // Check to see if we are on the WAVE apis
  514. if( pdsb->fdwDsbI & DSB_INTERNALF_WAVEEMULATED ) {
  515. if (pdsb == pds->pdsbPrimary) {
  516. // NOTE: The mechanics of the looping engine ensure that
  517. // mod'ing these is already taken care of
  518. int iawhWrite;
  519. iawhWrite = (pds->iawhPlaying + NUMELMS(pds->aWaveHeader) - 1) % NUMELMS(pds->aWaveHeader);
  520. *pdwPlay = pds->iawhPlaying * pds->cbDMASize;;
  521. *pdwWrite = iawhWrite * pds->cbDMASize;
  522. LEAVE_DLL_CSECT();
  523. return DS_OK;
  524. }
  525. //
  526. // This logic is somewhat screwy. We really should do a
  527. // better job of finding the current play position and the
  528. // current write position.
  529. //
  530. //
  531. // ??? Want to be sample accurate here ???
  532. //
  533. if (0 == (DSB_INTERNALF_STOP & pdsb->fdwDsbI)) {
  534. if (DSBCAPS_GETCURRENTPOSITION2 & pdsb->fdwBufferDesc) {
  535. *pdwPlay = pdsb->aposWhMix[pds->iawhPlaying] << pdsb->uBlockAlignShift;
  536. *pdwWrite = pdsb->posNextMix << pdsb->uBlockAlignShift;
  537. } else {
  538. *pdwPlay = pdsb->posNextMix << pdsb->uBlockAlignShift;
  539. *pdwWrite = (pdsb->posNextMix+1) << pdsb->uBlockAlignShift;
  540. if (*pdwWrite >= pdsb->cbBufferSize) *pdwWrite -= pdsb->cbBufferSize;
  541. }
  542. } else {
  543. *pdwPlay = pdsb->posNextMix << pdsb->uBlockAlignShift;
  544. *pdwWrite = pdsb->posNextMix << pdsb->uBlockAlignShift;
  545. }
  546. } else {
  547. // Get position on Secondary
  548. if (0 == (DSB_INTERNALF_STOP & pdsb->fdwDsbI)) {
  549. dsv = mxGetPosition(pdsb, pdwPlay, pdwWrite, NULL);
  550. if (DS_OK != dsv) {
  551. LEAVE_DLL_CSECT();
  552. return dsv;
  553. }
  554. } else {
  555. *pdwPlay = pdsb->posNextMix << pdsb->uBlockAlignShift;
  556. *pdwWrite = pdsb->posNextMix << pdsb->uBlockAlignShift;
  557. }
  558. }
  559. }
  560. // Round up positions to even samples
  561. if( cbSample > 1 ) {
  562. // Round up positions to sample position.
  563. *pdwPlay += cbSample - 1;
  564. *pdwWrite += cbSample - 1;
  565. *pdwPlay -= (*pdwPlay % cbSample);
  566. *pdwWrite -= (*pdwWrite % cbSample);
  567. }
  568. DPF(4,"Exit HW Get Postion %X Write %X", *pdwPlay, *pdwWrite);
  569. LEAVE_DLL_CSECT();
  570. return DS_OK;
  571. } // IDSHWBufferGetCurrentPosition()
  572. HRESULT FAR PASCAL IDSHWBufferGetFormat
  573. (
  574. LPDIRECTSOUNDBUFFER pidsb,
  575. LPWAVEFORMATEX pwfx,
  576. DWORD cbwfx,
  577. LPDWORD lpdwSizeReturned
  578. )
  579. {
  580. LPDSOUND pds;
  581. LPDSBUFFER pdsb;
  582. LPDSBUFFEREXTERNAL pdsbe;
  583. DWORD dwSize;
  584. LPWAVEFORMATEX pwfxToRet;
  585. DPF(4,"Entering Buffer get format method");
  586. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  587. RPF("IDirectSoundBuffer::GetFormat - Invalid Object or ref count");
  588. return DSERR_INVALIDPARAM;
  589. }
  590. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  591. pdsb = pdsbe->pdsb;
  592. pds = pdsb->pds;
  593. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  594. RPF("IDirectSoundBuffer::GetFormat - Invalid Object or ref count");
  595. return DSERR_INVALIDPARAM;
  596. }
  597. ASSERT( DSBUFFSIG == pdsb->dwSig );
  598. if( ( NULL == pwfx ) &&
  599. ( NULL == lpdwSizeReturned ) )
  600. {
  601. RPF("IDirectSoundBuffer::GetFormat - Both pwfx and lpdwSizeWritten are NULL.");
  602. return DSERR_INVALIDPARAM;
  603. }
  604. ENTER_DLL_CSECT();
  605. pwfxToRet = pdsb->pwfx;
  606. if ((pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) &&
  607. (pdsb->fdwDsbI & DSB_INTERNALF_WFX_WHILE_LOST)) {
  608. pwfxToRet = pdsb->pwfxSave;
  609. }
  610. else if( pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY )
  611. {
  612. // Primary buffer - return app's preferred format if it has one,
  613. // otherwise return the default format.
  614. if( pdsbe->pdse->pwfxApp ) {
  615. pwfxToRet = pdsbe->pdse->pwfxApp;
  616. } else {
  617. pwfxToRet = &pds->wfxDefault;
  618. }
  619. }
  620. if( NULL != lpdwSizeReturned )
  621. {
  622. if( !VALID_DWORD_PTR(lpdwSizeReturned) ) {
  623. RPF("IDirectSoundBuffer::GetFormat - Invalid lpdwSizeWritten pointer");
  624. LEAVE_DLL_CSECT();
  625. return DSERR_INVALIDPARAM;
  626. }
  627. *lpdwSizeReturned = SIZEOF_WAVEFORMATEX( pwfxToRet );
  628. }
  629. if( pwfx == NULL ) {
  630. // pwfx is NULL just return size needed.
  631. DPF(4,"Exiting buffer get format method - NULL pwfx");
  632. LEAVE_DLL_CSECT();
  633. return DS_OK;
  634. }
  635. dwSize = SIZEOF_WAVEFORMATEX(pwfxToRet);
  636. if(dwSize > cbwfx)
  637. {
  638. RPF("IDirectSoundBuffer::GetFormat - Not enough space for format");
  639. LEAVE_DLL_CSECT();
  640. return DSERR_INVALIDPARAM;
  641. }
  642. if( !VALID_SIZE_PTR(pwfx, dwSize) ) {
  643. DPF(0,"Invalid Format size");
  644. LEAVE_DLL_CSECT();
  645. return DSERR_INVALIDPARAM;
  646. }
  647. hmemcpy(pwfx,pwfxToRet,dwSize);
  648. DPF(4,"Exiting buffer get format method");
  649. LEAVE_DLL_CSECT();
  650. return DS_OK;
  651. } // IDSHWBufferGetFormat()
  652. HRESULT FAR PASCAL IDSHWBufferGetVolume
  653. (
  654. LPDIRECTSOUNDBUFFER pidsb,
  655. LPLONG plVolume
  656. )
  657. {
  658. LPDSOUND pds;
  659. LPDSBUFFER pdsb;
  660. LPDSBUFFEREXTERNAL pdsbe;
  661. DPF(3,"Entering get volume method");
  662. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  663. DPF(0,"Invalid Object or ref count");
  664. return DSERR_INVALIDPARAM;
  665. }
  666. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  667. pdsb = pdsbe->pdsb;
  668. pds = pdsb->pds;
  669. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  670. DPF(0,"Invalid Object or ref count");
  671. return DSERR_INVALIDPARAM;
  672. }
  673. ASSERT( DSBUFFSIG == pdsb->dwSig );
  674. if( !VALID_LONG_PTR(plVolume) ) {
  675. RPF("IDirectSoundBuffer::GetVolume - Invalid Volume pointer");
  676. return DSERR_INVALIDPARAM;
  677. }
  678. ENTER_DLL_CSECT();
  679. // Only primary buffers may have CTRLVOLUMEPRIMARY set.
  680. ASSERT( !(pdsbe->fdwDsbeI&DSBE_INTERNALF_CTRLVOLUMEPRIMARY) ||
  681. (pdsb->fdwDsbI&DSB_INTERNALF_PRIMARY) );
  682. if( !(pdsb->fdwBufferDesc & DSBCAPS_CTRLVOLUME) &&
  683. !(pdsbe->fdwDsbeI & DSBE_INTERNALF_CTRLVOLUMEPRIMARY) )
  684. {
  685. RPF("IDirectSoundBuffer::GetVolume - Caller did not have CTRL permission for Volume!");
  686. LEAVE_DLL_CSECT();
  687. return DSERR_CONTROLUNAVAIL;
  688. }
  689. if( (pdsbe->dwPriority < DSSCL_NORMAL)
  690. || (pdsbe->dwPriority > DSSCL_WRITEPRIMARY) ) {
  691. RPF("IDirectSoundBuffer::GetVolume - Invalid priority level or buffer owner");
  692. LEAVE_DLL_CSECT();
  693. return DSERR_PRIOLEVELNEEDED;
  694. }
  695. if ((pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) &&
  696. (pdsb->fdwDsbI & DSB_INTERNALF_VOLUME_WHILE_LOST)) {
  697. *plVolume = pdsb->lSaveVolume;
  698. } else if (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) {
  699. WAVEOUTCAPS woc;
  700. DWORD dwWaveVolume;
  701. UINT uWaveId;
  702. if ( (DS_OK == wavGetIdFromDrvGuid(&pds->guid, &uWaveId)) &&
  703. (!waveOutGetDevCaps(uWaveId, &woc, sizeof(woc))) &&
  704. (woc.dwSupport & WAVECAPS_VOLUME) &&
  705. (!waveOutGetVolume((HWAVEOUT)uWaveId, &dwWaveVolume)) )
  706. {
  707. if (woc.dwSupport & WAVECAPS_LRVOLUME) {
  708. dwWaveVolume = max((dwWaveVolume & 0xffff), (dwWaveVolume >> 16));
  709. } else {
  710. dwWaveVolume &= 0xffff;
  711. }
  712. *plVolume = AmpFactorToDB( dwWaveVolume );
  713. } else {
  714. DPF(0, "IDSHWBufferGetVolume: error: couldn't get wave volume");
  715. *plVolume = 0;
  716. }
  717. } else {
  718. *plVolume = pdsb->helInfo.lVolume;
  719. }
  720. DPF(3,"Exiting buffer get volume method");
  721. LEAVE_DLL_CSECT();
  722. return DS_OK;
  723. } // IDSHWBufferGetVolume()
  724. HRESULT FAR PASCAL IDSHWBufferGetPan
  725. (
  726. LPDIRECTSOUNDBUFFER pidsb,
  727. LPLONG plPan
  728. )
  729. {
  730. LPDSOUND pds;
  731. LPDSBUFFER pdsb;
  732. LPDSBUFFEREXTERNAL pdsbe;
  733. DPF(3,"Entering get pan method");
  734. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  735. RPF("IDirectSoundBuffer::GetPan - Invalid Object or ref count");
  736. return DSERR_INVALIDPARAM;
  737. }
  738. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  739. pdsb = pdsbe->pdsb;
  740. pds = pdsb->pds;
  741. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  742. RPF("IDirectSoundBuffer::GetPan - Invalid Object or ref count");
  743. return DSERR_INVALIDPARAM;
  744. }
  745. ASSERT( DSBUFFSIG == pdsb->dwSig );
  746. if( !VALID_LONG_PTR(plPan) ) {
  747. RPF("IDirectSoundBuffer::GetPan - Invalid Pan pointer");
  748. return DSERR_INVALIDPARAM;
  749. }
  750. ENTER_DLL_CSECT();
  751. if( (pdsbe->dwPriority < DSSCL_NORMAL)
  752. || (pdsbe->dwPriority > DSSCL_WRITEPRIMARY) ) {
  753. RPF("IDirectSoundBuffer::GetPan - Invalid priority level or buffer owner");
  754. LEAVE_DLL_CSECT();
  755. return DSERR_PRIOLEVELNEEDED;
  756. }
  757. // Only primary buffers may have CTRLPANPRIMARY set.
  758. ASSERT( !(pdsbe->fdwDsbeI&DSBE_INTERNALF_CTRLPANPRIMARY) ||
  759. (pdsb->fdwDsbI&DSB_INTERNALF_PRIMARY) );
  760. if (!(pdsb->fdwBufferDesc & DSBCAPS_CTRLPAN) &&
  761. !(pdsbe->fdwDsbeI & DSBE_INTERNALF_CTRLPANPRIMARY) )
  762. {
  763. RPF("IDirectSoundBuffer::GetPan - Control not available");
  764. LEAVE_DLL_CSECT();
  765. return DSERR_CONTROLUNAVAIL;
  766. }
  767. if ((pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) &&
  768. (pdsb->fdwDsbI & DSB_INTERNALF_PAN_WHILE_LOST)) {
  769. *plPan = pdsb->lSavePan;
  770. } else if (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) {
  771. WAVEOUTCAPS woc;
  772. DWORD dwWaveVolume;
  773. DWORD dwWaveVolumeL;
  774. DWORD dwWaveVolumeR;
  775. UINT uWaveId;
  776. if ( (DS_OK == wavGetIdFromDrvGuid(&pds->guid, &uWaveId)) &&
  777. (!waveOutGetDevCaps(uWaveId, &woc, sizeof(woc))) &&
  778. (woc.dwSupport & WAVECAPS_VOLUME) &&
  779. (!waveOutGetVolume((HWAVEOUT)uWaveId, &dwWaveVolume)) )
  780. {
  781. if (woc.dwSupport & WAVECAPS_LRVOLUME) {
  782. dwWaveVolumeL = dwWaveVolume & 0xffff;
  783. dwWaveVolumeR = dwWaveVolume >> 16;
  784. if (dwWaveVolumeL < dwWaveVolumeR) {
  785. // pan to right
  786. *plPan = -AmpFactorToDB((dwWaveVolumeL << 16) / dwWaveVolumeR);
  787. } else if (dwWaveVolumeR < dwWaveVolumeL) {
  788. // pan to left
  789. *plPan = AmpFactorToDB((dwWaveVolumeR << 16) / dwWaveVolumeL);
  790. } else {
  791. *plPan = 0;
  792. }
  793. } else {
  794. *plPan = 0;
  795. }
  796. } else {
  797. DPF(0, "IDSHWBufferGetVolume: error: couldn't get wave volume");
  798. *plPan = 0;
  799. }
  800. } else {
  801. *plPan = pdsb->helInfo.lPan;
  802. }
  803. DPF(3,"Exiting buffer get pan method");
  804. LEAVE_DLL_CSECT();
  805. return DS_OK;
  806. } // IDSHWBufferGetPan()
  807. HRESULT FAR PASCAL IDSHWBufferGetFrequency
  808. (
  809. LPDIRECTSOUNDBUFFER pidsb,
  810. LPDWORD pdwFrequency
  811. )
  812. {
  813. LPDSOUND pds;
  814. LPDSBUFFER pdsb;
  815. LPDSBUFFEREXTERNAL pdsbe;
  816. DPF(3,"Entering get frequency method");
  817. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  818. RPF("IDirectSoundBuffer::GetFrequency - Invalid Object or ref count");
  819. return DSERR_INVALIDPARAM;
  820. }
  821. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  822. pdsb = pdsbe->pdsb;
  823. pds = pdsb->pds;
  824. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  825. RPF("IDirectSoundBuffer::GetFrequency - Invalid Object or ref count");
  826. return DSERR_INVALIDPARAM;
  827. }
  828. ASSERT( DSBUFFSIG == pdsb->dwSig );
  829. if( !VALID_DWORD_PTR(pdwFrequency) ) {
  830. RPF("IDirectSoundBuffer::GetFrequency - Invalid Frequency pointer");
  831. return DSERR_INVALIDPARAM;
  832. }
  833. ENTER_DLL_CSECT();
  834. if( (pdsbe->dwPriority < DSSCL_NORMAL)
  835. || (pdsbe->dwPriority > DSSCL_WRITEPRIMARY) ) {
  836. RPF("IDirectSoundBuffer::GetFrequency - Invalid priority level or buffer owner");
  837. LEAVE_DLL_CSECT();
  838. return DSERR_PRIOLEVELNEEDED;
  839. }
  840. if (0 == (pdsb->fdwBufferDesc & DSBCAPS_CTRLFREQUENCY)) {
  841. RPF("IDirectSoundBuffer::GetFrequency - CTRLFREQUENCY unavailable");
  842. LEAVE_DLL_CSECT();
  843. return DSERR_CONTROLUNAVAIL;
  844. }
  845. // DSBCAPS_CTRLFREQUENCY is not supported on primary buffers
  846. ASSERT(0 == (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY));
  847. if ((pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) &&
  848. (pdsb->fdwDsbI & DSB_INTERNALF_FREQ_WHILE_LOST)) {
  849. *pdwFrequency = pdsb->dwSaveFreq;
  850. } else {
  851. *pdwFrequency = pdsb->helInfo.dwSampleRate;
  852. }
  853. DPF(3,"Exiting buffer get frequency method");
  854. LEAVE_DLL_CSECT();
  855. return DS_OK;
  856. } // IDSHWBufferGetFrequency()
  857. HRESULT FAR PASCAL IDSHWBufferGetStatus
  858. (
  859. LPDIRECTSOUNDBUFFER pidsb,
  860. LPDWORD pdwStatus
  861. )
  862. {
  863. LPDSOUND pds;
  864. LPDSBUFFER pdsb;
  865. LPDSBUFFEREXTERNAL pdsbe;
  866. DPF(5,"Entering HW get Status method");
  867. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  868. RPF("IDirectSoundBuffer::GetStatus - Invalid Object or ref count");
  869. return DSERR_INVALIDPARAM;
  870. }
  871. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  872. pdsb = pdsbe->pdsb;
  873. pds = pdsb->pds;
  874. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  875. RPF("IDirectSoundBuffer::GetStatus - Invalid Object or ref count");
  876. return DSERR_INVALIDPARAM;
  877. }
  878. ASSERT( DSBUFFSIG == pdsb->dwSig );
  879. if( !VALID_DWORD_PTR(pdwStatus) ) {
  880. RPF("IDirectSoundBuffer::GetStatus - Invalid Status pointer");
  881. return DSERR_INVALIDPARAM;
  882. }
  883. //
  884. //
  885. //
  886. ENTER_DLL_CSECT();
  887. *pdwStatus = 0;
  888. if( pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY )
  889. {
  890. if( pdsbe->dwPriority >= DSSCL_WRITEPRIMARY ) {
  891. if( !(pdsb->fdwDsbI & DSB_INTERNALF_STOP) ) {
  892. *pdwStatus |= DSBSTATUS_PLAYING;
  893. }
  894. }
  895. else if( pdsbe->fdwDsbeI & DSBE_INTERNALF_PLAYING ) {
  896. *pdwStatus |= DSBSTATUS_PLAYING;
  897. }
  898. }
  899. else
  900. {
  901. // Since secondary hardware buffers can't notify us when they have stopped, we poll
  902. // them by calling GetCurrentPosition on them. The GetCurrentPosition
  903. // method will check whether the buffer has stopped and update its status.
  904. if (pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE) {
  905. DWORD dwPlay, dwWrite;
  906. IDirectSoundBuffer_GetCurrentPosition(pidsb, &dwPlay, &dwWrite);
  907. }
  908. if( !(pdsb->fdwDsbI & DSB_INTERNALF_STOP) ) {
  909. *pdwStatus |= DSBSTATUS_PLAYING;
  910. }
  911. }
  912. if( pdsb->helInfo.hfFormat & H_LOOP ) {
  913. *pdwStatus |= DSBSTATUS_LOOPING;
  914. }
  915. if (pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) {
  916. *pdwStatus |= DSBSTATUS_BUFFERLOST;
  917. }
  918. DPF(5,"Exiting buffer get Status method");
  919. LEAVE_DLL_CSECT();
  920. return DS_OK;
  921. } // IDSHWBufferGetStatus()
  922. HRESULT FAR PASCAL IDSHWBufferInitialize
  923. (
  924. LPDIRECTSOUNDBUFFER pidsb,
  925. LPDIRECTSOUND pids,
  926. LPDSBUFFERDESC pdsbd
  927. )
  928. {
  929. LPDSBUFFER pdsb;
  930. LPDSBUFFEREXTERNAL pdsbe;
  931. LPDSOUND pds;
  932. LPDSOUNDEXTERNAL pdse;
  933. if( !VALID_DSBUFFERE_PTR(pidsb) ) {
  934. RPF("IDirectSoundBuffer::Initialize - Invalid DSBuffer Object or ref count");
  935. return DSERR_INVALIDPARAM;
  936. }
  937. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  938. pdsb = pdsbe->pdsb;
  939. pds = pdsb->pds;
  940. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  941. RPF("IDirectSoundBuffer::Initialize - Invalid DSBuffer Object or ref count");
  942. return DSERR_INVALIDPARAM;
  943. }
  944. ASSERT( DSBUFFSIG == pdsb->dwSig );
  945. pdse = (LPDSOUNDEXTERNAL)pids;
  946. pds = pdse->pds;
  947. if( !VALID_DSOUND_PTR(pds) || (0 == pdse->uRefCount)) {
  948. RPF("IDirectSoundBuffer::Initialize - Invalid DSound Object or ref count");
  949. return DSERR_INVALIDPARAM;
  950. }
  951. if( !VALID_DSBUFFERDESC_PTR(pdsbd) ) {
  952. RPF("IDirectSoundBuffer::Initialize - Invalid Buffer Description or dwSize member.");
  953. return DSERR_INVALIDPARAM;
  954. }
  955. // This is all we have to do for this rev...
  956. ENTER_DLL_CSECT();
  957. LEAVE_DLL_CSECT();
  958. return DSERR_ALREADYINITIALIZED;
  959. } // IDSHWBufferInitialize()
  960. HRESULT FAR PASCAL IDSHWBufferLock
  961. (
  962. LPDIRECTSOUNDBUFFER pidsb,
  963. DWORD dwWriteOffset,
  964. DWORD dwSize,
  965. LPLPVOID ppBuffer1,
  966. LPDWORD pcbBufferSize1,
  967. LPLPVOID ppBuffer2,
  968. LPDWORD pcbBufferSize2,
  969. DWORD dwFlags
  970. )
  971. {
  972. LPDSOUND pds;
  973. LPDSBUFFER pdsb;
  974. LPDSBUFFEREXTERNAL pdsbe;
  975. INT iExtraSize;
  976. DWORD dwPlay;
  977. DWORD dwWrite;
  978. DWORD cbSample;
  979. HRESULT hrslt;
  980. DWORD dwOffset1;
  981. LPVOID pBuffer1;
  982. DWORD cbBufferSize1;
  983. DWORD dwOffset2;
  984. LPVOID pBuffer2;
  985. DWORD cbBufferSize2;
  986. BOOL fCommittedAlias;
  987. DPF(4,"Entering LOCK HW obj %X start %X len %X",
  988. pidsb, dwWriteOffset, dwSize );
  989. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  990. RPF("IDirectSoundBuffer::Lock - Invalid Object or ref count");
  991. return DSERR_INVALIDPARAM;
  992. }
  993. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  994. pdsb = pdsbe->pdsb;
  995. pds = pdsb->pds;
  996. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  997. RPF("IDirectSoundBuffer::Lock - Invalid Object or ref count");
  998. return DSERR_INVALIDPARAM;
  999. }
  1000. ASSERT( DSBUFFSIG == pdsb->dwSig );
  1001. if (pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) {
  1002. return DSERR_BUFFERLOST;
  1003. }
  1004. if( (dwSize == 0) || (dwSize > pdsb->cbBufferSize) ) {
  1005. RPF("IDirectSoundBuffer::Lock - Size is too large for buffer");
  1006. return DSERR_INVALIDPARAM;
  1007. }
  1008. if( dwFlags & (~DSBLOCK_VALIDFLAGS)) {
  1009. RPF("IDirectSoundBuffer::Lock - Invalid flags passed to Lock");
  1010. return DSERR_INVALIDPARAM;
  1011. }
  1012. if( !VALID_DWORD_PTR(ppBuffer1) ) {
  1013. RPF("IDirectSoundBuffer::Lock - Invalid Pointer to Pointer to 1st section of buffer." );
  1014. return DSERR_INVALIDPARAM;
  1015. }
  1016. if( !VALID_DWORD_PTR(pcbBufferSize1) ) {
  1017. RPF("IDirectSoundBuffer::Lock - Invalid Pointer to DWORD to 1st buffer size." );
  1018. return DSERR_INVALIDPARAM;
  1019. }
  1020. if( dwWriteOffset >= pdsb->cbBufferSize ) {
  1021. RPF("IDirectSoundBuffer::Lock - Invalid Write Offset." );
  1022. return DSERR_INVALIDPARAM;
  1023. }
  1024. dwOffset1 = 0;
  1025. dwOffset2 = 0;
  1026. pBuffer1 = NULL;
  1027. cbBufferSize1 = 0;
  1028. pBuffer2 = NULL;
  1029. cbBufferSize2 = 0;
  1030. *ppBuffer1 = NULL;
  1031. *pcbBufferSize1 = 0;
  1032. if( (ppBuffer2 != NULL) && (pcbBufferSize2 != NULL) ) {
  1033. *ppBuffer2 = NULL;
  1034. *pcbBufferSize2 = 0;
  1035. }
  1036. ENTER_DLL_CSECT();
  1037. // Trying to free a buffer with active locks is a Bad Thing
  1038. //
  1039. ASSERT(0 == pdsbe->cLocks);
  1040. if( pdsbe != pds->pdsbePrimary ) {
  1041. if( (pdsbe->dwPriority < DSSCL_NORMAL)
  1042. || (pdsbe->dwPriority > DSSCL_WRITEPRIMARY)) {
  1043. RPF("IDirectSoundBuffer::Lock - Invalid priority level or buffer owner");
  1044. LEAVE_DLL_CSECT();
  1045. return DSERR_PRIOLEVELNEEDED;
  1046. }
  1047. }
  1048. // Must be WRITEPRIMARY to lock the primary buffer
  1049. if( (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) &&
  1050. (pdsbe->dwPriority < DSSCL_WRITEPRIMARY) )
  1051. {
  1052. RPF("IDirectSoundBuffer::Lock - Caller not WRITEPRIMARY");
  1053. LEAVE_DLL_CSECT();
  1054. return DSERR_PRIOLEVELNEEDED;
  1055. }
  1056. // Calculate general useful info
  1057. if( (pdsb->pwfx) && (pdsb->pwfx->nBlockAlign) ) {
  1058. cbSample = pdsb->pwfx->nBlockAlign;
  1059. } else {
  1060. cbSample = 4;
  1061. }
  1062. // Use the position from GetPos if needed.
  1063. if( dwFlags & DSBLOCK_FROMWRITECURSOR ) {
  1064. // Find current position
  1065. hrslt = pidsb->lpVtbl->GetCurrentPosition(
  1066. pidsb,
  1067. &dwPlay,
  1068. &dwWrite );
  1069. if(DS_OK != hrslt) {
  1070. DPF(0,"ERROR GetPosiiton return %ld obj %X ", hrslt, pdsb);
  1071. LEAVE_DLL_CSECT();
  1072. return hrslt;
  1073. }
  1074. // HACK - use better size?
  1075. // Check to see if we are on the WAVE apis
  1076. if( pdsb->fdwDsbI & DSB_INTERNALF_WAVEEMULATED ) {
  1077. // ??? Do we have to be able to get the position on the primary if
  1078. // they aren't allowed to lock it?
  1079. //
  1080. if (pdsb == pds->pdsbPrimary) {
  1081. DPF(0, "IDSBufferGetCurrentPosition on primary");
  1082. LEAVE_DLL_CSECT();
  1083. return DSERR_INVALIDCALL;
  1084. }
  1085. }
  1086. dwWriteOffset = dwWrite + cbSample;
  1087. }
  1088. // Round off positions to even samples
  1089. if( cbSample > 1 ) {
  1090. // Round of positions to sample position.
  1091. dwWriteOffset -= (dwWriteOffset % cbSample);
  1092. }
  1093. // Does buffer wrap?
  1094. iExtraSize = (LONG)(pdsb->cbBufferSize) - (LONG)(dwWriteOffset + dwSize);
  1095. if( (ppBuffer2 == NULL) || (pcbBufferSize2 == NULL) ) {
  1096. // Only report 1st pointer back to user.
  1097. dwOffset1 = dwWriteOffset;
  1098. if (pdsbe->pDSBufferAlias) {
  1099. pBuffer1 = pdsbe->pDSBufferAlias + dwWriteOffset;
  1100. } else {
  1101. pBuffer1 = pdsb->pDSBuffer + dwWriteOffset;
  1102. }
  1103. if( iExtraSize >= 0 ) {
  1104. cbBufferSize1 = dwSize;
  1105. } else {
  1106. cbBufferSize1 = pdsb->cbBufferSize - dwWriteOffset;
  1107. }
  1108. } else {
  1109. // Report both pointers to user
  1110. dwOffset1 = dwWriteOffset;
  1111. if (NULL != pdsbe->pDSBufferAlias) {
  1112. pBuffer1 = pdsbe->pDSBufferAlias + dwWriteOffset;
  1113. } else {
  1114. pBuffer1 = pdsb->pDSBuffer + dwWriteOffset;
  1115. }
  1116. if( iExtraSize >= 0 ) {
  1117. cbBufferSize1 = dwSize;
  1118. } else {
  1119. dwOffset2 = 0;
  1120. cbBufferSize1 = pdsb->cbBufferSize - dwWriteOffset;
  1121. if (pdsbe->pDSBufferAlias) {
  1122. pBuffer2 = pdsbe->pDSBufferAlias;
  1123. } else {
  1124. pBuffer2 = pdsb->pDSBuffer;
  1125. }
  1126. cbBufferSize2 = dwSize - cbBufferSize1;
  1127. }
  1128. }
  1129. // Check to see if we can lock this buffer at that pos
  1130. if( DSBLockAccess( pdsb, dwOffset1, cbBufferSize1 ) ) {
  1131. // This section is already locked
  1132. RPF("IDirectSoundBuffer::Lock - Section already locked." );
  1133. LEAVE_DLL_CSECT();
  1134. return DSERR_INVALIDCALL;
  1135. }
  1136. if( (cbBufferSize2 > 0) &&
  1137. DSBLockAccess( pdsb, dwOffset2, cbBufferSize2 ) ) {
  1138. // There is a wrap section and
  1139. // This section is already locked
  1140. // Unlock the previous seciton
  1141. DSBUnlockAccess( pdsb, dwOffset1 );
  1142. RPF("IDirectSoundBuffer::Lock - Section already locked." );
  1143. LEAVE_DLL_CSECT();
  1144. return DSERR_INVALIDCALL;
  1145. }
  1146. // Maintain a count of the number of locks on this buffer.
  1147. pdsbe->cLocks++;
  1148. ASSERT(pdsbe->cLocks > 0);
  1149. // If we have an alias buffer ptr, we need to commit the physical
  1150. // buffer memory to the aliased pointer if this is the first lock.
  1151. fCommittedAlias = FALSE;
  1152. if (pdsbe->pDSBufferAlias && (1 == pdsbe->cLocks)) {
  1153. if (!vxdMemCommitAlias(pdsbe->pDSBufferAlias, pdsb->pDSBuffer, pdsb->cbBufferSize))
  1154. {
  1155. pdsbe->cLocks--;
  1156. DSBUnlockAccess( pdsb, dwOffset1 );
  1157. DSBUnlockAccess( pdsb, dwOffset2 );
  1158. DPF(0, "Lock: error: vxdMemCommitAlias failed");
  1159. LEAVE_DLL_CSECT();
  1160. return DSERR_OUTOFMEMORY;
  1161. }
  1162. fCommittedAlias = TRUE;
  1163. }
  1164. // If this is a hardware buffer and they will be reading the memory
  1165. // from the system memory buffer, then get the driver to update
  1166. // the system memory from the card
  1167. // REMIND do we want to use LOCKF_READDATA?
  1168. // if( (dwFlags & DSB_LOCKF_READDATA) &&
  1169. if (pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE) {
  1170. // This is a HW buffer - Ask driver to lock
  1171. if ( ( (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) &&
  1172. !(pds->fdwDriverDesc & DSDDESC_DONTNEEDPRIMARYLOCK)) ||
  1173. (!(pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) &&
  1174. !(pds->fdwDriverDesc & DSDDESC_DONTNEEDSECONDARYLOCK)) )
  1175. {
  1176. DSVAL dsv;
  1177. dsv = vxdBufferLock( pdsb->hBuffer, &pBuffer1, &cbBufferSize1,
  1178. &pBuffer2, &cbBufferSize2, dwWriteOffset,
  1179. dwSize, 0 );
  1180. if (DS_OK != dsv) {
  1181. if (fCommittedAlias) {
  1182. vxdMemDecommitAlias(pdsbe->pDSBufferAlias, pdsb->cbBufferSize);
  1183. }
  1184. pdsbe->cLocks--;
  1185. DSBUnlockAccess( pdsb, dwOffset1 );
  1186. DSBUnlockAccess( pdsb, dwOffset2 );
  1187. DPF(0, "Lock: error: vxdBufferLock returned %08Xh", dsv);
  1188. LEAVE_DLL_CSECT();
  1189. return dsv;
  1190. }
  1191. }
  1192. }
  1193. *ppBuffer1 = pBuffer1;
  1194. *pcbBufferSize1 = cbBufferSize1;
  1195. if( (ppBuffer2 != NULL) && (pcbBufferSize2 != NULL) ) {
  1196. *ppBuffer2 = pBuffer2;
  1197. *pcbBufferSize2 = cbBufferSize2;
  1198. }
  1199. DPF(4,"Lock buffer ptr %X 1 %X 2 %X",pdsb->pDSBuffer, pBuffer1, pBuffer2);
  1200. DPF(4, "Lock offset 1 %X 2 %X ", dwWriteOffset, 0 );
  1201. DPF(4,"Exiting buffer lock method");
  1202. LEAVE_DLL_CSECT();
  1203. return DS_OK;
  1204. } // IDSHWBufferLock()
  1205. #ifdef DEBUG
  1206. DWORD dwLastTime;
  1207. #endif
  1208. #if 0
  1209. //
  1210. // !!! This code is no longer supported but is left here as a reference
  1211. // til we have complete confidence in the grace.cpp mixing code
  1212. //
  1213. VOID CALLBACK HWMixThreadCallback
  1214. (
  1215. UINT wTimerID,
  1216. UINT uMsg,
  1217. DWORD dwUser,
  1218. DWORD dw1,
  1219. DWORD dw2
  1220. )
  1221. {
  1222. volatile LPDSOUND pds;
  1223. LPDSBUFFER pdsb;
  1224. LPDSBUFFEREXTERNAL pdsbe;
  1225. UINT iCount;
  1226. LPDSBWAVEBLTI pdswb;
  1227. HRESULT hrslt;
  1228. DWORD dwPlay, dwWrite;
  1229. DWORD dwNewPos;
  1230. DWORD cbSample;
  1231. #ifdef DEBUG
  1232. DWORD dwTime;
  1233. DWORD dwEndTime;
  1234. #endif
  1235. ENTER_DLL_CSECT();
  1236. pds = (LPDSOUND)dwUser;
  1237. #pragma message( REMIND( "Find better way to synch pds in HwMixThreadCallback" ))
  1238. if (IsBadWritePtr(pds, sizeof(*pds)) || DSOUNDSIG != pds->dwSig) {
  1239. // DPF(0, "HwMixThreadCallback invalid pds=%08Xh", pds);
  1240. LEAVE_DLL_CSECT();
  1241. return;
  1242. }
  1243. #ifdef DEBUG
  1244. DPF(7,"*************** Mix Thread Prelim" );
  1245. dwTime = timeGetTime();
  1246. if( (dwTime - dwLastTime) > (pds->dwTimerDelay + (pds->dwTimerDelay)/2) ) {
  1247. DPF(0, "s %dms", dwTime - dwLastTime );
  1248. }
  1249. dwLastTime = dwTime;
  1250. DPF(5,"HW Mix Callback. %X", wTimerID );
  1251. #endif
  1252. DPF(7,"*************** Mix Thread CS " );
  1253. DPF(5,"Mix Thread " );
  1254. // Only do something if buffers (other than primary) playing
  1255. // or if a secondary buffer is jsut stopped
  1256. while( (pds->pdsbPrimary != NULL) &&
  1257. (!(pds->pdsbPrimary->fdwDsbI & DSB_INTERNALF_STOP)) &&
  1258. ((pds->dwBuffersPlaying > 0) ||
  1259. (pds->pdsbPrimary->fdwDsbI & DSB_INTERNALF_JUSTSTOPPED)) ) {
  1260. DPF(5,"Buffers playing");
  1261. // Only mix in if it is time
  1262. // Find current position
  1263. hrslt = pds->pdsbePrimary->lpVtbl->GetCurrentPosition(
  1264. (LPDIRECTSOUNDBUFFER)pds->pdsbePrimary,
  1265. &dwPlay,
  1266. &dwWrite );
  1267. if(DS_OK != hrslt) {
  1268. DPF(1,"ERROR DS getpos return %ld obj %X buff %X ",
  1269. hrslt, pds, pds->pdsbPrimary);
  1270. }
  1271. dwNewPos = ((pds->dwLastCopyPlayPos +
  1272. pds->pdsbPrimary->cbFracSecondSize) %
  1273. pds->pdsbPrimary->cbBufferSize);
  1274. // If PLAY <= NEW
  1275. // Do not do blt unless
  1276. // New in last frac and Play in 1st frac
  1277. // If PLAY > NEW
  1278. // Blt unless new is First and play in last frac
  1279. //
  1280. if( dwPlay > dwNewPos ) {
  1281. // Play > New
  1282. if( ((dwPlay + pds->pdsbPrimary->cbFracSecondSize) >
  1283. pds->pdsbPrimary->cbBufferSize) &&
  1284. (dwNewPos < pds->pdsbPrimary->cbFracSecondSize) ) {
  1285. // Play is in last frac and new us in 1st
  1286. // Do not blt
  1287. DPF( 5, "DO NOT BLT Play > New but new has wrapped " );
  1288. LEAVE_DLL_CSECT();
  1289. return;
  1290. } else {
  1291. // Blt new has not wrapped
  1292. DPF( 5, "BLT Play > New" );
  1293. }
  1294. } else {
  1295. // Play <= New
  1296. if( ((dwNewPos + pds->pdsbPrimary->cbFracSecondSize) >
  1297. pds->pdsbPrimary->cbBufferSize) &&
  1298. (dwPlay < pds->pdsbPrimary->cbFracSecondSize) ) {
  1299. // New is in last frac and Play in 1st
  1300. // Do blt
  1301. DPF( 5, "BLT Play <= New and play has wrapped " );
  1302. } else {
  1303. // Do not blt play has not wrapped
  1304. DPF( 5, "DO NOT BLT Play > New" );
  1305. LEAVE_DLL_CSECT();
  1306. return;
  1307. }
  1308. }
  1309. DPF(5," LAST COPY %X NEW %X ",pds->dwLastCopyPlayPos,dwNewPos);
  1310. DPF(5," Play %X write %X LastCopyPos %X",dwPlay, dwWrite,
  1311. pds->dwLastCopyPos);
  1312. pds->dwLastCopyPlayPos = dwNewPos;
  1313. // Set up blt info for dst
  1314. // Note that size of the BLT struct is set at init time.
  1315. pdswb = pds->pdswb;
  1316. pdswb->dwPosition = pds->dwLastCopyPos;
  1317. pdswb->cbCopyLength = pds->pdsbPrimary->cbFracSecondSize;
  1318. pdswb->fdwWaveBlt = DSBBLT_COPY;
  1319. pdswb->dwCount = 0;
  1320. DPF(5,"Focus Window hwnd=%08X", gpdsinfo->hwndSoundFocus);
  1321. // Get data for each buffer
  1322. iCount = 0;
  1323. pdsb = pds->pdsb;
  1324. while( pdsb != NULL ) {
  1325. DPF( 5, "PDSB %X Window %X", pdsb, pdsb->dsbe.hwndOwner );
  1326. if( (pdsb != pds->pdsbPrimary) &&
  1327. (!(pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE)) &&
  1328. (!(pdsb->fdwDsbI & DSB_INTERNALF_STOP)) &&
  1329. (pdsb->dsbe.hwndOwner == gpdsinfo->hwndSoundFocus) ) {
  1330. // We have a buffer that needs to be blt.
  1331. pdswb->padswbs[iCount].pdsbe = &pdsb->dsbe;
  1332. pdswb->padswbs[iCount].dwPosition = pdsb->dwNextCopyPos;
  1333. pdswb->padswbs[iCount].cbCopyLength = 0;
  1334. pdswb->padswbs[iCount].fdwWaveBltBuffer =
  1335. DSBBLTSRC_USEDSTLENGTH;
  1336. // If we are looping - set the flag for this buffer
  1337. if( pdsb->helInfo.hfFormat & H_LOOP ) {
  1338. pdswb->padswbs[iCount].fdwWaveBltBuffer |=
  1339. DSBBLT_BLTTODSTEND;
  1340. }
  1341. iCount++;
  1342. if( iCount >= LIMIT_BLT_SOURCES ) {
  1343. DPF(1,"PLAY ERROR TOO MANY BUFFERS ");
  1344. break;
  1345. }
  1346. }
  1347. pdsb = pdsb->pNext;
  1348. }
  1349. DPF(5,"Non Primary Buffers playing %X", iCount);
  1350. pdswb->dwCount = iCount;
  1351. hrslt = pds->pdsbePrimary->lpVtbl->WaveBlt(
  1352. (LPDIRECTSOUNDBUFFER)pds->pdsbePrimary,
  1353. (LPDSBWAVEBLT)pdswb);
  1354. if(DS_OK != hrslt) {
  1355. DPF(1,"PLAY ERROR DS Blt failed ");
  1356. }
  1357. // Now reset postions
  1358. iCount = 0;
  1359. pdsb = pds->pdsb;
  1360. while( pdsb != NULL ) {
  1361. if( (pdsb != pds->pdsbPrimary) &&
  1362. (!(pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE)) &&
  1363. (!(pdsb->fdwDsbI & DSB_INTERNALF_STOP)) ) {
  1364. if( (pdsb->dsbe.hwndOwner == gpdsinfo->hwndSoundFocus) ) {
  1365. // We have a buffer that was blt.
  1366. pdsb->dwNextCopyPos = pdswb->padswbs[iCount].dwPosition;
  1367. // Check to see if we are at the end and need to
  1368. // stop playing
  1369. // We only stop on non-looped buffers
  1370. if( !(pdswb->padswbs[iCount].fdwWaveBltBuffer &
  1371. DSBBLT_BLTTODSTEND) &&
  1372. ((pdsb->dwNextCopyPos >= pdsb->cbBufferSize) ||
  1373. (pdsb->dwNextCopyPos < 20 )) ) {
  1374. // HACK HACK - Watch for less than 20
  1375. // Instead of 0 since playback may wrap when
  1376. // Playback frequency is higher than value converted to
  1377. // For primary....
  1378. DPF(3,"Stop NON Looping buffer %X", pdsb);
  1379. // Buffer is not looped and
  1380. // Next copy is to be at end
  1381. pdsbe = &(pdsb->dsbe);
  1382. pdsbe->lpVtbl->Stop( (LPDIRECTSOUNDBUFFER)pdsbe );
  1383. // Note that the stop may kill off the primary buffer
  1384. // If primary was allocated at play time
  1385. // Set pos of next play back to start
  1386. pdsb->dwNextCopyPos = 0;
  1387. }
  1388. // Inc count into blt array
  1389. iCount++;
  1390. if( iCount >= LIMIT_BLT_SOURCES ) {
  1391. DPF(1,"PLAY ERROR TOO MANY BUFFERS ");
  1392. break;
  1393. }
  1394. } else {
  1395. // Buffer is playing, but is not from active app
  1396. // just advance pointers.
  1397. // We have a buffer that was blt.
  1398. pdsb->dwNextCopyPos += pdsb->cbFracSecondSize;
  1399. DPF(5,"Advance non active buffer %X by %X pos %X",
  1400. pdsb, pdsb->cbFracSecondSize, pdsb->dwNextCopyPos );
  1401. // Check to see if we are at the end and need to
  1402. // stop playing
  1403. // We only stop on non-looped buffers
  1404. if( (!(pdsb->helInfo.hfFormat & H_LOOP)) &&
  1405. ((pdsb->dwNextCopyPos >= pdsb->cbBufferSize) ||
  1406. (pdsb->dwNextCopyPos < 20 )) ) {
  1407. // HACK HACK - Watch for less than 20
  1408. // Instead of 0 since playback may wrap when
  1409. // Playback frequency is higher than value converted to
  1410. // For primary....
  1411. DPF(3,"Stop NON Looping bufferg %X", pdsb);
  1412. // Buffer is not looped and
  1413. // Next copy is to be at end
  1414. pdsbe = &(pdsb->dsbe);
  1415. pdsbe->lpVtbl->Stop( (LPDIRECTSOUNDBUFFER)pdsbe );
  1416. // Note that the stop may kill off the primary buffer
  1417. // If primary was allocated at play time
  1418. // Set pos of next play back to start
  1419. pdsb->dwNextCopyPos = 0;
  1420. } else {
  1421. // else if looping then wrap buffer
  1422. if( (pdsb->pwfx) && (pdsb->pwfx->nBlockAlign) ) {
  1423. cbSample = pdsb->pwfx->nBlockAlign;
  1424. } else {
  1425. cbSample = 4;
  1426. }
  1427. pdsb->dwNextCopyPos = (pdsb->dwNextCopyPos %
  1428. pdsb->cbBufferSize);
  1429. pdsb->dwNextCopyPos -= (pdsb->dwNextCopyPos%cbSample);
  1430. }
  1431. }
  1432. }
  1433. pdsb = pdsb->pNext;
  1434. }
  1435. // Primary buffer may no longer exist just exit if so....
  1436. if( pds->pdsbPrimary != NULL ) {
  1437. // Blt has been done advance pointers....
  1438. pds->dwLastCopyPos += pds->pdsbPrimary->cbFracSecondSize;
  1439. pds->dwLastCopyPos = pds->dwLastCopyPos %
  1440. pds->pdsbPrimary->cbBufferSize;
  1441. } else {
  1442. DPF(0,"****** ERROR, Primary now NULL in MIX ******");
  1443. }
  1444. }
  1445. #ifdef NOCOMP
  1446. if( pds->dwBuffersPlaying <= 0 ) {
  1447. if( pds->pdsbPrimary->fdwBuffer & DSBUFFERF_JUSTSTOPPED) {
  1448. DPF(3,"JustStop: Fill buffer");
  1449. pds->pdsbPrimary->fdwBuffer &= (~DSBUFFERF_JUSTSTOPPED);
  1450. // Set up blt info for dst
  1451. pdswb = pds->pdswb;
  1452. pdswb->dwPosition = 0;
  1453. pdswb->cbCopyLength = pds->pdsbPrimary->cbBufferSize;
  1454. pdswb->fdwWaveBlt = DSBBLT_COPY;
  1455. pdswb->dwCount = 0;
  1456. //ifndef HACKONBLTSIZE
  1457. if( pds->pdsbPrimary->pwfx->wBitsPerSample == 8 ) {
  1458. // Eight bit set to NULL value of 128
  1459. _fmemset( pds->pdsbPrimary->pDSBuffer,
  1460. 128,
  1461. pdswb->cbCopyLength);
  1462. } else {
  1463. // Sixteen bit set to NULL value of 0
  1464. _fmemset( pds->pdsbPrimary->pDSBuffer,
  1465. 0,
  1466. pdswb->cbCopyLength);
  1467. }
  1468. //else
  1469. hrslt = pds->pdsbPrimary->lpVtbl->WaveBlt(
  1470. (LPDIRECTSOUNDBUFFER)pds->pdsbPrimary,
  1471. (LPDSBWAVEBLT)pdswb);
  1472. if(DS_OK != hrslt) {
  1473. DPF(1,"PLAY ERROR FILL Blt failed ");
  1474. }
  1475. //endif
  1476. }
  1477. }
  1478. #endif
  1479. #ifdef DEBUG
  1480. dwEndTime = timeGetTime();
  1481. if( (dwEndTime - dwTime) > (pds->dwTimerDelay)/2 ) {
  1482. DPF(0, "d %dms", dwEndTime - dwTime );
  1483. }
  1484. #endif
  1485. LEAVE_DLL_CSECT();
  1486. } // HWMixThreadCallback()
  1487. #endif // !USEGRACE
  1488. HRESULT FAR PASCAL IDSHWBufferPlay
  1489. (
  1490. LPDIRECTSOUNDBUFFER pidsb,
  1491. DWORD dwReserved1,
  1492. DWORD dwReserved2,
  1493. DWORD fdwPlay
  1494. )
  1495. {
  1496. LPDSOUND pds;
  1497. LPDSBUFFER pdsb;
  1498. LPDSBUFFEREXTERNAL pdsbe;
  1499. DWORD dwPlay, dwWrite;
  1500. BOOL fResetDevice;
  1501. DPF(5, ";;Dump debug queue");
  1502. DPF(1,"Entering HW Play method pdsb %X flags %X",
  1503. pidsb, fdwPlay );
  1504. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  1505. RPF("IDirectSoundBuffer::Play - Invalid Object or ref count");
  1506. return DSERR_INVALIDPARAM;
  1507. }
  1508. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  1509. pdsb = pdsbe->pdsb;
  1510. pds = pdsb->pds;
  1511. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  1512. RPF("IDirectSoundBuffer::Play - Invalid Object or ref count");
  1513. return DSERR_INVALIDPARAM;
  1514. }
  1515. ASSERT( DSBUFFSIG == pdsb->dwSig );
  1516. if( fdwPlay & (~DSBPLAY_VALIDFLAGS)) {
  1517. RPF("IDirectSoundBuffer::Play - Invalid flags passed to Play");
  1518. return DSERR_INVALIDPARAM;
  1519. }
  1520. if((0 != dwReserved1) || (0 != dwReserved2)) {
  1521. RPF("IDirectSoundBuffer::Play - Reserved parameters were non-zero!");
  1522. return DSERR_INVALIDPARAM;
  1523. }
  1524. if (pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) {
  1525. return DSERR_BUFFERLOST;
  1526. }
  1527. ENTER_DLL_CSECT();
  1528. // If this is not our internal primary, then check for priority
  1529. if( pdsbe != pds->pdsbePrimary ) {
  1530. if( (pdsbe->dwPriority < DSSCL_NORMAL)
  1531. || (pdsbe->dwPriority > DSSCL_WRITEPRIMARY)) {
  1532. RPF("IDirectSoundBuffer::Play - Invalid priority level or buffer owner");
  1533. LEAVE_DLL_CSECT();
  1534. return DSERR_PRIOLEVELNEEDED;
  1535. }
  1536. }
  1537. //
  1538. // Fail if app has WRITEPRIMARY access and tries to play a secondary.
  1539. //
  1540. if( ( DSSCL_WRITEPRIMARY == pdsbe->dwPriority ) &&
  1541. !( pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY ) )
  1542. {
  1543. RPF("IDirectSoundBuffer::Play - Can't play secondary buffers when you have DSSCL_WRITEPRIMARY access.");
  1544. LEAVE_DLL_CSECT();
  1545. return DSERR_INVALIDCALL;
  1546. }
  1547. // If this is primary, then we cannot play without looping
  1548. if ((pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) &&
  1549. !(fdwPlay & DSBPLAY_LOOPING))
  1550. {
  1551. RPF("IDirectSoundBuffer::Play - Can't play Primary without LOOPING");
  1552. LEAVE_DLL_CSECT();
  1553. return DSERR_INVALIDPARAM;
  1554. }
  1555. // If the primary dsbe object's priority is less than WRITEPRIMARY then
  1556. // we set a flag saying that the external primary is playing and inc a
  1557. // count of external primaries that have playing status.
  1558. if( (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) &&
  1559. (pdsbe->dwPriority < DSSCL_WRITEPRIMARY) )
  1560. {
  1561. // Set flag saying the external primary is playing.
  1562. if (!(pdsbe->fdwDsbeI & DSBE_INTERNALF_PLAYING)) {
  1563. pdsbe->fdwDsbeI |= DSBE_INTERNALF_PLAYING;
  1564. pds->cPlayPrimary++;
  1565. ASSERT(pds->cPlayPrimary > 0);
  1566. }
  1567. LEAVE_DLL_CSECT();
  1568. return DS_OK;
  1569. }
  1570. // Since hardware buffers can't notify us when they have stopped, we poll
  1571. // them by calling GetCurrentPosition on them. The GetCurrentPosition
  1572. // method will check whether the buffer has stopped and update its status.
  1573. if ((pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE) &&
  1574. !(pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) &&
  1575. !(pdsb->fdwDsbI & DSB_INTERNALF_STOP))
  1576. {
  1577. DWORD dwPlay, dwWrite;
  1578. IDirectSoundBuffer_GetCurrentPosition(pidsb, &dwPlay, &dwWrite);
  1579. }
  1580. // If it is already playing, then we only need to worry about
  1581. // changes in LOOPING
  1582. if(!(pdsb->fdwDsbI & DSB_INTERNALF_STOP))
  1583. {
  1584. // it is already playing...
  1585. // Reset looping flags
  1586. // If the looping has changed then reset the HW device
  1587. fResetDevice = FALSE;
  1588. if(DSBPLAY_LOOPING & fdwPlay) {
  1589. if( !(pdsb->fdwDsbI & DSB_INTERNALF_LOOPING) ) {
  1590. fResetDevice = TRUE;
  1591. }
  1592. pdsb->fdwDsbI |= DSB_INTERNALF_LOOPING;
  1593. pdsb->helInfo.hfFormat |= H_LOOP;
  1594. } else {
  1595. if( pdsb->fdwDsbI & DSB_INTERNALF_LOOPING ) {
  1596. fResetDevice = TRUE;
  1597. }
  1598. pdsb->fdwDsbI &= (~DSB_INTERNALF_LOOPING);
  1599. pdsb->helInfo.hfFormat &= (~H_LOOP);
  1600. }
  1601. // If there was a change then either call the ds driver or
  1602. // call the mixer to remix
  1603. if (fResetDevice) {
  1604. if (pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE) {
  1605. vxdBufferPlay(pdsb->hBuffer, dwReserved1, dwReserved2,
  1606. fdwPlay & DSBPLAY_DRIVERFLAGSMASK);
  1607. } else if (!(pds->fdwInternal & DS_INTERNALF_WAVEEMULATED)) {
  1608. mxSignalRemix(pds, 0);
  1609. }
  1610. }
  1611. DPF(1,"Play: Exit - Already playing %X", pdsb);
  1612. LEAVE_DLL_CSECT();
  1613. return DS_OK;
  1614. }
  1615. // If this is the primary being told to play
  1616. if( pdsb == pds->pdsbPrimary ) {
  1617. // This is the primary being told to play
  1618. // Check to see if we are on the WAVE apis
  1619. if( pdsb->fdwDsbI & DSB_INTERNALF_WAVEEMULATED ) {
  1620. // Primary is always playing
  1621. // do nothing
  1622. DPF(1,"Playing Wave Emulated Primary %X", pdsb);
  1623. LEAVE_DLL_CSECT();
  1624. return DS_OK;
  1625. }
  1626. } else {
  1627. // If this is not a HW buffer then start the primary playing
  1628. if( !(pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE) ) {
  1629. // Start primary playing
  1630. // Note that we can say play again even though it is already
  1631. // playing
  1632. pds->pdsbePrimary->lpVtbl->Play(
  1633. (LPDIRECTSOUNDBUFFER)(pds->pdsbePrimary),
  1634. 0, 0,
  1635. (DSBPLAY_SECONDARY | DSBPLAY_LOOPING) );
  1636. }
  1637. }
  1638. dwPlay = 0;
  1639. dwWrite = 0;
  1640. if(DSBPLAY_LOOPING & fdwPlay) {
  1641. pdsb->fdwDsbI |= DSB_INTERNALF_LOOPING;
  1642. pdsb->helInfo.hfFormat |= H_LOOP;
  1643. } else {
  1644. pdsb->fdwDsbI &= (~DSB_INTERNALF_LOOPING);
  1645. pdsb->helInfo.hfFormat &= (~H_LOOP);
  1646. }
  1647. // If we are doing a play on the primary then
  1648. // start it off for mixing....
  1649. // Only do this if the play was forced by the secondary
  1650. // If it was not secondary forced, then user is locking and
  1651. // We do not need a primary
  1652. if( (pdsb == pds->pdsbPrimary) && (fdwPlay & DSBPLAY_SECONDARY) ) {
  1653. // Note that WaveEmulated Primary returned OK before this
  1654. ASSERT( !(pdsb->fdwDsbI & DSB_INTERNALF_WAVEEMULATED) );
  1655. DsbFillSilence( pdsb );
  1656. }
  1657. // If this is a primary buffer then we set its mixer state to START. This
  1658. // tells the mixer that it hasn't yet been mixed into.
  1659. if (DSB_INTERNALF_PRIMARY & pdsb->fdwDsbI) {
  1660. pdsb->iMixerState = DSPBMIXERSTATE_START;
  1661. }
  1662. //
  1663. //
  1664. pdsb->fdwDsbI &= (~DSB_INTERNALF_STOP);
  1665. // If we are playing on a HW buffer then tell the HW to play. Otherwise
  1666. // signal the mixer that we need to remix.
  1667. if( pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE ) {
  1668. DPF(2, "IDSHWPlay: note: playing hardware buffer");
  1669. vxdBufferPlay(pdsb->hBuffer, dwReserved1, dwReserved2,
  1670. fdwPlay & DSBPLAY_DRIVERFLAGSMASK);
  1671. } else {
  1672. // Add this to the mix list and signal the mixer. pdsb->posNextMix
  1673. // should be the desired starting position in this buffer (either 0 if
  1674. // never played or set by the last Stop or SetCurrentPosition
  1675. if( !(pdsb->fdwDsbI & DSB_INTERNALF_WAVEEMULATED )) {
  1676. mxListAdd(pdsb);
  1677. mxSignalRemix(pds, 0);
  1678. }
  1679. }
  1680. // Buffer is to play increase count
  1681. if( (pdsb != pds->pdsbPrimary) &&
  1682. (!(pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE)) ) {
  1683. pds->dwBuffersPlaying++;
  1684. }
  1685. DPF(1,"Playing presumably successful %X", pdsb);
  1686. LEAVE_DLL_CSECT();
  1687. return DS_OK;
  1688. } // IDSHWBufferPlay()
  1689. HRESULT FAR PASCAL IDSHWBufferSetCurrentPosition
  1690. (
  1691. LPDIRECTSOUNDBUFFER pidsb,
  1692. DWORD dwNewPos
  1693. )
  1694. {
  1695. LPDSOUND pds;
  1696. LPDSBUFFER pdsb;
  1697. LPDSBUFFEREXTERNAL pdsbe;
  1698. HRESULT hr;
  1699. DPF(4,"Entering buffer set position method");
  1700. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  1701. RPF("IDirectSoundBuffer::SetCurrentPosition - Invalid Object or ref count");
  1702. return DSERR_INVALIDPARAM;
  1703. }
  1704. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  1705. pdsb = pdsbe->pdsb;
  1706. pds = pdsb->pds;
  1707. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  1708. RPF("IDirectSoundBuffer::SetCurrentPosition - Invalid Object or ref count");
  1709. return DSERR_INVALIDPARAM;
  1710. }
  1711. ASSERT( DSBUFFSIG == pdsb->dwSig );
  1712. if (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) {
  1713. ASSERT(pds->pdsbPrimary == pdsb);
  1714. RPF("IDirectSoundBuffer::SetCurrentPosition - Illegal to SetCurrentPosition on primary");
  1715. return DSERR_INVALIDCALL;
  1716. }
  1717. // Since hardware buffers can't notify us when they have stopped, we poll
  1718. // them by calling GetCurrentPosition on them. The GetCurrentPosition
  1719. // method will check whether the buffer has stopped and update its status.
  1720. // We must do this before calling SetPosition otherwise we would set a new
  1721. // position before we found out whether the buffer was stopped.
  1722. if (pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE) {
  1723. DWORD dwPlay, dwWrite;
  1724. IDirectSoundBuffer_GetCurrentPosition(pidsb, &dwPlay, &dwWrite);
  1725. }
  1726. //
  1727. // Make sure we're sample-aligned.
  1728. //
  1729. dwNewPos >>= pdsb->uBlockAlignShift;
  1730. dwNewPos <<= pdsb->uBlockAlignShift;
  1731. ENTER_DLL_CSECT();
  1732. if( (pdsbe->dwPriority < DSSCL_NORMAL)
  1733. || (pdsbe->dwPriority > DSSCL_WRITEPRIMARY) ) {
  1734. RPF("IDirectSoundBuffer::SetCurrentPosition - Invalid priority level or buffer owner");
  1735. LEAVE_DLL_CSECT();
  1736. return DSERR_PRIOLEVELNEEDED;
  1737. }
  1738. if( dwNewPos >= pdsb->cbBufferSize) {
  1739. RPF("IDirectSoundBuffer::SetCurrentPosition - Invalid Position");
  1740. LEAVE_DLL_CSECT();
  1741. return DSERR_INVALIDPARAM;
  1742. }
  1743. if (pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) {
  1744. pdsb->fdwDsbI |= DSB_INTERNALF_SETPOS_WHILE_LOST;
  1745. pdsb->dwSavePosition = dwNewPos;
  1746. DPF(4, "Early out - set position while buffer lost");
  1747. LEAVE_DLL_CSECT();
  1748. return DS_OK;
  1749. }
  1750. hr = IDsbSetCurrentPositionI(pdsb, dwNewPos);
  1751. DPF(4,"Exiting buffer set position method");
  1752. LEAVE_DLL_CSECT();
  1753. return hr;
  1754. } // IDSHWBufferSetCurrentPosition()
  1755. HRESULT FAR PASCAL IDSHWBufferSetFormat
  1756. (
  1757. LPDIRECTSOUNDBUFFER pidsb,
  1758. LPWAVEFORMATEX pwfx
  1759. )
  1760. {
  1761. LPDSOUND pds;
  1762. LPDSOUNDEXTERNAL pdse;
  1763. LPDSBUFFER pdsb;
  1764. LPDSBUFFEREXTERNAL pdsbe;
  1765. LPWAVEFORMATEX pwfxNew;
  1766. int cbFormat;
  1767. HRESULT hr;
  1768. DPF(3,"Entering HW buffer set format method");
  1769. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  1770. RPF("IDirectSoundBuffer::SetFormat - Invalid Object or ref count");
  1771. return DSERR_INVALIDPARAM;
  1772. }
  1773. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  1774. pdsb = pdsbe->pdsb;
  1775. pdse = pdsbe->pdse;
  1776. pds = pdsb->pds;
  1777. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  1778. RPF("IDirectSoundBuffer::SetFormat - Invalid Object or ref count");
  1779. return DSERR_INVALIDPARAM;
  1780. }
  1781. ASSERT( DSBUFFSIG == pdsb->dwSig );
  1782. if( !VALID_WAVEFORMATEX_PTR(pwfx) ) {
  1783. RPF("IDirectSoundBuffer::SetFormat - Invalid Format Description");
  1784. return DSERR_BADFORMAT;
  1785. }
  1786. if( !ValidPCMFormat( pwfx ) ) {
  1787. RPF("IDirectSoundBuffer::SetFormat - Invalid Format Description");
  1788. return DSERR_BADFORMAT;
  1789. }
  1790. ENTER_DLL_CSECT();
  1791. if( (pdsbe->dwPriority < DSSCL_NORMAL)
  1792. || (pdsbe->dwPriority > DSSCL_WRITEPRIMARY) )
  1793. {
  1794. RPF("IDirectSoundBuffer::SetFormat - Invalid priority level or buffer owner");
  1795. LEAVE_DLL_CSECT();
  1796. return DSERR_PRIOLEVELNEEDED;
  1797. }
  1798. //
  1799. // We don't support this function for NORMAL apps.
  1800. //
  1801. if (pdsbe->dwPriority <= DSSCL_NORMAL) {
  1802. RPF("IDirectSoundBuffer::SetFormat - called by NORMAL app - need PRIORITY cooperative level or higher.");
  1803. LEAVE_DLL_CSECT();
  1804. return DSERR_PRIOLEVELNEEDED;
  1805. }
  1806. //
  1807. // This function is supported only for primary buffers.
  1808. //
  1809. if (0 == (DSB_INTERNALF_PRIMARY & pdsb->fdwDsbI)) {
  1810. RPF("IDirectSoundBuffer::SetFormat - Called on secondary buffer - only valid for primaries.");
  1811. LEAVE_DLL_CSECT();
  1812. return DSERR_INVALIDCALL;
  1813. }
  1814. //
  1815. // Verify that this is a valid format for this card.
  1816. //
  1817. if( DS_OK != DseVerifyValidFormat( pdse, pwfx ) )
  1818. {
  1819. RPF("IDirectSoundBuffer::SetFormat - Invalid Format Description for this card");
  1820. LEAVE_DLL_CSECT();
  1821. return DSERR_BADFORMAT;
  1822. }
  1823. //
  1824. // Copy the new app format
  1825. //
  1826. cbFormat = SIZEOF_WAVEFORMATEX(pwfx);
  1827. pwfxNew = (LPWAVEFORMATEX)MemAlloc(cbFormat);
  1828. if (NULL == pwfxNew) {
  1829. RPF("IDirectSoundBuffer::SetFormat - Out of memory for app's new format");
  1830. LEAVE_DLL_CSECT();
  1831. return DSERR_OUTOFMEMORY;
  1832. }
  1833. CopyMemory(pwfxNew, pwfx, cbFormat);
  1834. // If this buffer is lost, then we need to save the format and retry
  1835. // the set format when restore is called
  1836. //
  1837. if (pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) {
  1838. // If someone has already done this, override them -- free the
  1839. // previous format change and replace it with this one
  1840. //
  1841. if (pdsb->fdwDsbI & DSB_INTERNALF_WFX_WHILE_LOST) {
  1842. MemFree(pdsb->pwfxSave);
  1843. }
  1844. pdsb->fdwDsbI |= DSB_INTERNALF_WFX_WHILE_LOST;
  1845. pdsb->pwfxSave = pwfxNew;
  1846. DPF(4, "Early out - set wave format of primary while lost");
  1847. LEAVE_DLL_CSECT();
  1848. return DS_OK;
  1849. }
  1850. //
  1851. // Now we need to decide whether to actually change the format of
  1852. // the internal primary buffer
  1853. //
  1854. // Quite simply, if this app has sound focus, then we set the format
  1855. // of the internal primary buffer.
  1856. //
  1857. if (pdse->tidSound == gpdsinfo->tidSoundFocus || pdse->tidSound == gpdsinfo->tidStuckFocus) {
  1858. hr = IDsbSetFormatI(pdsb, pwfxNew, 0);
  1859. if (DS_OK != hr) {
  1860. DPF(0, "SetFormat: error: IDsbSetFormatI returned %08Xh", hr);
  1861. LEAVE_DLL_CSECT();
  1862. MemFree(pwfxNew);
  1863. return hr;
  1864. }
  1865. }
  1866. //
  1867. // Everything worked, so we save the app's new format in the app's
  1868. // pdse object, replacing any existing app format that might be there.
  1869. //
  1870. if (NULL != pdse->pwfxApp) {
  1871. DPF(1, "SetFormat: note: Freeing previous app format");
  1872. MemFree(pdse->pwfxApp);
  1873. }
  1874. pdse->pwfxApp = pwfxNew;
  1875. DPF(3,"Exiting buffer set format method");
  1876. LEAVE_DLL_CSECT();
  1877. return DS_OK;
  1878. } // IDSHWBufferSetFormat()
  1879. HRESULT FAR PASCAL IDSHWBufferSetVolume
  1880. (
  1881. LPDIRECTSOUNDBUFFER pidsb,
  1882. LONG lVolume
  1883. )
  1884. {
  1885. LPDSOUND pds;
  1886. LPDSBUFFER pdsb;
  1887. LPDSBUFFEREXTERNAL pdsbe;
  1888. LONG lPan;
  1889. LONG lTotalLeftDB;
  1890. LONG lTotalRightDB;
  1891. DSVOLUMEPAN dsVolPan;
  1892. DPF(3,"Entering buffer set volume method");
  1893. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  1894. RPF("IDirectSoundBuffer::SetVolume - Invalid Object or ref count");
  1895. return DSERR_INVALIDPARAM;
  1896. }
  1897. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  1898. pdsb = pdsbe->pdsb;
  1899. pds = pdsb->pds;
  1900. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  1901. RPF("IDirectSoundBuffer::SetVolume - Invalid Object or ref count");
  1902. return DSERR_INVALIDPARAM;
  1903. }
  1904. ASSERT( DSBUFFSIG == pdsb->dwSig );
  1905. if(( lVolume < -10000 ) || ( lVolume > 0 )) {
  1906. RPF("IDirectSoundBuffer::SetVolume - Volume: %l out of range", lVolume);
  1907. return DSERR_INVALIDPARAM;
  1908. }
  1909. ENTER_DLL_CSECT();
  1910. if (pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) {
  1911. pdsb->fdwDsbI |= DSB_INTERNALF_VOLUME_WHILE_LOST;
  1912. pdsb->lSaveVolume = lVolume;
  1913. DPF(4, "Early out - set volume while buffer lost");
  1914. LEAVE_DLL_CSECT();
  1915. return DS_OK;
  1916. }
  1917. // Only primary buffers may have CTRLVOLUMEPRIMARY set.
  1918. ASSERT( !(pdsbe->fdwDsbeI&DSBE_INTERNALF_CTRLVOLUMEPRIMARY) ||
  1919. (pdsb->fdwDsbI&DSB_INTERNALF_PRIMARY) );
  1920. if( !(pdsb->fdwBufferDesc & DSBCAPS_CTRLVOLUME) &&
  1921. !(pdsbe->fdwDsbeI & DSBE_INTERNALF_CTRLVOLUMEPRIMARY) )
  1922. {
  1923. RPF("IDirectSoundBuffer::SetVolume - Caller did not have CTRL permission for Volume!");
  1924. LEAVE_DLL_CSECT();
  1925. return DSERR_CONTROLUNAVAIL;
  1926. }
  1927. if( (pdsbe->dwPriority < DSSCL_NORMAL)
  1928. || (pdsbe->dwPriority > DSSCL_WRITEPRIMARY) ) {
  1929. RPF("IDirectSoundBuffer::SetVolume - Invalid priority level or buffer owner");
  1930. LEAVE_DLL_CSECT();
  1931. return DSERR_PRIOLEVELNEEDED;
  1932. }
  1933. pdsb->helInfo.lVolume = lVolume;
  1934. lPan = pdsb->helInfo.lPan;
  1935. //
  1936. // Compute multpliers (scaling factors) for the mixer to use
  1937. //
  1938. if (lPan >= 0) {
  1939. // left is attenuated
  1940. lTotalLeftDB = lVolume - lPan ;
  1941. lTotalRightDB = lVolume;
  1942. } else {
  1943. // right is attenuated
  1944. lTotalLeftDB = lVolume;
  1945. lTotalRightDB = lVolume - (-lPan);
  1946. }
  1947. dsVolPan.dwTotalLeftAmpFactor = DBToAmpFactor(lTotalLeftDB);
  1948. dsVolPan.dwTotalRightAmpFactor = DBToAmpFactor(lTotalRightDB);
  1949. dsVolPan.lVolume = lVolume;
  1950. dsVolPan.dwVolAmpFactor = DBToAmpFactor(lVolume);
  1951. dsVolPan.lPan = pdsb->helInfo.lPan;
  1952. if (lPan >= 0) {
  1953. // left is attenuated
  1954. dsVolPan.dwPanLeftAmpFactor = DBToAmpFactor(-lPan);
  1955. dsVolPan.dwPanRightAmpFactor = DBToAmpFactor(0);
  1956. } else {
  1957. // right is attenuated
  1958. dsVolPan.dwPanLeftAmpFactor = DBToAmpFactor(0);
  1959. dsVolPan.dwPanRightAmpFactor = DBToAmpFactor(lPan);
  1960. }
  1961. pdsb->helInfo.dwLVolume = dsVolPan.dwTotalLeftAmpFactor;
  1962. pdsb->helInfo.dwRVolume = dsVolPan.dwTotalRightAmpFactor;
  1963. pdsb->helInfo.dwMVolume = (pdsb->helInfo.dwLVolume + pdsb->helInfo.dwRVolume)/2;
  1964. DPF(3," Volume %ld Pan %ld left %Xh right %Xh ",
  1965. pdsb->helInfo.lVolume, pdsb->helInfo.lPan,
  1966. pdsb->helInfo.dwLVolume, pdsb->helInfo.dwRVolume );
  1967. if( pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE ) {
  1968. // Will this work on wave-em primaries??? [ask jimge]
  1969. if (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) {
  1970. WAVEOUTCAPS woc;
  1971. DWORD dwWaveVolume;
  1972. UINT uWaveId;
  1973. // Anyone can always set the volume on the primary
  1974. ASSERT(dsVolPan.dwTotalLeftAmpFactor <= 0xffff);
  1975. ASSERT(dsVolPan.dwTotalRightAmpFactor <= 0xffff);
  1976. if ( (DS_OK == wavGetIdFromDrvGuid(&pds->guid, &uWaveId)) &&
  1977. (!waveOutGetDevCaps(uWaveId, &woc, sizeof(woc))) )
  1978. {
  1979. if (woc.dwSupport & WAVECAPS_VOLUME) {
  1980. if (woc.dwSupport & WAVECAPS_LRVOLUME) {
  1981. dwWaveVolume = dsVolPan.dwTotalLeftAmpFactor;
  1982. dwWaveVolume |= dsVolPan.dwTotalRightAmpFactor << 16;
  1983. } else {
  1984. dwWaveVolume = dsVolPan.dwTotalLeftAmpFactor;
  1985. dwWaveVolume += dsVolPan.dwTotalRightAmpFactor;
  1986. dwWaveVolume /= 2;
  1987. }
  1988. if (!waveOutSetVolume((HWAVEOUT)uWaveId, dwWaveVolume)) {
  1989. // We never create primaries w/ CTRLVOLUME
  1990. #if 0
  1991. DPF(3," HW Change volume %l ", lVolume );
  1992. if( vxdBufferSetVolumePan( pdsb->hBuffer, &dsVolPan ) != DS_OK ) {
  1993. DPF(1," HAL Change VolumePan FAILED!!! ");
  1994. LEAVE_DLL_CSECT();
  1995. return DSERR_GENERIC;
  1996. }
  1997. DPF(3," Changed HW format ");
  1998. #endif
  1999. }
  2000. }
  2001. }
  2002. } else {
  2003. //
  2004. // This is a HW buffer so set the Volume to the device.
  2005. //
  2006. // If this buffer's app doesn't have sound focus, then we
  2007. // won't actually call the driver- the volume has been minimized
  2008. // in order to mute the buffer while the app is out of sound focus
  2009. //
  2010. if (!pdsbe->pdsb->fMixerMute) {
  2011. DPF(3," HW Change volume %l ", lVolume );
  2012. if( vxdBufferSetVolumePan( pdsb->hBuffer, &dsVolPan ) != DS_OK ) {
  2013. DPF(1," HAL Change VolumePan FAILED!!! ");
  2014. LEAVE_DLL_CSECT();
  2015. return DSERR_GENERIC;
  2016. }
  2017. DPF(3," Changed HW format ");
  2018. }
  2019. }
  2020. }
  2021. DPF(3,"Exiting set volume method");
  2022. LEAVE_DLL_CSECT();
  2023. return DS_OK;
  2024. } // IDSHWBufferSetVolume()
  2025. HRESULT FAR PASCAL IDSHWBufferSetPan
  2026. (
  2027. LPDIRECTSOUNDBUFFER pidsb,
  2028. LONG lPan
  2029. )
  2030. {
  2031. LPDSOUND pds;
  2032. LPDSBUFFER pdsb;
  2033. LPDSBUFFEREXTERNAL pdsbe;
  2034. LONG lVolume;
  2035. LONG lTotalLeftDB;
  2036. LONG lTotalRightDB;
  2037. DSVOLUMEPAN dsVolPan;
  2038. DPF(3,"Entering buffer set Pan method");
  2039. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  2040. RPF("IDirectSoundBuffer::SetPan - Invalid Object or ref count");
  2041. return DSERR_INVALIDPARAM;
  2042. }
  2043. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  2044. pdsb = pdsbe->pdsb;
  2045. pds = pdsb->pds;
  2046. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  2047. RPF("IDirectSoundBuffer::SetPan - Invalid Object or ref count");
  2048. return DSERR_INVALIDPARAM;
  2049. }
  2050. ASSERT( DSBUFFSIG == pdsb->dwSig );
  2051. if(( lPan < -10000 ) || ( lPan > 10000 )) {
  2052. RPF("IDirectSoundBuffer::SetPan - Pan: %l out of range", lPan);
  2053. return DSERR_INVALIDPARAM;
  2054. }
  2055. ENTER_DLL_CSECT();
  2056. if (pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) {
  2057. pdsb->fdwDsbI |= DSB_INTERNALF_PAN_WHILE_LOST;
  2058. pdsb->lSavePan = lPan;
  2059. DPF(4, "Early out - set pan while buffer lost");
  2060. LEAVE_DLL_CSECT();
  2061. return DS_OK;
  2062. }
  2063. // Only primary buffers may have CTRLPANPRIMARY set.
  2064. ASSERT( !(pdsbe->fdwDsbeI&DSBE_INTERNALF_CTRLPANPRIMARY) ||
  2065. (pdsb->fdwDsbI&DSB_INTERNALF_PRIMARY) );
  2066. if (!(pdsb->fdwBufferDesc & DSBCAPS_CTRLPAN) &&
  2067. !(pdsbe->fdwDsbeI & DSBE_INTERNALF_CTRLPANPRIMARY) )
  2068. {
  2069. RPF("IDirectSoundBuffer::SetPan - Caller did not have CTRL permission for Pan!");
  2070. LEAVE_DLL_CSECT();
  2071. return DSERR_CONTROLUNAVAIL;
  2072. }
  2073. if( (pdsbe->dwPriority < DSSCL_NORMAL)
  2074. || (pdsbe->dwPriority > DSSCL_WRITEPRIMARY) ) {
  2075. RPF("IDirectSoundBuffer::SetPan - Invalid priority level or buffer owner");
  2076. LEAVE_DLL_CSECT();
  2077. return DSERR_PRIOLEVELNEEDED;
  2078. }
  2079. pdsb->helInfo.lPan = lPan;
  2080. lVolume = pdsb->helInfo.lVolume;
  2081. //
  2082. // Compute multpliers (scaling factors) for the mixer to use
  2083. //
  2084. if (lPan >= 0) {
  2085. // left is attenuated
  2086. lTotalLeftDB = lVolume - lPan ;
  2087. lTotalRightDB = lVolume;
  2088. } else {
  2089. // right is attenuated
  2090. lTotalLeftDB = lVolume;
  2091. lTotalRightDB = lVolume - (-lPan);
  2092. }
  2093. dsVolPan.dwTotalLeftAmpFactor = DBToAmpFactor(lTotalLeftDB);
  2094. dsVolPan.dwTotalRightAmpFactor = DBToAmpFactor(lTotalRightDB);
  2095. dsVolPan.lVolume = lVolume;
  2096. dsVolPan.dwVolAmpFactor = DBToAmpFactor(lVolume);
  2097. dsVolPan.lPan = pdsb->helInfo.lPan;
  2098. if (lPan >= 0) {
  2099. // left is attenuated
  2100. dsVolPan.dwPanLeftAmpFactor = DBToAmpFactor(-lPan);
  2101. dsVolPan.dwPanRightAmpFactor = DBToAmpFactor(0);
  2102. } else {
  2103. // right is attenuated
  2104. dsVolPan.dwPanLeftAmpFactor = DBToAmpFactor(0);
  2105. dsVolPan.dwPanRightAmpFactor = DBToAmpFactor(lPan);
  2106. }
  2107. pdsb->helInfo.dwLVolume = dsVolPan.dwTotalLeftAmpFactor;
  2108. pdsb->helInfo.dwRVolume = dsVolPan.dwTotalRightAmpFactor;
  2109. pdsb->helInfo.dwMVolume = (pdsb->helInfo.dwLVolume + pdsb->helInfo.dwRVolume)/2;
  2110. DPF(3," Volume %ld Pan %ld left %Xh right %Xh ",
  2111. pdsb->helInfo.lVolume, pdsb->helInfo.lPan,
  2112. pdsb->helInfo.dwLVolume, pdsb->helInfo.dwRVolume );
  2113. if( pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE ) {
  2114. // Will this work on wave-em primaries??? [ask jimge]
  2115. if (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) {
  2116. WAVEOUTCAPS woc;
  2117. DWORD dwWaveVolume;
  2118. UINT uWaveId;
  2119. // Anyone can always set the volume on the primary
  2120. ASSERT(dsVolPan.dwTotalLeftAmpFactor <= 0xffff);
  2121. ASSERT(dsVolPan.dwTotalRightAmpFactor <= 0xffff);
  2122. if ( (DS_OK == wavGetIdFromDrvGuid(&pds->guid, &uWaveId)) &&
  2123. (!waveOutGetDevCaps(uWaveId, &woc, sizeof(woc))) )
  2124. {
  2125. if (woc.dwSupport & WAVECAPS_VOLUME) {
  2126. if (woc.dwSupport & WAVECAPS_LRVOLUME) {
  2127. dwWaveVolume = dsVolPan.dwTotalLeftAmpFactor;
  2128. dwWaveVolume |= dsVolPan.dwTotalRightAmpFactor << 16;
  2129. } else {
  2130. dwWaveVolume = dsVolPan.dwTotalLeftAmpFactor;
  2131. dwWaveVolume += dsVolPan.dwTotalRightAmpFactor;
  2132. dwWaveVolume /= 2;
  2133. }
  2134. if (!waveOutSetVolume((HWAVEOUT)uWaveId, dwWaveVolume)) {
  2135. // We never create primaries w/ CTRLVOLUME
  2136. #if 0
  2137. DPF(3," HW Change volume %l ", lVolume );
  2138. if( vxdBufferSetVolumePan( pdsb->hBuffer, &dsVolPan ) != DS_OK ) {
  2139. DPF(1," HAL Change VolumePan FAILED!!! ");
  2140. LEAVE_DLL_CSECT();
  2141. return DSERR_GENERIC;
  2142. }
  2143. DPF(3," Changed HW format ");
  2144. #endif
  2145. }
  2146. }
  2147. }
  2148. } else {
  2149. // This is a HW buffer so set the Pan to the device
  2150. //
  2151. // If this buffer's app doesn't have sound focus, then we
  2152. // won't actually call the driver- the volume has been minimized
  2153. // in order to mute the buffer while the app is out of sound focus
  2154. //
  2155. if (!pdsbe->pdsb->fMixerMute) {
  2156. DPF(3," HW Change pan %ld ", lPan );
  2157. if( DS_OK != vxdBufferSetVolumePan( pdsb->hBuffer, &dsVolPan )) {
  2158. DPF(1," HAL Change VolumePan FAILED!!! ");
  2159. LEAVE_DLL_CSECT();
  2160. return DSERR_GENERIC;
  2161. }
  2162. DPF(3," Changed HW pan");
  2163. }
  2164. }
  2165. }
  2166. DPF(3,"Exiting set Pan method");
  2167. LEAVE_DLL_CSECT();
  2168. return DS_OK;
  2169. } // IDSHWBufferSetPan()
  2170. HRESULT FAR PASCAL IDSHWBufferSetFrequency
  2171. (
  2172. LPDIRECTSOUNDBUFFER pidsb,
  2173. DWORD dwFrequency
  2174. )
  2175. {
  2176. LPDSOUND pds;
  2177. LPDSBUFFER pdsb;
  2178. LPDSBUFFEREXTERNAL pdsbe;
  2179. DPF(3,"Entering buffer set Frequency method");
  2180. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  2181. RPF("IDirectSoundBuffer::SetFrequency - Invalid Object or ref count");
  2182. return DSERR_INVALIDPARAM;
  2183. }
  2184. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  2185. pdsb = pdsbe->pdsb;
  2186. pds = pdsb->pds;
  2187. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  2188. RPF("IDirectSoundBuffer::SetFrequency - Invalid Object or ref count");
  2189. return DSERR_INVALIDPARAM;
  2190. }
  2191. ASSERT( DSBUFFSIG == pdsb->dwSig );
  2192. if( (dwFrequency != 0) &&
  2193. ((dwFrequency < 100) || (dwFrequency > 100000) ) ) {
  2194. RPF("IDirectSoundBuffer::SetFrequency - Invalid Frequency Range");
  2195. return DSERR_INVALIDPARAM;
  2196. }
  2197. ENTER_DLL_CSECT();
  2198. if (pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) {
  2199. pdsb->fdwDsbI |= DSB_INTERNALF_FREQ_WHILE_LOST;
  2200. pdsb->dwSaveFreq = dwFrequency;
  2201. DPF(4, "Early out - set freq while buffer lost");
  2202. LEAVE_DLL_CSECT();
  2203. return DS_OK;
  2204. }
  2205. if( !(pdsb->fdwBufferDesc & DSBCAPS_CTRLFREQUENCY )) {
  2206. RPF("IDirectSoundBuffer::SetFrequency - Caller did not have CTRL permission for Frequency!");
  2207. LEAVE_DLL_CSECT();
  2208. return DSERR_CONTROLUNAVAIL;
  2209. }
  2210. if( (pdsbe->dwPriority < DSSCL_NORMAL)
  2211. || (pdsbe->dwPriority > DSSCL_WRITEPRIMARY) ) {
  2212. RPF("IDirectSoundBuffer::SetFrequency - Invalid priority level or buffer owner");
  2213. LEAVE_DLL_CSECT();
  2214. return DSERR_PRIOLEVELNEEDED;
  2215. }
  2216. // Primary buffers never get DSBCAPS_CTRLFREQUENCY
  2217. ASSERT(0 == (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY));
  2218. if( dwFrequency == 0 ) {
  2219. dwFrequency = pdsb->pwfx->nSamplesPerSec;
  2220. }
  2221. if (dwFrequency == pdsb->helInfo.dwSampleRate) {
  2222. LEAVE_DLL_CSECT();
  2223. return DS_OK;
  2224. }
  2225. // If this buffer is being mixed, then signal the mixer
  2226. if ((0 == (DSB_INTERNALF_STOP & pdsb->fdwDsbI)) &&
  2227. (0 == (DSB_INTERNALF_HARDWARE & pdsb->fdwDsbI)) &&
  2228. (0 == (DS_INTERNALF_WAVEEMULATED & pds->fdwInternal)))
  2229. {
  2230. mxSignalRemix(pds, 0);
  2231. }
  2232. pdsb->helInfo.dwSampleRate = dwFrequency;
  2233. // Physically reset the device if a HW buffer has changed
  2234. if( pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE ) {
  2235. // This is a HW buffer so set the format to the device
  2236. DPF(3," Change HW RATE format %X freq %X",
  2237. pdsb->helInfo.hfFormat, pdsb->helInfo.dwSampleRate );
  2238. if( vxdBufferSetFrequency( pdsb->hBuffer, pdsb->helInfo.dwSampleRate ) != HAL_OK ) {
  2239. DPF(1," HAL Change RATE FAILED!!! ");
  2240. LEAVE_DLL_CSECT();
  2241. return DSERR_GENERIC;
  2242. }
  2243. DPF(4," Changed HW RATE ");
  2244. }
  2245. DPF(3,"Exiting set Frequency method");
  2246. LEAVE_DLL_CSECT();
  2247. return DS_OK;
  2248. } // IDSHWBufferSetFrequency()
  2249. HRESULT FAR PASCAL IDSHWBufferStop
  2250. (
  2251. LPDIRECTSOUNDBUFFER pidsb
  2252. )
  2253. {
  2254. LPDSOUND pds;
  2255. LPDSBUFFER pdsb;
  2256. LPDSBUFFEREXTERNAL pdsbe;
  2257. HRESULT hr;
  2258. DPF(3,"Enter buffer stop method %X", pidsb);
  2259. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  2260. RPF("IDirectSoundBuffer::Stop - Invalid Object or ref count");
  2261. return DSERR_INVALIDPARAM;
  2262. }
  2263. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  2264. pdsb = pdsbe->pdsb;
  2265. pds = pdsb->pds;
  2266. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  2267. RPF("IDirectSoundBuffer::Stop - Invalid Object or ref count");
  2268. return DSERR_INVALIDPARAM;
  2269. }
  2270. ASSERT( DSBUFFSIG == pdsb->dwSig );
  2271. //
  2272. // Shouldn't call this external method on our internal primary
  2273. // object - call IDsbStopI instead.
  2274. //
  2275. ASSERT( pdsbe != pds->pdsbePrimary );
  2276. if( (pdsbe->dwPriority < DSSCL_NORMAL)
  2277. || (pdsbe->dwPriority > DSSCL_WRITEPRIMARY)) {
  2278. RPF("IDirectSoundBuffer::Stop - Invalid priority level or buffer owner");
  2279. return DSERR_PRIOLEVELNEEDED;
  2280. }
  2281. if (pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) {
  2282. // All lost buffers are stopped by definition. Primary buffers
  2283. // may be playing for some other app, however. We can assert
  2284. // that this buffer is either primary or stopped.
  2285. ASSERT((pdsb->fdwDsbI & (DSB_INTERNALF_PRIMARY | DSB_INTERNALF_STOP)));
  2286. return DS_OK;
  2287. }
  2288. ENTER_DLL_CSECT();
  2289. // If the app has less than WRITEPRIMARY, we allow Stop
  2290. // on the external primary but stop the internal primary only if
  2291. // there are no other buffers playing on it.
  2292. if( ( pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY ) &&
  2293. ( pdsbe->dwPriority < DSSCL_WRITEPRIMARY ) )
  2294. {
  2295. ASSERT( pdsb == pds->pdsbPrimary );
  2296. if (pdsbe->fdwDsbeI & DSBE_INTERNALF_PLAYING ) {
  2297. pdsbe->fdwDsbeI &= ~DSBE_INTERNALF_PLAYING;
  2298. pds->cPlayPrimary--;
  2299. ASSERT(pds->cPlayPrimary >= 0);
  2300. if( (0 != pds->cPlayPrimary) || (0 != pds->dwBuffersPlaying) ){
  2301. LEAVE_DLL_CSECT();
  2302. return DS_OK;
  2303. }
  2304. pds->pdsbPrimary->fdwDsbI |= DSB_INTERNALF_JUSTSTOPPED;
  2305. }
  2306. }
  2307. hr = IDsbStopI( pdsb, FALSE );
  2308. LEAVE_DLL_CSECT();
  2309. return hr;
  2310. } // IDSHWBufferStop()
  2311. HRESULT FAR PASCAL IDSHWBufferRestore
  2312. (
  2313. LPDIRECTSOUNDBUFFER pidsb
  2314. )
  2315. {
  2316. LPDSOUND pds;
  2317. LPDSOUNDEXTERNAL pdse;
  2318. LPDSBUFFER pdsb;
  2319. LPDSBUFFEREXTERNAL pdsbe;
  2320. DWORD dwActivePrio;
  2321. DPF(4,"Enter buffer Restore method %X", pidsb);
  2322. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  2323. RPF("IDirectSoundBuffer::Restore - Invalid Object or ref count");
  2324. return DSERR_INVALIDPARAM;
  2325. }
  2326. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  2327. pdsb = pdsbe->pdsb;
  2328. pds = pdsb->pds;
  2329. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  2330. RPF("IDirectSoundBuffer::Restore - Invalid Object or ref count");
  2331. return DSERR_INVALIDPARAM;
  2332. }
  2333. ASSERT( DSBUFFSIG == pdsb->dwSig );
  2334. if (!(pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST)) {
  2335. RPF("IDirectSoundBuffer::Restore - Buffer is not lost! Restore returning success.");
  2336. return DS_OK;
  2337. }
  2338. ENTER_DLL_CSECT();
  2339. if (gpdsinfo->fApmSuspended) {
  2340. LEAVE_DLL_CSECT();
  2341. return DSERR_BUFFERLOST;
  2342. }
  2343. // This should never get called on the internal primary
  2344. ASSERT(pdsbe != pds->pdsbePrimary);
  2345. // We can restore the primary only if the app is WRITEPRIMARY and
  2346. // it is the active app.
  2347. if (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) {
  2348. if (pdsbe->dwPriority < DSSCL_WRITEPRIMARY) {
  2349. RPF("IDirectSoundBuffer::Restore - Can't restore primary; no DSSCL_WRITEPRIMARY");
  2350. LEAVE_DLL_CSECT();
  2351. return DSERR_PRIOLEVELNEEDED;
  2352. }
  2353. if (gpdsinfo->tidSoundFocus != pdsbe->pdse->tidSound) {
  2354. RPF("IDirectSoundBuffer::Restore - Tried to restore primary while not active");
  2355. LEAVE_DLL_CSECT();
  2356. return DSERR_BUFFERLOST;
  2357. }
  2358. // We need to clear LOST
  2359. DPF(1, "IDSHWBufferRestore: note: restoring primary dsbe %08Xh", pdsbe);
  2360. pdsbe->fdwDsbeI &= ~DSBE_INTERNALF_LOST;
  2361. LEAVE_DLL_CSECT();
  2362. return DS_OK;
  2363. }
  2364. // Validate that the active app no longer has WRITEPRIMARY
  2365. dwActivePrio = DSSCL_NORMAL;
  2366. for (pdse = gpdsinfo->pDSoundExternalObj; pdse; pdse = pdse->pNext) {
  2367. if (gpdsinfo->tidSoundFocus == pdse->tidSound && pdse->dwPriority > dwActivePrio) {
  2368. dwActivePrio = pdse->dwPriority;
  2369. }
  2370. }
  2371. if (dwActivePrio >= DSSCL_WRITEPRIMARY) {
  2372. DPF(4,"Restore: Active app still running at DSSCL_WRITEPRIMARY");
  2373. LEAVE_DLL_CSECT();
  2374. return DSERR_BUFFERLOST;
  2375. }
  2376. // "Once I was lost, but now I'm found
  2377. // Was blind but now can see"
  2378. pdsbe->fdwDsbeI &= ~DSBE_INTERNALF_LOST;
  2379. // Handle anything that was set while we were lost
  2380. //
  2381. if (pdsb->fdwDsbI & DSB_INTERNALF_SETPOS_WHILE_LOST) {
  2382. DPF(4, "Restore: SetCurrentPosition to %u", pdsb->dwSavePosition);
  2383. pdsbe->lpVtbl->SetCurrentPosition((LPDIRECTSOUNDBUFFER)pdsbe,
  2384. pdsb->dwSavePosition);
  2385. pdsb->fdwDsbI &= ~DSB_INTERNALF_SETPOS_WHILE_LOST;
  2386. }
  2387. if (pdsb->fdwDsbI & DSB_INTERNALF_VOLUME_WHILE_LOST) {
  2388. DPF(4, "Restore: SetVolume to %u", pdsb->lSaveVolume);
  2389. pdsbe->lpVtbl->SetVolume((LPDIRECTSOUNDBUFFER)pdsbe,
  2390. pdsb->lSaveVolume);
  2391. pdsb->fdwDsbI &= ~DSB_INTERNALF_VOLUME_WHILE_LOST;
  2392. }
  2393. if (pdsb->fdwDsbI & DSB_INTERNALF_PAN_WHILE_LOST) {
  2394. DPF(4, "Restore: Set pan to %u", pdsb->lSavePan);
  2395. pdsbe->lpVtbl->SetPan((LPDIRECTSOUNDBUFFER)pdsbe,
  2396. pdsb->lSavePan);
  2397. pdsb->fdwDsbI &= ~DSB_INTERNALF_PAN_WHILE_LOST;
  2398. }
  2399. if (pdsb->fdwDsbI & DSB_INTERNALF_FREQ_WHILE_LOST) {
  2400. DPF(4, "Restore: Set freq to %u", pdsb->dwSaveFreq);
  2401. pdsbe->lpVtbl->SetFrequency((LPDIRECTSOUNDBUFFER)pdsbe,
  2402. pdsb->dwSaveFreq);
  2403. pdsb->fdwDsbI &= ~DSB_INTERNALF_FREQ_WHILE_LOST;
  2404. }
  2405. if (pdsb->fdwDsbI & DSB_INTERNALF_WFX_WHILE_LOST) {
  2406. DPF(4, "Restore: Set format\n");
  2407. pdsbe->lpVtbl->SetFormat((LPDIRECTSOUNDBUFFER)pdsbe,
  2408. pdsb->pwfxSave);
  2409. pdsb->fdwDsbI &= ~DSB_INTERNALF_WFX_WHILE_LOST;
  2410. MemFree(pdsb->pwfxSave);
  2411. pdsb->pwfxSave = NULL;
  2412. }
  2413. DPF(3,"Exit Restore method");
  2414. LEAVE_DLL_CSECT();
  2415. return DS_OK;
  2416. } // IDSHWBufferRestore()
  2417. HRESULT FAR PASCAL IDSHWBufferUnlock
  2418. (
  2419. LPDIRECTSOUNDBUFFER pidsb,
  2420. LPVOID pBuffer,
  2421. DWORD dwWriteLen,
  2422. LPVOID pBufferWrap,
  2423. DWORD dwWrapWriteLen
  2424. )
  2425. {
  2426. LPDSOUND pds;
  2427. LPDSBUFFER pdsb;
  2428. LPDSBUFFEREXTERNAL pdsbe;
  2429. DWORD dwOffset1;
  2430. DWORD dwOffset2;
  2431. DPF(4,"Entering UNLock HW obj %X ", pidsb );
  2432. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsb) ) {
  2433. RPF("IDirectSoundBuffer::Unlock - Invalid Object or ref count");
  2434. return DSERR_INVALIDPARAM;
  2435. }
  2436. pdsbe = (LPDSBUFFEREXTERNAL)pidsb;
  2437. pdsb = pdsbe->pdsb;
  2438. pds = pdsb->pds;
  2439. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  2440. RPF("IDirectSoundBuffer::Unlock - Invalid Object or ref count");
  2441. return DSERR_INVALIDPARAM;
  2442. }
  2443. ASSERT( DSBUFFSIG == pdsb->dwSig );
  2444. if( !VALID_DWORD_PTR(pBuffer) ) {
  2445. RPF("IDirectSoundBuffer::Unlock - Invalid first buffer pointer.");
  2446. return DSERR_INVALIDPARAM;
  2447. }
  2448. ENTER_DLL_CSECT();
  2449. // If the buffer was lost while it was locked, then we'll unlock it but
  2450. // with write lengths of 0, effectively throwing away whatever the app
  2451. // may have written to the buffer but still unlocking the pointers.
  2452. if (pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) {
  2453. dwWriteLen = 0;
  2454. dwWrapWriteLen = 0;
  2455. }
  2456. if( pdsbe != pds->pdsbePrimary ) {
  2457. if( (pdsbe->dwPriority < DSSCL_NORMAL)
  2458. || (pdsbe->dwPriority > DSSCL_WRITEPRIMARY)) {
  2459. RPF("IDirectSoundBuffer::Unlock - Invalid priority level or buffer owner");
  2460. LEAVE_DLL_CSECT();
  2461. return DSERR_PRIOLEVELNEEDED;
  2462. }
  2463. }
  2464. if( (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) &&
  2465. (pdsbe->dwPriority < DSSCL_WRITEPRIMARY) )
  2466. {
  2467. RPF("IDirectSoundBuffer::Unlock - Can't unlock primary buffer: caller not WRITE_PRIMARY");
  2468. LEAVE_DLL_CSECT();
  2469. return DSERR_PRIOLEVELNEEDED;
  2470. }
  2471. DPF(5,"unlock buffer ptr %X 1 %X 2 %X",pdsb->pDSBuffer, pBuffer, pBufferWrap);
  2472. if (pdsbe->pDSBufferAlias) {
  2473. dwOffset1 = (DWORD)pBuffer - (DWORD)(pdsbe->pDSBufferAlias);
  2474. dwOffset2 = (DWORD)pBufferWrap - (DWORD)(pdsbe->pDSBufferAlias);
  2475. } else {
  2476. dwOffset1 = (DWORD)pBuffer - (DWORD)(pdsb->pDSBuffer);
  2477. dwOffset2 = (DWORD)pBufferWrap - (DWORD)(pdsb->pDSBuffer);
  2478. }
  2479. DPF(5, "Unlock offset 1 %X 2 %X ", dwOffset1, dwOffset2 );
  2480. if( DSBUnlockAccess( pdsb, dwOffset1 ) != DS_OK ) {
  2481. RPF("IDirectSoundBuffer::Unlock - Error unlocking section 1." );
  2482. LEAVE_DLL_CSECT();
  2483. return DSERR_INVALIDCALL;
  2484. }
  2485. if( (pBufferWrap != NULL) &&
  2486. (DSBUnlockAccess( pdsb, dwOffset2 ) != DS_OK) ) {
  2487. // There is a wrap section
  2488. RPF("IDirectSoundBuffer::Unlock - Error unlocking section2." );
  2489. LEAVE_DLL_CSECT();
  2490. return DSERR_INVALIDCALL;
  2491. }
  2492. // If this is a hardware buffer and they will be reading the memory
  2493. // from the system memory buffer, then get the driver to update
  2494. // the system memory from the card
  2495. if( (pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE) ) {
  2496. // This is a HW buffer - Ask driver to lock
  2497. if ( ( (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) &&
  2498. !(pds->fdwDriverDesc & DSDDESC_DONTNEEDPRIMARYLOCK)) ||
  2499. (!(pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) &&
  2500. !(pds->fdwDriverDesc & DSDDESC_DONTNEEDSECONDARYLOCK)) )
  2501. {
  2502. vxdBufferUnlock( pdsb->hBuffer, pBuffer, dwWriteLen,
  2503. pBufferWrap, dwWrapWriteLen);
  2504. }
  2505. }
  2506. // If this is a non wave-emulated software buffer that is currently
  2507. // playing, then we need to check whether any of the unlocked region lies
  2508. // in the premixed region of the buffer.
  2509. if (!(pds->fdwInternal & DS_INTERNALF_WAVEEMULATED) &&
  2510. !(pdsb->fdwDsbI & (DSB_INTERNALF_HARDWARE | DSB_INTERNALF_STOP)))
  2511. {
  2512. int iWriteCursor, iMixCursor;
  2513. int iPremixLen;
  2514. BOOL fRegionsIntersect;
  2515. mxGetPosition(pdsb, NULL, &iWriteCursor, &iMixCursor);
  2516. ASSERT(iWriteCursor >= 0);
  2517. ASSERT(iMixCursor >= 0);
  2518. iPremixLen = iMixCursor - iWriteCursor;
  2519. if (iPremixLen < 0) iPremixLen += pdsb->cbBufferSize;
  2520. ASSERT(iPremixLen >= 0);
  2521. fRegionsIntersect = CircularBufferRegionsIntersect(pdsb->cbBufferSize,
  2522. iWriteCursor, iPremixLen, dwOffset1, dwWriteLen);
  2523. if (!fRegionsIntersect && pBufferWrap) {
  2524. fRegionsIntersect = CircularBufferRegionsIntersect(pdsb->cbBufferSize,
  2525. iWriteCursor, iPremixLen, dwOffset2, dwWrapWriteLen);
  2526. }
  2527. if (fRegionsIntersect) {
  2528. DPF(2, "Lock: note: unlocked premixed region");
  2529. mxSignalRemix(pdsb->pds, 0);
  2530. }
  2531. }
  2532. // Maintain a count of the number of locks on this buffer.
  2533. pdsbe->cLocks--;
  2534. ASSERT(pdsbe->cLocks >= 0);
  2535. // If we have a buffer alias ptr and this is the last unlock then we need
  2536. // to decommit the physical buffer memory from the alias ptr
  2537. if (pdsbe->pDSBufferAlias && (0 == pdsbe->cLocks)) {
  2538. vxdMemDecommitAlias(pdsbe->pDSBufferAlias, pdsb->cbBufferSize);
  2539. }
  2540. DPF(4,"Exiting unlock method");
  2541. LEAVE_DLL_CSECT();
  2542. return DS_OK;
  2543. } // IDSHWBufferUnlock()
  2544. HRESULT FAR PASCAL IDSHWBufferWaveBlt
  2545. (
  2546. LPDIRECTSOUNDBUFFER pidsbDst,
  2547. LPDSBWAVEBLT pidswb
  2548. )
  2549. {
  2550. LPDSOUND pds;
  2551. LPDSBUFFER pdsb;
  2552. LPDSBUFFEREXTERNAL pdsbe;
  2553. LPDSBUFFEREXTERNAL pdsbeSrc;
  2554. LPDSBUFFER pdsbDst;
  2555. DWORD dwDstPlay;
  2556. DWORD dwDstWrite;
  2557. DWORD dwDstPosition;
  2558. LPBYTE pDstBuffer;
  2559. DWORD dwDstLock;
  2560. LPBYTE pDstBuffer2;
  2561. DWORD dwDstLock2;
  2562. LPBYTE pMixBuffer;
  2563. DWORD cbMixBufferSize;
  2564. int cbAdjustedMixBuffer;
  2565. HRESULT hrslt;
  2566. LPDSBWAVEBLTI pdswb;
  2567. DWORD i;
  2568. LPHALSTRBUF pHelInfo;
  2569. DPF(4,"Entering wave blt method");
  2570. if( !VALID_DSBUFFERE_PTR((LPDSBUFFEREXTERNAL)pidsbDst) ) {
  2571. RPF("IDirectSoundBuffer::WaveBlt - Invalid Object or ref count");
  2572. return DSERR_INVALIDPARAM;
  2573. }
  2574. pdsbe = (LPDSBUFFEREXTERNAL)pidsbDst;
  2575. pdsb = pdsbe->pdsb;
  2576. pdsbDst = pdsb;
  2577. pds = pdsb->pds;
  2578. if( !VALID_DSBUFFER_PTR(pdsb) || (0 == pdsbe->uRefCount)) {
  2579. RPF("IDirectSoundBuffer::WaveBlt - Invalid Object or ref count");
  2580. return DSERR_INVALIDPARAM;
  2581. }
  2582. ASSERT( DSBUFFSIG == pdsb->dwSig );
  2583. pdswb = (LPDSBWAVEBLTI)(pidswb);
  2584. if( !VALID_DSBWAVEBLT_PTR(pdswb) ) {
  2585. RPF("IDirectSoundBuffer::WaveBlt - Invalid BLT structure");
  2586. return DSERR_INVALIDPARAM;
  2587. }
  2588. if( pdswb->fdwWaveBlt & (~DSBBLT_VALIDFLAGS)) {
  2589. RPF("IDirectSoundBuffer::WaveBlt - Invalid flags passed to WaveBlt");
  2590. return DSERR_INVALIDPARAM;
  2591. }
  2592. if (pdsbe->fdwDsbeI & DSBE_INTERNALF_LOST) {
  2593. return DSERR_BUFFERLOST;
  2594. }
  2595. ENTER_DLL_CSECT();
  2596. if( pdsbe != pds->pdsbePrimary ) {
  2597. if( (pdsbe->dwPriority < DSSCL_NORMAL)
  2598. || (pdsbe->dwPriority > DSSCL_WRITEPRIMARY)) {
  2599. RPF("IDirectSoundBuffer::WaveBlt - Invalid priority level or buffer owner");
  2600. LEAVE_DLL_CSECT();
  2601. return DSERR_PRIOLEVELNEEDED;
  2602. }
  2603. }
  2604. if( (pdsb->fdwDsbI & DSB_INTERNALF_PRIMARY) &&
  2605. (pdsbe->dwPriority < DSSCL_WRITEPRIMARY) )
  2606. {
  2607. RPF("IDirectSoundBuffer::WaveBlt - Can't wavblt on primary buffer: caller not WRITEPRIMARY");
  2608. LEAVE_DLL_CSECT();
  2609. return DSERR_PRIOLEVELNEEDED;
  2610. }
  2611. // Init local copy of position
  2612. dwDstPosition = pdswb->dwPosition;
  2613. // Check sources are valid
  2614. for( i = 0; i < pdswb->dwCount; i++ ) {
  2615. // Check object and ref count are fine
  2616. if( !VALID_DSBUFFERE_PTR(pdswb->padswbs[i].pdsbe) ||
  2617. (0 == pdswb->padswbs[i].pdsbe->uRefCount) ) {
  2618. RPF("IDirectSoundBuffer::WaveBlt - Invalid object or ref count on src buffer");
  2619. LEAVE_DLL_CSECT();
  2620. return DSERR_INVALIDPARAM;
  2621. }
  2622. }
  2623. // Check to see this is a buffer we can blt to
  2624. if( pdsbDst->cbMixBufferSize == 0 ) {
  2625. RPF("IDirectSoundBuffer::WaveBlt - Trying to blt to a nomix buffer");
  2626. LEAVE_DLL_CSECT();
  2627. return DSERR_CONTROLUNAVAIL;
  2628. }
  2629. // Check formats are the PCM
  2630. if( !CheckFormatsPCM( pdsbDst, pdswb ) ) {
  2631. RPF("IDirectSoundBuffer::WaveBlt - Formats not the PCM");
  2632. LEAVE_DLL_CSECT();
  2633. return DSERR_CONTROLUNAVAIL;
  2634. }
  2635. // Check the size of the blt against dst buffer total size
  2636. if( pdswb->cbCopyLength >= pdsbDst->cbBufferSize ) {
  2637. pdswb->cbCopyLength = pdsbDst->cbBufferSize -
  2638. pdsbDst->pwfx->nBlockAlign;
  2639. }
  2640. // Do nothing on NULL copy
  2641. if( 0 == pdswb->cbCopyLength )
  2642. {
  2643. RPF("IDirectSoundBuffer::WaveBlt - Zero source size");
  2644. LEAVE_DLL_CSECT();
  2645. return DS_OK;
  2646. }
  2647. // Get Positions in buffer
  2648. hrslt = pidsbDst->lpVtbl->GetCurrentPosition(pidsbDst,
  2649. &dwDstPlay,
  2650. &dwDstWrite );
  2651. if(DS_OK != hrslt)
  2652. {
  2653. DPF(1,"DS get position failed return %ld ", hrslt);
  2654. LEAVE_DLL_CSECT();
  2655. return hrslt;
  2656. }
  2657. // Reset position
  2658. if( pdswb->fdwWaveBlt & DSBBLT_DSTWRITECURSOR ) {
  2659. DPF(5,"Wave BLT DST current pos");
  2660. dwDstPosition = dwDstWrite;
  2661. }
  2662. // Check for writing at current play pos
  2663. if( dwDstPosition == dwDstPlay ) {
  2664. // if stopped this is fine... Go forward....
  2665. if( pdsbDst->fdwDsbI & DSB_INTERNALF_STOP ) {
  2666. DPF(1,"DstPostion == PlayPosition - Ok we are stopped ");
  2667. } else {
  2668. DPF(1,"DstPostion == PlayPosition - NOT Ok NOT stopped ");
  2669. LEAVE_DLL_CSECT();
  2670. return DSERR_INVALIDCALL;
  2671. }
  2672. }
  2673. // Lock buffers for copy
  2674. DPF(4, "Lock Dest %X ", pdsbDst );
  2675. hrslt = pidsbDst->lpVtbl->Lock(pidsbDst,
  2676. dwDstPosition,
  2677. pdswb->cbCopyLength,
  2678. &pDstBuffer,
  2679. &dwDstLock,
  2680. &pDstBuffer2,
  2681. &dwDstLock2,
  2682. 0L);
  2683. if(DS_OK != hrslt)
  2684. {
  2685. DPF(1,"DS Buffer Lock failed ");
  2686. LEAVE_DLL_CSECT();
  2687. return hrslt;
  2688. }
  2689. // Get the helInfo for mixing
  2690. pHelInfo = &(pdsbDst->helInfo);
  2691. // For each source buffer get the relevant info
  2692. for( i = 0; i < pdswb->dwCount; i++ ) {
  2693. // Get Positions in buffer
  2694. DPF(4,"**************Blt Source %X", pdswb->padswbs[i].pdsbe->pdsb );
  2695. pdsbeSrc = pdswb->padswbs[i].pdsbe;
  2696. pdswb->padswbs[i].cbBufferSize =
  2697. pdswb->padswbs[i].pdsbe->pdsb->cbBufferSize;
  2698. // Since these are emulated buffers, we do not need to lock them
  2699. // since they are just system meory
  2700. // Copy may be in 2 sections to end of buffer
  2701. // and from start of buffer
  2702. // If required set sourc or dest based on position
  2703. if( pdswb->padswbs[i].fdwWaveBltBuffer & DSBBLTSRC_SRCCURRENTPOS ) {
  2704. hrslt = pdsbeSrc->lpVtbl->
  2705. GetCurrentPosition((LPDIRECTSOUNDBUFFER)pdsbeSrc,
  2706. &(pdswb->padswbs[i].dwPlay),
  2707. &(pdswb->padswbs[i].dwWrite) );
  2708. if(DS_OK != hrslt) {
  2709. DPF(1,"DS get position failed return %ld ", hrslt);
  2710. LEAVE_DLL_CSECT();
  2711. return hrslt;
  2712. }
  2713. DPF(5, "Src Postion Play %X", pdswb->padswbs[i].dwPlay );
  2714. DPF(5, "Src Postion Write %X", pdswb->padswbs[i].dwWrite );
  2715. pdswb->padswbs[i].dwPosition = pdswb->padswbs[i].dwPlay;
  2716. }
  2717. DPF(4,"Wave BLT SRC Pos %X",pdswb->padswbs[i].dwPosition );
  2718. pdswb->padswbs[i].cbCopyLength = 0x0800000;
  2719. if( !(pdswb->padswbs[i].fdwWaveBltBuffer & DSBBLT_BLTTODSTEND) ) {
  2720. // Limit size to end of buffer
  2721. DPF(5," Wave BLT src LIMIT NOLOOP");
  2722. pdswb->padswbs[i].cbCopyLength =
  2723. pdswb->padswbs[i].cbBufferSize -
  2724. pdswb->padswbs[i].dwPosition;
  2725. }
  2726. DPF(5,"Wave BLT copy length %X", pdswb->padswbs[i].cbCopyLength );
  2727. pdswb->padswbs[i].cbLeftToCopy = pdswb->padswbs[i].cbCopyLength;
  2728. DPF(5,"Wave BLT OBJ src %X",pdswb->padswbs[i].pdsbe->pdsb );
  2729. DPF(5,"Wave BLT obj buffer %X",pdswb->padswbs[i].pdsbe->pdsb->pDSBuffer );
  2730. DPF(5,"Wave BLT SRC Pos %X",pdswb->padswbs[i].dwPosition );
  2731. DPF(5,"Wave BLT SRC Length %X",pdswb->padswbs[i].cbCopyLength );
  2732. }
  2733. // Grab the mix buffer -
  2734. // Mix buffer is 32 bit so size the copies as Mix/2 or Mix/4
  2735. pMixBuffer = pdsbDst->pMixBuffer;
  2736. cbMixBufferSize = pdsbDst->cbMixBufferSize;
  2737. if( pdsbDst->pwfx->wBitsPerSample == 16 ) {
  2738. cbAdjustedMixBuffer = cbMixBufferSize / 2;
  2739. } else {
  2740. cbAdjustedMixBuffer = cbMixBufferSize / 4;
  2741. }
  2742. #ifdef NOCOMP
  2743. if( (pdswb->dwCount == 1) &&
  2744. (pdswb->fdwWaveBlt & DSBBLT_COPY) ) {
  2745. // Blt is jsut a copy from one src to dest don't need mix
  2746. } else {
  2747. #endif
  2748. if( pdswb->dwCount == 0 ) {
  2749. // No source buffers
  2750. // Just blank out the dest buffer.....
  2751. DPF(5, "silence dst pos %X lenght %X ",
  2752. dwDstPosition,
  2753. pdswb->cbCopyLength );
  2754. if( pdsbDst->pwfx->wBitsPerSample == 8 ) {
  2755. // Eight bit set to NULL value of 128
  2756. // Check for wrap around end
  2757. _fmemset( pDstBuffer, 128, dwDstLock );
  2758. if( dwDstLock2 ) {
  2759. _fmemset( pDstBuffer2, 128, dwDstLock2 );
  2760. }
  2761. } else {
  2762. // Sixteen bit set to NULL value of 0
  2763. // Check for wrap around end
  2764. _fmemset( pDstBuffer, 0, dwDstLock );
  2765. if( dwDstLock2 ) {
  2766. _fmemset( pDstBuffer2, 0, dwDstLock2 );
  2767. }
  2768. }
  2769. } else {
  2770. // Blt is not a simple blt - use mix buffer
  2771. int cbRemainingDstCopy;
  2772. cbRemainingDstCopy = pdswb->cbCopyLength;
  2773. DPF(5, "Start mix loop cbCopyLength %x", cbRemainingDstCopy);
  2774. do {
  2775. int cbThisDstCopy;
  2776. cbThisDstCopy = min(cbRemainingDstCopy, cbAdjustedMixBuffer);
  2777. ASSERT(cbThisDstCopy > 0);
  2778. DPF(5, "\n\ncbThisDstCopy %x\n", cbThisDstCopy);
  2779. DPF(5, "Begin Mix session pMix %X ", pMixBuffer );
  2780. DPF(5, "Begin Mix session cbMixSize %X ", cbMixBufferSize );
  2781. DPF(5, "Begin Mix session helinfo %X ", pHelInfo );
  2782. DPF(5, "Begin Mix session dst length %X ", cbThisDstCopy );
  2783. {
  2784. MIXSESSION mixSession;
  2785. mixSession.pBuildBuffer = pMixBuffer;
  2786. mixSession.dwBuildSize = cbMixBufferSize;
  2787. mixSession.HALOutStrBuf = *pHelInfo;
  2788. mixSession.pBuffer = pdsbDst->pDSBuffer;
  2789. mixSession.cbBuffer = pdsbDst->cbBufferSize;
  2790. mixSession.nOutputBytes = cbThisDstCopy;
  2791. mixBeginSession(&mixSession);
  2792. }
  2793. // Check to see if we mix into the src buffer fist
  2794. if( pdswb->fdwWaveBlt & DSBBLT_COPY ) {
  2795. DPF(5,"Wave BLT copy - do not first copy dst ");
  2796. } else {
  2797. MIXINPUT mixInput;
  2798. DWORD dw;
  2799. DPF(5,"Wave BLT Mix");
  2800. DPF(5, "DST HEL MIX Buf helInfo %X ", pHelInfo);
  2801. DPF(5, "DST HEL MIX position %X ", dwDstPosition );
  2802. DPF(5, "DST HEL MIX length %X ", cbThisDstCopy );
  2803. DPF(5, "DST HEL MIX build pos %X ", 0 );
  2804. dw = dwDstPosition;
  2805. mixInput.HALInStrBuf = *pHelInfo;
  2806. mixInput.pBuffer = pdsbDst->pDSBuffer;
  2807. mixInput.cbBuffer = pdsbDst->cbBufferSize;
  2808. mixInput.pdwInputPos = &dw;
  2809. mixInput.dwInputBytes = cbThisDstCopy;
  2810. mixInput.dwOutputOffset = 0;
  2811. mixMixSession(&mixInput);
  2812. }
  2813. // For each source buffer mix into mix buffer
  2814. for( i = 0; i < pdswb->dwCount; i++ ) {
  2815. MIXINPUT mixInput;
  2816. DWORD dwPosition;
  2817. DPF(5, " HEL MIX Buf helInfo %X ", &(pdswb->padswbs[i].pdsbe->pdsb->helInfo) );
  2818. DPF(5, " HEL MIX position %X ", pdswb->padswbs[i].dwPosition );
  2819. DPF(5, " HEL MIX length %X ", pdswb->padswbs[i].cbLeftToCopy );
  2820. DPF(5, " HEL MIX build pos %X ", 0 );
  2821. if (pdswb->padswbs[i].cbLeftToCopy > 0) {
  2822. int cbCopied;
  2823. mixInput.HALInStrBuf = pdswb->padswbs[i].pdsbe->pdsb->helInfo;
  2824. mixInput.pBuffer = pdswb->padswbs[i].pdsbe->pdsb->pDSBuffer;
  2825. mixInput.cbBuffer = pdswb->padswbs[i].pdsbe->pdsb->cbBufferSize;
  2826. mixInput.pdwInputPos = &dwPosition;
  2827. mixInput.dwInputBytes = pdswb->padswbs[i].cbLeftToCopy;
  2828. mixInput.dwOutputOffset = 0;
  2829. dwPosition = pdswb->padswbs[i].dwPosition;
  2830. mixMixSession(&mixInput);
  2831. // Because of resampling, the position may wrap past
  2832. // beginning of buffer. You'll have to understand the
  2833. // mixer code if you wanna know why. This can make
  2834. // cbLeftToCopy go below 0.
  2835. cbCopied = dwPosition - pdswb->padswbs[i].dwPosition;
  2836. if (dwPosition <= pdswb->padswbs[i].dwPosition) {
  2837. cbCopied += pdswb->padswbs[i].cbBufferSize;
  2838. }
  2839. pdswb->padswbs[i].cbLeftToCopy -= cbCopied;
  2840. pdswb->padswbs[i].dwPosition = dwPosition;
  2841. DPF(5, " HEL MIX NEW position %X ", pdswb->padswbs[i].dwPosition );
  2842. }
  2843. }
  2844. //
  2845. // When all secondary buffers have been mixed into the build buffer,
  2846. // copy the build buffer to the output stream
  2847. //
  2848. DPF(5, "Write Mix position %X ", dwDstPosition );
  2849. mixWriteSession(dwDstPosition);
  2850. dwDstPosition = (dwDstPosition + cbThisDstCopy) % pdsbDst->cbBufferSize;
  2851. cbRemainingDstCopy -= cbThisDstCopy;
  2852. ASSERT(cbRemainingDstCopy >= 0);
  2853. // DPF(3,"End Mix Position");
  2854. } while (cbRemainingDstCopy > 0);
  2855. }
  2856. // Done copy - unlock buffers
  2857. DPF(5,"done copy - unlock now Dest %X", pidsbDst);
  2858. hrslt = pidsbDst->lpVtbl->Unlock(pidsbDst,pDstBuffer, dwDstLock,
  2859. pDstBuffer2, dwDstLock2);
  2860. if(DS_OK != hrslt)
  2861. {
  2862. DPF(1,"DS Buffer UnLock failed ");
  2863. LEAVE_DLL_CSECT();
  2864. return hrslt;
  2865. }
  2866. DPF(4,"Exiting wave blt method");
  2867. LEAVE_DLL_CSECT();
  2868. return DS_OK;
  2869. } // IDSHWBufferWaveBlt()
  2870. //--------------------------------------------------------------------------;
  2871. //
  2872. // void DSBufferCreateTable
  2873. //
  2874. // Description:
  2875. //
  2876. //
  2877. // Arguments:
  2878. // LPDSOUNDBUFFERCALLBACKS lpVtbl:
  2879. //
  2880. // Return (void):
  2881. //
  2882. // History:
  2883. // 02/17/95 Fwong
  2884. //
  2885. //--------------------------------------------------------------------------;
  2886. void FNGLOBAL DSHWBufferCreateTable
  2887. (
  2888. LPDSOUNDBUFFERCALLBACKS lpVtbl
  2889. )
  2890. {
  2891. DPF(4,"Entering HW buffer create table");
  2892. lpVtbl->QueryInterface = IDSHWBufferQueryInterface;
  2893. lpVtbl->AddRef = IDSHWBufferAddRef;
  2894. lpVtbl->Release = IDSHWBufferRelease;
  2895. lpVtbl->GetCaps = IDSHWBufferGetCaps;
  2896. lpVtbl->GetCurrentPosition = IDSHWBufferGetCurrentPosition;
  2897. lpVtbl->GetFormat = IDSHWBufferGetFormat;
  2898. lpVtbl->GetVolume = IDSHWBufferGetVolume;
  2899. lpVtbl->GetPan = IDSHWBufferGetPan;
  2900. lpVtbl->GetFrequency = IDSHWBufferGetFrequency;
  2901. lpVtbl->GetStatus = IDSHWBufferGetStatus;
  2902. lpVtbl->Initialize = IDSHWBufferInitialize;
  2903. lpVtbl->Lock = IDSHWBufferLock;
  2904. lpVtbl->Play = IDSHWBufferPlay;
  2905. lpVtbl->SetCurrentPosition = IDSHWBufferSetCurrentPosition;
  2906. lpVtbl->SetFormat = IDSHWBufferSetFormat;
  2907. lpVtbl->SetVolume = IDSHWBufferSetVolume;
  2908. lpVtbl->SetPan = IDSHWBufferSetPan;
  2909. lpVtbl->SetFrequency = IDSHWBufferSetFrequency;
  2910. lpVtbl->Stop = IDSHWBufferStop;
  2911. lpVtbl->Unlock = IDSHWBufferUnlock;
  2912. lpVtbl->Restore = IDSHWBufferRestore;
  2913. DPF(4,"Exiting HW buffer create table");
  2914. } // DSHWBufferCreateTable()
  2915. //--------------------------------------------------------------------------;
  2916. //
  2917. // void DSBufferActivate
  2918. //
  2919. // Description:
  2920. // This is called on an external buffer object to notify the buffer that
  2921. // the owning app has been activated (i.e., the app gains sound focus).
  2922. //
  2923. // Arguments:
  2924. // LPDSBUFFEREXTERNAL:
  2925. //
  2926. // Return (void):
  2927. //
  2928. // History:
  2929. // 08/01/95 FrankYe
  2930. //
  2931. //--------------------------------------------------------------------------;
  2932. void DSBufferActivate(LPDSBUFFEREXTERNAL pdsbe)
  2933. {
  2934. LPDSOUND pds;
  2935. LPDSBUFFER pdsb;
  2936. LONG lVolume;
  2937. LONG lPan;
  2938. LONG lTotalLeftDB;
  2939. LONG lTotalRightDB;
  2940. DSVOLUMEPAN dsVolPan;
  2941. ASSERT(VALID_DSBUFFERE_PTR(pdsbe));
  2942. pdsb = pdsbe->pdsb;
  2943. ASSERT(VALID_DSBUFFER_PTR(pdsb) && (0 != pdsbe->uRefCount));
  2944. ASSERT( DSBUFFSIG == pdsb->dwSig );
  2945. pds = pdsb->pds;
  2946. // Don't need to do anything on primary buffers
  2947. if (DSB_INTERNALF_PRIMARY & pdsb->fdwDsbI) return;
  2948. pdsb->fMixerMute = FALSE;
  2949. // On software buffers, reseting the fMuteMixer flag is enough
  2950. // and the mixer does the rest.
  2951. if (0 == (pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE)) return;
  2952. // For hardware buffers...
  2953. // Restore volume levels
  2954. lVolume = pdsb->helInfo.lVolume;
  2955. lPan = pdsb->helInfo.lPan;
  2956. // Compute multpliers (scaling factors) for the mixer to use
  2957. if (lPan >= 0) {
  2958. // left is attenuated
  2959. lTotalLeftDB = lVolume - lPan ;
  2960. lTotalRightDB = lVolume;
  2961. } else {
  2962. // right is attenuated
  2963. lTotalLeftDB = lVolume;
  2964. lTotalRightDB = lVolume - (-lPan);
  2965. }
  2966. dsVolPan.dwTotalLeftAmpFactor = DBToAmpFactor(lTotalLeftDB);
  2967. dsVolPan.dwTotalRightAmpFactor = DBToAmpFactor(lTotalRightDB);
  2968. dsVolPan.lVolume = lVolume;
  2969. dsVolPan.dwVolAmpFactor = DBToAmpFactor(lVolume);
  2970. dsVolPan.lPan = pdsb->helInfo.lPan;
  2971. if (lPan >= 0) {
  2972. // left is attenuated
  2973. dsVolPan.dwPanLeftAmpFactor = DBToAmpFactor(-lPan);
  2974. dsVolPan.dwPanRightAmpFactor = DBToAmpFactor(0);
  2975. } else {
  2976. // right is attenuated
  2977. dsVolPan.dwPanLeftAmpFactor = DBToAmpFactor(0);
  2978. dsVolPan.dwPanRightAmpFactor = DBToAmpFactor(lPan);
  2979. }
  2980. pdsb->helInfo.dwLVolume = dsVolPan.dwTotalLeftAmpFactor;
  2981. pdsb->helInfo.dwRVolume = dsVolPan.dwTotalRightAmpFactor;
  2982. pdsb->helInfo.dwMVolume = (pdsb->helInfo.dwLVolume + pdsb->helInfo.dwRVolume)/2;
  2983. vxdBufferSetVolumePan( pdsb->hBuffer, &dsVolPan );
  2984. return;
  2985. } // DSBufferActivate()
  2986. //--------------------------------------------------------------------------;
  2987. //
  2988. // void DSBufferDeactivate
  2989. //
  2990. // Description:
  2991. //
  2992. //
  2993. // Arguments:
  2994. // LPDSBUFFEREXTERNAL:
  2995. //
  2996. // Return (void):
  2997. //
  2998. // History:
  2999. // 08/01/95 FrankYe
  3000. //
  3001. //--------------------------------------------------------------------------;
  3002. void DSBufferDeactivate(LPDSBUFFEREXTERNAL pdsbe)
  3003. {
  3004. LPDSOUND pds;
  3005. LPDSBUFFER pdsb;
  3006. DSVOLUMEPAN dsVolPan;
  3007. ASSERT(VALID_DSBUFFERE_PTR(pdsbe));
  3008. pdsb = pdsbe->pdsb;
  3009. ASSERT(VALID_DSBUFFER_PTR(pdsb) && (0 != pdsbe->uRefCount));
  3010. ASSERT( DSBUFFSIG == pdsb->dwSig );
  3011. pds = pdsb->pds;
  3012. pdsb->fMixerMute = TRUE;
  3013. // For software buffers, setting fMixerMute is enough
  3014. // and the mixer does the rest.
  3015. if (0 == (pdsb->fdwDsbI & DSB_INTERNALF_HARDWARE)) return;
  3016. // Non-WRITEPRIMARY primary buffers need nothing done. If this is a
  3017. // primary buffer for a WRITEPRIMARY app, we need to mark it as lost
  3018. // and fill the buffer with silence.
  3019. if (DSB_INTERNALF_PRIMARY & pdsb->fdwDsbI) {
  3020. if (pdsbe->dwPriority < DSSCL_WRITEPRIMARY) return;
  3021. DPF(1, "DsBufferDeactivate: note: losing primary dsbe %08Xh", pdsbe);
  3022. // If the app's primary buffer is locked and we have an alias buffer ptr
  3023. // then we redirect the alias ptr to some dummy buffer. That way, the
  3024. // app can keep writing to the ptr and the data goes into the bit
  3025. // bucket (actually, the data goes into the dummy buffer).
  3026. if (pdsbe->pDSBufferAlias && (pdsbe->cLocks)) {
  3027. BOOL fSuccess;
  3028. DPF(1, "DsBufferDeactivate: note: losing primary while locked");
  3029. fSuccess = vxdMemRedirectAlias(pdsbe->pDSBufferAlias, pdsb->cbBufferSize);
  3030. ASSERT(fSuccess);
  3031. }
  3032. DsbFillSilence(pdsb);
  3033. pdsbe->fdwDsbeI |= DSBE_INTERNALF_LOST;
  3034. return;
  3035. }
  3036. dsVolPan.dwTotalLeftAmpFactor = DBToAmpFactor(-10000);
  3037. dsVolPan.dwTotalRightAmpFactor = DBToAmpFactor(-10000);
  3038. dsVolPan.lVolume = -10000;
  3039. dsVolPan.dwVolAmpFactor = DBToAmpFactor(-10000);
  3040. dsVolPan.lPan = 0;
  3041. dsVolPan.dwPanLeftAmpFactor = DBToAmpFactor(0);
  3042. dsVolPan.dwPanRightAmpFactor = DBToAmpFactor(0);
  3043. vxdBufferSetVolumePan( pdsb->hBuffer, &dsVolPan );
  3044. return;
  3045. }