📄 dsdriverbuffer.cpp
字号:
}
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP DsPlaybackDriverBuffer::Play(
/* [in] */ DWORD reserved1,
/* [in] */ DWORD reserved2,
/* [in] */ DWORD dsbPlayFlags)
{
FUNCMSG1("DsDriverBuffer::Play, loop = %s",
((dsbPlayFlags & DSBPLAY_LOOPING) != 0)? TEXT("TRUE"):TEXT("FALSE"));
HRESULT hr = S_OK;
// Tell the device to start playing this buffer.
CriticalSectionAcquisition csa(&m_csBuffer);
// save flags
m_dsbPlayFlags = dsbPlayFlags;
// If already playing, return OK
// Special case -- for Single shot buffers, we need to restart
if(m_bIsRunning && (m_dsbPlayFlags & DSBPLAY_LOOPING) )
return hr;
// IDsDriverBuffer::Play does not support SetPosition other than 0.
// several things would have to get generalized here... including figuring out which
// chunk we're starting on and what the initial count would be.
if (!m_pCX5530->SetupPlay(m_uChannel, m_wfxFormat.nChannels, m_wfxFormat.wBitsPerSample, m_dwCurrentFrequency, (m_dsbPlayFlags & DSBPLAY_LOOPING) != 0))
return DSERR_GENERIC;
SetDMABuffer();
StartDMAChannel();
FUNCMSG("-DsPlaybackDriverBuffer::Play");
return hr;
}
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP DsPlaybackDriverBuffer::Stop(void)
{
FUNCMSG1("DsDriverBuffer::Stop -- buf %d", m_uChannel);
HRESULT hr = DS_OK;
if(!m_bIsRunning)
return hr;
// Stop the buffer from playing here.
StopDMAChannel();
// --for SetEvent
// We need to have the right ACL's to be able to set the events
// which were created in another process.
// Save the old permissions.
DWORD dwSavedPermissions = GetCurrentPermissions();
SetProcPermissions( DWORD (-1) );
__try
{
// set the Stop notification, if one is registered
if (m_hEventStop != NULL) {
SetEvent(m_hEventStop);
}
}
__except(1 /*EXCEPTION_EXECUTE_HANDLER*/)
{
// happens when you kill the client process
ERRMSG("DsDriverBuffer::Stop -- Error setting notification event");
}
// Restore the old permissions.
SetProcPermissions( dwSavedPermissions );
m_bIsRunning = false;
return hr;
}
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP DsPlaybackDriverBuffer::GetPosition( LPDWORD pdwPlay, LPDWORD pdwWrite)
{
//FUNCMSG("+DsPlaybackDriverBuffer::GetPosition");
HRESULT hr = DS_OK;
CriticalSectionAcquisition csa(&m_csBuffer);
// Return the current play and write positions in the buffer.
// Play is what's currently coming out of the speaker.
// Write is what's already committed (so place ahead of
// which it is OK to write new data).
if(!pdwPlay || !pdwWrite)
{
ERRMSG("DsPlaybackDriverBuffer::GetPosition: bad parms");
return DSERR_INVALIDPARAM;
}
if (! m_bIsRunning)
{
//ERRMSG("DsPlaybackDriverBuffer::GetPosition: buffer not playing");
*pdwPlay = *pdwWrite = 0;
return hr;
}
// the current DMA position for the curent channel, as a
*pdwPlay = GetDMAPosition();
// Since the card DMA reads data 8 long words(32 bytes) at a time, the write position
// will be the next block of 32 bytes that is going to be transferred. For more safety,
// we'll keep the write position another 32 byte chunk ahead.
*pdwWrite = (*pdwPlay + (32 - *pdwPlay % 32) + 32) % m_ulSize;
// FUNCMSG3("-DsDriverBuffer::GetPosition: size 0x%x, write 0x%x, play 0x%x\r\n",
// m_ulSize, *pdwWrite, *pdwPlay);
return hr;
}
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP DsPlaybackDriverBuffer::SetPosition(/* [in] */ DWORD dwPosition)
{
FUNCMSG("DsDriverBuffer::SetPosition");
HRESULT hr = DS_OK;
// Move play position of buffer to specified position.
if (dwPosition == 0)
{
// all we really support is setting the position to 0
return DS_OK;
}
return DSERR_UNSUPPORTED;
//return hr;
}
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP DsPlaybackDriverBuffer::SetFormat(
/* [in] */ LPWAVEFORMATEX pwfxFormatEx)
{
FUNCMSG("DsDriverBuffer::SetFormat");
if (m_bIsRunning)
{
return DSERR_INVALIDCALL;
}
if (!pwfxFormatEx || !m_pCX5530->IsFormatSupported(pwfxFormatEx))
{
WARNMSG("DsPlaybackDriverBuffer::SetFormat: Format not supported");
return DSERR_UNSUPPORTED;
}
CriticalSectionAcquisition csa(&m_csBuffer);
// Change format of existing buffer.
//save format
memcpy(&m_wfxFormat, pwfxFormatEx, sizeof(WAVEFORMATEX));
return DS_OK;
}
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP DsPlaybackDriverBuffer::SetVolumePan(/* [in] */ PDSVOLUMEPAN pdsVolumePan)
{
FUNCMSG("+DsPlaybackDriverBuffer::SetVolumePan");
HRESULT hr = DS_OK;
CriticalSectionAcquisition csa(&m_csBuffer);
// Set the volume and pan for this buffer.
return m_pCX5530->SetVolumePan(m_uChannel, pdsVolumePan);
}
//////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP DsPlaybackDriverBuffer::SetFrequency(/* [in] */ DWORD dwFrequency)
{
FUNCMSG1("DsPlaybackDriverBuffer::SetFrequency: %d", dwFrequency);
CriticalSectionAcquisition csa(&m_csBuffer);
if (dwFrequency == DSBFREQUENCY_ORIGINAL)
{
// restore original freq
dwFrequency = m_wfxFormat.nSamplesPerSec;
}
HRESULT hr = m_pCX5530->SetFrequency(false, dwFrequency);
if (SUCCEEDED(hr))
m_dwCurrentFrequency = dwFrequency;
return hr;
}
STDMETHODIMP DsPlaybackDriverBuffer::GetStatus( LPDWORD pdwStatus)
{
FUNCMSG("+DsDriverBuffer::GetStatus");
if (!pdwStatus)
{
ERRMSG("DsPlaybackDriverBuffer::GetStatus: bad parms");
return DSERR_INVALIDPARAM;
}
if (m_bIsRunning)
{
if (m_dsbPlayFlags & DSBPLAY_LOOPING)
{
*pdwStatus = DSBSTATUS_PLAYING | DSBSTATUS_LOOPING;
}
else
{
*pdwStatus = DSBSTATUS_PLAYING;
}
}
else
{
*pdwStatus = 0;
}
return DS_OK;
}
void DsPlaybackDriverBuffer::ProcessInterrupt()
{
// FUNCMSG2("+DsPlaybackDriverBuffer::ProcessInterrupt(%d) at %d", intsrc, GetTickCount());
bool bStop = IsStopInterrupt();
CHardwareBuffer::ProcessInterrupt();
// test for looping
// note that single-shot mode and notification positions are not mutually exclusive
//If LOOP is not specified (one shot buffers)
// we'll stop the buffer on an interrupt
if(bStop && !(m_dsbPlayFlags & DSBPLAY_LOOPING))
{
//reset the hardware dma channel
INFMSG("DsPlaybackDriverBuffer::ProcessInterrupt calling Stop");
Stop();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -