windows-nt/Source/XPSP1/NT/multimedia/directx/dplay/dvoice/dxvtlib/fulldup.cpp

1014 lines
26 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*==========================================================================;
*
* Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
*
* File: fulldup.cpp
* Content: Implements a process that uses DirectSound and
* DirectSoundCapture to test the systems full duplex
* capability. Note that WinMain is in fdtest.cpp, but
* the guts are here.
* History:
* Date By Reason
* ============
* 08/19/99 pnewson created
* 10/28/99 pnewson Bug #113937 audible clicking during full duplex test
* 11/02/99 pnewson Fix: Bug #116365 - using wrong DSBUFFERDESC
* 01/21/2000 pnewson Changed over to using a dpvoice loopback session
* for full duplex testing
* 04/19/2000 pnewson Error handling cleanup
* 07/12/2000 rodtoll Bug #31468 - Add diagnostic spew to logfile to show what is failing the HW Wizard
***************************************************************************/
#include "dxvtlibpch.h"
#undef DPF_SUBCOMP
#define DPF_SUBCOMP DN_SUBCOMP_VOICE
static HRESULT OpenIPCObjects();
static HRESULT CloseIPCObjects();
static HRESULT CommandLoop(CFullDuplexIPC* lpipcFullDuplex);
static HRESULT DispatchCommand(CFullDuplexIPC* lpipcFullDuplex, SFDTestCommand* pfdtc);
static HRESULT CommandFullDuplexStart(SFDTestCommandFullDuplexStart* pfdtcFullDuplexStart, HRESULT* phrIPC);
static HRESULT CommandFullDuplexStop(SFDTestCommandFullDuplexStop* pfdtcFullDuplexStop, HRESULT* phrIPC);
static HRESULT PlayAndCheckRender(LPDIRECTSOUNDBUFFER lpdsb, HANDLE hEvent);
static HRESULT PlayAndCheckCapture(LPDIRECTSOUNDCAPTUREBUFFER lpdscb, HANDLE hEvent);
static HRESULT AttemptCapture();
// one global struct to store this process's state data.
struct SFullDuplexData
{
LPDIRECTPLAYVOICESERVER lpdpvs;
LPDIRECTPLAYVOICECLIENT lpdpvc;
PDIRECTPLAY8SERVER lpdp8;
};
SFullDuplexData g_FullDuplexData;
#undef DPF_MODNAME
#define DPF_MODNAME "FullDuplexProcess"
HRESULT FullDuplexProcess(HINSTANCE hResDLLInstance, HINSTANCE hPrevInstance, TCHAR *szCmdLine, int iCmdShow)
{
HRESULT hr;
CFullDuplexIPC ipcFullDuplex;
BOOL fIPCInitialized = FALSE;
PDIRECTPLAYVOICECLIENT pdpvClient = NULL;
g_FullDuplexData.lpdp8 = NULL;
DPF_ENTER();
// Create dummy voice object so that voice process state gets initialized
hr = CoCreateInstance( CLSID_DirectPlayVoiceClient, NULL, CLSCTX_INPROC, IID_IDirectPlayVoiceClient, (void **) &pdpvClient );
if( FAILED( hr ) )
{
Diagnostics_Write(DVF_ERRORLEVEL, "Unable to create dummy dp8 object hr: 0x%x", hr);
goto error_cleanup;
}
if (!InitGlobGuard())
{
hr = DVERR_OUTOFMEMORY;
goto error_cleanup;
}
hr = ipcFullDuplex.Init();
if (FAILED(hr))
{
Diagnostics_Write(DVF_ERRORLEVEL, "CIPCFullDuplex::Init() failed, hr: 0x%x", hr);
goto error_cleanup;
}
fIPCInitialized = TRUE;
// Startup DirectPlay once so that we don't have to do it over and over
// again for the test.
hr = StartDirectPlay( &g_FullDuplexData.lpdp8 );
if( FAILED( hr ) )
{
Diagnostics_Write(DVF_ERRORLEVEL, "Failed to start transport hr: 0x%x", hr);
goto error_cleanup;
}
// start up the testing loop
hr = CommandLoop(&ipcFullDuplex);
if (FAILED(hr))
{
Diagnostics_Write(DVF_ERRORLEVEL, "CommandLoop failed, hr: 0x%x", hr);
goto error_cleanup;
}
hr = StopDirectPlay( g_FullDuplexData.lpdp8 );
g_FullDuplexData.lpdp8 = NULL;
if( FAILED( hr ) )
{
Diagnostics_Write(DVF_ERRORLEVEL, "Failed to stop transport hr: 0x%x", hr);
goto error_cleanup;
}
// close the mutex, events and shared memory stuff
hr = ipcFullDuplex.Deinit();
if (FAILED(hr))
{
Diagnostics_Write(DVF_ERRORLEVEL, "CIPCFullDuplex::Deinit() failed, hr: 0x%x", hr);
goto error_cleanup;
}
// Destroy dummy client object which will shutdown dplayvoice state
pdpvClient->Release();
DeinitGlobGuard();
DPF_EXIT();
return S_OK;
error_cleanup:
if (fIPCInitialized == TRUE)
{
ipcFullDuplex.Deinit();
fIPCInitialized = FALSE;
}
if( g_FullDuplexData.lpdp8 )
{
g_FullDuplexData.lpdp8->Release();
g_FullDuplexData.lpdp8 = NULL;
}
if( pdpvClient )
pdpvClient->Release();
DeinitGlobGuard();
DPF_EXIT();
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CommandLoop"
HRESULT CommandLoop(CFullDuplexIPC* lpipcFullDuplex)
{
BOOL fRet;
LONG lRet;
HRESULT hr;
DWORD dwRet;
SFDTestCommand fdtc;
DPF_ENTER();
// Kick the supervisor process to let it know
// we're ready to go.
hr = lpipcFullDuplex->SignalParentReady();
if (FAILED(hr))
{
return hr;
}
// enter the main command loop
while (1)
{
// wait for a command from the supervisor process
fdtc.dwSize = sizeof(fdtc);
hr = lpipcFullDuplex->Receive(&fdtc);
if (FAILED(hr))
{
break;
}
// dispatch the command
hr = DispatchCommand(lpipcFullDuplex, &fdtc);
if (FAILED(hr))
{
break;
}
if (hr == DV_EXIT)
{
DPFX(DPFPREP, DVF_INFOLEVEL, "Exiting FullDuplex process command loop");
break;
}
}
DPF_EXIT();
return hr;
}
#undef DPF_MODNAME
#define DPF_MODNAME "DispatchCommand"
HRESULT DispatchCommand(CFullDuplexIPC* lpipcFullDuplex, SFDTestCommand* pfdtc)
{
HRESULT hr;
HRESULT hrIPC;
DPF_ENTER();
switch (pfdtc->fdtcc)
{
case fdtccExit:
// ok - reply to the calling process to let them
// know we are getting out.
DPFX(DPFPREP, DVF_INFOLEVEL, "FullDuplex received Exit command");
lpipcFullDuplex->Reply(DV_EXIT);
// returning this code will break us out of
// the command processing loop
DPFX(DPFPREP, DVF_INFOLEVEL, "Exit");
return DV_EXIT;
case fdtccFullDuplexStart:
hr = CommandFullDuplexStart(&(pfdtc->fdtu.fdtcFullDuplexStart), &hrIPC);
if (FAILED(hr))
{
lpipcFullDuplex->Reply(hrIPC);
DPF_EXIT();
return hr;
}
hr = lpipcFullDuplex->Reply(hrIPC);
DPF_EXIT();
return hr;
case fdtccFullDuplexStop:
hr = CommandFullDuplexStop(&(pfdtc->fdtu.fdtcFullDuplexStop), &hrIPC);
if (FAILED(hr))
{
lpipcFullDuplex->Reply(hrIPC);
DPF_EXIT();
return hr;
}
hr = lpipcFullDuplex->Reply(hrIPC);
DPF_EXIT();
return hr;
default:
// Don't know this command. Reply with the appropriate
// code.
DPFX(DPFPREP, DVF_WARNINGLEVEL, "FullDuplex received Unknown command");
lpipcFullDuplex->Reply(DVERR_UNKNOWN);
// While this is an error, it is one that the calling
// process needs to figure out. In the meantime, this
// process will happily continue on.
DPF_EXIT();
return S_OK;
}
}
/*
#undef DPF_MODNAME
#define DPF_MODNAME "CommandFullDuplexStart"
HRESULT CommandFullDuplexStart(SFDTestCommandFullDuplexStart* pfdtcFullDuplexStart, HRESULT* phrIPC)
{
HRESULT hr;
DSBUFFERDESC1 dsbd;
WAVEFORMATEX wfx;
DWORD dwSizeWritten;
DSBCAPS dsbc;
LPVOID lpvAudio1 = NULL;
DWORD dwAudio1Size = NULL;
LPVOID lpvAudio2 = NULL;
DWORD dwAudio2Size = NULL;
HANDLE hFullDuplexRenderEvent;
HANDLE hFullDuplexCaptureEvent;
DSBPOSITIONNOTIFY dsbPositionNotify;
DWORD dwRet;
LONG lRet;
LPDIRECTSOUNDBUFFER lpdsb;
HANDLE hEvent;
BYTE bSilence;
DPF_ENTER();
// create the DirectSound interface
DPFX(DPFPREP, DVF_INFOLEVEL, "Creating DirectSound");
GlobGuardIn();
hr = DirectSoundCreate(&pfdtcFullDuplexStart->guidRenderDevice, &g_lpdsFullDuplexRender, NULL);
GlobGuardOut();
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "DirectSoundCreate failed, code: %i", HRESULT_CODE(hr));
*phrIPC = DVERR_SOUNDINITFAILURE;
goto error_level_0;
}
// create the DirectSoundCapture interface
DPFX(DPFPREP, DVF_INFOLEVEL, "Creating DirectSoundCapture");
GlobGuardIn();
hr = DirectSoundCaptureCreate(&pfdtcFullDuplexStart->guidCaptureDevice, &g_lpdscFullDuplexCapture, NULL);
GlobGuardOut();
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "DirectSoundCaptureCreate failed, code: %i", HRESULT_CODE(hr));
*phrIPC = DVERR_SOUNDINITFAILURE;
goto error_level_1;
}
// set to normal mode
DPFX(DPFPREP, DVF_INFOLEVEL, "Setting Cooperative Level");
GlobGuardIn();
hr = g_lpdsFullDuplexRender->SetCooperativeLevel(GetDesktopWindow(), DSSCL_NORMAL);
GlobGuardOut();
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "SetCooperativeLevel failed, code: %i", HRESULT_CODE(hr));
*phrIPC = DVERR_SOUNDINITFAILURE;
goto error_level_2;
}
// Create a secondary buffer object.
DPFX(DPFPREP, DVF_INFOLEVEL, "Creating Secondary Buffer");
CopyMemory(&wfx, &gc_wfxSecondaryFormat, sizeof(wfx));
ZeroMemory(&dsbd, sizeof(dsbd));
dsbd.dwSize = sizeof(dsbd);
dsbd.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_CTRLVOLUME;
dsbd.dwBufferBytes =
(wfx.nSamplesPerSec
* wfx.nBlockAlign)
/ (1000 / gc_dwFrameSize);
dsbd.dwReserved = 0;
dsbd.lpwfxFormat = &wfx;
GlobGuardIn();
hr = g_lpdsFullDuplexRender->CreateSoundBuffer((LPDSBUFFERDESC)&dsbd, &g_lpdsbFullDuplexSecondary, NULL);
GlobGuardOut();
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "CreateSoundBuffer failed, code: %i", HRESULT_CODE(hr));
*phrIPC = DVERR_SOUNDINITFAILURE;
goto error_level_2;
}
// clear out the secondary buffer
DPFX(DPFPREP, DVF_INFOLEVEL, "Clearing Secondary Buffer");
GlobGuardIn();
hr = g_lpdsbFullDuplexSecondary->Lock(
0,
0,
&lpvAudio1,
&dwAudio1Size,
&lpvAudio2,
&dwAudio2Size,
DSBLOCK_ENTIREBUFFER);
GlobGuardOut();
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Lock failed, code: %i", HRESULT_CODE(hr));
*phrIPC = DVERR_SOUNDINITFAILURE;
goto error_level_3;
}
if (lpvAudio1 == NULL)
{
*phrIPC = DVERR_SOUNDINITFAILURE;
goto error_level_3;
}
if (pfdtcFullDuplexStart->wfxRenderFormat.wBitsPerSample == 8)
{
bSilence = 0x80;
}
else
{
bSilence = 0x00;
}
memset(lpvAudio1, bSilence, dwAudio1Size);
if (lpvAudio2 != NULL)
{
memset(lpvAudio2, bSilence, dwAudio2Size);
}
GlobGuardIn();
hr = g_lpdsbFullDuplexSecondary->Unlock(
lpvAudio1,
dwAudio1Size,
lpvAudio2,
dwAudio2Size);
GlobGuardOut();
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unlock failed, code: %i", HRESULT_CODE(hr));
*phrIPC = DVERR_SOUNDINITFAILURE;
goto error_level_3;
}
// Set up one notification position in the buffer so
// we can tell if it is really playing, or lying to us.
DPFX(DPFPREP, DVF_INFOLEVEL, "Querying for IDirectSoundNotify");
GlobGuardIn();
hr = g_lpdsbFullDuplexSecondary->QueryInterface(
IID_IDirectSoundNotify,
(LPVOID*)&g_lpdsnFullDuplexSecondary);
GlobGuardOut();
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "QueryInterface(IID_DirectSoundNotify) failed, code: %i", HRESULT_CODE(hr));
*phrIPC = DVERR_SOUNDINITFAILURE;
goto error_level_3;
}
DPFX(DPFPREP, DVF_INFOLEVEL, "Creating Notification Event");
GlobGuardIn();
g_hFullDuplexRenderEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
hFullDuplexRenderEvent = g_hFullDuplexRenderEvent;
GlobGuardOut();
if (hFullDuplexRenderEvent == NULL)
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "CreateEvent failed, code: %i", HRESULT_CODE(hr));
*phrIPC = DVERR_WIN32;
goto error_level_4;
}
DPFX(DPFPREP, DVF_INFOLEVEL, "calling SetNotificationPositions");
dsbPositionNotify.dwOffset = 0;
dsbPositionNotify.hEventNotify = hFullDuplexRenderEvent;
GlobGuardIn();
hr = g_lpdsnFullDuplexSecondary->SetNotificationPositions(1, &dsbPositionNotify);
GlobGuardOut();
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "SetNotificationPositions failed, code: %i", HRESULT_CODE(hr));
*phrIPC = DVERR_SOUNDINITFAILURE;
goto error_level_5;
}
// start the secondary buffer and confirm that it's running
GlobGuardIn();
lpdsb = g_lpdsbFullDuplexSecondary;
hEvent = g_hFullDuplexRenderEvent;
GlobGuardOut();
hr = PlayAndCheckRender(lpdsb, hEvent);
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Render verification test failed, code: %i", HRESULT_CODE(hr));
*phrIPC = DVERR_SOUNDINITFAILURE;
goto error_level_5;
}
hr = AttemptCapture();
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "AttemptCapture() failed, code: %i", HRESULT_CODE(hr));
*phrIPC = DVERR_SOUNDINITFAILURE;
goto error_level_6;
}
DPF_EXIT();
return S_OK;
// error block
error_level_6:
GlobGuardIn();
g_lpdsbFullDuplexSecondary->Stop();
GlobGuardOut();
error_level_5:
GlobGuardIn();
CloseHandle(g_hFullDuplexRenderEvent);
g_hFullDuplexRenderEvent = NULL;
GlobGuardOut();
error_level_4:
GlobGuardIn();
g_lpdsnFullDuplexSecondary->Release();
g_lpdsnFullDuplexSecondary = NULL;
GlobGuardOut();
error_level_3:
GlobGuardIn();
g_lpdsbFullDuplexSecondary->Release();
g_lpdsbFullDuplexSecondary = NULL;
GlobGuardOut();
error_level_2:
GlobGuardIn();
g_lpdscFullDuplexCapture->Release();
g_lpdscFullDuplexCapture = NULL;
GlobGuardOut();
error_level_1:
GlobGuardIn();
g_lpdsFullDuplexRender->Release();
g_lpdsFullDuplexRender = NULL;
GlobGuardOut();
error_level_0:
// error for other process, not this one.
DPF_EXIT();
return S_OK;
}
*/
#undef DPF_MODNAME
#define DPF_MODNAME "CommandFullDuplexStart"
HRESULT CommandFullDuplexStart(SFDTestCommandFullDuplexStart* pfdtcFullDuplexStart, HRESULT* phrIPC)
{
DPF_ENTER();
HRESULT hr;
Diagnostics_Write( DVF_INFOLEVEL, "-----------------------------------------------------------" );
hr = Diagnostics_DeviceInfo( &pfdtcFullDuplexStart->guidRenderDevice, &pfdtcFullDuplexStart->guidCaptureDevice );
if( FAILED( hr ) )
{
Diagnostics_Write( 0, "Error getting device information hr=0x%x", hr );
}
Diagnostics_Write( DVF_INFOLEVEL, "-----------------------------------------------------------" );
*phrIPC = StartLoopback(
&g_FullDuplexData.lpdpvs,
&g_FullDuplexData.lpdpvc,
&g_FullDuplexData.lpdp8,
NULL,
GetDesktopWindow(),
pfdtcFullDuplexStart->guidCaptureDevice,
pfdtcFullDuplexStart->guidRenderDevice,
pfdtcFullDuplexStart->dwFlags);
DPFX(DPFPREP, DVF_INFOLEVEL, "StartLoopback() return hr=0x%x", *phrIPC );
DPF_EXIT();
return DV_OK;
}
#undef DPF_MODNAME
#define DPF_MODNAME "CommandFullDuplexStop"
HRESULT CommandFullDuplexStop(SFDTestCommandFullDuplexStop* pfdtcFullDuplexStop, HRESULT* phrIPC)
{
DPF_ENTER();
*phrIPC = StopLoopback(
g_FullDuplexData.lpdpvs,
g_FullDuplexData.lpdpvc,
g_FullDuplexData.lpdp8);
if( FAILED( *phrIPC ) )
{
Diagnostics_Write( DVF_ERRORLEVEL, "Full Duplex Result = 0x%x", *phrIPC );
}
else
{
Diagnostics_Write( DVF_INFOLEVEL, "Full Duplex Result = DV_OK" );
}
DPF_EXIT();
return DV_OK;
}
/*
#undef DPF_MODNAME
#define DPF_MODNAME "CommandFullDuplexStop"
HRESULT CommandFullDuplexStop(SFDTestCommandFullDuplexStop* pfdtcFullDuplexStop, HRESULT* phrIPC)
{
HRESULT hr;
LONG lRet;
HANDLE hFullDuplexRenderEvent;
HANDLE hFullDuplexCaptureEvent;
DWORD dwRet;
DPF_ENTER();
*phrIPC = S_OK;
hr = S_OK;
// wait for one more notification to ensure the buffer is
// still playing - give the buffer up to 10 times
// as long as it should need to actually notify us.
DPFX(DPFPREP, DVF_INFOLEVEL, "Waiting for 2 notifications to confirm playback is still working");
GlobGuardIn();
hFullDuplexRenderEvent = g_hFullDuplexRenderEvent;
GlobGuardOut();
dwRet = WaitForSingleObject(hFullDuplexRenderEvent, 10 * gc_dwFrameSize);
if (dwRet != WAIT_OBJECT_0)
{
// check for timeout
if (dwRet == WAIT_TIMEOUT)
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Wait for notification timed out! Buffer is not really playing");
*phrIPC = DVERR_SOUNDINITFAILURE;
}
else
{
lRet = GetLastError();
DPFX(DPFPREP, DVF_WARNINGLEVEL, "WaitForSingleObject failed, code: %i", lRet);
hr = DVERR_WIN32;
*phrIPC = hr;
}
}
if (SUCCEEDED(hr))
{
dwRet = WaitForSingleObject(hFullDuplexRenderEvent, 10 * gc_dwFrameSize);
if (dwRet != WAIT_OBJECT_0)
{
// check for timeout
if (dwRet == WAIT_TIMEOUT)
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Wait for notification timed out! Buffer is not really playing");
*phrIPC = DVERR_SOUNDINITFAILURE;
}
else
{
lRet = GetLastError();
DPFX(DPFPREP, DVF_WARNINGLEVEL, "WaitForSingleObject failed, code: %i", lRet);
hr = DVERR_WIN32;
*phrIPC = hr;
}
}
}
// also wait for the capture buffer...
DPFX(DPFPREP, DVF_INFOLEVEL, "Waiting for 2 notifications to confirm capture is still working");
GlobGuardIn();
hFullDuplexCaptureEvent = g_hFullDuplexCaptureEvent;
GlobGuardOut();
dwRet = WaitForSingleObject(hFullDuplexCaptureEvent, 10 * gc_dwFrameSize);
if (dwRet != WAIT_OBJECT_0)
{
// check for timeout
if (dwRet == WAIT_TIMEOUT)
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Wait for notification timed out! Buffer is not really playing");
*phrIPC = DVERR_SOUNDINITFAILURE;
}
else
{
lRet = GetLastError();
DPFX(DPFPREP, DVF_WARNINGLEVEL, "WaitForSingleObject failed, code: %i", lRet);
hr = DVERR_WIN32;
*phrIPC = hr;
}
}
if (SUCCEEDED(hr))
{
dwRet = WaitForSingleObject(hFullDuplexCaptureEvent, 10 * gc_dwFrameSize);
if (dwRet != WAIT_OBJECT_0)
{
// check for timeout
if (dwRet == WAIT_TIMEOUT)
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Wait for notification timed out! Buffer is not really playing");
*phrIPC = DVERR_SOUNDINITFAILURE;
}
else
{
lRet = GetLastError();
DPFX(DPFPREP, DVF_WARNINGLEVEL, "WaitForSingleObject failed, code: %i", lRet);
hr = DVERR_WIN32;
*phrIPC = hr;
}
}
}
DPFX(DPFPREP, DVF_INFOLEVEL, "Stopping Capture Buffer");
GlobGuardIn();
hr = g_lpdscbFullDuplexCapture->Stop();
GlobGuardOut();
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Stop failed, code: %i", HRESULT_CODE(hr));
*phrIPC = DVERR_SOUNDINITFAILURE;
}
DPFX(DPFPREP, DVF_INFOLEVEL, "Stopping Secondary Buffer");
GlobGuardIn();
hr = g_lpdsbFullDuplexSecondary->Stop();
GlobGuardOut();
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Stop failed, code: %i", HRESULT_CODE(hr));
*phrIPC = DVERR_SOUNDINITFAILURE;
}
GlobGuardIn();
if (g_hFullDuplexCaptureEvent != NULL)
{
DPFX(DPFPREP, DVF_INFOLEVEL, "Closing Capture Buffer Notification Event Handle");
CloseHandle(g_hFullDuplexCaptureEvent);
g_hFullDuplexCaptureEvent = NULL;
}
if (g_lpdsnFullDuplexCapture != NULL)
{
DPFX(DPFPREP, DVF_INFOLEVEL, "Releasing DirectSoundNotifier (capture)");
g_lpdsnFullDuplexCapture->Release();
g_lpdsnFullDuplexCapture = NULL;
}
if (g_lpdscbFullDuplexCapture != NULL)
{
DPFX(DPFPREP, DVF_INFOLEVEL, "Releasing DirectSoundCaptureBuffer");
g_lpdscbFullDuplexCapture->Release();
g_lpdscbFullDuplexCapture = NULL;
}
if (g_lpdscFullDuplexCapture != NULL)
{
DPFX(DPFPREP, DVF_INFOLEVEL, "Releasing DirectSoundCapture");
g_lpdscFullDuplexCapture->Release();
g_lpdscFullDuplexCapture = NULL;
}
if (g_hFullDuplexRenderEvent != NULL)
{
DPFX(DPFPREP, DVF_INFOLEVEL, "Closing Secondary Buffer Notification Event Handle");
if (!CloseHandle(g_hFullDuplexRenderEvent))
{
lRet = GetLastError();
DPFX(DPFPREP, DVF_WARNINGLEVEL, "CloseHandle failed, code: %i", lRet);
*phrIPC = DVERR_WIN32;
hr = *phrIPC;
}
g_hFullDuplexRenderEvent = NULL;
}
if (g_lpdsnFullDuplexSecondary != NULL)
{
DPFX(DPFPREP, DVF_INFOLEVEL, "Releasing Secondary Notifier");
g_lpdsnFullDuplexSecondary->Release();
g_lpdsnFullDuplexSecondary = NULL;
}
if (g_lpdsbFullDuplexSecondary != NULL)
{
DPFX(DPFPREP, DVF_INFOLEVEL, "Releasing Secondary Buffer");
g_lpdsbFullDuplexSecondary->Release();
g_lpdsbFullDuplexSecondary = NULL;
}
if (g_lpdsFullDuplexRender != NULL)
{
DPFX(DPFPREP, DVF_INFOLEVEL, "Releasing DirectSound");
g_lpdsFullDuplexRender->Release();
g_lpdsFullDuplexRender = NULL;
}
GlobGuardOut();
DPF_EXIT();
return hr;
}
*/
/*
#undef DPF_MODNAME
#define DPF_MODNAME "PlayAndCheckRender"
HRESULT PlayAndCheckRender(LPDIRECTSOUNDBUFFER lpdsb, HANDLE hEvent)
{
HRESULT hr;
DWORD dwRet;
LONG lRet;
DPF_ENTER();
// start playing the secondary buffer
DPFX(DPFPREP, DVF_INFOLEVEL, "Playing Secondary Buffer");
GlobGuardIn();
hr = lpdsb->Play(0, 0, DSBPLAY_LOOPING);
GlobGuardOut();
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Play failed, code: %i", HRESULT_CODE(hr));
hr = DVERR_SOUNDINITFAILURE;
goto error_level_0;
}
// wait for the first notification to ensure the buffer has
// really started to play - give the buffer up to 10 times
// as long as it should need to actually notify us.
DPFX(DPFPREP, DVF_INFOLEVEL, "Waiting for notification to confirm playback is working");
dwRet = WaitForSingleObject(hEvent, 10 * gc_dwFrameSize);
if (dwRet != WAIT_OBJECT_0)
{
// check for timeout
if (dwRet == WAIT_TIMEOUT)
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Wait for notification timed out! Buffer is not really playing");
hr = DVERR_SOUNDINITFAILURE;
goto error_level_1;
}
else
{
lRet = GetLastError();
DPFX(DPFPREP, DVF_ERRORLEVEL, "WaitForSingleObject failed, code: %i", lRet);
hr = DVERR_WIN32;
goto error_level_1;
}
}
DPFX(DPFPREP, DVF_INFOLEVEL, "First notification received, continuing");
DPF_EXIT();
return S_OK;
// error block
error_level_1:
GlobGuardIn();
lpdsb->Stop();
GlobGuardOut();
error_level_0:
DPF_EXIT();
return hr;
}
*/
/*
#undef DPF_MODNAME
#define DPF_MODNAME "PlayAndCheckCapture"
HRESULT PlayAndCheckCapture(LPDIRECTSOUNDCAPTUREBUFFER lpdscb, HANDLE hEvent)
{
HRESULT hr;
DWORD dwRet;
LONG lRet;
DPF_ENTER();
// start playing the capture buffer
DPFX(DPFPREP, DVF_INFOLEVEL, "Starting Capture Buffer");
GlobGuardIn();
hr = lpdscb->Start(DSCBSTART_LOOPING);
GlobGuardOut();
if (FAILED(hr))
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Start failed, code: %i", HRESULT_CODE(hr));
hr = DVERR_SOUNDINITFAILURE;
goto error_level_0;
}
// wait for the first notification to ensure the buffer has
// really started to capture - give the buffer up to 10 times
// as long as it should need to actually notify us.
DPFX(DPFPREP, DVF_INFOLEVEL, "Waiting for notification to confirm capture is working");
dwRet = WaitForSingleObject(hEvent, 10 * gc_dwFrameSize);
if (dwRet != WAIT_OBJECT_0)
{
// check for timeout
if (dwRet == WAIT_TIMEOUT)
{
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Wait for notification timed out! Buffer is not really playing");
hr = DVERR_SOUNDINITFAILURE;
goto error_level_1;
}
else
{
lRet = GetLastError();
DPFX(DPFPREP, DVF_ERRORLEVEL, "WaitForSingleObject failed, code: %i", lRet);
hr = DVERR_WIN32;
goto error_level_1;
}
}
DPFX(DPFPREP, DVF_INFOLEVEL, "First notification received, continuing");
DPF_EXIT();
return S_OK;
// error block
error_level_1:
GlobGuardIn();
lpdscb->Stop();
GlobGuardOut();
error_level_0:
DPF_EXIT();
return hr;
}
*/
/*
#undef DPF_MODNAME
#define DPF_MODNAME "AttemptCapture"
HRESULT AttemptCapture()
{
DPF_ENTER();
DWORD dwIndex;
BOOL fCaptureFailed;
HANDLE hFullDuplexCaptureEvent;
DSBPOSITIONNOTIFY dsbPositionNotify;
DSCBUFFERDESC dscbd;
LPDIRECTSOUNDCAPTUREBUFFER lpdscb;
HRESULT hr;
HANDLE hEvent;
WAVEFORMATEX wfx;
fCaptureFailed = TRUE;
dwIndex = 0;
while (1)
{
CopyMemory(&wfx, &gc_rgwfxCaptureFormats[dwIndex], sizeof(wfx));
if (wfx.wFormatTag == 0
&& wfx.nChannels == 0
&& wfx.nSamplesPerSec == 0
&& wfx.nAvgBytesPerSec == 0
&& wfx.nBlockAlign == 0
&& wfx.wBitsPerSample == 0
&& wfx.cbSize == 0)
{
// we've found the last element of the array, break out.
break;
}
// create the capture buffer
DPFX(DPFPREP, DVF_INFOLEVEL, "Creating DirectSoundCaptureBuffer");
ZeroMemory(&dscbd, sizeof(dscbd));
dscbd.dwSize = sizeof(dscbd);
dscbd.dwFlags = 0;
dscbd.dwBufferBytes =
(wfx.nSamplesPerSec
* wfx.nBlockAlign)
/ (1000 / gc_dwFrameSize);
dscbd.dwReserved = 0;
dscbd.lpwfxFormat = &wfx;
GlobGuardIn();
hr = g_lpdscFullDuplexCapture->CreateCaptureBuffer(&dscbd, &g_lpdscbFullDuplexCapture, NULL);
GlobGuardOut();
if (FAILED(hr))
{
// try the next format
++dwIndex;
continue;
}
// setup the notifier on the capture buffer
DPFX(DPFPREP, DVF_INFOLEVEL, "Querying for IDirectSoundNotify");
GlobGuardIn();
hr = g_lpdscbFullDuplexCapture->QueryInterface(
IID_IDirectSoundNotify,
(LPVOID*)&g_lpdsnFullDuplexCapture);
GlobGuardOut();
if (FAILED(hr))
{
// Once the above works, this should not fail, so treat
// this as a real error
DPFX(DPFPREP, DVF_ERRORLEVEL, "QueryInterface(IID_DirectSoundNotify) failed, code: %i", HRESULT_CODE(hr));
GlobGuardIn();
g_lpdscbFullDuplexCapture->Release();
GlobGuardOut();
DPF_EXIT();
return hr;
}
DPFX(DPFPREP, DVF_INFOLEVEL, "Creating Notification Event");
GlobGuardIn();
g_hFullDuplexCaptureEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
hFullDuplexCaptureEvent = g_hFullDuplexCaptureEvent;
GlobGuardOut();
if (hFullDuplexCaptureEvent == NULL)
{
// Once the above works, this should not fail, so treat
// this as a real error
DPFX(DPFPREP, DVF_INFOLEVEL, "CreateEvent failed, code: %i", HRESULT_CODE(hr));
GlobGuardIn();
g_lpdscbFullDuplexCapture->Release();
g_lpdsnFullDuplexCapture->Release();
GlobGuardOut();
DPF_EXIT();
return DVERR_WIN32;
}
DPFX(DPFPREP, DVF_INFOLEVEL, "calling SetNotificationPositions");
dsbPositionNotify.dwOffset = 0;
dsbPositionNotify.hEventNotify = hFullDuplexCaptureEvent;
GlobGuardIn();
hr = g_lpdsnFullDuplexCapture->SetNotificationPositions(1, &dsbPositionNotify);
GlobGuardOut();
if (FAILED(hr))
{
// Once the above works, this should not fail, so treat
// this as a real error
DPFX(DPFPREP, DVF_ERRORLEVEL, "SetNotificationPositions failed, code: %i", HRESULT_CODE(hr));
GlobGuardIn();
g_lpdscbFullDuplexCapture->Release();
g_lpdsnFullDuplexCapture->Release();
CloseHandle(hFullDuplexCaptureEvent);
GlobGuardOut();
DPF_EXIT();
return hr;
}
// start the capture buffer and confirm that it is actually working
GlobGuardIn();
lpdscb = g_lpdscbFullDuplexCapture;
hEvent = g_hFullDuplexCaptureEvent;
GlobGuardOut();
hr = PlayAndCheckCapture(lpdscb, hEvent);
if (FAILED(hr))
{
// This can happen, so just try the next format
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Capture verification test failed, code: %i", HRESULT_CODE(hr));
GlobGuardIn();
g_lpdscbFullDuplexCapture->Release();
g_lpdsnFullDuplexCapture->Release();
CloseHandle(hFullDuplexCaptureEvent);
GlobGuardOut();
++dwIndex;
continue;
}
// If we get here, capture is up and running, so return success!
DPF_EXIT();
return S_OK;
}
// if we get here, none of the formats worked, so return directsound error
DPF_EXIT();
return DVERR_SOUNDINITFAILURE;
}
*/