From: <man...@us...> - 2014-03-03 18:51:21
|
Revision: 3818 http://sourceforge.net/p/modplug/code/3818 Author: manxorist Date: 2014-03-03 18:51:12 +0000 (Mon, 03 Mar 2014) Log Message: ----------- [Ref] sounddev: Split SoundDeviceThread.cpp from SoundDevice.cpp . [Ref] sounddev: Rename SoundDevices.h to SoundDeviceThread.h . Modified Paths: -------------- trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters trunk/OpenMPT/sounddev/SoundDevice.cpp trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp trunk/OpenMPT/sounddev/SoundDeviceASIO.h trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp trunk/OpenMPT/sounddev/SoundDeviceDirectSound.h trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp trunk/OpenMPT/sounddev/SoundDevicePortAudio.h trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp trunk/OpenMPT/sounddev/SoundDeviceWaveout.h Added Paths: ----------- trunk/OpenMPT/sounddev/SoundDeviceThread.cpp trunk/OpenMPT/sounddev/SoundDeviceThread.h Removed Paths: ------------- trunk/OpenMPT/sounddev/SoundDevices.h Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2014-03-03 18:08:27 UTC (rev 3817) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2014-03-03 18:51:12 UTC (rev 3818) @@ -553,6 +553,10 @@ > </File> <File + RelativePath="..\sounddev\SoundDeviceThread.cpp" + > + </File> + <File RelativePath="..\sounddev\SoundDeviceWaveout.cpp" > </File> @@ -1215,7 +1219,7 @@ > </File> <File - RelativePath="..\sounddev\SoundDevices.h" + RelativePath="..\sounddev\SoundDeviceThread.h" > </File> <File @@ -1259,11 +1263,11 @@ > </File> <File - RelativePath=".\svn_version\svn_version.h" + RelativePath="..\common\svn_version_default\svn_version.h" > </File> <File - RelativePath="..\common\svn_version_default\svn_version.h" + RelativePath=".\svn_version\svn_version.h" > </File> <File Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2014-03-03 18:08:27 UTC (rev 3817) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj 2014-03-03 18:51:12 UTC (rev 3818) @@ -457,6 +457,7 @@ <ClCompile Include="..\sounddev\SoundDeviceASIO.cpp" /> <ClCompile Include="..\sounddev\SoundDeviceDirectSound.cpp" /> <ClCompile Include="..\sounddev\SoundDevicePortAudio.cpp" /> + <ClCompile Include="..\sounddev\SoundDeviceThread.cpp" /> <ClCompile Include="..\sounddev\SoundDeviceWaveout.cpp" /> <ClCompile Include="..\sounddsp\AGC.cpp" /> <ClCompile Include="..\sounddsp\DSP.cpp" /> @@ -656,7 +657,7 @@ <ClInclude Include="..\sounddev\SoundDeviceASIO.h" /> <ClInclude Include="..\sounddev\SoundDeviceDirectSound.h" /> <ClInclude Include="..\sounddev\SoundDevicePortAudio.h" /> - <ClInclude Include="..\sounddev\SoundDevices.h" /> + <ClInclude Include="..\sounddev\SoundDeviceThread.h" /> <ClInclude Include="..\sounddev\SoundDeviceWaveout.h" /> <ClInclude Include="..\sounddsp\AGC.h" /> <ClInclude Include="..\sounddsp\DSP.h" /> Modified: trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters =================================================================== --- trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2014-03-03 18:08:27 UTC (rev 3817) +++ trunk/OpenMPT/mptrack/mptrack_10.vcxproj.filters 2014-03-03 18:51:12 UTC (rev 3818) @@ -505,6 +505,9 @@ <ClCompile Include="..\test\TestToolsLib.cpp"> <Filter>test</Filter> </ClCompile> + <ClCompile Include="..\sounddev\SoundDeviceThread.cpp"> + <Filter>Source Files\sounddev</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\soundlib\Loaders.h"> @@ -594,9 +597,6 @@ <ClInclude Include="..\sounddsp\Reverb.h"> <Filter>Header Files\sounddsp</Filter> </ClInclude> - <ClInclude Include="..\sounddev\SoundDevices.h"> - <Filter>Header Files\sounddev</Filter> - </ClInclude> <ClInclude Include="..\sounddev\SoundDevice.h"> <Filter>Header Files\sounddev</Filter> </ClInclude> @@ -990,6 +990,9 @@ <ClInclude Include="..\test\TestTools.h"> <Filter>test</Filter> </ClInclude> + <ClInclude Include="..\sounddev\SoundDeviceThread.h"> + <Filter>Header Files\sounddev</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <None Include="res\bitmap1.bmp"> Modified: trunk/OpenMPT/sounddev/SoundDevice.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-03-03 18:08:27 UTC (rev 3817) +++ trunk/OpenMPT/sounddev/SoundDevice.cpp 2014-03-03 18:51:12 UTC (rev 3818) @@ -12,7 +12,6 @@ #include "stdafx.h" #include "SoundDevice.h" -#include "SoundDevices.h" #include "../common/misc_util.h" #include "../common/StringFixer.h" @@ -398,428 +397,6 @@ } -CAudioThread::CAudioThread(CSoundDeviceWithThread &SoundDevice) : m_SoundDevice(SoundDevice) -//------------------------------------------------------------------------------------------ -{ - - m_HasXP = (mpt::Windows::GetWinNTVersion() >= mpt::Windows::VerWinXP); - - m_hKernel32DLL = NULL; - - pCreateWaitableTimer = nullptr; - pSetWaitableTimer = nullptr; - pCancelWaitableTimer = nullptr; - m_hKernel32DLL = LoadLibrary(TEXT("kernel32.dll")); - #if _WIN32_WINNT >= _WIN32_WINNT_WINXP - m_HasXP = true; - pCreateWaitableTimer = &CreateWaitableTimer; - pSetWaitableTimer = &SetWaitableTimer; - pCancelWaitableTimer = &CancelWaitableTimer; - #else - if(m_HasXP && m_hKernel32DLL) - { - pCreateWaitableTimer = (FCreateWaitableTimer)GetProcAddress(m_hKernel32DLL, "CreateWaitableTimerA"); - pSetWaitableTimer = (FSetWaitableTimer)GetProcAddress(m_hKernel32DLL, "SetWaitableTimer"); - pCancelWaitableTimer = (FCancelWaitableTimer)GetProcAddress(m_hKernel32DLL, "CancelWaitableTimer"); - if(!pCreateWaitableTimer || !pSetWaitableTimer || !pCancelWaitableTimer) - { - m_HasXP = false; - } - } - #endif - - m_WakeupInterval = 0.0; - m_hPlayThread = NULL; - m_dwPlayThreadId = 0; - m_hAudioWakeUp = NULL; - m_hAudioThreadTerminateRequest = NULL; - m_hAudioThreadGoneIdle = NULL; - m_hHardwareWakeupEvent = INVALID_HANDLE_VALUE; - m_AudioThreadActive = 0; - m_hAudioWakeUp = CreateEvent(NULL, FALSE, FALSE, NULL); - m_hAudioThreadTerminateRequest = CreateEvent(NULL, FALSE, FALSE, NULL); - m_hAudioThreadGoneIdle = CreateEvent(NULL, TRUE, FALSE, NULL); - m_hPlayThread = CreateThread(NULL, 0, AudioThreadWrapper, (LPVOID)this, 0, &m_dwPlayThreadId); -} - - -CAudioThread::~CAudioThread() -//--------------------------- -{ - if(m_hPlayThread != NULL) - { - SetEvent(m_hAudioThreadTerminateRequest); - WaitForSingleObject(m_hPlayThread, INFINITE); - m_dwPlayThreadId = 0; - m_hPlayThread = NULL; - } - if(m_hAudioThreadTerminateRequest) - { - CloseHandle(m_hAudioThreadTerminateRequest); - m_hAudioThreadTerminateRequest = 0; - } - if(m_hAudioThreadGoneIdle != NULL) - { - CloseHandle(m_hAudioThreadGoneIdle); - m_hAudioThreadGoneIdle = 0; - } - if(m_hAudioWakeUp != NULL) - { - CloseHandle(m_hAudioWakeUp); - m_hAudioWakeUp = NULL; - } - - pCreateWaitableTimer = nullptr; - pSetWaitableTimer = nullptr; - pCancelWaitableTimer = nullptr; - - if(m_hKernel32DLL) - { - FreeLibrary(m_hKernel32DLL); - m_hKernel32DLL = NULL; - } - -} - - -CPriorityBooster::CPriorityBooster(bool boostPriority) -//---------------------------------------------------- - : m_HasVista(false) - , m_hAvRtDLL(NULL) - , pAvSetMmThreadCharacteristics(nullptr) - , pAvRevertMmThreadCharacteristics(nullptr) - , m_BoostPriority(boostPriority) - , task_idx(0) - , hTask(NULL) -{ - - m_HasVista = (mpt::Windows::GetWinNTVersion() >= mpt::Windows::VerWinVista); - - if(m_HasVista) - { - m_hAvRtDLL = LoadLibrary(TEXT("avrt.dll")); - if(m_hAvRtDLL && m_hAvRtDLL != INVALID_HANDLE_VALUE) - { - pAvSetMmThreadCharacteristics = (FAvSetMmThreadCharacteristics)GetProcAddress(m_hAvRtDLL, "AvSetMmThreadCharacteristicsA"); - pAvRevertMmThreadCharacteristics = (FAvRevertMmThreadCharacteristics)GetProcAddress(m_hAvRtDLL, "AvRevertMmThreadCharacteristics"); - } - if(!pAvSetMmThreadCharacteristics || !pAvRevertMmThreadCharacteristics) - { - m_HasVista = false; - } - } - - #ifdef _DEBUG - m_BoostPriority = false; - #endif - - if(m_BoostPriority) - { - if(m_HasVista) - { - hTask = pAvSetMmThreadCharacteristics(TEXT("Pro Audio"), &task_idx); - } else - { - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); - } - } - -} - - -CPriorityBooster::~CPriorityBooster() -//----------------------------------- -{ - - if(m_BoostPriority) - { - if(m_HasVista) - { - pAvRevertMmThreadCharacteristics(hTask); - hTask = NULL; - task_idx = 0; - } else - { - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); - } - } - - pAvRevertMmThreadCharacteristics = nullptr; - pAvSetMmThreadCharacteristics = nullptr; - - if(m_hAvRtDLL) - { - FreeLibrary(m_hAvRtDLL); - m_hAvRtDLL = NULL; - } - -} - - -class CPeriodicWaker -{ -private: - CAudioThread &self; - - double sleepSeconds; - long sleepMilliseconds; - int64 sleep100Nanoseconds; - - Util::MultimediaClock clock_noxp; - - bool period_noxp_set; - bool periodic_xp_timer; - - HANDLE sleepEvent; - -public: - - CPeriodicWaker(CAudioThread &self_, double sleepSeconds_) : self(self_), sleepSeconds(sleepSeconds_) - //-------------------------------------------------------------------------------------------------- - { - - sleepMilliseconds = static_cast<long>(sleepSeconds * 1000.0); - sleep100Nanoseconds = static_cast<int64>(sleepSeconds * 10000000.0); - if(sleepMilliseconds < 1) sleepMilliseconds = 1; - if(sleep100Nanoseconds < 1) sleep100Nanoseconds = 1; - - period_noxp_set = false; - periodic_xp_timer = (sleep100Nanoseconds >= 10000); // can be represented as a millisecond period, otherwise use non-periodic timers which allow higher precision but might me slower because we have to set them again in each period - - sleepEvent = NULL; - - if(self.m_HasXP) - { - if(periodic_xp_timer) - { - sleepEvent = self.pCreateWaitableTimer(NULL, FALSE, NULL); - LARGE_INTEGER dueTime; - dueTime.QuadPart = 0 - sleep100Nanoseconds; // negative time means relative - self.pSetWaitableTimer(sleepEvent, &dueTime, sleepMilliseconds, NULL, NULL, FALSE); - } else - { - sleepEvent = self.pCreateWaitableTimer(NULL, TRUE, NULL); - } - } else - { - sleepEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - clock_noxp.SetResolution(1); // increase resolution of multimedia timer - period_noxp_set = true; - } - - } - - long GetSleepMilliseconds() const - //------------------------------- - { - return sleepMilliseconds; - } - - HANDLE GetWakeupEvent() const - //--------------------------- - { - return sleepEvent; - } - - void Retrigger() - //-------------- - { - if(self.m_HasXP) - { - if(!periodic_xp_timer) - { - LARGE_INTEGER dueTime; - dueTime.QuadPart = 0 - sleep100Nanoseconds; // negative time means relative - self.pSetWaitableTimer(sleepEvent, &dueTime, 0, NULL, NULL, FALSE); - } - } else - { - timeSetEvent(sleepMilliseconds, 1, (LPTIMECALLBACK)sleepEvent, NULL, TIME_ONESHOT | TIME_CALLBACK_EVENT_SET); - } - } - - CPeriodicWaker::~CPeriodicWaker() - //------------------------------- - { - if(self.m_HasXP) - { - if(periodic_xp_timer) - { - self.pCancelWaitableTimer(sleepEvent); - } - CloseHandle(sleepEvent); - sleepEvent = NULL; - } else - { - if(period_noxp_set) - { - clock_noxp.SetResolution(0); - period_noxp_set = false; - } - CloseHandle(sleepEvent); - sleepEvent = NULL; - } - } - -}; - - -DWORD WINAPI CAudioThread::AudioThreadWrapper(LPVOID user) -{ - return ((CAudioThread*)user)->AudioThread(); -} -DWORD CAudioThread::AudioThread() -//------------------------------- -{ - - bool terminate = false; - while(!terminate) - { - - bool idle = true; - while(!terminate && idle) - { - HANDLE waithandles[2] = {m_hAudioThreadTerminateRequest, m_hAudioWakeUp}; - SetEvent(m_hAudioThreadGoneIdle); - switch(WaitForMultipleObjects(2, waithandles, FALSE, INFINITE)) - { - case WAIT_OBJECT_0: - terminate = true; - break; - case WAIT_OBJECT_0+1: - idle = false; - break; - } - } - - if(!terminate) - { - - CPriorityBooster priorityBooster(m_SoundDevice.m_Settings.BoostThreadPriority); - CPeriodicWaker periodicWaker(*this, m_WakeupInterval); - - m_SoundDevice.StartFromSoundThread(); - - while(!terminate && IsActive()) - { - - m_SoundDevice.FillAudioBufferLocked(); - - periodicWaker.Retrigger(); - - if(m_hHardwareWakeupEvent != INVALID_HANDLE_VALUE) - { - HANDLE waithandles[4] = {m_hAudioThreadTerminateRequest, m_hAudioWakeUp, m_hHardwareWakeupEvent, periodicWaker.GetWakeupEvent()}; - switch(WaitForMultipleObjects(4, waithandles, FALSE, periodicWaker.GetSleepMilliseconds())) - { - case WAIT_OBJECT_0: - terminate = true; - break; - } - } else - { - HANDLE waithandles[3] = {m_hAudioThreadTerminateRequest, m_hAudioWakeUp, periodicWaker.GetWakeupEvent()}; - switch(WaitForMultipleObjects(3, waithandles, FALSE, periodicWaker.GetSleepMilliseconds())) - { - case WAIT_OBJECT_0: - terminate = true; - break; - } - } - - } - - m_SoundDevice.StopFromSoundThread(); - - } - - } - - SetEvent(m_hAudioThreadGoneIdle); - - return 0; - -} - - -void CAudioThread::SetWakeupEvent(HANDLE ev) -//------------------------------------------ -{ - m_hHardwareWakeupEvent = ev; -} - - -void CAudioThread::SetWakeupInterval(double seconds) -//-------------------------------------------------- -{ - m_WakeupInterval = seconds; -} - - -void CAudioThread::Activate() -//--------------------------- -{ - if(InterlockedExchangeAdd(&m_AudioThreadActive, 0)) - { - ALWAYS_ASSERT(false); - return; - } - ResetEvent(m_hAudioThreadGoneIdle); - InterlockedExchange(&m_AudioThreadActive, 1); - SetEvent(m_hAudioWakeUp); -} - - -void CAudioThread::Deactivate() -//----------------------------- -{ - if(!InterlockedExchangeAdd(&m_AudioThreadActive, 0)) - { - ALWAYS_ASSERT(false); - return; - } - InterlockedExchange(&m_AudioThreadActive, 0); - WaitForSingleObject(m_hAudioThreadGoneIdle, INFINITE); -} - - -void CSoundDeviceWithThread::FillAudioBufferLocked() -//-------------------------------------------------- -{ - SourceFillAudioBufferLocked(); -} - - -void CSoundDeviceWithThread::SetWakeupEvent(HANDLE ev) -//---------------------------------------------------- -{ - m_AudioThread.SetWakeupEvent(ev); -} - - -void CSoundDeviceWithThread::SetWakeupInterval(double seconds) -//------------------------------------------------------------ -{ - m_AudioThread.SetWakeupInterval(seconds); -} - - -bool CSoundDeviceWithThread::InternalStart() -//------------------------------------------ -{ - m_AudioThread.Activate(); - return true; -} - - -void CSoundDeviceWithThread::InternalStop() -//----------------------------------------- -{ - m_AudioThread.Deactivate(); -} - - - /////////////////////////////////////////////////////////////////////////////////////// // // Global Functions Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2014-03-03 18:08:27 UTC (rev 3817) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2014-03-03 18:51:12 UTC (rev 3818) @@ -12,7 +12,6 @@ #include "stdafx.h" #include "SoundDevice.h" -#include "SoundDevices.h" #include "SoundDeviceASIO.h" Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.h 2014-03-03 18:08:27 UTC (rev 3817) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.h 2014-03-03 18:51:12 UTC (rev 3818) @@ -11,7 +11,7 @@ #pragma once -#include "SoundDevices.h" +#include "SoundDevice.h" #include "../common/FlagSet.h" Modified: trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp 2014-03-03 18:08:27 UTC (rev 3817) +++ trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp 2014-03-03 18:51:12 UTC (rev 3818) @@ -12,7 +12,7 @@ #include "stdafx.h" #include "SoundDevice.h" -#include "SoundDevices.h" +#include "SoundDeviceThread.h" #include "SoundDeviceDirectSound.h" Modified: trunk/OpenMPT/sounddev/SoundDeviceDirectSound.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceDirectSound.h 2014-03-03 18:08:27 UTC (rev 3817) +++ trunk/OpenMPT/sounddev/SoundDeviceDirectSound.h 2014-03-03 18:51:12 UTC (rev 3818) @@ -11,7 +11,8 @@ #pragma once -#include "SoundDevices.h" +#include "SoundDevice.h" +#include "SoundDeviceThread.h" #ifndef NO_DSOUND #include <dsound.h> Modified: trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp 2014-03-03 18:08:27 UTC (rev 3817) +++ trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp 2014-03-03 18:51:12 UTC (rev 3818) @@ -12,7 +12,6 @@ #include "stdafx.h" #include "SoundDevice.h" -#include "SoundDevices.h" #include "SoundDevicePortAudio.h" Modified: trunk/OpenMPT/sounddev/SoundDevicePortAudio.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevicePortAudio.h 2014-03-03 18:08:27 UTC (rev 3817) +++ trunk/OpenMPT/sounddev/SoundDevicePortAudio.h 2014-03-03 18:51:12 UTC (rev 3818) @@ -10,7 +10,7 @@ #pragma once -#include "SoundDevices.h" +#include "SoundDevice.h" #ifndef NO_PORTAUDIO #include "portaudio/include/portaudio.h" Copied: trunk/OpenMPT/sounddev/SoundDeviceThread.cpp (from rev 3817, trunk/OpenMPT/sounddev/SoundDevice.cpp) =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceThread.cpp (rev 0) +++ trunk/OpenMPT/sounddev/SoundDeviceThread.cpp 2014-03-03 18:51:12 UTC (rev 3818) @@ -0,0 +1,442 @@ +/* + * SoundDeviceThread.cpp + * --------------------- + * Purpose: Sound device threading driver helpers. + * Notes : (currently none) + * Authors: Olivier Lapicque + * OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#include "stdafx.h" + +#include "SoundDevice.h" +#include "SoundDeviceThread.h" + +#include "../common/misc_util.h" + +#include <algorithm> +#include <iterator> + + +CAudioThread::CAudioThread(CSoundDeviceWithThread &SoundDevice) : m_SoundDevice(SoundDevice) +//------------------------------------------------------------------------------------------ +{ + + m_HasXP = (mpt::Windows::GetWinNTVersion() >= mpt::Windows::VerWinXP); + + m_hKernel32DLL = NULL; + + pCreateWaitableTimer = nullptr; + pSetWaitableTimer = nullptr; + pCancelWaitableTimer = nullptr; + m_hKernel32DLL = LoadLibrary(TEXT("kernel32.dll")); + #if _WIN32_WINNT >= _WIN32_WINNT_WINXP + m_HasXP = true; + pCreateWaitableTimer = &CreateWaitableTimer; + pSetWaitableTimer = &SetWaitableTimer; + pCancelWaitableTimer = &CancelWaitableTimer; + #else + if(m_HasXP && m_hKernel32DLL) + { + pCreateWaitableTimer = (FCreateWaitableTimer)GetProcAddress(m_hKernel32DLL, "CreateWaitableTimerA"); + pSetWaitableTimer = (FSetWaitableTimer)GetProcAddress(m_hKernel32DLL, "SetWaitableTimer"); + pCancelWaitableTimer = (FCancelWaitableTimer)GetProcAddress(m_hKernel32DLL, "CancelWaitableTimer"); + if(!pCreateWaitableTimer || !pSetWaitableTimer || !pCancelWaitableTimer) + { + m_HasXP = false; + } + } + #endif + + m_WakeupInterval = 0.0; + m_hPlayThread = NULL; + m_dwPlayThreadId = 0; + m_hAudioWakeUp = NULL; + m_hAudioThreadTerminateRequest = NULL; + m_hAudioThreadGoneIdle = NULL; + m_hHardwareWakeupEvent = INVALID_HANDLE_VALUE; + m_AudioThreadActive = 0; + m_hAudioWakeUp = CreateEvent(NULL, FALSE, FALSE, NULL); + m_hAudioThreadTerminateRequest = CreateEvent(NULL, FALSE, FALSE, NULL); + m_hAudioThreadGoneIdle = CreateEvent(NULL, TRUE, FALSE, NULL); + m_hPlayThread = CreateThread(NULL, 0, AudioThreadWrapper, (LPVOID)this, 0, &m_dwPlayThreadId); +} + + +CAudioThread::~CAudioThread() +//--------------------------- +{ + if(m_hPlayThread != NULL) + { + SetEvent(m_hAudioThreadTerminateRequest); + WaitForSingleObject(m_hPlayThread, INFINITE); + m_dwPlayThreadId = 0; + m_hPlayThread = NULL; + } + if(m_hAudioThreadTerminateRequest) + { + CloseHandle(m_hAudioThreadTerminateRequest); + m_hAudioThreadTerminateRequest = 0; + } + if(m_hAudioThreadGoneIdle != NULL) + { + CloseHandle(m_hAudioThreadGoneIdle); + m_hAudioThreadGoneIdle = 0; + } + if(m_hAudioWakeUp != NULL) + { + CloseHandle(m_hAudioWakeUp); + m_hAudioWakeUp = NULL; + } + + pCreateWaitableTimer = nullptr; + pSetWaitableTimer = nullptr; + pCancelWaitableTimer = nullptr; + + if(m_hKernel32DLL) + { + FreeLibrary(m_hKernel32DLL); + m_hKernel32DLL = NULL; + } + +} + + +CPriorityBooster::CPriorityBooster(bool boostPriority) +//---------------------------------------------------- + : m_HasVista(false) + , m_hAvRtDLL(NULL) + , pAvSetMmThreadCharacteristics(nullptr) + , pAvRevertMmThreadCharacteristics(nullptr) + , m_BoostPriority(boostPriority) + , task_idx(0) + , hTask(NULL) +{ + + m_HasVista = (mpt::Windows::GetWinNTVersion() >= mpt::Windows::VerWinVista); + + if(m_HasVista) + { + m_hAvRtDLL = LoadLibrary(TEXT("avrt.dll")); + if(m_hAvRtDLL && m_hAvRtDLL != INVALID_HANDLE_VALUE) + { + pAvSetMmThreadCharacteristics = (FAvSetMmThreadCharacteristics)GetProcAddress(m_hAvRtDLL, "AvSetMmThreadCharacteristicsA"); + pAvRevertMmThreadCharacteristics = (FAvRevertMmThreadCharacteristics)GetProcAddress(m_hAvRtDLL, "AvRevertMmThreadCharacteristics"); + } + if(!pAvSetMmThreadCharacteristics || !pAvRevertMmThreadCharacteristics) + { + m_HasVista = false; + } + } + + #ifdef _DEBUG + m_BoostPriority = false; + #endif + + if(m_BoostPriority) + { + if(m_HasVista) + { + hTask = pAvSetMmThreadCharacteristics(TEXT("Pro Audio"), &task_idx); + } else + { + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); + } + } + +} + + +CPriorityBooster::~CPriorityBooster() +//----------------------------------- +{ + + if(m_BoostPriority) + { + if(m_HasVista) + { + pAvRevertMmThreadCharacteristics(hTask); + hTask = NULL; + task_idx = 0; + } else + { + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); + } + } + + pAvRevertMmThreadCharacteristics = nullptr; + pAvSetMmThreadCharacteristics = nullptr; + + if(m_hAvRtDLL) + { + FreeLibrary(m_hAvRtDLL); + m_hAvRtDLL = NULL; + } + +} + + +class CPeriodicWaker +{ +private: + CAudioThread &self; + + double sleepSeconds; + long sleepMilliseconds; + int64 sleep100Nanoseconds; + + Util::MultimediaClock clock_noxp; + + bool period_noxp_set; + bool periodic_xp_timer; + + HANDLE sleepEvent; + +public: + + CPeriodicWaker(CAudioThread &self_, double sleepSeconds_) : self(self_), sleepSeconds(sleepSeconds_) + //-------------------------------------------------------------------------------------------------- + { + + sleepMilliseconds = static_cast<long>(sleepSeconds * 1000.0); + sleep100Nanoseconds = static_cast<int64>(sleepSeconds * 10000000.0); + if(sleepMilliseconds < 1) sleepMilliseconds = 1; + if(sleep100Nanoseconds < 1) sleep100Nanoseconds = 1; + + period_noxp_set = false; + periodic_xp_timer = (sleep100Nanoseconds >= 10000); // can be represented as a millisecond period, otherwise use non-periodic timers which allow higher precision but might me slower because we have to set them again in each period + + sleepEvent = NULL; + + if(self.m_HasXP) + { + if(periodic_xp_timer) + { + sleepEvent = self.pCreateWaitableTimer(NULL, FALSE, NULL); + LARGE_INTEGER dueTime; + dueTime.QuadPart = 0 - sleep100Nanoseconds; // negative time means relative + self.pSetWaitableTimer(sleepEvent, &dueTime, sleepMilliseconds, NULL, NULL, FALSE); + } else + { + sleepEvent = self.pCreateWaitableTimer(NULL, TRUE, NULL); + } + } else + { + sleepEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + clock_noxp.SetResolution(1); // increase resolution of multimedia timer + period_noxp_set = true; + } + + } + + long GetSleepMilliseconds() const + //------------------------------- + { + return sleepMilliseconds; + } + + HANDLE GetWakeupEvent() const + //--------------------------- + { + return sleepEvent; + } + + void Retrigger() + //-------------- + { + if(self.m_HasXP) + { + if(!periodic_xp_timer) + { + LARGE_INTEGER dueTime; + dueTime.QuadPart = 0 - sleep100Nanoseconds; // negative time means relative + self.pSetWaitableTimer(sleepEvent, &dueTime, 0, NULL, NULL, FALSE); + } + } else + { + timeSetEvent(sleepMilliseconds, 1, (LPTIMECALLBACK)sleepEvent, NULL, TIME_ONESHOT | TIME_CALLBACK_EVENT_SET); + } + } + + CPeriodicWaker::~CPeriodicWaker() + //------------------------------- + { + if(self.m_HasXP) + { + if(periodic_xp_timer) + { + self.pCancelWaitableTimer(sleepEvent); + } + CloseHandle(sleepEvent); + sleepEvent = NULL; + } else + { + if(period_noxp_set) + { + clock_noxp.SetResolution(0); + period_noxp_set = false; + } + CloseHandle(sleepEvent); + sleepEvent = NULL; + } + } + +}; + + +DWORD WINAPI CAudioThread::AudioThreadWrapper(LPVOID user) +{ + return ((CAudioThread*)user)->AudioThread(); +} +DWORD CAudioThread::AudioThread() +//------------------------------- +{ + + bool terminate = false; + while(!terminate) + { + + bool idle = true; + while(!terminate && idle) + { + HANDLE waithandles[2] = {m_hAudioThreadTerminateRequest, m_hAudioWakeUp}; + SetEvent(m_hAudioThreadGoneIdle); + switch(WaitForMultipleObjects(2, waithandles, FALSE, INFINITE)) + { + case WAIT_OBJECT_0: + terminate = true; + break; + case WAIT_OBJECT_0+1: + idle = false; + break; + } + } + + if(!terminate) + { + + CPriorityBooster priorityBooster(m_SoundDevice.m_Settings.BoostThreadPriority); + CPeriodicWaker periodicWaker(*this, m_WakeupInterval); + + m_SoundDevice.StartFromSoundThread(); + + while(!terminate && IsActive()) + { + + m_SoundDevice.FillAudioBufferLocked(); + + periodicWaker.Retrigger(); + + if(m_hHardwareWakeupEvent != INVALID_HANDLE_VALUE) + { + HANDLE waithandles[4] = {m_hAudioThreadTerminateRequest, m_hAudioWakeUp, m_hHardwareWakeupEvent, periodicWaker.GetWakeupEvent()}; + switch(WaitForMultipleObjects(4, waithandles, FALSE, periodicWaker.GetSleepMilliseconds())) + { + case WAIT_OBJECT_0: + terminate = true; + break; + } + } else + { + HANDLE waithandles[3] = {m_hAudioThreadTerminateRequest, m_hAudioWakeUp, periodicWaker.GetWakeupEvent()}; + switch(WaitForMultipleObjects(3, waithandles, FALSE, periodicWaker.GetSleepMilliseconds())) + { + case WAIT_OBJECT_0: + terminate = true; + break; + } + } + + } + + m_SoundDevice.StopFromSoundThread(); + + } + + } + + SetEvent(m_hAudioThreadGoneIdle); + + return 0; + +} + + +void CAudioThread::SetWakeupEvent(HANDLE ev) +//------------------------------------------ +{ + m_hHardwareWakeupEvent = ev; +} + + +void CAudioThread::SetWakeupInterval(double seconds) +//-------------------------------------------------- +{ + m_WakeupInterval = seconds; +} + + +void CAudioThread::Activate() +//--------------------------- +{ + if(InterlockedExchangeAdd(&m_AudioThreadActive, 0)) + { + ALWAYS_ASSERT(false); + return; + } + ResetEvent(m_hAudioThreadGoneIdle); + InterlockedExchange(&m_AudioThreadActive, 1); + SetEvent(m_hAudioWakeUp); +} + + +void CAudioThread::Deactivate() +//----------------------------- +{ + if(!InterlockedExchangeAdd(&m_AudioThreadActive, 0)) + { + ALWAYS_ASSERT(false); + return; + } + InterlockedExchange(&m_AudioThreadActive, 0); + WaitForSingleObject(m_hAudioThreadGoneIdle, INFINITE); +} + + +void CSoundDeviceWithThread::FillAudioBufferLocked() +//-------------------------------------------------- +{ + SourceFillAudioBufferLocked(); +} + + +void CSoundDeviceWithThread::SetWakeupEvent(HANDLE ev) +//---------------------------------------------------- +{ + m_AudioThread.SetWakeupEvent(ev); +} + + +void CSoundDeviceWithThread::SetWakeupInterval(double seconds) +//------------------------------------------------------------ +{ + m_AudioThread.SetWakeupInterval(seconds); +} + + +bool CSoundDeviceWithThread::InternalStart() +//------------------------------------------ +{ + m_AudioThread.Activate(); + return true; +} + + +void CSoundDeviceWithThread::InternalStop() +//----------------------------------------- +{ + m_AudioThread.Deactivate(); +} + Copied: trunk/OpenMPT/sounddev/SoundDeviceThread.h (from rev 3817, trunk/OpenMPT/sounddev/SoundDevices.h) =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceThread.h (rev 0) +++ trunk/OpenMPT/sounddev/SoundDeviceThread.h 2014-03-03 18:51:12 UTC (rev 3818) @@ -0,0 +1,93 @@ +/* + * SoundDeviceThread.h + * ------------------- + * Purpose: Sound device threading driver helpers. + * Notes : (currently none) + * Authors: Olivier Lapicque + * OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + + +#pragma once + +#include "SoundDevice.h" + + +class CSoundDeviceWithThread; + + +class CPriorityBooster +{ +private: + typedef HANDLE (WINAPI *FAvSetMmThreadCharacteristics)(LPCTSTR, LPDWORD); + typedef BOOL (WINAPI *FAvRevertMmThreadCharacteristics)(HANDLE); +private: + bool m_HasVista; + HMODULE m_hAvRtDLL; + FAvSetMmThreadCharacteristics pAvSetMmThreadCharacteristics; + FAvRevertMmThreadCharacteristics pAvRevertMmThreadCharacteristics; + bool m_BoostPriority; + DWORD task_idx; + HANDLE hTask; +public: + CPriorityBooster(bool boostPriority); + ~CPriorityBooster(); +}; + + +class CAudioThread +{ + friend class CPeriodicWaker; +private: + CSoundDeviceWithThread & m_SoundDevice; + + bool m_HasXP; + HMODULE m_hKernel32DLL; + typedef HANDLE (WINAPI *FCreateWaitableTimer)(LPSECURITY_ATTRIBUTES, BOOL, LPCTSTR); + typedef BOOL (WINAPI *FSetWaitableTimer)(HANDLE, const LARGE_INTEGER *, LONG, PTIMERAPCROUTINE, LPVOID, BOOL); + typedef BOOL (WINAPI *FCancelWaitableTimer)(HANDLE); + FCreateWaitableTimer pCreateWaitableTimer; + FSetWaitableTimer pSetWaitableTimer; + FCancelWaitableTimer pCancelWaitableTimer; + + double m_WakeupInterval; + HANDLE m_hAudioWakeUp; + HANDLE m_hPlayThread; + HANDLE m_hAudioThreadTerminateRequest; + HANDLE m_hAudioThreadGoneIdle; + HANDLE m_hHardwareWakeupEvent; + DWORD m_dwPlayThreadId; + LONG m_AudioThreadActive; + static DWORD WINAPI AudioThreadWrapper(LPVOID user); + DWORD AudioThread(); + bool IsActive() { return InterlockedExchangeAdd(&m_AudioThreadActive, 0)?true:false; } +public: + CAudioThread(CSoundDeviceWithThread &SoundDevice); + ~CAudioThread(); + void Activate(); + void Deactivate(); + void SetWakeupEvent(HANDLE ev); + void SetWakeupInterval(double seconds); +}; + + +class CSoundDeviceWithThread : public ISoundDevice +{ + friend class CAudioThread; +protected: + CAudioThread m_AudioThread; +private: + void FillAudioBufferLocked(); +protected: + void SetWakeupEvent(HANDLE ev); + void SetWakeupInterval(double seconds); +public: + CSoundDeviceWithThread(SoundDeviceID id, const std::wstring &internalID) : ISoundDevice(id, internalID), m_AudioThread(*this) {} + virtual ~CSoundDeviceWithThread() {} + bool InternalStart(); + void InternalStop(); + virtual void StartFromSoundThread() = 0; + virtual void StopFromSoundThread() = 0; +}; + Modified: trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp 2014-03-03 18:08:27 UTC (rev 3817) +++ trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp 2014-03-03 18:51:12 UTC (rev 3818) @@ -12,7 +12,7 @@ #include "stdafx.h" #include "SoundDevice.h" -#include "SoundDevices.h" +#include "SoundDeviceThread.h" #include "SoundDeviceWaveout.h" Modified: trunk/OpenMPT/sounddev/SoundDeviceWaveout.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceWaveout.h 2014-03-03 18:08:27 UTC (rev 3817) +++ trunk/OpenMPT/sounddev/SoundDeviceWaveout.h 2014-03-03 18:51:12 UTC (rev 3818) @@ -11,7 +11,8 @@ #pragma once -#include "SoundDevices.h" +#include "SoundDevice.h" +#include "SoundDeviceThread.h" #include <MMSystem.h> Deleted: trunk/OpenMPT/sounddev/SoundDevices.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevices.h 2014-03-03 18:08:27 UTC (rev 3817) +++ trunk/OpenMPT/sounddev/SoundDevices.h 2014-03-03 18:51:12 UTC (rev 3818) @@ -1,93 +0,0 @@ -/* - * SoundDevices.h - * -------------- - * Purpose: Sound device driver helpers. - * Notes : (currently none) - * Authors: Olivier Lapicque - * OpenMPT Devs - * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. - */ - - -#pragma once - -#include "SoundDevice.h" - - -class CSoundDeviceWithThread; - - -class CPriorityBooster -{ -private: - typedef HANDLE (WINAPI *FAvSetMmThreadCharacteristics)(LPCTSTR, LPDWORD); - typedef BOOL (WINAPI *FAvRevertMmThreadCharacteristics)(HANDLE); -private: - bool m_HasVista; - HMODULE m_hAvRtDLL; - FAvSetMmThreadCharacteristics pAvSetMmThreadCharacteristics; - FAvRevertMmThreadCharacteristics pAvRevertMmThreadCharacteristics; - bool m_BoostPriority; - DWORD task_idx; - HANDLE hTask; -public: - CPriorityBooster(bool boostPriority); - ~CPriorityBooster(); -}; - - -class CAudioThread -{ - friend class CPeriodicWaker; -private: - CSoundDeviceWithThread & m_SoundDevice; - - bool m_HasXP; - HMODULE m_hKernel32DLL; - typedef HANDLE (WINAPI *FCreateWaitableTimer)(LPSECURITY_ATTRIBUTES, BOOL, LPCTSTR); - typedef BOOL (WINAPI *FSetWaitableTimer)(HANDLE, const LARGE_INTEGER *, LONG, PTIMERAPCROUTINE, LPVOID, BOOL); - typedef BOOL (WINAPI *FCancelWaitableTimer)(HANDLE); - FCreateWaitableTimer pCreateWaitableTimer; - FSetWaitableTimer pSetWaitableTimer; - FCancelWaitableTimer pCancelWaitableTimer; - - double m_WakeupInterval; - HANDLE m_hAudioWakeUp; - HANDLE m_hPlayThread; - HANDLE m_hAudioThreadTerminateRequest; - HANDLE m_hAudioThreadGoneIdle; - HANDLE m_hHardwareWakeupEvent; - DWORD m_dwPlayThreadId; - LONG m_AudioThreadActive; - static DWORD WINAPI AudioThreadWrapper(LPVOID user); - DWORD AudioThread(); - bool IsActive() { return InterlockedExchangeAdd(&m_AudioThreadActive, 0)?true:false; } -public: - CAudioThread(CSoundDeviceWithThread &SoundDevice); - ~CAudioThread(); - void Activate(); - void Deactivate(); - void SetWakeupEvent(HANDLE ev); - void SetWakeupInterval(double seconds); -}; - - -class CSoundDeviceWithThread : public ISoundDevice -{ - friend class CAudioThread; -protected: - CAudioThread m_AudioThread; -private: - void FillAudioBufferLocked(); -protected: - void SetWakeupEvent(HANDLE ev); - void SetWakeupInterval(double seconds); -public: - CSoundDeviceWithThread(SoundDeviceID id, const std::wstring &internalID) : ISoundDevice(id, internalID), m_AudioThread(*this) {} - virtual ~CSoundDeviceWithThread() {} - bool InternalStart(); - void InternalStop(); - virtual void StartFromSoundThread() = 0; - virtual void StopFromSoundThread() = 0; -}; - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |