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:
parent
3334409ac7
commit
529a3bf14f
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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<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,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<shared_ptr<Stream>>::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<shared_ptr<Stream>>::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(){
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
@ -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;
|
||||
|
@ -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;
|
||||
|
10
threading.h
10
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;
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user