/*========================================================================== * * 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; }