358 lines
9.7 KiB
C++
358 lines
9.7 KiB
C++
|
/*==========================================================================
|
||
|
*
|
||
|
* Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
|
||
|
*
|
||
|
* File: dsplayd.cpp
|
||
|
* Content:
|
||
|
* This module contains the implementation of the
|
||
|
* CDirectSoundPlaybackDevice.
|
||
|
*
|
||
|
* History:
|
||
|
* Date By Reason
|
||
|
* ==== == ======
|
||
|
* 07/16/99 rodtoll Created
|
||
|
* 07/30/99 rodtoll Updated to allow creation of object using a pre-created
|
||
|
* DirectSound Object.
|
||
|
* 10/05/99 rodtoll Added DPF_MODNAMEs
|
||
|
* 10/14/99 rodtoll Added 3d caps to primary buffer created
|
||
|
* 10/27/99 rodtoll Bug #115431: Must release primary buffer
|
||
|
* 11/12/99 rodtoll Modified abstraction for new waveOut support.
|
||
|
* Now abstracted types look almost like dsound objects
|
||
|
* 12/01/99 rodtoll Bug #121815 - Static in playback/record
|
||
|
* Added implementations of Set/GetMixerQuality
|
||
|
* (For Win2k/Millenium/Systems w/DX7)
|
||
|
* 01/27/2000 rodtoll Updated sound classes to accept playback flags,
|
||
|
* buffer structures and DSBUFFERDESC instead of DSBUFFERDESC1
|
||
|
* 02/16/2000 rodtoll Fixed so primary buffer is not released
|
||
|
* 02/17/2000 rodtoll Updated so primary buffer is held instead of released immediately
|
||
|
* 04/21/2000 rodtoll Bug #32952 - Does not run on Win95 GOLD w/o IE4 -- modified
|
||
|
* to allow reads of REG_BINARY when expecting REG_DWORD
|
||
|
* 04/24/2000 rodtoll Bug #33203 - Removed workaround for aureal vortex 1 problem -- had
|
||
|
* problems on Vortex 2.
|
||
|
* 06/09/00 rmt Updates to split CLSID and allow whistler compat and support external create funcs
|
||
|
* 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
|
||
|
* 08/28/2000 masonb Voice Merge: Changed ccomutil.h to comutil.h
|
||
|
* 04/04/2001 rodtoll WINBUG #343428 - DPVOICE: Voice wizard's playback is very choppy.
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include "dxvutilspch.h"
|
||
|
|
||
|
|
||
|
#undef DPF_SUBCOMP
|
||
|
#define DPF_SUBCOMP DN_SUBCOMP_VOICE
|
||
|
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CDirectSoundPlaybackDevice::CDirectSoundPlaybackDevice"
|
||
|
CDirectSoundPlaybackDevice::CDirectSoundPlaybackDevice(
|
||
|
): CAudioPlaybackDevice(), m_hwndOwner(NULL), m_lpdsDirectSound(NULL), m_guidDevice(GUID_NULL), m_lpdsPrimaryBuffer(NULL), m_fEmulated(FALSE)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CDirectSoundPlaybackDevice::~CDirectSoundPlaybackDevice"
|
||
|
CDirectSoundPlaybackDevice::~CDirectSoundPlaybackDevice()
|
||
|
{
|
||
|
if( m_lpdsPrimaryBuffer != NULL )
|
||
|
{
|
||
|
m_lpdsPrimaryBuffer->Release();
|
||
|
m_lpdsPrimaryBuffer = NULL;
|
||
|
}
|
||
|
|
||
|
if( m_lpdsDirectSound != NULL )
|
||
|
{
|
||
|
m_lpdsDirectSound->Release();
|
||
|
m_lpdsDirectSound = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CDirectSoundPlaybackDevice::CheckAndSetEmulated"
|
||
|
HRESULT CDirectSoundPlaybackDevice::CheckAndSetEmulated( )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
DSCAPS dsCaps;
|
||
|
|
||
|
ZeroMemory( &dsCaps, sizeof( DSCAPS ) );
|
||
|
dsCaps.dwSize = sizeof( DSCAPS );
|
||
|
|
||
|
hr = m_lpdsDirectSound->GetCaps( &dsCaps );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
m_fEmulated = FALSE;
|
||
|
Diagnostics_Write(DVF_ERRORLEVEL, "Querying for playback caps failed hr=0x%x", hr );
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
m_fEmulated = (dsCaps.dwFlags & DSCAPS_EMULDRIVER);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CDirectSoundPlaybackDevice::Initialize"
|
||
|
HRESULT CDirectSoundPlaybackDevice::Initialize( LPDIRECTSOUND lpdsDirectSound, const GUID &guidDevice )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
m_guidDevice = guidDevice;
|
||
|
|
||
|
hr = lpdsDirectSound->QueryInterface( IID_IDirectSound, (void **) &m_lpdsDirectSound );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
Diagnostics_Write(DVF_ERRORLEVEL, "DirectSound Object passed failed. 0x%x Creating internal", hr );
|
||
|
m_lpdsDirectSound = NULL;
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
hr = CheckAndSetEmulated();
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
m_lpdsDirectSound->Release();
|
||
|
m_lpdsDirectSound = NULL;
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
return DV_OK;
|
||
|
}
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CDirectSoundPlaybackDevice::Initialize"
|
||
|
HRESULT CDirectSoundPlaybackDevice::Initialize( const GUID &guidDevice, HWND hwndOwner, WAVEFORMATEX *lpwfxFormat, BOOL fPriorityMode )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
DSBUFFERDESC dsbdesc;
|
||
|
DWORD dwPriority;
|
||
|
|
||
|
m_guidDevice = guidDevice;
|
||
|
|
||
|
if( m_lpdsDirectSound != NULL )
|
||
|
{
|
||
|
Diagnostics_Write(DVF_ERRORLEVEL, "Already initialized" );
|
||
|
return DVERR_INITIALIZED;
|
||
|
}
|
||
|
|
||
|
hr = COM_CoCreateInstance( CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER , IID_IDirectSound, (void **) &m_lpdsDirectSound );
|
||
|
|
||
|
DSERTRACK_Update( "DSD::CoCreateInstance()", hr );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
Diagnostics_Write(DVF_ERRORLEVEL, "Unable to load directsound hr=0x%x", hr );
|
||
|
goto INITIALIZE_ERROR;
|
||
|
}
|
||
|
|
||
|
hr = m_lpdsDirectSound->Initialize( &guidDevice );
|
||
|
|
||
|
DSERTRACK_Update( "DSD::Initialize()", hr );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
Diagnostics_Write(DVF_ERRORLEVEL, "Unable to initialize directsound hr=0x%x", hr );
|
||
|
goto INITIALIZE_ERROR;
|
||
|
}
|
||
|
|
||
|
if( fPriorityMode )
|
||
|
{
|
||
|
dwPriority = DSSCL_PRIORITY;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
dwPriority = DSSCL_NORMAL;
|
||
|
}
|
||
|
|
||
|
hr = m_lpdsDirectSound->SetCooperativeLevel( hwndOwner, dwPriority );
|
||
|
|
||
|
DSERTRACK_Update( "DSD::SetCooperativeLevel()", hr );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
Diagnostics_Write(DVF_ERRORLEVEL, "Unable to set cooperative level hr=0x%x", hr );
|
||
|
goto INITIALIZE_ERROR;
|
||
|
}
|
||
|
|
||
|
if( fPriorityMode && lpwfxFormat != NULL )
|
||
|
{
|
||
|
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
|
||
|
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
|
||
|
dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D;
|
||
|
dsbdesc.dwBufferBytes = 0;
|
||
|
dsbdesc.lpwfxFormat = NULL;
|
||
|
|
||
|
hr = m_lpdsDirectSound->CreateSoundBuffer( (DSBUFFERDESC *) &dsbdesc, &m_lpdsPrimaryBuffer, NULL );
|
||
|
|
||
|
DSERTRACK_Update( "DSD::CreateSoundBuffer() (Primary)", hr );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
Diagnostics_Write(DVF_ERRORLEVEL, "Create of primary buffer failed. Trying DX5 dsound hr=0x%x", hr );
|
||
|
dsbdesc.dwSize = sizeof( DSBUFFERDESC1 );
|
||
|
|
||
|
hr = m_lpdsDirectSound->CreateSoundBuffer( (DSBUFFERDESC *) &dsbdesc, &m_lpdsPrimaryBuffer, NULL );
|
||
|
}
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
Diagnostics_Write(DVF_ERRORLEVEL, "Could not create primary sound buffer" );
|
||
|
goto INITIALIZE_ERROR;
|
||
|
}
|
||
|
|
||
|
hr = m_lpdsPrimaryBuffer->SetFormat( lpwfxFormat );
|
||
|
|
||
|
DSERTRACK_Update( "DSD::SetFormat() (Primary)", hr );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
Diagnostics_Write(DVF_ERRORLEVEL, "Could not set the format" );
|
||
|
goto INITIALIZE_ERROR;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_hwndOwner = hwndOwner;
|
||
|
|
||
|
hr = CheckAndSetEmulated();
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
Diagnostics_Write(DVF_ERRORLEVEL, "Could not get emulated state hr=0x%x", hr );
|
||
|
goto INITIALIZE_ERROR;
|
||
|
}
|
||
|
|
||
|
return DV_OK;
|
||
|
|
||
|
INITIALIZE_ERROR:
|
||
|
|
||
|
if( m_lpdsPrimaryBuffer )
|
||
|
{
|
||
|
m_lpdsPrimaryBuffer->Release();
|
||
|
m_lpdsPrimaryBuffer = NULL;
|
||
|
}
|
||
|
|
||
|
if( m_lpdsDirectSound != NULL )
|
||
|
{
|
||
|
m_lpdsDirectSound->Release();
|
||
|
m_lpdsDirectSound = NULL;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CDirectSoundPlaybackDevice::CreateBuffer"
|
||
|
HRESULT CDirectSoundPlaybackDevice::CreateBuffer( LPDSBUFFERDESC lpdsBufferDesc, DWORD dwFrameSize, CAudioPlaybackBuffer **lplpapBuffer )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
LPDIRECTSOUNDBUFFER lpdsBuffer;
|
||
|
|
||
|
hr = m_lpdsDirectSound->CreateSoundBuffer( (DSBUFFERDESC *) lpdsBufferDesc, &lpdsBuffer, NULL );
|
||
|
|
||
|
DSERTRACK_Update( "DSD::CreateSoundBuffer() ", hr );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
lpdsBufferDesc->dwSize = sizeof( DSBUFFERDESC1 );
|
||
|
|
||
|
Diagnostics_Write(DVF_ERRORLEVEL, "Unable to create sound buffer under DX7. Attempting DX5 create hr=0x%x", hr );
|
||
|
|
||
|
hr = m_lpdsDirectSound->CreateSoundBuffer( (DSBUFFERDESC *) lpdsBufferDesc, &lpdsBuffer, NULL );
|
||
|
}
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
Diagnostics_Write(DVF_ERRORLEVEL, "Failed to create the sound buffer hr=0x%x", hr );
|
||
|
return hr;
|
||
|
}
|
||
|
/*
|
||
|
// Freee wave format
|
||
|
delete dsBufferDesc.lpwfxFormat;
|
||
|
|
||
|
hr = lpdsBuffer->SetFrequency( 8000 );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, 0, "Could not set frequency hr=0x%x", hr );
|
||
|
return hr;
|
||
|
}*/
|
||
|
|
||
|
*lplpapBuffer = new CDirectSoundPlaybackBuffer( lpdsBuffer );
|
||
|
|
||
|
lpdsBuffer->Release();
|
||
|
|
||
|
if( *lplpapBuffer == NULL )
|
||
|
{
|
||
|
Diagnostics_Write(DVF_ERRORLEVEL, "Out of memory" );
|
||
|
return DVERR_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
return DV_OK;
|
||
|
}
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CDirectSoundPlaybackDevice::GetPlaybackDevice"
|
||
|
LPDIRECTSOUND CDirectSoundPlaybackDevice::GetPlaybackDevice( )
|
||
|
{
|
||
|
return m_lpdsDirectSound;
|
||
|
}
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CDirectSoundPlaybackDevice::GetMixerQuality"
|
||
|
HRESULT CDirectSoundPlaybackDevice::GetMixerQuality( DIRECTSOUNDMIXER_SRCQUALITY *psrcQuality )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
LPKSPROPERTYSET pPropertySet = NULL;
|
||
|
|
||
|
hr = DirectSoundPrivateCreate( &pPropertySet );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to get int to get mixer quality hr=0x%x", hr );
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
hr = PrvGetMixerSrcQuality( pPropertySet, m_guidDevice, psrcQuality );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to retrieve mixer quality hr=0x%x", hr );
|
||
|
}
|
||
|
|
||
|
pPropertySet->Release();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "CDirectSoundPlaybackDevice::SetMixerQuality"
|
||
|
HRESULT CDirectSoundPlaybackDevice::SetMixerQuality( const DIRECTSOUNDMIXER_SRCQUALITY srcQuality )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
LPKSPROPERTYSET pPropertySet = NULL;
|
||
|
|
||
|
hr = DirectSoundPrivateCreate( &pPropertySet );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to get int to set mixer quality hr=0x%x", hr );
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
hr = PrvSetMixerSrcQuality( pPropertySet, m_guidDevice, srcQuality );
|
||
|
|
||
|
if( FAILED( hr ) )
|
||
|
{
|
||
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to set mixer quality hr=0x%x", hr );
|
||
|
}
|
||
|
|
||
|
pPropertySet->Release();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|