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