1
0
mirror of https://github.com/danog/libtgvoip.git synced 2025-01-22 13:01:21 +01:00

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
This commit is contained in:
Grishka 2018-08-07 23:10:31 +03:00
parent 3334409ac7
commit 529a3bf14f
12 changed files with 152 additions and 156 deletions

View File

@ -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;
}

View File

@ -90,7 +90,10 @@ namespace tgvoip{
class Buffer{
public:
Buffer(size_t capacity){
if(capacity>0)
data=(unsigned char *) malloc(capacity);
else
data=NULL;
length=capacity;
};
Buffer(const Buffer& other)=delete;

View File

@ -122,7 +122,6 @@ extern FILE* tgvoipLogFile;
VoIPController::VoIPController() : activeNetItfName(""),
currentAudioInput("default"),
currentAudioOutput("default"),
outgoingPacketsBufferPool(1024, 20),
proxyAddress(""),
proxyUsername(""),
proxyPassword(""){
@ -411,9 +410,7 @@ 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
@ -428,22 +425,17 @@ void VoIPController::HandleAudioInput(unsigned char *data, size_t len, unsigned
/*.seq=*/GenerateOutSeq(),
/*.type=*/PKT_STREAM_DATA,
/*.len=*/pkt.GetLength(),
/*.data=*/buf,
/*.data=*/Buffer(move(pkt)),
/*.endpoint=*/0,
};
sendQueue->Put(p);
}else{
LOGW("Out of outgoing packet buffers!");
}
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=BufferOutputStream(1500);
pkt.WriteByte(outgoingStreams[0]->id);
pkt.WriteInt32(audioTimestampOut);
pkt.WriteByte((unsigned char)ecAudioPackets.size());
@ -456,13 +448,10 @@ void VoIPController::HandleAudioInput(unsigned char *data, size_t len, unsigned
GenerateOutSeq(),
PKT_STREAM_EC,
pkt.GetLength(),
buf,
Buffer(move(pkt)),
0
};
sendQueue->Put(p);
}else{
LOGW("Out of outgoing packet buffers!");
}
sendQueue->Put(move(p));
}
audioTimestampOut+=outgoingStreams[0]->frameDuration;
@ -685,12 +674,7 @@ void VoIPController::SendInit(){
for(shared_ptr<Endpoint>& 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> 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,10 +1340,7 @@ 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);
@ -1380,12 +1360,11 @@ simpleAudioBlock random_id:long random_bytes:string raw_data:string = DecryptedA
/*.seq=*/GenerateOutSeq(),
/*.type=*/PKT_INIT_ACK,
/*.len=*/out.GetLength(),
/*.data=*/buf,
/*.data=*/Buffer(move(out)),
/*.endpoint=*/0
});
}
}
}
if(type==PKT_INIT_ACK){
LOGD("Received 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,
/*.data=*/Buffer(),
/*.endpoint=*/endpoint->id
});
}
endpoint->lastPingTime=GetCurrentTime();
}
if(endpoint->type==Endpoint::TYPE_UDP_RELAY || (useTCP && endpoint->type==Endpoint::TYPE_TCP_RELAY)){
@ -3086,41 +3057,36 @@ 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());
Buffer buf(qp->data.Length());
if(qp->firstSentTime==0)
qp->firstSentTime=qp->lastSentTime;
if(qp->data.Length())
memcpy(buf, *qp->data, qp->data.Length());
buf.CopyFrom(qp->data, qp->data.Length());
sendQueue->Put(PendingOutgoingPacket{
/*.seq=*/seq,
/*.type=*/qp->type,
/*.len=*/qp->data.Length(),
/*.data=*/buf,
/*.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,
/*.data=*/Buffer(),
/*.endpoint=*/0
});
}
}
void VoIPController::SendPublicEndpointsRequest(){
if(!allowP2p)

View File

@ -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<unsigned char, 4, int> signalBarsHistory;
BufferPool outgoingPacketsBufferPool;
int udpConnectivityState;
double lastUdpPingTime;
int udpPingCount;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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<tgvoip::AudioInputDevice>& 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;

View File

@ -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<tgvoip::AudioOutputDevice>& 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;

View File

@ -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;
};
}