diff --git a/VoIPController.cpp b/VoIPController.cpp index 83f6cdd488..1571ddf2ce 100644 --- a/VoIPController.cpp +++ b/VoIPController.cpp @@ -1221,6 +1221,12 @@ void VoIPController::RunTickThread(){ conctl->Tick(); if(state==STATE_ESTABLISHED){ + if((audioInput && !audioInput->IsInitialized()) || (audioOutput && !audioOutput->IsInitialized())){ + LOGE("Audio I/O failed"); + lastError=TGVOIP_ERROR_AUDIO_IO; + SetState(STATE_FAILED); + } + int act=conctl->GetBandwidthControlAction(); if(act==TGVOIP_CONCTL_ACT_DECREASE){ uint32_t bitrate=encoder->GetBitrate(); diff --git a/os/windows/AudioInputWASAPI.cpp b/os/windows/AudioInputWASAPI.cpp index e52837efde..7c665bdd38 100644 --- a/os/windows/AudioInputWASAPI.cpp +++ b/os/windows/AudioInputWASAPI.cpp @@ -9,7 +9,6 @@ #include "AudioInputWASAPI.h" #include "../../logging.h" #include "../../VoIPController.h" -#include #define BUFFER_SIZE 960 #define CHECK_RES(res, msg) {if(FAILED(res)){LOGE("%s failed: HRESULT=0x%08X", msg, res); failed=true; return;}} @@ -50,15 +49,17 @@ AudioInputWASAPI::AudioInputWASAPI(std::string deviceID){ format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; format.wBitsPerSample=16; +#ifdef TGVOIP_WINDOWS_DESKTOP res=CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&enumerator)); CHECK_RES(res, "CoCreateInstance(MMDeviceEnumerator)"); res=enumerator->RegisterEndpointNotificationCallback(this); CHECK_RES(res, "enumerator->RegisterEndpointNotificationCallback"); + audioSessionControl=NULL; + device=NULL; +#endif audioClient=NULL; captureClient=NULL; - audioSessionControl=NULL; - device=NULL; thread=NULL; SetCurrentDevice(deviceID); @@ -69,25 +70,33 @@ AudioInputWASAPI::~AudioInputWASAPI(){ audioClient->Stop(); } +#ifdef TGVOIP_WINDOWS_DESKTOP if(audioSessionControl){ audioSessionControl->UnregisterAudioSessionNotification(this); } +#endif SetEvent(shutdownEvent); if(thread){ - WaitForSingleObject(thread, INFINITE); + WaitForSingleObjectEx(thread, INFINITE, false); CloseHandle(thread); } +#ifdef TGVOIP_WINDOWS_DESKTOP SafeRelease(&audioSessionControl); +#endif SafeRelease(&captureClient); SafeRelease(&audioClient); +#ifdef TGVOIP_WINDOWS_DESKTOP SafeRelease(&device); +#endif CloseHandle(shutdownEvent); CloseHandle(audioSamplesReadyEvent); CloseHandle(streamSwitchEvent); +#ifdef TGVOIP_WINDOWS_DESKTOP if(enumerator) enumerator->UnregisterEndpointNotificationCallback(this); SafeRelease(&enumerator); +#endif } void AudioInputWASAPI::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){ @@ -116,6 +125,7 @@ bool AudioInputWASAPI::IsRecording(){ } void AudioInputWASAPI::EnumerateDevices(std::vector& devs){ +#ifdef TGVOIP_WINDOWS_DESKTOP HRESULT res; res=CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); SCHECK_RES(res, "CoInitializeEx"); @@ -173,6 +183,7 @@ void AudioInputWASAPI::EnumerateDevices(std::vector& d SafeRelease(&deviceCollection); SafeRelease(&deviceEnumerator); +#endif } void AudioInputWASAPI::SetCurrentDevice(std::string deviceID){ @@ -193,14 +204,17 @@ void AudioInputWASAPI::ActuallySetCurrentDevice(std::string deviceID){ CHECK_RES(res, "audioClient->Stop"); } +#ifdef TGVOIP_WINDOWS_DESKTOP if(audioSessionControl){ res=audioSessionControl->UnregisterAudioSessionNotification(this); CHECK_RES(res, "audioSessionControl->UnregisterAudioSessionNotification"); } SafeRelease(&audioSessionControl); +#endif SafeRelease(&captureClient); SafeRelease(&audioClient); +#ifdef TGVOIP_WINDOWS_DESKTOP SafeRelease(&device); IMMDeviceCollection *deviceCollection = NULL; @@ -240,9 +254,22 @@ void AudioInputWASAPI::ActuallySetCurrentDevice(std::string deviceID){ if(deviceCollection) SafeRelease(&deviceCollection); + + if(!device){ + LOGE("Didn't find capture device; failing"); + failed=true; + return; + } res=device->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, (void**)&audioClient); CHECK_RES(res, "device->Activate"); +#else + Platform::String^ defaultDevID=Windows::Media::Devices::MediaDevice::GetDefaultAudioCaptureId(Windows::Media::Devices::AudioDeviceRole::Communications); + HRESULT res1, res2; + audioClient=WindowsSandboxUtils::ActivateAudioDevice(defaultDevID->Data(), &res1, &res2); + CHECK_RES(res1, "activate1"); + CHECK_RES(res2, "activate2"); +#endif res = audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST | 0x80000000/*AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM*/, 60 * 10000, 0, &format, NULL); CHECK_RES(res, "audioClient->Initialize"); @@ -259,11 +286,13 @@ void AudioInputWASAPI::ActuallySetCurrentDevice(std::string deviceID){ res = audioClient->GetService(IID_PPV_ARGS(&captureClient)); CHECK_RES(res, "audioClient->GetService"); +#ifdef TGVOIP_WINDOWS_DESKTOP res=audioClient->GetService(IID_PPV_ARGS(&audioSessionControl)); CHECK_RES(res, "audioClient->GetService(IAudioSessionControl)"); res=audioSessionControl->RegisterAudioSessionNotification(this); CHECK_RES(res, "audioSessionControl->RegisterAudioSessionNotification"); +#endif if(isRecording) audioClient->Start(); @@ -283,15 +312,13 @@ void AudioInputWASAPI::RunThread() { HRESULT res=CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); CHECK_RES(res, "CoInitializeEx in capture thread"); - uint32_t bufferSize; - res=audioClient->GetBufferSize(&bufferSize); - CHECK_RES(res, "audioClient->GetBufferSize"); + uint32_t bufferSize=0; uint32_t framesWritten=0; bool running=true; while(running){ - DWORD waitResult=WaitForMultipleObjects(3, waitArray, false, INFINITE); + DWORD waitResult=WaitForMultipleObjectsEx(3, waitArray, false, INFINITE, false); if(waitResult==WAIT_OBJECT_0){ // shutdownEvent LOGV("capture thread shutting down"); running=false; @@ -299,8 +326,13 @@ void AudioInputWASAPI::RunThread() { LOGV("stream switch"); ActuallySetCurrentDevice(streamChangeToDevice); ResetEvent(streamSwitchEvent); + bufferSize=0; LOGV("stream switch done"); }else if(waitResult==WAIT_OBJECT_0+2){ // audioSamplesReadyEvent + if(bufferSize==0){ + res=audioClient->GetBufferSize(&bufferSize); + CHECK_RES(res, "audioClient->GetBufferSize"); + } BYTE* data; uint32_t framesAvailable; DWORD flags; @@ -326,6 +358,7 @@ void AudioInputWASAPI::RunThread() { } } +#ifdef TGVOIP_WINDOWS_DESKTOP HRESULT AudioInputWASAPI::OnSessionDisconnected(AudioSessionDisconnectReason reason) { if(!isDefaultDevice){ streamChangeToDevice="default"; @@ -370,4 +403,5 @@ HRESULT AudioInputWASAPI::QueryInterface(REFIID iid, void** obj){ } return S_OK; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/os/windows/AudioInputWASAPI.h b/os/windows/AudioInputWASAPI.h index f8273810a3..705546d668 100644 --- a/os/windows/AudioInputWASAPI.h +++ b/os/windows/AudioInputWASAPI.h @@ -7,20 +7,38 @@ #ifndef LIBTGVOIP_AUDIOINPUTWASAPI_H #define LIBTGVOIP_AUDIOINPUTWASAPI_H +#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP +#define TGVOIP_WINDOWS_PHONE +#endif +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY==WINAPI_FAMILY_DESKTOP_APP +#define TGVOIP_WINDOWS_DESKTOP +#endif + #include #include #include #pragma warning(push) #pragma warning(disable : 4201) #include +#ifdef TGVOIP_WINDOWS_DESKTOP #include +#include +#else +#include +#include "WindowsSandboxUtils.h" +#endif #pragma warning(pop) #include "../../audio/AudioInput.h" namespace tgvoip{ namespace audio{ +#ifdef TGVOIP_WINDOWS_DESKTOP class AudioInputWASAPI : public AudioInput, IMMNotificationClient, IAudioSessionEvents{ +#else +class AudioInputWASAPI : public AudioInput{ +#endif + public: AudioInputWASAPI(std::string deviceID); virtual ~AudioInputWASAPI(); @@ -45,15 +63,18 @@ private: HANDLE thread; IAudioClient* audioClient; IAudioCaptureClient* captureClient; +#ifdef TGVOIP_WINDOWS_DESKTOP IMMDeviceEnumerator* enumerator; IAudioSessionControl* audioSessionControl; IMMDevice* device; +#endif unsigned char remainingData[10240]; size_t remainingDataLen; bool isDefaultDevice; ULONG refCount; std::string streamChangeToDevice; +#ifdef TGVOIP_WINDOWS_DESKTOP STDMETHOD(OnDisplayNameChanged) (LPCWSTR /*NewDisplayName*/, LPCGUID /*EventContext*/) { return S_OK; }; STDMETHOD(OnIconPathChanged) (LPCWSTR /*NewIconPath*/, LPCGUID /*EventContext*/) { return S_OK; }; STDMETHOD(OnSimpleVolumeChanged) (float /*NewSimpleVolume*/, BOOL /*NewMute*/, LPCGUID /*EventContext*/) { return S_OK; } @@ -71,6 +92,7 @@ private: // IUnknown // STDMETHOD(QueryInterface)(REFIID iid, void **pvObject); +#endif }; } diff --git a/os/windows/AudioOutputWASAPI.cpp b/os/windows/AudioOutputWASAPI.cpp index c2f08be887..3f86415e9c 100644 --- a/os/windows/AudioOutputWASAPI.cpp +++ b/os/windows/AudioOutputWASAPI.cpp @@ -9,7 +9,6 @@ #include "AudioOutputWASAPI.h" #include "../../logging.h" #include "../../VoIPController.h" -#include #define BUFFER_SIZE 960 #define CHECK_RES(res, msg) {if(FAILED(res)){LOGE("%s failed: HRESULT=0x%08X", msg, res); failed=true; return;}} @@ -54,15 +53,17 @@ AudioOutputWASAPI::AudioOutputWASAPI(std::string deviceID){ format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; format.wBitsPerSample=16; +#ifdef TGVOIP_WINDOWS_DESKTOP res=CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&enumerator)); CHECK_RES(res, "CoCreateInstance(MMDeviceEnumerator)"); res=enumerator->RegisterEndpointNotificationCallback(this); CHECK_RES(res, "enumerator->RegisterEndpointNotificationCallback"); + audioSessionControl=NULL; + device=NULL; +#endif audioClient=NULL; renderClient=NULL; - audioSessionControl=NULL; - device=NULL; thread=NULL; SetCurrentDevice(deviceID); @@ -73,25 +74,31 @@ AudioOutputWASAPI::~AudioOutputWASAPI(){ audioClient->Stop(); } +#ifdef TGVOIP_WINDOWS_DESKTOP if(audioSessionControl){ audioSessionControl->UnregisterAudioSessionNotification(this); } +#endif SetEvent(shutdownEvent); if(thread){ - WaitForSingleObject(thread, INFINITE); + WaitForSingleObjectEx(thread, INFINITE, false); CloseHandle(thread); } - SafeRelease(&audioSessionControl); SafeRelease(&renderClient); SafeRelease(&audioClient); +#ifdef TGVOIP_WINDOWS_DESKTOP SafeRelease(&device); + SafeRelease(&audioSessionControl); +#endif CloseHandle(shutdownEvent); CloseHandle(audioSamplesReadyEvent); CloseHandle(streamSwitchEvent); +#ifdef TGVOIP_WINDOWS_DESKTOP if(enumerator) enumerator->UnregisterEndpointNotificationCallback(this); SafeRelease(&enumerator); +#endif } void AudioOutputWASAPI::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){ @@ -120,6 +127,7 @@ bool AudioOutputWASAPI::IsPlaying(){ } void AudioOutputWASAPI::EnumerateDevices(std::vector& devs){ +#ifdef TGVOIP_WINDOWS_DESKTOP HRESULT res; res=CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); SCHECK_RES(res, "CoInitializeEx"); @@ -177,6 +185,7 @@ void AudioOutputWASAPI::EnumerateDevices(std::vector& SafeRelease(&deviceCollection); SafeRelease(&deviceEnumerator); +#endif } void AudioOutputWASAPI::SetCurrentDevice(std::string deviceID){ @@ -197,16 +206,20 @@ void AudioOutputWASAPI::ActuallySetCurrentDevice(std::string deviceID){ CHECK_RES(res, "audioClient->Stop"); } +#ifdef TGVOIP_WINDOWS_DESKTOP if(audioSessionControl){ res=audioSessionControl->UnregisterAudioSessionNotification(this); CHECK_RES(res, "audioSessionControl->UnregisterAudioSessionNotification"); } SafeRelease(&audioSessionControl); +#endif SafeRelease(&renderClient); SafeRelease(&audioClient); +#ifdef TGVOIP_WINDOWS_DESKTOP SafeRelease(&device); + IMMDeviceCollection *deviceCollection = NULL; if(deviceID=="default"){ @@ -243,9 +256,22 @@ void AudioOutputWASAPI::ActuallySetCurrentDevice(std::string deviceID){ if(deviceCollection) SafeRelease(&deviceCollection); + + if(!device){ + LOGE("Didn't find playback device; failing"); + failed=true; + return; + } res=device->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, (void**)&audioClient); CHECK_RES(res, "device->Activate"); +#else + Platform::String^ defaultDevID=Windows::Media::Devices::MediaDevice::GetDefaultAudioRenderId(Windows::Media::Devices::AudioDeviceRole::Communications); + HRESULT res1, res2; + audioClient=WindowsSandboxUtils::ActivateAudioDevice(defaultDevID->Data(), &res1, &res2); + CHECK_RES(res1, "activate1"); + CHECK_RES(res2, "activate2"); +#endif res = audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST | 0x80000000/*AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM*/, 60 * 10000, 0, &format, NULL); CHECK_RES(res, "audioClient->Initialize"); @@ -269,11 +295,13 @@ void AudioOutputWASAPI::ActuallySetCurrentDevice(std::string deviceID){ res = renderClient->ReleaseBuffer(bufSize, AUDCLNT_BUFFERFLAGS_SILENT); CHECK_RES(res, "renderClient->ReleaseBuffer"); +#ifdef TGVOIP_WINDOWS_DESKTOP res=audioClient->GetService(IID_PPV_ARGS(&audioSessionControl)); CHECK_RES(res, "audioClient->GetService(IAudioSessionControl)"); res=audioSessionControl->RegisterAudioSessionNotification(this); CHECK_RES(res, "audioSessionControl->RegisterAudioSessionNotification"); +#endif if(isPlaying) audioClient->Start(); @@ -301,7 +329,7 @@ void AudioOutputWASAPI::RunThread() { bool running=true; while(running){ - DWORD waitResult=WaitForMultipleObjects(3, waitArray, false, INFINITE); + DWORD waitResult=WaitForMultipleObjectsEx(3, waitArray, false, INFINITE, false); if(waitResult==WAIT_OBJECT_0){ // shutdownEvent LOGV("render thread shutting down"); running=false; @@ -338,6 +366,7 @@ void AudioOutputWASAPI::RunThread() { } } +#ifdef TGVOIP_WINDOWS_DESKTOP HRESULT AudioOutputWASAPI::OnSessionDisconnected(AudioSessionDisconnectReason reason) { if(!isDefaultDevice){ streamChangeToDevice="default"; @@ -382,4 +411,5 @@ HRESULT AudioOutputWASAPI::QueryInterface(REFIID iid, void** obj){ } return S_OK; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/os/windows/AudioOutputWASAPI.h b/os/windows/AudioOutputWASAPI.h index 07385a8961..80caaab63e 100644 --- a/os/windows/AudioOutputWASAPI.h +++ b/os/windows/AudioOutputWASAPI.h @@ -7,20 +7,37 @@ #ifndef LIBTGVOIP_AUDIOOUTPUTWASAPI_H #define LIBTGVOIP_AUDIOOUTPUTWASAPI_H +#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP +#define TGVOIP_WINDOWS_PHONE +#endif +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY==WINAPI_FAMILY_DESKTOP_APP +#define TGVOIP_WINDOWS_DESKTOP +#endif + #include #include #include #pragma warning(push) #pragma warning(disable : 4201) #include +#ifdef TGVOIP_WINDOWS_DESKTOP #include +#include +#else +#include +#include "WindowsSandboxUtils.h" +#endif #pragma warning(pop) #include "../../audio/AudioOutput.h" namespace tgvoip{ namespace audio{ +#ifdef TGVOIP_WINDOWS_DESKTOP class AudioOutputWASAPI : public AudioOutput, IMMNotificationClient, IAudioSessionEvents{ +#else +class AudioOutputWASAPI : public AudioOutput{ +#endif public: AudioOutputWASAPI(std::string deviceID); virtual ~AudioOutputWASAPI(); @@ -45,15 +62,18 @@ private: HANDLE thread; IAudioClient* audioClient; IAudioRenderClient* renderClient; +#ifdef TGVOIP_WINDOWS_DESKTOP IMMDeviceEnumerator* enumerator; IAudioSessionControl* audioSessionControl; IMMDevice* device; +#endif unsigned char remainingData[10240]; size_t remainingDataLen; bool isDefaultDevice; ULONG refCount; std::string streamChangeToDevice; +#ifdef TGVOIP_WINDOWS_DESKTOP STDMETHOD(OnDisplayNameChanged) (LPCWSTR /*NewDisplayName*/, LPCGUID /*EventContext*/) { return S_OK; }; STDMETHOD(OnIconPathChanged) (LPCWSTR /*NewIconPath*/, LPCGUID /*EventContext*/) { return S_OK; }; STDMETHOD(OnSimpleVolumeChanged) (float /*NewSimpleVolume*/, BOOL /*NewMute*/, LPCGUID /*EventContext*/) { return S_OK; } @@ -71,6 +91,7 @@ private: // IUnknown // STDMETHOD(QueryInterface)(REFIID iid, void **pvObject); +#endif }; } diff --git a/os/windows/WindowsSandboxUtils.cpp b/os/windows/WindowsSandboxUtils.cpp new file mode 100644 index 0000000000..73df353950 --- /dev/null +++ b/os/windows/WindowsSandboxUtils.cpp @@ -0,0 +1,39 @@ + +// +// libtgvoip is free and unencumbered public domain software. +// For more information, see http://unlicense.org or the UNLICENSE file +// you should have received with this source code distribution. +// + +#include "WindowsSandboxUtils.h" +#include +#include +#include + +using namespace tgvoip; +using namespace Microsoft::WRL; + +IAudioClient* WindowsSandboxUtils::ActivateAudioDevice(const wchar_t* devID, HRESULT* callRes, HRESULT* actRes){ + // Did I say that I hate pointlessly asynchronous things? + HANDLE event = CreateEventEx(NULL, NULL, 0, 0); + ActivationHandler activationHandler(event); + Windows::ApplicationModel::Core::CoreApplication::GetCurrentView()->CoreWindow->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([devID, callRes, actRes, activationHandler](){ + ComPtr actHandler; + Platform::String^ sel=Windows::Media::Devices::MediaDevice::GetDefaultAudioRenderId(Windows::Media::Devices::AudioDeviceRole::Communications); + HRESULT cr=ActivateAudioInterfaceAsync(sel->Data(), __uuidof(IAudioClient), NULL, (IActivateAudioInterfaceCompletionHandler*)&activationHandler, &actHandler); + if(callRes) + *callRes=cr; + })); + WaitForSingleObjectEx(event, INFINITE, false); + CloseHandle(event); + if(actRes) + *actRes=activationHandler.actResult; + return activationHandler.client; +} + +STDMETHODIMP ActivationHandler::ActivateCompleted(IActivateAudioInterfaceAsyncOperation* op){ + HRESULT res = op->GetActivateResult(&actResult, (IUnknown**)&client); + SetEvent(event); + + return S_OK; +} diff --git a/os/windows/WindowsSandboxUtils.h b/os/windows/WindowsSandboxUtils.h new file mode 100644 index 0000000000..c040f93083 --- /dev/null +++ b/os/windows/WindowsSandboxUtils.h @@ -0,0 +1,29 @@ + +// +// libtgvoip is free and unencumbered public domain software. +// For more information, see http://unlicense.org or the UNLICENSE file +// you should have received with this source code distribution. +// + +#include +#include + +namespace tgvoip{ + +using namespace Microsoft::WRL; + +class ActivationHandler : public RuntimeClass< RuntimeClassFlags< ClassicCom >, FtmBase, IActivateAudioInterfaceCompletionHandler >{ +public: + ActivationHandler(HANDLE _event); + STDMETHOD(ActivateCompleted)(IActivateAudioInterfaceAsyncOperation* op); + HANDLE event; + IAudioClient* client; + HRESULT actResult; +}; + + +class WindowsSandboxUtils{ +public: + static IAudioClient* ActivateAudioDevice(const wchar_t* devID, HRESULT* callResult, HRESULT* actResult); +}; +} diff --git a/threading.h b/threading.h index 25ed676fec..ae5ea49b57 100644 --- a/threading.h +++ b/threading.h @@ -118,12 +118,20 @@ typedef HANDLE tgvoip_lock_t; // uncomment for XP compatibility //typedef CONDITION_VARIABLE tgvoip_lock_t; #define start_thread(ref, entry, arg) (ref=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)entry, arg, 0, NULL)) +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY!=WINAPI_FAMILY_PHONE_APP #define join_thread(thread) {WaitForSingleObject(thread, INFINITE); CloseHandle(thread);} +#else +#define join_thread(thread) {WaitForSingleObjectEx(thread, INFINITE, false); CloseHandle(thread);} +#endif #define set_thread_name(thread, name) // threads in Windows don't have names #define set_thread_priority(thread, priority) SetThreadPriority(thread, priority) #define get_thread_max_priority() THREAD_PRIORITY_HIGHEST #define get_thread_min_priority() THREAD_PRIORITY_LOWEST +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY!=WINAPI_FAMILY_PHONE_APP #define init_mutex(mutex) InitializeCriticalSection(&mutex) +#else +#define init_mutex(mutex) InitializeCriticalSectionEx(&mutex, 0, 0) +#endif #define free_mutex(mutex) DeleteCriticalSection(&mutex) #define lock_mutex(mutex) EnterCriticalSection(&mutex) #define unlock_mutex(mutex) LeaveCriticalSection(&mutex) @@ -140,7 +148,11 @@ namespace tgvoip{ class Semaphore{ public: Semaphore(unsigned int maxCount, unsigned int initValue){ +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY!=WINAPI_FAMILY_PHONE_APP h=CreateSemaphore(NULL, initValue, maxCount, NULL); +#else + h=CreateSemaphoreEx(NULL, initValue, maxCount, NULL, 0, 0); +#endif } ~Semaphore(){ @@ -148,7 +160,11 @@ public: } void Acquire(){ +#if !defined(WINAPI_FAMILY) || WINAPI_FAMILY!=WINAPI_FAMILY_PHONE_APP WaitForSingleObject(h, INFINITE); +#else + WaitForSingleObjectEx(h, INFINITE, false); +#endif } void Release(){