windows-nt/Source/XPSP1/NT/multimedia/directx/dplay/dvoice/dxvutils/dsplayb.cpp
2020-09-26 16:20:57 +08:00

376 lines
9.3 KiB
C++

/*==========================================================================
*
* Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
*
* File: dscrecb.cpp
* Content:
* This module contains the implementation of the
* CDirectSoundPlaybackBuffer.
*
* History:
* Date By Reason
* ==== == ======
* 07/16/99 rodtoll Created
* 08/04/99 rodtoll Updated to take dsound ranges for volume
* 08/27/99 rodtoll Updated CreateBuffer call to remove DX7 dependencies.
* 09/07/99 rodtoll Added 3d caps to buffer
* 09/20/99 rodtoll Added memory allocation failure checks
* 10/05/99 rodtoll Added DPF_MODNAMEs
* 11/02/99 pnewson Fix: Bug #116365 - using wrong DSBUFFERDESC
* 11/12/99 rodtoll Modified abstraction for new waveOut support.
* Now abstracted types look almost like dsound objects
* 01/27/2000 rodtoll Updated sound classes to accept playback flags,
* buffer structures and DSBUFFERDESC instead of DSBUFFERDESC1
* 04/17/2000 rodtoll Fix: Bug #32215 - Session Lost after resuming from hibernation
* 07/12/2000 rodtoll Bug #31468 - Add diagnostic spew to logfile to show what is failing the HW Wizard
* 08/03/2000 rodtoll Bug #41457 - DPVOICE: need way to discover which specific dsound call failed when returning DVERR_SOUNDINITFAILURE
* 10/04/2000 rodtoll Bug #43510 - DPVOICE: Apps receive a DVMSGID_SESSIONLOST w/DVERR_LOCKEDBUFFER
***************************************************************************/
#include "dxvutilspch.h"
#undef DPF_SUBCOMP
#define DPF_SUBCOMP DN_SUBCOMP_VOICE
#define DSOUND_STARTUPLATENCY 1
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackBuffer::CDirectSoundPlaybackBuffer"
CDirectSoundPlaybackBuffer::CDirectSoundPlaybackBuffer(
LPDIRECTSOUNDBUFFER lpdsBuffer
): CAudioPlaybackBuffer(), m_dwLastPosition(0), m_dwPriority(0),m_dwFlags(0),m_fPlaying(FALSE)
{
HRESULT hr;
hr = lpdsBuffer->QueryInterface( IID_IDirectSoundBuffer, (void **) &m_lpdsBuffer );
if( FAILED( hr ) )
{
Diagnostics_Write(DVF_ERRORLEVEL, "Unable to get dsound buffer interface" );
m_lpdsBuffer = NULL;
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackBuffer::CDirectSoundPlaybackBuffer"
CDirectSoundPlaybackBuffer::~CDirectSoundPlaybackBuffer()
{
if( m_lpdsBuffer != NULL )
{
m_lpdsBuffer->Release();
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackBuffer::Lock"
HRESULT CDirectSoundPlaybackBuffer::Lock( DWORD dwWriteCursor, DWORD dwWriteBytes, LPVOID *lplpvBuffer1, LPDWORD lpdwSize1, LPVOID *lplpvBuffer2, LPDWORD lpdwSize2, DWORD dwFlags )
{
if( m_lpdsBuffer == NULL )
{
Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
return DVERR_NOTINITIALIZED;
}
HRESULT hr;
while( 1 )
{
hr = m_lpdsBuffer->Lock( dwWriteCursor, dwWriteBytes, lplpvBuffer1, lpdwSize1, lplpvBuffer2, lpdwSize2, dwFlags );
if( hr == DSERR_BUFFERLOST )
{
DPFX(DPFPREP, 0, "Buffer lost while locking buffer" );
hr = Restore();
}
else
{
DSERTRACK_Update( "DSB::Lock()", hr );
break;
}
if( hr == DSERR_BUFFERLOST )
Sleep( 50 );
}
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackBuffer::UnLock"
HRESULT CDirectSoundPlaybackBuffer::UnLock( LPVOID lpvBuffer1, DWORD dwSize1, LPVOID lpvBuffer2, DWORD dwSize2 )
{
if( m_lpdsBuffer == NULL )
{
Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
return DVERR_NOTINITIALIZED;
}
HRESULT hr;
hr = m_lpdsBuffer->Unlock( lpvBuffer1, dwSize1, lpvBuffer2, dwSize2 );
if( hr == DSERR_BUFFERLOST )
{
hr = DS_OK;
}
DSERTRACK_Update( "DSB::UnLock()", hr );
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackBuffer::SetVolume"
HRESULT CDirectSoundPlaybackBuffer::SetVolume( LONG lVolume )
{
if( m_lpdsBuffer == NULL )
{
Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
return DVERR_NOTINITIALIZED;
}
HRESULT hr;
while( 1 )
{
hr = m_lpdsBuffer->SetVolume( lVolume );
if( hr == DSERR_BUFFERLOST )
{
DPFX(DPFPREP, 0, "Buffer lost while setting volume" );
hr = Restore();
}
else
{
break;
}
if( hr == DSERR_BUFFERLOST )
Sleep( 50 );
}
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackBuffer::GetCurrentPosition"
HRESULT CDirectSoundPlaybackBuffer::GetCurrentPosition( LPDWORD lpdwPosition )
{
HRESULT hr;
if( m_lpdsBuffer == NULL )
{
Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
return DVERR_NOTINITIALIZED;
}
while( 1 )
{
hr = m_lpdsBuffer->GetCurrentPosition( NULL, lpdwPosition );
if( SUCCEEDED( hr ) )
{
DSERTRACK_Update( "DSB::GetCurrentPosition()", hr );
m_dwLastPosition = *lpdwPosition;
break;
}
else if( hr == DSERR_BUFFERLOST )
{
DPFX(DPFPREP, 0, "Buffer lost while getting current position" );
hr = Restore();
DPFX(DPFPREP, 0, "Restore --> 0x%x", hr );
}
else
{
DSERTRACK_Update( "DSB::GetCurrentPosition()", hr );
break;
}
if( hr == DSERR_BUFFERLOST )
Sleep( 50 );
}
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackBuffer::SetCurrentPosition"
HRESULT CDirectSoundPlaybackBuffer::SetCurrentPosition( DWORD dwPosition )
{
HRESULT hr;
if( m_lpdsBuffer == NULL )
{
Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
return DVERR_NOTINITIALIZED;
}
while( 1 )
{
hr = m_lpdsBuffer->SetCurrentPosition( dwPosition );
if( SUCCEEDED( hr ) )
{
DSERTRACK_Update( "DSB::SetCurrentPosition()", hr );
m_dwLastPosition = dwPosition;
break;
}
else if( hr == DSERR_BUFFERLOST )
{
DPFX(DPFPREP, 0, "Buffer lost while setting position" );
hr = Restore();
}
else
{
DSERTRACK_Update( "DSB::SetCurrentPosition()", hr );
break;
}
if( hr == DSERR_BUFFERLOST )
Sleep( 50 );
}
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackBuffer::Get3DBuffer"
HRESULT CDirectSoundPlaybackBuffer::Get3DBuffer( LPDIRECTSOUND3DBUFFER *lplpds3dBuffer )
{
if( m_lpdsBuffer == NULL )
{
Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
return DVERR_NOTINITIALIZED;
}
return m_lpdsBuffer->QueryInterface( IID_IDirectSound3DBuffer, (void **) lplpds3dBuffer );
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackBuffer::Play"
HRESULT CDirectSoundPlaybackBuffer::Play( DWORD dwPriority, DWORD dwFlags )
{
if( m_lpdsBuffer == NULL )
{
Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
return DVERR_NOTINITIALIZED;
}
HRESULT hr;
m_dwPriority = dwPriority ;
m_dwFlags = dwFlags;
while( 1 )
{
hr = m_lpdsBuffer->Play( 0, dwPriority, dwFlags );
if( hr == DSERR_BUFFERLOST )
{
DPFX(DPFPREP, 0, "Error playing buffer" );
hr = Restore();
}
else
{
break;
}
if( hr == DSERR_BUFFERLOST )
Sleep( 50 );
}
m_fPlaying = TRUE;
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackBuffer::Stop"
HRESULT CDirectSoundPlaybackBuffer::Stop()
{
if( m_lpdsBuffer == NULL )
{
Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
return DVERR_NOTINITIALIZED;
}
HRESULT hr;
while( 1 )
{
hr = m_lpdsBuffer->Stop( );
m_fPlaying = FALSE;
if( hr == DSERR_BUFFERLOST )
{
DPFX(DPFPREP, 0, "Error stopping buffer" );
hr = Restore();
// If buffer is lost during restore, no need to stop
break;
}
else
{
DSERTRACK_Update( "DSB::Stop()", hr );
break;
}
if( hr == DSERR_BUFFERLOST )
Sleep( 50 );
}
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackBuffer::Restore"
HRESULT CDirectSoundPlaybackBuffer::Restore()
{
if( m_lpdsBuffer == NULL )
{
Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
return DVERR_NOTINITIALIZED;
}
HRESULT hr = m_lpdsBuffer->Restore( );
DPFX(DPFPREP, 0, "Restore result --> 0x%x", hr );
if( SUCCEEDED( hr ) )
{
if( m_fPlaying )
{
// Attempt to restore current position as well
hr = m_lpdsBuffer->SetCurrentPosition( m_dwLastPosition );
if( FAILED( hr ) )
{
DPFX(DPFPREP, 0, "Error setting position after restore hr=0x%x", hr );
return hr;
}
hr = Play(m_dwPriority, m_dwFlags);
}
}
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundPlaybackBuffer::GetStartupLatency"
DWORD CDirectSoundPlaybackBuffer::GetStartupLatency()
{
return DSOUND_STARTUPLATENCY;
}