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

443 lines
10 KiB
C++

/*==========================================================================
*
* Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
*
* File: dscrecb.cpp
* Content:
* This module contains the implementation of the
* CDirectSoundCaptureRecordBuffer.
*
* History:
* Date By Reason
* ==== == ======
* 11/04/99 rodtoll Created
* 11/22/99 rodtoll Added code to allow specification of wave device ID
* 11/23/99 rodtoll Updated to use waveIn device ID or DSound 7.1 when they are avail
* rodtoll Updated with new Microphone select member
* 12/08/99 rodtoll Bug #115783 - Will always adjust volume of default device
* Now uses new CMixerLine class for adjusting volumes/selecting mic
* 12/08/99 rodtoll Bug #121054 - DirectX 7.1 support.
* - Added hwndOwner param for capture focus support
* - Added lpfLostFocus param to GetCurrentPosition so upper
* layers can detect lost focus.
* 01/28/2000 rodtoll Bug #130465: Record Mute/Unmute must call YieldFocus() / ClaimFocus()
* 02/10/2000 rodtoll Removed more capture focus code
* 04/19/2000 rodtoll Re-enabled capture focus behaviour
* 08/03/2000 rodtoll Bug #41457 - DPVOICE: need way to discover which specific dsound call failed when returning DVERR_SOUNDINITFAILURE
* 04/22/2001 rodtoll Fixed bug in lockup simulation code (TESTING PURPOSES ONLY)
*
***************************************************************************/
#include "dxvutilspch.h"
#undef DPF_SUBCOMP
#define DPF_SUBCOMP DN_SUBCOMP_VOICE
#define DSC_STARTUP_LATENCY 1
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::CDirectSoundCaptureRecordBuffer"
CDirectSoundCaptureRecordBuffer::CDirectSoundCaptureRecordBuffer(
LPDIRECTSOUNDCAPTUREBUFFER lpdscBuffer, HWND hwndOwner, const GUID &guidDevice, UINT uiWaveDeviceID, LPDSCBUFFERDESC lpdsBufferDesc
): CAudioRecordBuffer(), m_lpwfxRecordFormat(NULL), m_lpdscBuffer7(NULL),
m_guidDevice(guidDevice), m_uiWaveDeviceID(uiWaveDeviceID),
#ifdef LOCKUP_SIMULATION
m_dwNumSinceLastLockup(0), m_dwLastPosition(0),
#endif
m_hwndOwner(hwndOwner), m_fUseCaptureFocus( FALSE )
{
HRESULT hr;
DWORD dwSize;
if( lpdsBufferDesc->dwFlags & DSCBCAPS_FOCUSAWARE )
{
DPFX(DPFPREP, 1, "Enabling focus" );
m_fUseCaptureFocus = TRUE;
}
else
{
DPFX(DPFPREP, 1, "Disabling focus" );
m_fUseCaptureFocus = FALSE;
}
hr = lpdscBuffer->QueryInterface( IID_IDirectSoundCaptureBuffer, (void **) &m_lpdscBuffer );
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get dsound buffer interface" );
m_lpdscBuffer = NULL;
}
hr = lpdscBuffer->QueryInterface( IID_IDirectSoundCaptureBuffer7_1, (void **) &m_lpdscBuffer7 );
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Could not retrieve new interface hr=0x%x.", hr );
hr = m_mixerLine.Initialize( m_uiWaveDeviceID );
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to acquire volume controls hr=0x%x", hr );
DNASSERT( FALSE );
}
}
else
{
if( m_fUseCaptureFocus )
{
hr = m_lpdscBuffer7->SetFocusHWND( hwndOwner );
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to set the focus window hr = 0x%x", hr );
DNASSERT( FALSE );
}
}
}
hr = lpdscBuffer->GetFormat( NULL, 0, &dwSize );
m_lpwfxRecordFormat = (LPWAVEFORMATEX) new BYTE[dwSize];
if( m_lpwfxRecordFormat == NULL )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to allocate space for record format" );
DNASSERT( FALSE );
}
hr = lpdscBuffer->GetFormat( m_lpwfxRecordFormat, dwSize, NULL );
if( FAILED( hr ) )
{
delete [] ((LPBYTE) m_lpwfxRecordFormat);
m_lpwfxRecordFormat = NULL;
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::CDirectSoundCaptureRecordBuffer"
CDirectSoundCaptureRecordBuffer::~CDirectSoundCaptureRecordBuffer()
{
if( m_lpdscBuffer7 != NULL )
{
m_lpdscBuffer7->Release();
}
if( m_lpdscBuffer != NULL )
{
m_lpdscBuffer->Release();
}
if( m_lpwfxRecordFormat != NULL )
{
delete [] ((LPBYTE) m_lpwfxRecordFormat);
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::Lock"
HRESULT CDirectSoundCaptureRecordBuffer::Lock( DWORD dwWriteCursor, DWORD dwWriteBytes, LPVOID *lplpvBuffer1, LPDWORD lpdwSize1, LPVOID *lplpvBuffer2, LPDWORD lpdwSize2, DWORD dwFlags )
{
HRESULT hr;
if( m_lpdscBuffer == NULL )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "No DirectSoundCapture Buffer Available" );
return DVERR_NOTINITIALIZED;
}
hr = m_lpdscBuffer->Lock( dwWriteCursor, dwWriteBytes, lplpvBuffer1, lpdwSize1, lplpvBuffer2, lpdwSize2, dwFlags );
DSERTRACK_Update( "DSCB::Lock()", hr );
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::UnLock"
HRESULT CDirectSoundCaptureRecordBuffer::UnLock( LPVOID lpvBuffer1, DWORD dwSize1, LPVOID lpvBuffer2, DWORD dwSize2 )
{
HRESULT hr;
if( m_lpdscBuffer == NULL )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "No DirectSoundCapture Buffer Available" );
return DVERR_NOTINITIALIZED;
}
hr = m_lpdscBuffer->Unlock( lpvBuffer1, dwSize1, lpvBuffer2, dwSize2 );
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::SetVolume"
HRESULT CDirectSoundCaptureRecordBuffer::SetVolume( LONG lVolume )
{
if( m_lpdscBuffer == NULL )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "No DirectSoundCapture Buffer Available" );
return DVERR_NOTINITIALIZED;
}
HRESULT hr;
if( m_lpdscBuffer7 != NULL )
{
hr = m_lpdscBuffer7->SetVolume( lVolume );
}
else
{
hr = m_mixerLine.SetMasterRecordVolume( lVolume );
}
// This is only a warning condition
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_INFOLEVEL, "Could not set master volume hr=0x%x", hr );
}
if( m_lpdscBuffer7 != NULL )
{
hr = m_lpdscBuffer7->SetMicVolume( lVolume );
}
else
{
hr = m_mixerLine.SetMicrophoneVolume( lVolume );
}
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_INFOLEVEL, "Unable to set Microphone volume hr=0x%x", hr );
return hr;
}
return DV_OK;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::GetVolume"
HRESULT CDirectSoundCaptureRecordBuffer::GetVolume( LPLONG lplVolume )
{
if( m_lpdscBuffer == NULL )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "No DirectSoundCapture Buffer Available" );
return DVERR_NOTINITIALIZED;
}
HRESULT hr;
if( m_lpdscBuffer7 != NULL )
{
hr = m_lpdscBuffer7->GetMicVolume( lplVolume );
}
else
{
hr = m_mixerLine.GetMicrophoneVolume( lplVolume );
}
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to get Microphone volume hr=0x%x", hr );
if( m_lpdscBuffer7 != NULL )
{
hr = m_lpdscBuffer7->GetVolume( lplVolume );
}
else
{
hr = m_mixerLine.GetMasterRecordVolume( lplVolume );
}
// This is only a warning condition
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Could not get master record volume hr=0x%x", hr );
return hr;
}
return hr;
}
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::GetCurrentPosition"
HRESULT CDirectSoundCaptureRecordBuffer::GetCurrentPosition( LPDWORD lpdwPosition, LPBOOL lpfLostFocus )
{
if( m_lpdscBuffer == NULL )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "No DirectSoundCapture Buffer Available" );
return DVERR_NOTINITIALIZED;
}
#ifdef LOCKUP_SIMULATION
m_dwNumSinceLastLockup++;
if( m_dwNumSinceLastLockup > LOCKUP_NUM_CALLS_BEFORE_LOCKUP )
{
*lpdwPosition = m_dwLastPosition;
*lpfLostFocus = FALSE;
return DV_OK;
}
#endif
HRESULT hr;
if( m_lpdscBuffer7 != NULL && m_fUseCaptureFocus )
{
DWORD dwStatus;
hr = m_lpdscBuffer7->GetStatus( &dwStatus );
if( FAILED( hr ) )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "Error getting status hr=0x%x", hr );
*lpfLostFocus = FALSE;
}
else
{
*lpfLostFocus = (dwStatus & DSCBSTATUS_LOSTFOCUS) ? TRUE : FALSE;
}
}
else
{
*lpfLostFocus = FALSE;
}
hr = m_lpdscBuffer->GetCurrentPosition( NULL, lpdwPosition );
#ifdef LOCKUP_SIMULATION
m_dwLastPosition = *lpdwPosition;
#endif
DSERTRACK_Update( "DSCB::GetCurrentPosition()", hr );
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::Play"
HRESULT CDirectSoundCaptureRecordBuffer::Record( BOOL fLooping )
{
if( m_lpdscBuffer == NULL )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
return DVERR_NOTINITIALIZED;
}
HRESULT hr;
hr = m_lpdscBuffer->Start( (fLooping) ? DSCBSTART_LOOPING : 0 );
#ifdef LOCKUP_SIMULATION
#ifdef LOCKUP_STOPFAIL
if( m_dwNumSinceLastLockup > LOCKUP_NUM_CALLS_BEFORE_LOCKUP )
{
hr = DSERR_GENERIC;
}
#else
m_dwNumSinceLastLockup = 0;
#endif
#endif
DSERTRACK_Update( "DSCB::Start()", hr );
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::Stop"
HRESULT CDirectSoundCaptureRecordBuffer::Stop()
{
if( m_lpdscBuffer == NULL )
{
DPFX(DPFPREP, DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
return DVERR_NOTINITIALIZED;
}
HRESULT hr;
hr = m_lpdscBuffer->Stop( );
#ifdef LOCKUP_SIMULATION
#ifdef LOCKUP_STOPFAIL
if( m_dwNumSinceLastLockup > LOCKUP_NUM_CALLS_BEFORE_LOCKUP )
{
hr = DSERR_GENERIC;
}
#endif
#endif
DSERTRACK_Update( "DSCB::Stop()", hr );
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::GetStartupLatency"
DWORD CDirectSoundCaptureRecordBuffer::GetStartupLatency()
{
return DSC_STARTUP_LATENCY;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::GetRecordFormat"
LPWAVEFORMATEX CDirectSoundCaptureRecordBuffer::GetRecordFormat()
{
return m_lpwfxRecordFormat;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::SelectMicrophone"
HRESULT CDirectSoundCaptureRecordBuffer::SelectMicrophone( BOOL fSelect )
{
if( m_lpdscBuffer7 != NULL )
{
return m_lpdscBuffer7->EnableMic( fSelect );
}
else
{
return m_mixerLine.EnableMicrophone( fSelect );
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::ClaimFocus"
HRESULT CDirectSoundCaptureRecordBuffer::ClaimFocus( )
{
if( m_lpdscBuffer7 != NULL && m_fUseCaptureFocus)
{
return m_lpdscBuffer7->ClaimFocus();
}
else
{
return DVERR_NOTSUPPORTED;
}
}
#undef DPF_MODNAME
#define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::YieldFocus"
HRESULT CDirectSoundCaptureRecordBuffer::YieldFocus( )
{
if( m_lpdscBuffer7 != NULL && m_fUseCaptureFocus )
{
return m_lpdscBuffer7->YieldFocus();
}
else
{
return DVERR_NOTSUPPORTED;
}
}