mirror of https://github.com/snes9xgit/snes9x.git
win32: stop trying to send audio data after device removal
This commit is contained in:
parent
f1ac3dc6d3
commit
d7dc9acf2f
|
@ -20,17 +20,25 @@ CWaveOut::~CWaveOut(void)
|
||||||
DeInitSoundOutput();
|
DeInitSoundOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CALLBACK WaveCallback(HWAVEOUT hWave, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
|
void CALLBACK CWaveOut::WaveCallback(HWAVEOUT hWave, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
|
||||||
{
|
{
|
||||||
|
CWaveOut *wo = (CWaveOut*)dwUser;
|
||||||
if (uMsg == WOM_DONE)
|
if (uMsg == WOM_DONE)
|
||||||
{
|
{
|
||||||
InterlockedDecrement(((volatile LONG *)dwUser));
|
InterlockedDecrement(&wo->bufferCount);
|
||||||
SetEvent(GUI.SoundSyncEvent);
|
SetEvent(GUI.SoundSyncEvent);
|
||||||
}
|
}
|
||||||
|
else if (uMsg == WOM_CLOSE) // also sent on device removals
|
||||||
|
{
|
||||||
|
// this stops any output from being sent to the non existing device
|
||||||
|
wo->initDone = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWaveOut::SetupSound()
|
bool CWaveOut::SetupSound()
|
||||||
{
|
{
|
||||||
|
DeInitSoundOutput();
|
||||||
|
|
||||||
WAVEFORMATEX wfx;
|
WAVEFORMATEX wfx;
|
||||||
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
wfx.nChannels = 2;
|
wfx.nChannels = 2;
|
||||||
|
@ -43,7 +51,7 @@ bool CWaveOut::SetupSound()
|
||||||
// subtract -1, we added "Default" as first index - Default will yield -1, which is WAVE_MAPPER
|
// subtract -1, we added "Default" as first index - Default will yield -1, which is WAVE_MAPPER
|
||||||
int device_index = FindDeviceIndex(GUI.AudioDevice) - 1;
|
int device_index = FindDeviceIndex(GUI.AudioDevice) - 1;
|
||||||
|
|
||||||
waveOutOpen(&hWaveOut, device_index, &wfx, (DWORD_PTR)WaveCallback, (DWORD_PTR)&bufferCount, CALLBACK_FUNCTION);
|
waveOutOpen(&hWaveOut, device_index, &wfx, (DWORD_PTR)WaveCallback, (DWORD_PTR)this, CALLBACK_FUNCTION);
|
||||||
|
|
||||||
UINT32 blockTime = GUI.SoundBufferSize / blockCount;
|
UINT32 blockTime = GUI.SoundBufferSize / blockCount;
|
||||||
singleBufferSamples = (Settings.SoundPlaybackRate * blockTime) / 1000;
|
singleBufferSamples = (Settings.SoundPlaybackRate * blockTime) / 1000;
|
||||||
|
@ -91,7 +99,7 @@ bool CWaveOut::InitSoundOutput()
|
||||||
|
|
||||||
void CWaveOut::DeInitSoundOutput()
|
void CWaveOut::DeInitSoundOutput()
|
||||||
{
|
{
|
||||||
if (!initDone)
|
if (!hWaveOut)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
StopPlayback();
|
StopPlayback();
|
||||||
|
@ -109,6 +117,7 @@ void CWaveOut::DeInitSoundOutput()
|
||||||
waveHeaders.clear();
|
waveHeaders.clear();
|
||||||
|
|
||||||
waveOutClose(hWaveOut);
|
waveOutClose(hWaveOut);
|
||||||
|
hWaveOut = NULL;
|
||||||
|
|
||||||
initDone = false;
|
initDone = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,4 +44,6 @@ class CWaveOut : public IS9xSoundOutput
|
||||||
void SetVolume(double volume);
|
void SetVolume(double volume);
|
||||||
std::vector<std::wstring> GetDeviceList();
|
std::vector<std::wstring> GetDeviceList();
|
||||||
int FindDeviceIndex(TCHAR *audio_device);
|
int FindDeviceIndex(TCHAR *audio_device);
|
||||||
|
|
||||||
|
static void CALLBACK WaveCallback(HWAVEOUT hWave, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2);
|
||||||
};
|
};
|
||||||
|
|
|
@ -108,6 +108,8 @@ bool CXAudio2::InitXAudio2(void)
|
||||||
if(initDone)
|
if(initDone)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
DeInitXAudio2();
|
||||||
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
if ( FAILED(hr = XAudio2Create( &pXAudio2, 0 , XAUDIO2_DEFAULT_PROCESSOR ) ) ) {
|
if ( FAILED(hr = XAudio2Create( &pXAudio2, 0 , XAUDIO2_DEFAULT_PROCESSOR ) ) ) {
|
||||||
DXTRACE_ERR_MSGBOX(TEXT("Unable to create XAudio2 object."),hr);
|
DXTRACE_ERR_MSGBOX(TEXT("Unable to create XAudio2 object."),hr);
|
||||||
|
@ -115,6 +117,7 @@ bool CXAudio2::InitXAudio2(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
initDone = true;
|
initDone = true;
|
||||||
|
pXAudio2->RegisterForCallbacks(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "IS9xSoundOutput.h"
|
#include "IS9xSoundOutput.h"
|
||||||
|
|
||||||
class CXAudio2 : public IXAudio2VoiceCallback, public IS9xSoundOutput
|
class CXAudio2 : public IXAudio2VoiceCallback, public IXAudio2EngineCallback, public IS9xSoundOutput
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
IXAudio2SourceVoice *pSourceVoice;
|
IXAudio2SourceVoice *pSourceVoice;
|
||||||
|
@ -56,6 +56,23 @@ public:
|
||||||
STDMETHODIMP_(void) OnVoiceProcessingPassStart(UINT32 BytesRequired) {}
|
STDMETHODIMP_(void) OnVoiceProcessingPassStart(UINT32 BytesRequired) {}
|
||||||
|
|
||||||
|
|
||||||
|
// inherited from IXAudio2EngineCallback - we only use OnCriticalError
|
||||||
|
|
||||||
|
// Called by XAudio2 just before an audio processing pass begins.
|
||||||
|
STDMETHODIMP_(void) OnProcessingPassStart() {}
|
||||||
|
|
||||||
|
// Called just after an audio processing pass ends.
|
||||||
|
STDMETHODIMP_(void) OnProcessingPassEnd() {}
|
||||||
|
|
||||||
|
// Called in the event of a critical system error which requires XAudio2
|
||||||
|
// to be closed down and restarted. The error code is given in Error.
|
||||||
|
STDMETHODIMP_(void) OnCriticalError(HRESULT Error)
|
||||||
|
{
|
||||||
|
// this stops any output from being sent to the non existing device
|
||||||
|
initDone = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Inherited from IS9xSoundOutput
|
// Inherited from IS9xSoundOutput
|
||||||
bool InitSoundOutput(void) { return InitXAudio2(); }
|
bool InitSoundOutput(void) { return InitXAudio2(); }
|
||||||
void DeInitSoundOutput(void) { DeInitXAudio2(); }
|
void DeInitSoundOutput(void) { DeInitXAudio2(); }
|
||||||
|
|
Loading…
Reference in New Issue