You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
573 lines
15 KiB
573 lines
15 KiB
/*==========================================================================;
|
|
*
|
|
* Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: priority.cpp
|
|
* Content: Implements a process that uses DirectSound in prioirty
|
|
* mode to simulate an aggressive external playback only
|
|
* application (such as a game) that may be running while
|
|
* the full duplex application is in use. 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 Workaround for broken SetNotificationPositions call.
|
|
* undef DSOUND_BROKEN once the SetNotificationPositions
|
|
* no longer broken.
|
|
* 02/15/2000 pnewson Removed the workaround for bug 116365
|
|
* 04/04/2000 pnewson Changed a SendMessage to PostMessage to fix deadlock
|
|
* 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
|
|
* 08/25/2000 rodtoll Bug #43363 - CommandPriorityStart does not init return param and uses stack trash.
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "dxvtlibpch.h"
|
|
|
|
|
|
#undef DPF_SUBCOMP
|
|
#define DPF_SUBCOMP DN_SUBCOMP_VOICE
|
|
|
|
|
|
static HRESULT CommandLoop(CPriorityIPC* lpipcPriority);
|
|
static HRESULT DispatchCommand(CPriorityIPC* lpipcPriority, SFDTestCommand* pfdtc);
|
|
static HRESULT CommandPriorityStart(SFDTestCommandPriorityStart* pfdtcPriorityStart, HRESULT* phrIPC);
|
|
static HRESULT CommandPriorityStop(SFDTestCommandPriorityStop* pfdtcPriorityStop, HRESULT* phrIPC);
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "PriorityProcess"
|
|
HRESULT PriorityProcess(HINSTANCE hResDLLInstance, HINSTANCE hPrevInstance, TCHAR *szCmdLine, int iCmdShow)
|
|
{
|
|
|
|
//DEBUG_ONLY(_asm int 3;)
|
|
|
|
DPF_ENTER();
|
|
|
|
HRESULT hr;
|
|
CPriorityIPC ipcPriority;
|
|
BOOL fIPCInit = FALSE;
|
|
BOOL fGuardInit = FALSE;
|
|
|
|
if (!InitGlobGuard())
|
|
{
|
|
return DVERR_OUTOFMEMORY;
|
|
}
|
|
fGuardInit = TRUE;
|
|
|
|
// Init the common control library. Use the old style
|
|
// call, so we're compatibile right back to 95.
|
|
InitCommonControls();
|
|
|
|
// get the mutex, events and shared memory stuff
|
|
hr = ipcPriority.Init();
|
|
if (FAILED(hr))
|
|
{
|
|
goto error_cleanup;
|
|
}
|
|
fIPCInit = TRUE;
|
|
|
|
// start up the testing loop
|
|
hr = CommandLoop(&ipcPriority);
|
|
if (FAILED(hr))
|
|
{
|
|
goto error_cleanup;
|
|
}
|
|
|
|
// close the mutex, events and shared memory stuff
|
|
hr = ipcPriority.Deinit();
|
|
fIPCInit = FALSE;
|
|
if (FAILED(hr))
|
|
{
|
|
goto error_cleanup;
|
|
}
|
|
|
|
DeinitGlobGuard();
|
|
|
|
DPF_EXIT();
|
|
return S_OK;
|
|
|
|
error_cleanup:
|
|
if (fIPCInit == TRUE)
|
|
{
|
|
ipcPriority.Deinit();
|
|
fIPCInit = FALSE;
|
|
}
|
|
|
|
if (fGuardInit == TRUE)
|
|
{
|
|
DeinitGlobGuard();
|
|
fGuardInit = FALSE;
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return hr;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CommandLoop"
|
|
static HRESULT CommandLoop(CPriorityIPC* lpipcPriority)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
BOOL fRet;
|
|
LONG lRet;
|
|
HRESULT hr;
|
|
DWORD dwRet;
|
|
SFDTestCommand fdtc;
|
|
|
|
// Kick the supervisor process to let it know
|
|
// we're ready to go.
|
|
hr = lpipcPriority->SignalParentReady();
|
|
if (FAILED(hr))
|
|
{
|
|
DPF_EXIT();
|
|
return hr;
|
|
}
|
|
|
|
// enter the main command loop
|
|
while (1)
|
|
{
|
|
// wait for a command from the supervisor process
|
|
fdtc.dwSize = sizeof(fdtc);
|
|
hr = lpipcPriority->Receive(&fdtc);
|
|
if (FAILED(hr))
|
|
{
|
|
Diagnostics_Write(DVF_ERRORLEVEL, "CPriorityIPC::Receive() failed, hr: 0x%x", hr);
|
|
break;
|
|
}
|
|
|
|
// dispatch the command
|
|
hr = DispatchCommand(lpipcPriority, &fdtc);
|
|
if (FAILED(hr))
|
|
{
|
|
Diagnostics_Write(DVF_ERRORLEVEL, "DispatchCommand() failed, hr: 0x%x", hr);
|
|
break;
|
|
}
|
|
if (hr == DV_EXIT)
|
|
{
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Exiting Priority process command loop");
|
|
break;
|
|
}
|
|
}
|
|
|
|
DPF_EXIT();
|
|
return hr;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DispatchCommand"
|
|
static HRESULT DispatchCommand(CPriorityIPC* lpipcPriority, SFDTestCommand* pfdtc)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
HRESULT hr;
|
|
HRESULT hrIPC;
|
|
|
|
switch (pfdtc->fdtcc)
|
|
{
|
|
case fdtccExit:
|
|
// ok - reply to the calling process to let them
|
|
// know we are getting out.
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Priority received Exit command");
|
|
lpipcPriority->Reply(DV_EXIT);
|
|
|
|
// returning this code will break us out of
|
|
// the command processing loop
|
|
DPF_EXIT();
|
|
return DV_EXIT;
|
|
|
|
case fdtccPriorityStart:
|
|
hr = CommandPriorityStart(&(pfdtc->fdtu.fdtcPriorityStart), &hrIPC);
|
|
if (FAILED(hr))
|
|
{
|
|
lpipcPriority->Reply(hrIPC);
|
|
DPF_EXIT();
|
|
return hr;
|
|
}
|
|
hr = lpipcPriority->Reply(hrIPC);
|
|
DPF_EXIT();
|
|
return hr;
|
|
|
|
case fdtccPriorityStop:
|
|
hr = CommandPriorityStop(&(pfdtc->fdtu.fdtcPriorityStop), &hrIPC);
|
|
if (FAILED(hr))
|
|
{
|
|
lpipcPriority->Reply(hrIPC);
|
|
DPF_EXIT();
|
|
return hr;
|
|
}
|
|
hr = lpipcPriority->Reply(hrIPC);
|
|
DPF_EXIT();
|
|
return hr;
|
|
|
|
default:
|
|
// Don't know this command. Reply with the appropriate
|
|
// code.
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Priority received Unknown command");
|
|
hr = lpipcPriority->Reply(DVERR_UNKNOWN);
|
|
if (FAILED(hr))
|
|
{
|
|
DPF_EXIT();
|
|
return hr;
|
|
}
|
|
|
|
// 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 "CommandPriorityStart"
|
|
HRESULT CommandPriorityStart(SFDTestCommandPriorityStart* pfdtcPriorityStart, HRESULT* phrIPC)
|
|
{
|
|
DPF_ENTER();
|
|
*phrIPC = DV_OK;
|
|
HRESULT hr = S_OK;
|
|
DSBUFFERDESC dsbd;
|
|
WAVEFORMATEX wfx;
|
|
DWORD dwSizeWritten;
|
|
DSBCAPS dsbc;
|
|
LPVOID lpvAudio1 = NULL;
|
|
DWORD dwAudio1Size = NULL;
|
|
LPVOID lpvAudio2 = NULL;
|
|
DWORD dwAudio2Size = NULL;
|
|
DSBPOSITIONNOTIFY dsbPositionNotify;
|
|
DWORD dwRet;
|
|
LONG lRet;
|
|
BOOL fRet;
|
|
HWND hwnd;
|
|
BYTE bSilence;
|
|
BOOL bBufferPlaying = FALSE;
|
|
GUID guidTmp;
|
|
|
|
memset( &guidTmp, 0x00, sizeof( GUID ) );
|
|
|
|
// initalize the global vars
|
|
GlobGuardIn();
|
|
g_lpdsPriorityRender = NULL;
|
|
g_lpdsbPriorityPrimary = NULL;
|
|
g_lpdsbPrioritySecondary = NULL;
|
|
GlobGuardOut();
|
|
|
|
Diagnostics_Write( DVF_INFOLEVEL, "-----------------------------------------------------------" );
|
|
|
|
hr = Diagnostics_DeviceInfo( &pfdtcPriorityStart->guidRenderDevice, &guidTmp );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
Diagnostics_Write( 0, "Error getting device information hr=0x%x", hr );
|
|
}
|
|
|
|
Diagnostics_Write( DVF_INFOLEVEL, "-----------------------------------------------------------" );
|
|
Diagnostics_Write( DVF_INFOLEVEL, "Primary Format: " );
|
|
|
|
Diagnositcs_WriteWAVEFORMATEX( DVF_INFOLEVEL, &pfdtcPriorityStart->wfxRenderFormat );
|
|
|
|
// make sure the priority dialog is in the foreground
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Bringing Wizard to the foreground");
|
|
fRet = SetForegroundWindow(pfdtcPriorityStart->hwndWizard);
|
|
if (!fRet)
|
|
{
|
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to bring wizard to foreground, continuing anyway...");
|
|
}
|
|
|
|
// kick the progress bar forward one tick
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Incrementing progress bar in dialog");
|
|
PostMessage(pfdtcPriorityStart->hwndProgress, PBM_STEPIT, 0, 0);
|
|
|
|
// create the DirectSound interface
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Creating DirectSound");
|
|
GlobGuardIn();
|
|
hr = DirectSoundCreate(&pfdtcPriorityStart->guidRenderDevice, &g_lpdsPriorityRender, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
g_lpdsPriorityRender = NULL;
|
|
GlobGuardOut();
|
|
Diagnostics_Write(DVF_ERRORLEVEL, "DirectSoundCreate failed, code: 0x%x", hr);
|
|
*phrIPC = DVERR_SOUNDINITFAILURE;
|
|
hr = DV_OK;
|
|
goto error_cleanup;
|
|
}
|
|
GlobGuardOut();
|
|
|
|
// set to priority mode
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Setting Cooperative Level");
|
|
GlobGuardIn();
|
|
hr = g_lpdsPriorityRender->SetCooperativeLevel(pfdtcPriorityStart->hwndWizard, DSSCL_PRIORITY);
|
|
GlobGuardOut();
|
|
if (FAILED(hr))
|
|
{
|
|
Diagnostics_Write(DVF_ERRORLEVEL, "SetCooperativeLevel failed, code: 0x%x", hr);
|
|
*phrIPC = DVERR_SOUNDINITFAILURE;
|
|
hr = DV_OK;
|
|
goto error_cleanup;
|
|
}
|
|
|
|
// Create a primary buffer object with 3d controls.
|
|
// We're not actually going to use the controls, but a game probably would,
|
|
// and we are really trying to emulate a game in this process.
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Creating Primary Sound Buffer");
|
|
ZeroMemory(&dsbd, sizeof(dsbd));
|
|
dsbd.dwSize = sizeof(dsbd);
|
|
dsbd.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER;
|
|
dsbd.dwBufferBytes = 0;
|
|
dsbd.dwReserved = 0;
|
|
dsbd.lpwfxFormat = NULL;
|
|
dsbd.guid3DAlgorithm = DS3DALG_DEFAULT;
|
|
GlobGuardIn();
|
|
hr = g_lpdsPriorityRender->CreateSoundBuffer((LPDSBUFFERDESC)&dsbd, &g_lpdsbPriorityPrimary, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
g_lpdsbPriorityPrimary = NULL;
|
|
GlobGuardOut();
|
|
Diagnostics_Write(DVF_ERRORLEVEL, "CreateSoundBuffer failed, code: 0x%x", hr);
|
|
*phrIPC = DVERR_SOUNDINITFAILURE;
|
|
hr = DV_OK;
|
|
goto error_cleanup;
|
|
}
|
|
GlobGuardOut();
|
|
|
|
// Set the format of the primary buffer to the requested format.
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Setting Primary Buffer Format");
|
|
|
|
GlobGuardIn();
|
|
hr = g_lpdsbPriorityPrimary->SetFormat(&pfdtcPriorityStart->wfxRenderFormat);
|
|
GlobGuardOut();
|
|
if (FAILED(hr))
|
|
{
|
|
Diagnostics_Write(DVF_ERRORLEVEL, "SetFormat failed, code: 0x%x ", hr);
|
|
*phrIPC = DVERR_SOUNDINITFAILURE;
|
|
hr = DV_OK;
|
|
goto error_cleanup;
|
|
}
|
|
|
|
// check to make sure the SetFormat actually worked
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Verifying Primary Buffer Format");
|
|
GlobGuardIn();
|
|
hr = g_lpdsbPriorityPrimary->GetFormat(&wfx, sizeof(wfx), &dwSizeWritten);
|
|
GlobGuardOut();
|
|
if (FAILED(hr))
|
|
{
|
|
Diagnostics_Write(DVF_ERRORLEVEL, "GetFormat failed, code: 0x%x ", hr);
|
|
*phrIPC = DVERR_SOUNDINITFAILURE;
|
|
hr = DV_OK;
|
|
goto error_cleanup;
|
|
}
|
|
|
|
if (dwSizeWritten != sizeof(wfx))
|
|
{
|
|
*phrIPC = DVERR_SOUNDINITFAILURE;
|
|
hr = DV_OK;
|
|
goto error_cleanup;
|
|
}
|
|
|
|
if (memcmp(&wfx, &pfdtcPriorityStart->wfxRenderFormat, sizeof(wfx)) != 0)
|
|
{
|
|
// This is an interesting case. Is it really a full duplex error that
|
|
// we are unable to initialize a primary buffer in this format?
|
|
// Perhaps not. Perhaps it is sufficient that we can get full duplex
|
|
// sound even if the forground priority mode app attempts to play
|
|
// using this format. So just dump a debug note, and move along...
|
|
DPFX(DPFPREP, DVF_WARNINGLEVEL, "Warning: SetFormat on primary buffer did not actually set the format");
|
|
}
|
|
|
|
// Create a secondary buffer object with 3d controls.
|
|
// We're not actually going to use the controls, but a game probably would,
|
|
// and we are really trying to emulate a game in this process.
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Creating Secondary Buffer");
|
|
dsbd.dwSize = sizeof(dsbd);
|
|
dsbd.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY;
|
|
|
|
dsbd.dwBufferBytes =
|
|
(pfdtcPriorityStart->wfxSecondaryFormat.nSamplesPerSec
|
|
* pfdtcPriorityStart->wfxSecondaryFormat.nBlockAlign)
|
|
/ (1000 / gc_dwFrameSize);
|
|
dsbd.dwReserved = 0;
|
|
dsbd.guid3DAlgorithm = DS3DALG_DEFAULT;
|
|
dsbd.lpwfxFormat = &(pfdtcPriorityStart->wfxSecondaryFormat);
|
|
|
|
GlobGuardIn();
|
|
hr = g_lpdsPriorityRender->CreateSoundBuffer((LPDSBUFFERDESC)&dsbd, &g_lpdsbPrioritySecondary, NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
g_lpdsbPrioritySecondary = NULL;
|
|
GlobGuardOut();
|
|
Diagnostics_Write(DVF_ERRORLEVEL, "CreateSoundBuffer failed, code: 0x%x Primary ", hr);
|
|
*phrIPC = DVERR_SOUNDINITFAILURE;
|
|
hr = DV_OK;
|
|
goto error_cleanup;
|
|
}
|
|
GlobGuardOut();
|
|
|
|
// clear out the secondary buffer
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Clearing Secondary Buffer");
|
|
GlobGuardIn();
|
|
hr = g_lpdsbPrioritySecondary->Lock(
|
|
0,
|
|
0,
|
|
&lpvAudio1,
|
|
&dwAudio1Size,
|
|
&lpvAudio2,
|
|
&dwAudio2Size,
|
|
DSBLOCK_ENTIREBUFFER);
|
|
GlobGuardOut();
|
|
if (FAILED(hr))
|
|
{
|
|
Diagnostics_Write(DVF_ERRORLEVEL, "Lock failed, code: 0x%x ", hr);
|
|
*phrIPC = DVERR_SOUNDINITFAILURE;
|
|
hr = DV_OK;
|
|
goto error_cleanup;
|
|
}
|
|
|
|
if (lpvAudio1 == NULL)
|
|
{
|
|
*phrIPC = DVERR_SOUNDINITFAILURE;
|
|
hr = DV_OK;
|
|
goto error_cleanup;
|
|
}
|
|
|
|
if (pfdtcPriorityStart->wfxSecondaryFormat.wBitsPerSample == 8)
|
|
{
|
|
bSilence = 0x80;
|
|
}
|
|
else
|
|
{
|
|
bSilence = 0x00;
|
|
}
|
|
memset(lpvAudio1, bSilence, dwAudio1Size);
|
|
if (lpvAudio2 != NULL)
|
|
{
|
|
memset(lpvAudio2, bSilence, dwAudio2Size);
|
|
}
|
|
|
|
GlobGuardIn();
|
|
hr = g_lpdsbPrioritySecondary->Unlock(
|
|
lpvAudio1,
|
|
dwAudio1Size,
|
|
lpvAudio2,
|
|
dwAudio2Size);
|
|
GlobGuardOut();
|
|
if (FAILED(hr))
|
|
{
|
|
Diagnostics_Write(DVF_ERRORLEVEL, "Unlock failed, code: 0x%x ", hr);
|
|
*phrIPC = DVERR_SOUNDINITFAILURE;
|
|
hr = DV_OK;
|
|
goto error_cleanup;
|
|
}
|
|
|
|
// start playing the secondary buffer
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Playing Secondary Buffer");
|
|
GlobGuardIn();
|
|
hr = g_lpdsbPrioritySecondary->Play(0, 0, DSBPLAY_LOOPING);
|
|
GlobGuardOut();
|
|
if (FAILED(hr))
|
|
{
|
|
Diagnostics_Write(DVF_ERRORLEVEL, "Play failed, code: 0x%x ", hr);
|
|
*phrIPC = DVERR_SOUNDINITFAILURE;
|
|
hr = DV_OK;
|
|
goto error_cleanup;
|
|
}
|
|
bBufferPlaying = TRUE;
|
|
|
|
DPF_EXIT();
|
|
|
|
Diagnostics_Write(DVF_INFOLEVEL, "Priority Result = DV_OK" );
|
|
|
|
return DV_OK;
|
|
|
|
error_cleanup:
|
|
GlobGuardIn();
|
|
|
|
if (bBufferPlaying == TRUE)
|
|
{
|
|
if (g_lpdsbPrioritySecondary != NULL)
|
|
{
|
|
g_lpdsbPrioritySecondary->Stop();
|
|
}
|
|
bBufferPlaying = FALSE;
|
|
}
|
|
|
|
if (g_lpdsbPrioritySecondary != NULL)
|
|
{
|
|
g_lpdsbPrioritySecondary->Release();
|
|
g_lpdsbPrioritySecondary = NULL;
|
|
}
|
|
|
|
if (g_lpdsbPriorityPrimary != NULL)
|
|
{
|
|
g_lpdsbPriorityPrimary->Release();
|
|
g_lpdsbPriorityPrimary = NULL;
|
|
}
|
|
|
|
if (g_lpdsPriorityRender != NULL)
|
|
{
|
|
g_lpdsPriorityRender->Release();
|
|
g_lpdsPriorityRender = NULL;
|
|
}
|
|
|
|
GlobGuardOut();
|
|
|
|
DPF_EXIT();
|
|
Diagnostics_Write(DVF_INFOLEVEL, "Priority Result = 0x%x", hr );
|
|
return hr;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CommandPriorityStop"
|
|
HRESULT CommandPriorityStop(SFDTestCommandPriorityStop* pfdtcPriorityStop, HRESULT* phrIPC)
|
|
{
|
|
DPF_ENTER();
|
|
|
|
HRESULT hr;
|
|
LONG lRet;
|
|
DWORD dwRet;
|
|
|
|
*phrIPC = S_OK;
|
|
hr = S_OK;
|
|
|
|
GlobGuardIn();
|
|
if (g_lpdsbPrioritySecondary != NULL)
|
|
{
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Stopping Secondary Buffer");
|
|
hr = g_lpdsbPrioritySecondary->Stop();
|
|
}
|
|
GlobGuardOut();
|
|
if (FAILED(hr))
|
|
{
|
|
Diagnostics_Write(DVF_ERRORLEVEL, "Stop failed, code: 0x%x", hr);
|
|
*phrIPC = DVERR_SOUNDINITFAILURE;
|
|
hr = DV_OK;
|
|
}
|
|
|
|
GlobGuardIn();
|
|
|
|
if (g_lpdsbPrioritySecondary != NULL)
|
|
{
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Releasing Secondary Buffer");
|
|
g_lpdsbPrioritySecondary->Release();
|
|
g_lpdsbPrioritySecondary = NULL;
|
|
}
|
|
if (g_lpdsbPriorityPrimary != NULL)
|
|
{
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Releasing Primary Buffer");
|
|
g_lpdsbPriorityPrimary->Release();
|
|
g_lpdsbPriorityPrimary = NULL;
|
|
}
|
|
if (g_lpdsPriorityRender != NULL)
|
|
{
|
|
DPFX(DPFPREP, DVF_INFOLEVEL, "Releasing DirectSound");
|
|
g_lpdsPriorityRender->Release();
|
|
g_lpdsPriorityRender = NULL;
|
|
}
|
|
GlobGuardOut();
|
|
|
|
DPF_EXIT();
|
|
return hr;
|
|
}
|
|
|