From 529a3bf14f8af05725be7d603f1e609026fc311b Mon Sep 17 00:00:00 2001 From: Grishka Date: Tue, 7 Aug 2018 23:10:31 +0300 Subject: [PATCH] 2.2.2: more fixes - Probable fix for a mysterious crash in WASAPI - Hopefully fixes telegramdesktop/tdesktop/4219 by setting PA stream role and bypassing filters - Outgoing packet queue now uses Buffer instead of BufferPool --- BlockingQueue.h | 12 +- Buffers.h | 5 +- VoIPController.cpp | 218 +++++++++++++------------------ VoIPController.h | 6 +- os/linux/AudioInputPulse.cpp | 5 +- os/linux/AudioOutputPulse.cpp | 10 +- os/linux/AudioPulse.cpp | 17 ++- os/linux/AudioPulse.h | 7 +- os/linux/PulseFunctions.h | 6 +- os/windows/AudioInputWASAPI.cpp | 6 +- os/windows/AudioOutputWASAPI.cpp | 6 +- threading.h | 10 +- 12 files changed, 152 insertions(+), 156 deletions(-) diff --git a/BlockingQueue.h b/BlockingQueue.h index 92fa318..0184348 100644 --- a/BlockingQueue.h +++ b/BlockingQueue.h @@ -29,12 +29,12 @@ public: void Put(T thing){ MutexGuard sync(mutex); - queue.push_back(thing); + queue.push_back(std::move(thing)); bool didOverflow=false; while(queue.size()>capacity){ didOverflow=true; if(overflowCallback){ - overflowCallback(queue.front()); + overflowCallback(std::move(queue.front())); queue.pop_front(); }else{ abort(); @@ -47,16 +47,14 @@ public: T GetBlocking(){ semaphore.Acquire(); MutexGuard sync(mutex); - T r=GetInternal(); - return r; + return GetInternal(); } T Get(){ MutexGuard sync(mutex); if(queue.size()>0) semaphore.Acquire(); - T r=GetInternal(); - return r; + return GetInternal(); } unsigned int Size(){ @@ -75,7 +73,7 @@ private: T GetInternal(){ //if(queue.size()==0) // return NULL; - T r=queue.front(); + T r=std::move(queue.front()); queue.pop_front(); return r; } diff --git a/Buffers.h b/Buffers.h index 4b5042c..94fe512 100644 --- a/Buffers.h +++ b/Buffers.h @@ -90,7 +90,10 @@ namespace tgvoip{ class Buffer{ public: Buffer(size_t capacity){ - data=(unsigned char *) malloc(capacity); + if(capacity>0) + data=(unsigned char *) malloc(capacity); + else + data=NULL; length=capacity; }; Buffer(const Buffer& other)=delete; diff --git a/VoIPController.cpp b/VoIPController.cpp index f78357a..fbb1915 100644 --- a/VoIPController.cpp +++ b/VoIPController.cpp @@ -122,7 +122,6 @@ extern FILE* tgvoipLogFile; VoIPController::VoIPController() : activeNetItfName(""), currentAudioInput("default"), currentAudioOutput("default"), - outgoingPacketsBufferPool(1024, 20), proxyAddress(""), proxyUsername(""), proxyPassword(""){ @@ -411,58 +410,48 @@ void VoIPController::HandleAudioInput(unsigned char *data, size_t len, unsigned } //LOGV("Audio packet size %u", (unsigned int)len); - unsigned char* buf=outgoingPacketsBufferPool.Get(); - if(buf){ - BufferOutputStream pkt(buf, outgoingPacketsBufferPool.GetSingleBufferSize()); + BufferOutputStream pkt(1500); - unsigned char flags=(unsigned char) (len>255 ? STREAM_DATA_FLAG_LEN16 : 0); - pkt.WriteByte((unsigned char) (1 | flags)); // streamID + flags - if(len>255) - pkt.WriteInt16((int16_t) len); - else - pkt.WriteByte((unsigned char) len); - pkt.WriteInt32(audioTimestampOut); - pkt.WriteBytes(data, len); + unsigned char flags=(unsigned char) (len>255 ? STREAM_DATA_FLAG_LEN16 : 0); + pkt.WriteByte((unsigned char) (1 | flags)); // streamID + flags + if(len>255) + pkt.WriteInt16((int16_t) len); + else + pkt.WriteByte((unsigned char) len); + pkt.WriteInt32(audioTimestampOut); + pkt.WriteBytes(data, len); - PendingOutgoingPacket p{ - /*.seq=*/GenerateOutSeq(), - /*.type=*/PKT_STREAM_DATA, - /*.len=*/pkt.GetLength(), - /*.data=*/buf, - /*.endpoint=*/0, - }; - sendQueue->Put(p); - }else{ - LOGW("Out of outgoing packet buffers!"); - } + PendingOutgoingPacket p{ + /*.seq=*/GenerateOutSeq(), + /*.type=*/PKT_STREAM_DATA, + /*.len=*/pkt.GetLength(), + /*.data=*/Buffer(move(pkt)), + /*.endpoint=*/0, + }; + sendQueue->Put(move(p)); if(secondaryData && secondaryLen && shittyInternetMode){ Buffer ecBuf(secondaryLen); ecBuf.CopyFrom(secondaryData, 0, secondaryLen); ecAudioPackets.push_back(move(ecBuf)); while(ecAudioPackets.size()>4) ecAudioPackets.erase(ecAudioPackets.begin()); - buf=outgoingPacketsBufferPool.Get(); - if(buf){ - BufferOutputStream pkt(buf, outgoingPacketsBufferPool.GetSingleBufferSize()); - pkt.WriteByte(outgoingStreams[0]->id); - pkt.WriteInt32(audioTimestampOut); - pkt.WriteByte((unsigned char)ecAudioPackets.size()); - for(Buffer& ecData:ecAudioPackets){ - pkt.WriteByte((unsigned char)ecData.Length()); - pkt.WriteBytes(ecData); - } - - PendingOutgoingPacket p{ - GenerateOutSeq(), - PKT_STREAM_EC, - pkt.GetLength(), - buf, - 0 - }; - sendQueue->Put(p); - }else{ - LOGW("Out of outgoing packet buffers!"); + pkt=BufferOutputStream(1500); + pkt.WriteByte(outgoingStreams[0]->id); + pkt.WriteInt32(audioTimestampOut); + pkt.WriteByte((unsigned char)ecAudioPackets.size()); + for(Buffer& ecData:ecAudioPackets){ + pkt.WriteByte((unsigned char)ecData.Length()); + pkt.WriteBytes(ecData); } + + PendingOutgoingPacket p{ + GenerateOutSeq(), + PKT_STREAM_EC, + pkt.GetLength(), + Buffer(move(pkt)), + 0 + }; + sendQueue->Put(move(p)); } audioTimestampOut+=outgoingStreams[0]->frameDuration; @@ -685,12 +674,7 @@ void VoIPController::SendInit(){ for(shared_ptr& e:endpoints){ if(e->type==Endpoint::TYPE_TCP_RELAY && !useTCP) continue; - unsigned char *pkt=outgoingPacketsBufferPool.Get(); - if(!pkt){ - LOGW("can't send init, queue overflow"); - continue; - } - BufferOutputStream out(pkt, outgoingPacketsBufferPool.GetSingleBufferSize()); + BufferOutputStream out(1024); out.WriteInt32(PROTOCOL_VERSION); out.WriteInt32(MIN_PROTOCOL_VERSION); uint32_t flags=0; @@ -722,7 +706,7 @@ void VoIPController::SendInit(){ /*.seq=*/initSeq, /*.type=*/PKT_INIT, /*.len=*/out.GetLength(), - /*.data=*/pkt, + /*.data=*/Buffer(move(out)), /*.endpoint=*/e->id }); } @@ -899,7 +883,7 @@ void VoIPController::RunSendThread(void* arg){ unsigned char buf[1500]; while(runReceiver){ PendingOutgoingPacket pkt=sendQueue->GetBlocking(); - if(pkt.data){ + //if(pkt.data.Length()){ shared_ptr endpoint; if(pkt.endpoint){ endpoint=GetEndpointByID(pkt.endpoint); @@ -910,13 +894,12 @@ void VoIPController::RunSendThread(void* arg){ if((endpoint->type==Endpoint::TYPE_TCP_RELAY && useTCP) || (endpoint->type!=Endpoint::TYPE_TCP_RELAY && useUDP)){ BufferOutputStream p(buf, sizeof(buf)); WritePacketHeader(pkt.seq, &p, pkt.type, (uint32_t)pkt.len); - p.WriteBytes(pkt.data, pkt.len); + p.WriteBytes(pkt.data); SendPacket(p.GetBuffer(), p.GetLength(), endpoint, pkt); } - outgoingPacketsBufferPool.Reuse(pkt.data); - }else{ - LOGE("tried to send null packet"); - } + //}else{ + // LOGE("tried to send null packet"); + //} } LOGI("=== send thread exiting ==="); } @@ -1357,33 +1340,29 @@ simpleAudioBlock random_id:long random_bytes:string raw_data:string = DecryptedA in.ReadInt32(); } - unsigned char *buf=outgoingPacketsBufferPool.Get(); - if(buf){ - BufferOutputStream out(buf, outgoingPacketsBufferPool.GetSingleBufferSize()); - //WritePacketHeader(out, PKT_INIT_ACK, (peerVersion>=2 ? 10 : 2)+(peerVersion>=2 ? 6 : 4)*outgoingStreams.size()); + BufferOutputStream out(1024); - out.WriteInt32(PROTOCOL_VERSION); - out.WriteInt32(MIN_PROTOCOL_VERSION); + out.WriteInt32(PROTOCOL_VERSION); + out.WriteInt32(MIN_PROTOCOL_VERSION); - out.WriteByte((unsigned char) outgoingStreams.size()); - for(vector>::iterator s=outgoingStreams.begin(); s!=outgoingStreams.end(); ++s){ - out.WriteByte((*s)->id); - out.WriteByte((*s)->type); - if(peerVersion<5) - out.WriteByte((unsigned char) ((*s)->codec==CODEC_OPUS ? CODEC_OPUS_OLD : 0)); - else - out.WriteInt32((*s)->codec); - out.WriteInt16((*s)->frameDuration); - out.WriteByte((unsigned char) ((*s)->enabled ? 1 : 0)); - } - sendQueue->Put(PendingOutgoingPacket{ - /*.seq=*/GenerateOutSeq(), - /*.type=*/PKT_INIT_ACK, - /*.len=*/out.GetLength(), - /*.data=*/buf, - /*.endpoint=*/0 - }); + out.WriteByte((unsigned char) outgoingStreams.size()); + for(vector>::iterator s=outgoingStreams.begin(); s!=outgoingStreams.end(); ++s){ + out.WriteByte((*s)->id); + out.WriteByte((*s)->type); + if(peerVersion<5) + out.WriteByte((unsigned char) ((*s)->codec==CODEC_OPUS ? CODEC_OPUS_OLD : 0)); + else + out.WriteInt32((*s)->codec); + out.WriteInt16((*s)->frameDuration); + out.WriteByte((unsigned char) ((*s)->enabled ? 1 : 0)); } + sendQueue->Put(PendingOutgoingPacket{ + /*.seq=*/GenerateOutSeq(), + /*.type=*/PKT_INIT_ACK, + /*.len=*/out.GetLength(), + /*.data=*/Buffer(move(out)), + /*.endpoint=*/0 + }); } } if(type==PKT_INIT_ACK){ @@ -1527,18 +1506,13 @@ simpleAudioBlock random_id:long random_bytes:string raw_data:string = DecryptedA LOGW("Received p2p ping but p2p is disabled by manual override"); return; } - unsigned char* buf=outgoingPacketsBufferPool.Get(); - if(!buf){ - LOGW("Dropping pong packet, queue overflow"); - return; - } - BufferOutputStream pkt(buf, outgoingPacketsBufferPool.GetSingleBufferSize()); + BufferOutputStream pkt(128); pkt.WriteInt32(pseq); sendQueue->Put(PendingOutgoingPacket{ /*.seq=*/GenerateOutSeq(), /*.type=*/PKT_PONG, /*.len=*/pkt.GetLength(), - /*.data=*/buf, + /*.data=*/Buffer(move(pkt)), /*.endpoint=*/srcEndpoint->id, }); } @@ -2846,16 +2820,13 @@ void VoIPController::SendRelayPings(){ continue; if(GetCurrentTime()-endpoint->lastPingTime>=10){ LOGV("Sending ping to %s", endpoint->GetAddress().ToString().c_str()); - unsigned char* buf=outgoingPacketsBufferPool.Get(); - if(buf){ - sendQueue->Put(PendingOutgoingPacket{ - /*.seq=*/(endpoint->lastPingSeq=GenerateOutSeq()), - /*.type=*/PKT_PING, - /*.len=*/0, - /*.data=*/buf, - /*.endpoint=*/endpoint->id - }); - } + sendQueue->Put(PendingOutgoingPacket{ + /*.seq=*/(endpoint->lastPingSeq=GenerateOutSeq()), + /*.type=*/PKT_PING, + /*.len=*/0, + /*.data=*/Buffer(), + /*.endpoint=*/endpoint->id + }); endpoint->lastPingTime=GetCurrentTime(); } if(endpoint->type==Endpoint::TYPE_UDP_RELAY || (useTCP && endpoint->type==Endpoint::TYPE_TCP_RELAY)){ @@ -3086,40 +3057,35 @@ void VoIPController::UpdateQueuedPackets(){ } if(GetCurrentTime()-qp->lastSentTime>=qp->retryInterval){ messageThread.Post(std::bind(&VoIPController::UpdateQueuedPackets, this), qp->retryInterval); - unsigned char *buf=outgoingPacketsBufferPool.Get(); - if(buf){ - uint32_t seq=GenerateOutSeq(); - qp->seqs.Add(seq); - qp->lastSentTime=GetCurrentTime(); - //LOGD("Sending queued packet, seq=%u, type=%u, len=%u", seq, qp.type, qp.data.Length()); - if(qp->firstSentTime==0) - qp->firstSentTime=qp->lastSentTime; - if(qp->data.Length()) - memcpy(buf, *qp->data, qp->data.Length()); - sendQueue->Put(PendingOutgoingPacket{ - /*.seq=*/seq, - /*.type=*/qp->type, - /*.len=*/qp->data.Length(), - /*.data=*/buf, - /*.endpoint=*/0 - }); - } + uint32_t seq=GenerateOutSeq(); + qp->seqs.Add(seq); + qp->lastSentTime=GetCurrentTime(); + //LOGD("Sending queued packet, seq=%u, type=%u, len=%u", seq, qp.type, qp.data.Length()); + Buffer buf(qp->data.Length()); + if(qp->firstSentTime==0) + qp->firstSentTime=qp->lastSentTime; + if(qp->data.Length()) + buf.CopyFrom(qp->data, qp->data.Length()); + sendQueue->Put(PendingOutgoingPacket{ + /*.seq=*/seq, + /*.type=*/qp->type, + /*.len=*/qp->data.Length(), + /*.data=*/move(buf), + /*.endpoint=*/0 + }); } ++qp; } } void VoIPController::SendNopPacket(){ - unsigned char* buf=outgoingPacketsBufferPool.Get(); - if(buf){ - sendQueue->Put(PendingOutgoingPacket{ - /*.seq=*/(firstSentPing=GenerateOutSeq()), - /*.type=*/PKT_NOP, - /*.len=*/0, - /*.data=*/buf, - /*.endpoint=*/0 - }); - } + sendQueue->Put(PendingOutgoingPacket{ + /*.seq=*/(firstSentPing=GenerateOutSeq()), + /*.type=*/PKT_NOP, + /*.len=*/0, + /*.data=*/Buffer(), + /*.endpoint=*/0 + }); } void VoIPController::SendPublicEndpointsRequest(){ diff --git a/VoIPController.h b/VoIPController.h index 8f7148e..031c30d 100644 --- a/VoIPController.h +++ b/VoIPController.h @@ -34,7 +34,7 @@ #include "PacketReassembler.h" #include "MessageThread.h" -#define LIBTGVOIP_VERSION "2.2.1" +#define LIBTGVOIP_VERSION "2.2.2" #ifdef _WIN32 #undef GetCurrentTime @@ -384,9 +384,8 @@ namespace tgvoip{ struct PendingOutgoingPacket{ uint32_t seq; unsigned char type; - //Buffer data; size_t len; - unsigned char* data; + Buffer data; int64_t endpoint; }; struct SegmentedPacket{ @@ -554,7 +553,6 @@ namespace tgvoip{ NetworkSocket* openingTcpSocket; HistoricBuffer signalBarsHistory; - BufferPool outgoingPacketsBufferPool; int udpConnectivityState; double lastUdpPingTime; int udpPingCount; diff --git a/os/linux/AudioInputPulse.cpp b/os/linux/AudioInputPulse.cpp index 3bcabe8..f54f49b 100644 --- a/os/linux/AudioInputPulse.cpp +++ b/os/linux/AudioInputPulse.cpp @@ -39,7 +39,10 @@ AudioInputPulse::AudioInputPulse(pa_context* context, pa_threaded_mainloop* main .channels=1 }; - stream=pa_stream_new(context, "libtgvoip capture", &sample_specifications, NULL); + pa_proplist* proplist=pa_proplist_new(); + pa_proplist_sets(proplist, PA_PROP_FILTER_APPLY, ""); // according to PA sources, this disables any possible filters + stream=pa_stream_new_with_proplist(context, "libtgvoip capture", &sample_specifications, NULL, proplist); + pa_proplist_free(proplist); if(!stream){ LOGE("Error initializing PulseAudio (pa_stream_new)"); failed=true; diff --git a/os/linux/AudioOutputPulse.cpp b/os/linux/AudioOutputPulse.cpp index 33568dd..cb3fb83 100644 --- a/os/linux/AudioOutputPulse.cpp +++ b/os/linux/AudioOutputPulse.cpp @@ -41,7 +41,10 @@ AudioOutputPulse::AudioOutputPulse(pa_context* context, pa_threaded_mainloop* ma }; pa_threaded_mainloop_lock(mainloop); - stream=pa_stream_new(context, "libtgvoip playback", &sample_specifications, NULL); + pa_proplist* proplist=pa_proplist_new(); + pa_proplist_sets(proplist, PA_PROP_FILTER_APPLY, ""); // according to PA sources, this disables any possible filters + stream=pa_stream_new_with_proplist(context, "libtgvoip playback", &sample_specifications, NULL, proplist); + pa_proplist_free(proplist); if(!stream){ LOGE("Error initializing PulseAudio (pa_stream_new)"); pa_threaded_mainloop_unlock(mainloop); @@ -154,7 +157,10 @@ void AudioOutputPulse::StreamWriteCallback(pa_stream *stream, size_t requestedBy } void AudioOutputPulse::StreamWriteCallback(pa_stream *stream, size_t requestedBytes) { - assert(requestedBytes<=sizeof(remainingData)); + //assert(requestedBytes<=sizeof(remainingData)); + if(requestedBytes>sizeof(remainingData)){ + requestedBytes=960*2; // force buffer size to 20ms. This probably wrecks the jitter buffer, but still better than crashing + } while(requestedBytes>remainingDataSize){ if(isPlaying){ InvokeCallback(remainingData+remainingDataSize, 960*2); diff --git a/os/linux/AudioPulse.cpp b/os/linux/AudioPulse.cpp index 0ee3bc8..4265d35 100644 --- a/os/linux/AudioPulse.cpp +++ b/os/linux/AudioPulse.cpp @@ -22,6 +22,7 @@ void* AudioPulse::lib=NULL; DECLARE_DL_FUNCTION(pa_threaded_mainloop_new); DECLARE_DL_FUNCTION(pa_threaded_mainloop_get_api); DECLARE_DL_FUNCTION(pa_context_new); +DECLARE_DL_FUNCTION(pa_context_new_with_proplist); DECLARE_DL_FUNCTION(pa_context_set_state_callback); DECLARE_DL_FUNCTION(pa_threaded_mainloop_lock); DECLARE_DL_FUNCTION(pa_threaded_mainloop_unlock); @@ -29,7 +30,7 @@ DECLARE_DL_FUNCTION(pa_threaded_mainloop_start); DECLARE_DL_FUNCTION(pa_context_connect); DECLARE_DL_FUNCTION(pa_context_get_state); DECLARE_DL_FUNCTION(pa_threaded_mainloop_wait); -DECLARE_DL_FUNCTION(pa_stream_new); +DECLARE_DL_FUNCTION(pa_stream_new_with_proplist); DECLARE_DL_FUNCTION(pa_stream_set_state_callback); DECLARE_DL_FUNCTION(pa_stream_set_write_callback); DECLARE_DL_FUNCTION(pa_stream_connect_playback); @@ -57,6 +58,9 @@ DECLARE_DL_FUNCTION(pa_mainloop_free); DECLARE_DL_FUNCTION(pa_context_get_sink_info_list); DECLARE_DL_FUNCTION(pa_context_get_source_info_list); DECLARE_DL_FUNCTION(pa_operation_get_state); +DECLARE_DL_FUNCTION(pa_proplist_new); +DECLARE_DL_FUNCTION(pa_proplist_sets); +DECLARE_DL_FUNCTION(pa_proplist_free); #include "PulseFunctions.h" @@ -75,6 +79,7 @@ bool AudioPulse::Load(){ LOAD_DL_FUNCTION(pa_threaded_mainloop_new); LOAD_DL_FUNCTION(pa_threaded_mainloop_get_api); LOAD_DL_FUNCTION(pa_context_new); + LOAD_DL_FUNCTION(pa_context_new_with_proplist); LOAD_DL_FUNCTION(pa_context_set_state_callback); LOAD_DL_FUNCTION(pa_threaded_mainloop_lock); LOAD_DL_FUNCTION(pa_threaded_mainloop_unlock); @@ -82,7 +87,7 @@ bool AudioPulse::Load(){ LOAD_DL_FUNCTION(pa_context_connect); LOAD_DL_FUNCTION(pa_context_get_state); LOAD_DL_FUNCTION(pa_threaded_mainloop_wait); - LOAD_DL_FUNCTION(pa_stream_new); + LOAD_DL_FUNCTION(pa_stream_new_with_proplist); LOAD_DL_FUNCTION(pa_stream_set_state_callback); LOAD_DL_FUNCTION(pa_stream_set_write_callback); LOAD_DL_FUNCTION(pa_stream_connect_playback); @@ -110,6 +115,9 @@ bool AudioPulse::Load(){ LOAD_DL_FUNCTION(pa_context_get_sink_info_list); LOAD_DL_FUNCTION(pa_context_get_source_info_list); LOAD_DL_FUNCTION(pa_operation_get_state); + LOAD_DL_FUNCTION(pa_proplist_new); + LOAD_DL_FUNCTION(pa_proplist_sets); + LOAD_DL_FUNCTION(pa_proplist_free); loaded=true; return true; @@ -146,7 +154,10 @@ AudioPulse::AudioPulse(std::string inputDevice, std::string outputDevice){ { snprintf(exeName, sizeof(exeName), "Process %d", getpid()); } - context=pa_context_new(mainloopApi, exeName); + pa_proplist* proplist=pa_proplist_new(); + pa_proplist_sets(proplist, PA_PROP_MEDIA_ROLE, "phone"); + context=pa_context_new_with_proplist(mainloopApi, exeName, proplist); + pa_proplist_free(proplist); if(!context){ LOGE("Error initializing PulseAudio (pa_context_new)"); failed=true; diff --git a/os/linux/AudioPulse.h b/os/linux/AudioPulse.h index 26bdd42..395967a 100644 --- a/os/linux/AudioPulse.h +++ b/os/linux/AudioPulse.h @@ -31,6 +31,7 @@ namespace tgvoip{ DECLARE_DL_FUNCTION(pa_threaded_mainloop_new); DECLARE_DL_FUNCTION(pa_threaded_mainloop_get_api); DECLARE_DL_FUNCTION(pa_context_new); + DECLARE_DL_FUNCTION(pa_context_new_with_proplist); DECLARE_DL_FUNCTION(pa_context_set_state_callback); DECLARE_DL_FUNCTION(pa_threaded_mainloop_lock); DECLARE_DL_FUNCTION(pa_threaded_mainloop_unlock); @@ -38,7 +39,7 @@ namespace tgvoip{ DECLARE_DL_FUNCTION(pa_context_connect); DECLARE_DL_FUNCTION(pa_context_get_state); DECLARE_DL_FUNCTION(pa_threaded_mainloop_wait); - DECLARE_DL_FUNCTION(pa_stream_new); + DECLARE_DL_FUNCTION(pa_stream_new_with_proplist); DECLARE_DL_FUNCTION(pa_stream_set_state_callback); DECLARE_DL_FUNCTION(pa_stream_set_write_callback); DECLARE_DL_FUNCTION(pa_stream_connect_playback); @@ -68,6 +69,10 @@ namespace tgvoip{ DECLARE_DL_FUNCTION(pa_context_get_source_info_list); DECLARE_DL_FUNCTION(pa_operation_get_state); + DECLARE_DL_FUNCTION(pa_proplist_new); + DECLARE_DL_FUNCTION(pa_proplist_sets); + DECLARE_DL_FUNCTION(pa_proplist_free); + private: static void* lib; static bool loaded; diff --git a/os/linux/PulseFunctions.h b/os/linux/PulseFunctions.h index 794c05f..a71a87d 100644 --- a/os/linux/PulseFunctions.h +++ b/os/linux/PulseFunctions.h @@ -4,6 +4,7 @@ #define pa_threaded_mainloop_new AudioPulse::_import_pa_threaded_mainloop_new #define pa_threaded_mainloop_get_api AudioPulse::_import_pa_threaded_mainloop_get_api #define pa_context_new AudioPulse::_import_pa_context_new +#define pa_context_new_with_proplist AudioPulse::_import_pa_context_new_with_proplist #define pa_context_set_state_callback AudioPulse::_import_pa_context_set_state_callback #define pa_threaded_mainloop_lock AudioPulse::_import_pa_threaded_mainloop_lock #define pa_threaded_mainloop_unlock AudioPulse::_import_pa_threaded_mainloop_unlock @@ -11,7 +12,7 @@ #define pa_context_connect AudioPulse::_import_pa_context_connect #define pa_context_get_state AudioPulse::_import_pa_context_get_state #define pa_threaded_mainloop_wait AudioPulse::_import_pa_threaded_mainloop_wait -#define pa_stream_new AudioPulse::_import_pa_stream_new +#define pa_stream_new_with_proplist AudioPulse::_import_pa_stream_new_with_proplist #define pa_stream_set_state_callback AudioPulse::_import_pa_stream_set_state_callback #define pa_stream_set_write_callback AudioPulse::_import_pa_stream_set_write_callback #define pa_stream_connect_playback AudioPulse::_import_pa_stream_connect_playback @@ -39,5 +40,8 @@ #define pa_context_get_sink_info_list AudioPulse::_import_pa_context_get_sink_info_list #define pa_context_get_source_info_list AudioPulse::_import_pa_context_get_source_info_list #define pa_operation_get_state AudioPulse::_import_pa_operation_get_state +#define pa_proplist_new AudioPulse::_import_pa_proplist_new +#define pa_proplist_sets AudioPulse::_import_pa_proplist_sets +#define pa_proplist_free AudioPulse::_import_pa_proplist_free #endif //LIBTGVOIP_PULSE_FUNCTIONS_H \ No newline at end of file diff --git a/os/windows/AudioInputWASAPI.cpp b/os/windows/AudioInputWASAPI.cpp index a75bc84..c5f580a 100644 --- a/os/windows/AudioInputWASAPI.cpp +++ b/os/windows/AudioInputWASAPI.cpp @@ -30,7 +30,7 @@ AudioInputWASAPI::AudioInputWASAPI(std::string deviceID){ remainingDataLen=0; refCount=1; HRESULT res; - res=CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + res=CoInitializeEx(NULL, COINIT_MULTITHREADED); CHECK_RES(res, "CoInitializeEx"); #ifdef TGVOIP_WINXP_COMPAT HANDLE (WINAPI *__CreateEventExA)(LPSECURITY_ATTRIBUTES lpEventAttributes, LPCSTR lpName, DWORD dwFlags, DWORD dwDesiredAccess); @@ -123,7 +123,7 @@ bool AudioInputWASAPI::IsRecording(){ void AudioInputWASAPI::EnumerateDevices(std::vector& devs){ #ifdef TGVOIP_WINDOWS_DESKTOP HRESULT res; - res=CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + res=CoInitializeEx(NULL, COINIT_MULTITHREADED); SCHECK_RES(res, "CoInitializeEx"); IMMDeviceEnumerator *deviceEnumerator = NULL; @@ -324,7 +324,7 @@ void AudioInputWASAPI::RunThread() { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); HANDLE waitArray[]={shutdownEvent, streamSwitchEvent, audioSamplesReadyEvent}; - HRESULT res=CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + HRESULT res=CoInitializeEx(NULL, COINIT_MULTITHREADED); CHECK_RES(res, "CoInitializeEx in capture thread"); uint32_t bufferSize=0; diff --git a/os/windows/AudioOutputWASAPI.cpp b/os/windows/AudioOutputWASAPI.cpp index 68405a4..6459c87 100755 --- a/os/windows/AudioOutputWASAPI.cpp +++ b/os/windows/AudioOutputWASAPI.cpp @@ -34,7 +34,7 @@ AudioOutputWASAPI::AudioOutputWASAPI(std::string deviceID){ remainingDataLen=0; refCount=1; HRESULT res; - res=CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + res=CoInitializeEx(NULL, COINIT_MULTITHREADED); CHECK_RES(res, "CoInitializeEx"); #ifdef TGVOIP_WINXP_COMPAT HANDLE (WINAPI *__CreateEventExA)(LPSECURITY_ATTRIBUTES lpEventAttributes, LPCSTR lpName, DWORD dwFlags, DWORD dwDesiredAccess); @@ -119,7 +119,7 @@ bool AudioOutputWASAPI::IsPlaying(){ void AudioOutputWASAPI::EnumerateDevices(std::vector& devs){ #ifdef TGVOIP_WINDOWS_DESKTOP HRESULT res; - res=CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + res=CoInitializeEx(NULL, COINIT_MULTITHREADED); SCHECK_RES(res, "CoInitializeEx"); IMMDeviceEnumerator *deviceEnumerator = NULL; @@ -324,7 +324,7 @@ void AudioOutputWASAPI::RunThread() { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); HANDLE waitArray[]={shutdownEvent, streamSwitchEvent, audioSamplesReadyEvent}; - HRESULT res=CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + HRESULT res=CoInitializeEx(NULL, COINIT_MULTITHREADED); CHECK_RES(res, "CoInitializeEx in render thread"); uint32_t bufferSize; diff --git a/threading.h b/threading.h index cef6d3c..0bcf7c3 100644 --- a/threading.h +++ b/threading.h @@ -75,7 +75,6 @@ namespace tgvoip{ public: Thread(MethodPointerBase* entry, void* arg) : entry(entry), arg(arg){ name=NULL; - thread=NULL; } virtual ~Thread(){ @@ -83,11 +82,13 @@ namespace tgvoip{ } void Start(){ - pthread_create(&thread, NULL, Thread::ActualEntryPoint, this); + if(pthread_create(&thread, NULL, Thread::ActualEntryPoint, this)==0){ + valid=true; + } } void Join(){ - if(thread) + if(valid) pthread_join(thread, NULL); } @@ -107,7 +108,7 @@ namespace tgvoip{ } bool IsCurrent(){ - return thread==pthread_self(); + return pthread_equal(thread, pthread_self())!=0; } private: @@ -131,6 +132,7 @@ namespace tgvoip{ pthread_t thread; const char* name; bool maxPriority=false; + bool valid=false; }; }