376 lines
9.3 KiB
C++
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;
|
||
|
}
|