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.
 
 
 
 
 
 

423 lines
11 KiB

//--------------------------------------------------------------------------;
//
// File: idsi.c
//
// Copyright (c) 1995 Microsoft Corporation. All Rights Reserved.
//
// Abstract:
// This file contains worker functions called internally by
// IDirectSound member functions. These functions operate on
// DSOUND objects (i.e., internal direct sound objects) and
// do not perform parameter validation nor do they take the
// DLL critical sections. In all cases, the calling function
// is responsible for doing this.
//
// Contents:
// IDsCreateSoundBufferI
//
//--------------------------------------------------------------------------;
#include "dsoundpr.h"
//--------------------------------------------------------------------------;
//
// HRESULT DsInitializeDefaultFormat
//
// Description:
// Fills in the wfxDefault member of the ds object. The format
// is based on the system default stored in the dsinfo but may
// deviate depending on the capabilities of the ds object.
//
// Note that this may be called before the ds object has been
// completely constructed, as it is called from DirectSoundCreate.
//
// Arguments:
// LPDSOUND pds
//
// Return (DSVAL):
//
// History:
// 07/17/95 FrankYe Created
//
//--------------------------------------------------------------------------;
#define FNAME "DsInitializeDefaultFormat: "
HRESULT DsInitializeDefaultFormat(LPDSOUND pds)
{
LPWAVEFORMATEX pwfx;
DSDRIVERCAPS dsDrvCaps;
HRESULT hr;
// DirectSound supports only PCM formats for now.
// This function assumes PCM formats.
ASSERT(WAVE_FORMAT_PCM == gpdsinfo->pwfxUserDefault->wFormatTag);
pwfx = &pds->wfxDefault;
//
// Handle wave emulated ds objects
//
if (DS_INTERNALF_WAVEEMULATED & pds->fdwInternal) {
BOOL fBreak;
MMRESULT mmr;
int i, j, k;
//
// Start with the user default
//
CopyMemory(pwfx, gpdsinfo->pwfxUserDefault, sizeof(pds->wfxDefault));
// We search for a format that works.
//
// i loop cycles through nChannels
// j loop cycles through sample rate
// k loop cycles through bit resolution
//
// We loop like this so that the number of channels is least likely
// to deviate from the user format, sample rate is next least likely.
//
i = 0;
do {
j = 0;
do {
k = 0;
do {
// Fix up nBlockAlign and nAvgBytesPerSec
pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample/8;
pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
mmr = waveOutOpen(NULL, pds->uDeviceID, pwfx, 0, 0, WAVE_FORMAT_QUERY);
fBreak = (MMSYSERR_NOERROR == mmr);
if (fBreak) break;
if (pwfx->wBitsPerSample == 16) {
pwfx->wBitsPerSample = 8;
} else {
pwfx->wBitsPerSample = 16;
}
} while (++k < 2);
if (fBreak) break;
if (pwfx->nSamplesPerSec == 44100) {
pwfx->nSamplesPerSec = 22050;
} else if (pwfx->nSamplesPerSec == 22050) {
pwfx->nSamplesPerSec = 11025;
} else if (pwfx->nSamplesPerSec == 11025) {
pwfx->nSamplesPerSec = 8000;
} else {
pwfx->nSamplesPerSec = 44100;
}
} while (++j < 4);
if (fBreak) break;
if (pwfx->nChannels == 2) {
pwfx->nChannels = 1;
} else {
pwfx->nChannels = 2;
}
} while (++i < 2);
if (MMSYSERR_NOERROR != mmr) {
DPF(0, FNAME "error: waveOutOpen.Query returned %08Xh", mmr);
// Couldn't come up with anything. Put back user default.
CopyMemory(pwfx, gpdsinfo->pwfxUserDefault, sizeof(pds->wfxDefault));
return DSERR_GENERIC;
}
return DS_OK;
}
// If we fall through, we are not on a wave emulated object
ASSERT(0 == (DS_INTERNALF_WAVEEMULATED & pds->fdwInternal));
//
// Handle non-wave emulated ds objects
//
FillMemory(&dsDrvCaps, sizeof(dsDrvCaps), 0);
hr = vxdDrvGetCaps(pds->hHal, &dsDrvCaps);
if (DS_OK != hr) {
DPF(0, FNAME "error: vxdDrvGetDriverCaps returned %08Xh", hr);
return hr;
}
//
// Start with the user default
//
CopyMemory(pwfx, gpdsinfo->pwfxUserDefault, sizeof(pds->wfxDefault));
// Adjust resolution
if (pwfx->wBitsPerSample == 16) {
if (!(DSCAPS_PRIMARY16BIT & dsDrvCaps.dwFlags)) {
// Try 8-bit
pwfx->wBitsPerSample = 8;
ASSERT(DSCAPS_PRIMARY8BIT & dsDrvCaps.dwFlags);
}
} else {
if (!(DSCAPS_PRIMARY8BIT & dsDrvCaps.dwFlags)) {
// Try 16-bit
pwfx->wBitsPerSample = 16;
ASSERT(DSCAPS_PRIMARY16BIT & dsDrvCaps.dwFlags);
}
}
// Adjust mono/stereo
if (pwfx->nChannels == 2) {
if (!(DSCAPS_PRIMARYSTEREO & dsDrvCaps.dwFlags)) {
// Try mono
pwfx->nChannels = 1;
ASSERT(DSCAPS_PRIMARYMONO & dsDrvCaps.dwFlags);
}
} else {
if (!(DSCAPS_PRIMARYMONO & dsDrvCaps.dwFlags)) {
// Try stereo
pwfx->nChannels = 2;
ASSERT(DSCAPS_PRIMARYSTEREO & dsDrvCaps.dwFlags);
}
}
// Fix up nBlockAlign and nAvgBytesPerSec
pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample/8;
pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
return DS_OK;
}
#undef FNAME
//--------------------------------------------------------------------------;
//
// HRESULT DsCreateHardwareBuffer
//
// Description:
//
// Arguments:
// LPDSOUND pds
//
// LPDSBUFFER pdsb
//
// LPDSBUFFERDESC pdsbd
//
// LPBOOL pfTrySoftware: If an error is encountered such that we
// should not retry creating the buffer as a software buffer,
// then this routine will write FALSE to this flag. Otherwise
// this routine WILL NOT WRITE to this flag.
//
// Return (DSVAL):
//
// History:
// 07/17/95 FrankYe Created
//
//--------------------------------------------------------------------------;
HRESULT DsCreateHardwareBuffer
(
LPDSOUND pds,
LPDSBUFFER pdsb,
LPDSBUFFERDESC pdsbd,
LPBOOL pfTrySoftware
)
{
LPWAVEFORMATEX pwfx = pdsb->pwfx;
DWORD dwcbBufferSize = pdsb->cbBufferSize;
DWORD dwFlags = pdsbd->dwFlags;
LPBYTE pBuffer = NULL;
HANDLE hBuffer = NULL;
DSVAL dsv = DS_OK;
pdsb->dwCardAddress = 0;
//
// We are asking for a HW buffer...
//
DPF(3,"HW Create HW buffer");
DPF(3,"HW Create - sample rate %d", pdsb->helInfo.dwSampleRate );
DPF(3,"HW Create - hfForamt %X", pdsb->helInfo.hfFormat );
//
// See whether we should use system memory for the sound buffer
//
if( (DSDDESC_USESYSTEMMEMORY & pds->fdwDriverDesc) &&
!(pdsbd->dwFlags & DSBCAPS_PRIMARYBUFFER ) ) {
// Allocate the buffer sound buffer in system memory
pBuffer = (LPBYTE)MemAlloc(dwcbBufferSize);
if(NULL == pBuffer) {
DPF(0,"DSDDESC_USESYSTEMMEMORY buffer alloc failed");
dsv = DSERR_OUTOFMEMORY;
*pfTrySoftware = FALSE;
goto retDestruct;
}
DPF(1, " allocated system memory at %08Xh", pBuffer);
}
//
// see whether to allocate on-card memory
//
if( (NULL != pds->pDriverHeap) && !(pdsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) ) {
// Use dmemmgr to allocate on-card buffer and pass
// that allocation to the driver
pdsb->dwCardAddress = VidMemAlloc( pds->pDriverHeap,
dwcbBufferSize + pds->dwMemAllocExtra,
1);
if (0 == pdsb->dwCardAddress) {
dsv = DSERR_ALLOCATED;
goto retDestruct;
}
DPF(1, " allocated card memory at %08Xh", pdsb->dwCardAddress);
}
//
// now ask driver to create sound buffer
//
dsv = vxdDrvCreateSoundBuffer( pds->hHal, pwfx,
dwFlags & DSBCAPS_DRIVERFLAGSMASK,
pdsb->dwCardAddress, &dwcbBufferSize,
&pBuffer, &hBuffer );
if (DS_OK != dsv) {
DPF(0,"vxdDrvCreateSoundBuffer failed");
hBuffer = NULL;
goto retDestruct;
}
//
// see whether we should set format via mmsystem
//
if ( (DSDDESC_DOMMSYSTEMSETFORMAT & pds->fdwDriverDesc) &&
(DSBCAPS_PRIMARYBUFFER & pdsbd->dwFlags) )
{
//
// We need to set the wave format by doing a waveOutOpen on the
// mmsystem wave device
//
UINT uDeviceID;
MMRESULT mmr;
DPF(3, "CreateSoundBuffer: DSDCAPS_DOMMSYSTEMSETFORMAT");
ASSERT(pds->hwo);
waveOutGetID(pds->hwo, &uDeviceID);
HelperWaveClose( (DWORD)(pds->hwo) );
pds->hwo = NULL;
mmr = (MMRESULT)HelperWaveOpen(&(pds->hwo),
uDeviceID,
pwfx);
if (MMSYSERR_NOERROR != mmr) {
pds->hwo = NULL;
if (MMSYSERR_ALLOCATED == mmr) dsv = DSERR_BUFFERLOST;
if (MMSYSERR_NOMEM == mmr) dsv = DSERR_OUTOFMEMORY;
if (DS_OK == dsv) dsv = DSERR_GENERIC;
*pfTrySoftware = FALSE;
goto retDestruct;
}
}
//
// all went okay
//
DPF(3,"IDSHWCreateSoundBuffer buffer alloc OK");
DPF(3," lin addr %X", pBuffer );
DPF(3," length %X", dwcbBufferSize );
ASSERT(NULL != hBuffer);
pdsb->hBuffer = hBuffer;
pdsb->pDSBuffer = pBuffer;
pdsb->cbBufferSize = dwcbBufferSize;
pdsb->fdwDsbI &= (~DSB_INTERNALF_EMULATED);
pdsb->fdwDsbI |= DSB_INTERNALF_HARDWARE;
retDestruct:
if (DS_OK == dsv) return dsv;
// release buffer
if (NULL != hBuffer) {
vxdBufferRelease(hBuffer);
hBuffer = NULL;
}
// free card memory
if (0 != pdsb->dwCardAddress) {
ASSERT(NULL != pds->pDriverHeap);
ASSERT(!(pdsbd->dwFlags & DSBCAPS_PRIMARYBUFFER));
VidMemFree(pds->pDriverHeap, pdsb->dwCardAddress);
pdsb->dwCardAddress = 0;
}
// free sysalloc mem
if( (DSDDESC_USESYSTEMMEMORY & pds->fdwDriverDesc) &&
(0 == (pdsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) &&
(NULL != pBuffer) ) {
MemFree(pBuffer);
pBuffer = NULL;
}
return dsv;
}
//--------------------------------------------------------------------------;
//
// HRESULT DsCreateSoftwareBuffer
//
// Description:
//
// Arguments:
// LPDSOUND pds
//
// LPDSBUFFER pdsb
//
// LPDSBUFFERDESC pdsbd
//
// Return (DSVAL):
//
// History:
// 07/17/95 FrankYe Created
//
//--------------------------------------------------------------------------;
HRESULT DsCreateSoftwareBuffer
(
LPDSOUND pds,
LPDSBUFFER pdsb,
LPDSBUFFERDESC pdsbd
)
{
DPF(3,"HW Create Emulated secondary buffer");
// Allocate the buffer
pdsb->pDSBuffer = (LPBYTE)MemAlloc(pdsbd->dwBufferBytes);
if(NULL == pdsb->pDSBuffer) {
DPF(1,"IDSHWCreateSoundBuffer buffer alloc fail");
return DSERR_OUTOFMEMORY;
}
pdsb->cbBufferSize = pdsbd->dwBufferBytes;
pdsb->fdwDsbI &= (~DSB_INTERNALF_HARDWARE);
pdsb->fdwDsbI |= DSB_INTERNALF_EMULATED;
// Make sure both copies of the flags reflect that this
// is a software buffer.
pdsbd->dwFlags &= (~DSBCAPS_LOCHARDWARE);
pdsbd->dwFlags |= DSBCAPS_LOCSOFTWARE;
pdsb->fdwBufferDesc &= (~DSBCAPS_LOCHARDWARE);
pdsb->fdwBufferDesc |= DSBCAPS_LOCSOFTWARE;
DPF(3,"--------Alloc data for Emulated obj %X buff %X len %X",
pdsb, pdsb->pDSBuffer, pdsb->cbBufferSize );
return DS_OK;
}