mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-05 22:11:22 +00:00
2.2
- Refactored audio I/O to allow sharing a common context between input and output, for those OSes that require this - Rewritten periodic operation handling to use a "run loop" thingy instead of an ugly loop formerly known as tick thread - Fixed a bunch of compiler warnings (closes #13) - Added automake so you no longer need to use the GYP file for standalone builds (closes #43)
This commit is contained in:
parent
dacde29548
commit
5380aaba0d
81
Buffers.h
81
Buffers.h
@ -11,7 +11,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdexcept>
|
||||
#include <array>
|
||||
#include <limits>
|
||||
#include <stddef.h>
|
||||
#include "threading.h"
|
||||
|
||||
namespace tgvoip{
|
||||
@ -157,6 +161,83 @@ namespace tgvoip{
|
||||
unsigned char* data;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
template <typename T, size_t size, typename AVG_T=T> class HistoricBuffer{
|
||||
public:
|
||||
HistoricBuffer(){
|
||||
std::fill(data.begin(), data.end(), (T)0);
|
||||
}
|
||||
|
||||
AVG_T Average(){
|
||||
AVG_T avg=(AVG_T)0;
|
||||
for(T& i:data){
|
||||
avg+=i;
|
||||
}
|
||||
return avg/(AVG_T)size;
|
||||
}
|
||||
|
||||
AVG_T Average(size_t firstN){
|
||||
AVG_T avg=(AVG_T)0;
|
||||
for(size_t i=0;i<firstN;i++){
|
||||
avg+=(*this)[i];
|
||||
}
|
||||
return avg/(AVG_T)firstN;
|
||||
}
|
||||
|
||||
AVG_T NonZeroAverage(){
|
||||
AVG_T avg=(AVG_T)0;
|
||||
int nonZeroCount=0;
|
||||
for(T& i:data){
|
||||
if(i!=0){
|
||||
nonZeroCount++;
|
||||
avg+=i;
|
||||
}
|
||||
}
|
||||
if(nonZeroCount==0)
|
||||
return (AVG_T)0;
|
||||
return avg/(AVG_T)nonZeroCount;
|
||||
}
|
||||
|
||||
void Add(T el){
|
||||
data[offset]=el;
|
||||
offset=(offset+1)%size;
|
||||
}
|
||||
|
||||
T Min(){
|
||||
T min=std::numeric_limits<T>::max();
|
||||
for(T& i:data){
|
||||
if(i<min)
|
||||
min=i;
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
T Max(){
|
||||
T max=std::numeric_limits<T>::min();
|
||||
for(T& i:data){
|
||||
if(i>max)
|
||||
max=i;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
void Reset(){
|
||||
std::fill(data.begin(), data.end(), (T)0);
|
||||
offset=0;
|
||||
}
|
||||
|
||||
T& operator[](size_t i){
|
||||
assert(i<size);
|
||||
// [0] should return the most recent entry, [1] the one before it, and so on
|
||||
ptrdiff_t _i=offset-i-1;
|
||||
if(_i<0)
|
||||
_i=size+_i;
|
||||
return data[_i];
|
||||
}
|
||||
private:
|
||||
std::array<T, size> data;
|
||||
ptrdiff_t offset=0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //LIBTGVOIP_BUFFERINPUTSTREAM_H
|
||||
|
||||
@ -15,16 +15,10 @@
|
||||
using namespace tgvoip;
|
||||
|
||||
CongestionControl::CongestionControl(){
|
||||
memset(rttHistory, 0, sizeof(rttHistory));
|
||||
memset(inflightPackets, 0, sizeof(inflightPackets));
|
||||
memset(inflightHistory, 0, sizeof(inflightHistory));
|
||||
tmpRtt=0;
|
||||
tmpRttCount=0;
|
||||
rttHistorySize=0;
|
||||
rttHistoryTop=0;
|
||||
lastSentSeq=0;
|
||||
inflightHistoryTop=0;
|
||||
state=TGVOIP_CONCTL_STARTUP;
|
||||
lastActionTime=0;
|
||||
lastActionRtt=0;
|
||||
stateTransitionTime=0;
|
||||
@ -41,25 +35,11 @@ size_t CongestionControl::GetAcknowledgedDataSize(){
|
||||
}
|
||||
|
||||
double CongestionControl::GetAverageRTT(){
|
||||
if(rttHistorySize==0)
|
||||
return 0;
|
||||
double avg=0;
|
||||
int i;
|
||||
for(i=0;i<30 && i<rttHistorySize;i++){
|
||||
int x=(rttHistoryTop-i-1)%100;
|
||||
avg+=rttHistory[x>=0 ? x : (100+x)];
|
||||
//LOGV("adding [%d] %f", x>=0 ? x : (100+x), rttHistory[x>=0 ? x : (100+x)]);
|
||||
}
|
||||
return avg/i;
|
||||
return rttHistory.NonZeroAverage();
|
||||
}
|
||||
|
||||
size_t CongestionControl::GetInflightDataSize(){
|
||||
size_t avg=0;
|
||||
int i;
|
||||
for(i=0;i<30;i++){
|
||||
avg+=inflightHistory[i];
|
||||
}
|
||||
return avg/30;
|
||||
return inflightHistory.Average();
|
||||
}
|
||||
|
||||
|
||||
@ -68,13 +48,7 @@ size_t CongestionControl::GetCongestionWindow(){
|
||||
}
|
||||
|
||||
double CongestionControl::GetMinimumRTT(){
|
||||
int i;
|
||||
double min=INFINITY;
|
||||
for(i=0;i<100;i++){
|
||||
if(rttHistory[i]>0 && rttHistory[i]<min)
|
||||
min=rttHistory[i];
|
||||
}
|
||||
return min;
|
||||
return rttHistory.Min();
|
||||
}
|
||||
|
||||
void CongestionControl::PacketAcknowledged(uint32_t seq){
|
||||
@ -128,10 +102,7 @@ void CongestionControl::Tick(){
|
||||
tickCount++;
|
||||
MutexGuard sync(mutex);
|
||||
if(tmpRttCount>0){
|
||||
rttHistory[rttHistoryTop]=tmpRtt/tmpRttCount;
|
||||
rttHistoryTop=(rttHistoryTop+1)%100;
|
||||
if(rttHistorySize<100)
|
||||
rttHistorySize++;
|
||||
rttHistory.Add(tmpRtt/tmpRttCount);
|
||||
tmpRtt=0;
|
||||
tmpRttCount=0;
|
||||
}
|
||||
@ -144,8 +115,7 @@ void CongestionControl::Tick(){
|
||||
LOGD("Packet with seq %u was not acknowledged", inflightPackets[i].seq);
|
||||
}
|
||||
}
|
||||
inflightHistory[inflightHistoryTop]=inflightDataSize;
|
||||
inflightHistoryTop=(inflightHistoryTop+1)%30;
|
||||
inflightHistory.Add(inflightDataSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -10,11 +10,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "threading.h"
|
||||
|
||||
#define TGVOIP_CONCTL_STARTUP 0
|
||||
#define TGVOIP_CONCTL_DRAIN 1
|
||||
#define TGVOIP_CONCTL_PROBE_BW 2
|
||||
#define TGVOIP_CONCTL_PROBE_RTT 3
|
||||
#include "Buffers.h"
|
||||
|
||||
#define TGVOIP_CONCTL_ACT_INCREASE 1
|
||||
#define TGVOIP_CONCTL_ACT_DECREASE 2
|
||||
@ -47,19 +43,15 @@ public:
|
||||
uint32_t GetSendLossCount();
|
||||
|
||||
private:
|
||||
double rttHistory[100];
|
||||
HistoricBuffer<double, 100> rttHistory;
|
||||
HistoricBuffer<size_t, 30> inflightHistory;
|
||||
tgvoip_congestionctl_packet_t inflightPackets[100];
|
||||
size_t inflightHistory[30];
|
||||
int state;
|
||||
uint32_t lossCount;
|
||||
double tmpRtt;
|
||||
double lastActionTime;
|
||||
double lastActionRtt;
|
||||
double stateTransitionTime;
|
||||
int tmpRttCount;
|
||||
char rttHistorySize;
|
||||
unsigned int rttHistoryTop;
|
||||
unsigned int inflightHistoryTop;
|
||||
uint32_t lastSentSeq;
|
||||
uint32_t tickCount;
|
||||
size_t inflightDataSize;
|
||||
|
||||
@ -40,13 +40,12 @@ namespace webrtc{
|
||||
#endif
|
||||
|
||||
EchoCanceller::EchoCanceller(bool enableAEC, bool enableNS, bool enableAGC){
|
||||
#ifndef TGVOIP_NO_DSP
|
||||
this->enableAEC=enableAEC;
|
||||
this->enableAGC=enableAGC;
|
||||
this->enableNS=enableNS;
|
||||
isOn=true;
|
||||
|
||||
#ifndef TGVOIP_NO_DSP
|
||||
|
||||
splittingFilter=new webrtc::SplittingFilter(1, 3, 960);
|
||||
splittingFilterFarend=new webrtc::SplittingFilter(1, 3, 960);
|
||||
|
||||
@ -111,10 +110,14 @@ EchoCanceller::EchoCanceller(bool enableAEC, bool enableNS, bool enableAGC){
|
||||
}else{
|
||||
agc=NULL;
|
||||
}
|
||||
#else
|
||||
this->enableAEC=this->enableAGC=enableAGC=this->enableNS=enableNS=false;
|
||||
isOn=true;
|
||||
#endif
|
||||
}
|
||||
|
||||
EchoCanceller::~EchoCanceller(){
|
||||
#ifndef TGVOIP_NO_DSP
|
||||
if(enableAEC){
|
||||
running=false;
|
||||
farendQueue->Put(NULL);
|
||||
@ -147,6 +150,7 @@ EchoCanceller::~EchoCanceller(){
|
||||
delete (webrtc::IFChannelBuffer*)splittingFilterOut;
|
||||
delete (webrtc::IFChannelBuffer*)splittingFilterFarendIn;
|
||||
delete (webrtc::IFChannelBuffer*)splittingFilterFarendOut;
|
||||
#endif
|
||||
}
|
||||
|
||||
void EchoCanceller::Start(){
|
||||
@ -166,13 +170,16 @@ void EchoCanceller::SpeakerOutCallback(unsigned char* data, size_t len){
|
||||
WebRtcAecm_BufferFarend(state, (int16_t*)(data+offset), AEC_FRAME_SIZE);
|
||||
offset+=OFFSET_STEP;
|
||||
}*/
|
||||
#ifndef TGVOIP_NO_DSP
|
||||
int16_t* buf=(int16_t*)farendBufferPool->Get();
|
||||
if(buf){
|
||||
memcpy(buf, data, 960*2);
|
||||
farendQueue->Put(buf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef TGVOIP_NO_DSP
|
||||
void EchoCanceller::RunBufferFarendThread(void* arg){
|
||||
while(running){
|
||||
int16_t* samplesIn=farendQueue->GetBlocking();
|
||||
@ -197,6 +204,7 @@ void EchoCanceller::RunBufferFarendThread(void* arg){
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void EchoCanceller::Enable(bool enabled){
|
||||
isOn=enabled;
|
||||
@ -208,6 +216,7 @@ void EchoCanceller::ProcessInput(unsigned char* data, unsigned char* out, size_t
|
||||
memcpy(out, data, len);
|
||||
return;
|
||||
}
|
||||
#ifndef TGVOIP_NO_DSP
|
||||
int16_t* samplesIn=(int16_t*)data;
|
||||
int16_t* samplesOut=(int16_t*)out;
|
||||
|
||||
@ -355,9 +364,11 @@ void EchoCanceller::ProcessInput(unsigned char* data, unsigned char* out, size_t
|
||||
((webrtc::SplittingFilter*)splittingFilter)->Synthesis(bufOut, bufIn);
|
||||
|
||||
memcpy(samplesOut, bufIn->ibuf_const()->bands(0)[0], 960*2);
|
||||
#endif
|
||||
}
|
||||
|
||||
void EchoCanceller::SetAECStrength(int strength){
|
||||
#ifndef TGVOIP_NO_DSP
|
||||
if(aec){
|
||||
#ifndef TGVOIP_USE_DESKTOP_DSP
|
||||
AecmConfig cfg;
|
||||
@ -366,6 +377,7 @@ void EchoCanceller::SetAECStrength(int strength){
|
||||
WebRtcAecm_set_config(aec, cfg);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
AudioEffect::~AudioEffect(){
|
||||
@ -377,6 +389,7 @@ void AudioEffect::SetPassThrough(bool passThrough){
|
||||
}
|
||||
|
||||
AutomaticGainControl::AutomaticGainControl(){
|
||||
#ifndef TGVOIP_NO_DSP
|
||||
splittingFilter=new webrtc::SplittingFilter(1, 3, 960);
|
||||
splittingFilterIn=new webrtc::IFChannelBuffer(960, 1, 1);
|
||||
splittingFilterOut=new webrtc::IFChannelBuffer(960, 1, 3);
|
||||
@ -389,16 +402,20 @@ AutomaticGainControl::AutomaticGainControl(){
|
||||
WebRtcAgc_Init(agc, 0, 255, kAgcModeAdaptiveDigital, 48000);
|
||||
WebRtcAgc_set_config(agc, agcConfig);
|
||||
agcMicLevel=0;
|
||||
#endif
|
||||
}
|
||||
|
||||
AutomaticGainControl::~AutomaticGainControl(){
|
||||
#ifndef TGVOIP_NO_DSP
|
||||
delete (webrtc::SplittingFilter*)splittingFilter;
|
||||
delete (webrtc::IFChannelBuffer*)splittingFilterIn;
|
||||
delete (webrtc::IFChannelBuffer*)splittingFilterOut;
|
||||
WebRtcAgc_Free(agc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AutomaticGainControl::Process(int16_t *inOut, size_t numSamples){
|
||||
#ifndef TGVOIP_NO_DSP
|
||||
if(passThrough)
|
||||
return;
|
||||
if(numSamples!=960){
|
||||
@ -438,5 +455,6 @@ void AutomaticGainControl::Process(int16_t *inOut, size_t numSamples){
|
||||
((webrtc::SplittingFilter*)splittingFilter)->Synthesis(bufOut, bufIn);
|
||||
|
||||
memcpy(inOut, bufIn->ibuf_const()->bands(0)[0], 960*2);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -17,14 +17,6 @@ JitterBuffer::JitterBuffer(MediaStreamItf *out, uint32_t step):bufferPool(JITTER
|
||||
out->SetCallback(JitterBuffer::CallbackOut, this);
|
||||
this->step=step;
|
||||
memset(slots, 0, sizeof(jitter_packet_t)*JITTER_SLOT_COUNT);
|
||||
minDelay=6;
|
||||
lostCount=0;
|
||||
needBuffering=true;
|
||||
tickCount=0;
|
||||
dontIncMinDelay=0;
|
||||
dontDecMinDelay=0;
|
||||
lostPackets=0;
|
||||
outstandingDelayChange=0;
|
||||
if(step<30){
|
||||
minMinDelay=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_min_delay_20", 6);
|
||||
maxMinDelay=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_max_delay_20", 25);
|
||||
@ -101,14 +93,13 @@ void JitterBuffer::Reset(){
|
||||
slots[i].buffer=NULL;
|
||||
}
|
||||
}
|
||||
memset(delayHistory, 0, sizeof(delayHistory));
|
||||
memset(lateHistory, 0, sizeof(lateHistory));
|
||||
delayHistory.Reset();
|
||||
lateHistory.Reset();
|
||||
adjustingDelay=false;
|
||||
lostSinceReset=0;
|
||||
gotSinceReset=0;
|
||||
expectNextAtTime=0;
|
||||
memset(deviationHistory, 0, sizeof(deviationHistory));
|
||||
deviationPtr=0;
|
||||
deviationHistory.Reset();
|
||||
outstandingDelayChange=0;
|
||||
dontChangeDelay=0;
|
||||
}
|
||||
@ -124,15 +115,6 @@ size_t JitterBuffer::HandleOutput(unsigned char *buffer, size_t len, int offsetI
|
||||
if(outstandingDelayChange<0){
|
||||
playbackScaledDuration=40;
|
||||
outstandingDelayChange+=20;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}else{
|
||||
playbackScaledDuration=80;
|
||||
outstandingDelayChange-=20;
|
||||
@ -265,8 +247,7 @@ void JitterBuffer::PutInternal(jitter_packet_t* pkt, bool overwriteExisting){
|
||||
if(expectNextAtTime!=0){
|
||||
double dev=expectNextAtTime-time;
|
||||
//LOGV("packet dev %f", dev);
|
||||
deviationHistory[deviationPtr]=dev;
|
||||
deviationPtr=(deviationPtr+1)%64;
|
||||
deviationHistory.Add(dev);
|
||||
expectNextAtTime+=step/1000.0;
|
||||
}else{
|
||||
expectNextAtTime=time+step/1000.0;
|
||||
@ -338,27 +319,14 @@ void JitterBuffer::Tick(){
|
||||
MutexGuard m(mutex);
|
||||
int i;
|
||||
|
||||
memmove(&lateHistory[1], lateHistory, 63*sizeof(int));
|
||||
lateHistory[0]=latePacketCount;
|
||||
lateHistory.Add(latePacketCount);
|
||||
latePacketCount=0;
|
||||
bool absolutelyNoLatePackets=true;
|
||||
bool absolutelyNoLatePackets=lateHistory.Max()==0;
|
||||
|
||||
double avgLate64=0, avgLate32=0, avgLate16=0;
|
||||
for(i=0;i<64;i++){
|
||||
avgLate64+=lateHistory[i];
|
||||
if(i<32)
|
||||
avgLate32+=lateHistory[i];
|
||||
if(i<16){
|
||||
avgLate16+=lateHistory[i];
|
||||
}
|
||||
if(lateHistory[i]>0)
|
||||
absolutelyNoLatePackets=false;
|
||||
}
|
||||
avgLate64/=64;
|
||||
avgLate32/=32;
|
||||
avgLate16/=16;
|
||||
double avgLate16=lateHistory.Average(16);
|
||||
//LOGV("jitter: avg late=%.1f, %.1f, %.1f", avgLate16, avgLate32, avgLate64);
|
||||
if(avgLate16>=resyncThreshold){
|
||||
LOGV("resyncing: avgLate16=%f, resyncThreshold=%f", avgLate16, resyncThreshold);
|
||||
wasReset=true;
|
||||
}
|
||||
|
||||
@ -367,24 +335,11 @@ void JitterBuffer::Tick(){
|
||||
dontDecMinDelay--;
|
||||
}
|
||||
|
||||
memmove(&delayHistory[1], delayHistory, 63*sizeof(int));
|
||||
delayHistory[0]=GetCurrentDelay();
|
||||
|
||||
avgDelay=0;
|
||||
int min=100;
|
||||
for(i=0;i<32;i++){
|
||||
avgDelay+=delayHistory[i];
|
||||
if(delayHistory[i]<min)
|
||||
min=delayHistory[i];
|
||||
}
|
||||
avgDelay/=32;
|
||||
delayHistory.Add(GetCurrentDelay());
|
||||
avgDelay=delayHistory.Average(32);
|
||||
|
||||
double stddev=0;
|
||||
double avgdev=0;
|
||||
for(i=0;i<64;i++){
|
||||
avgdev+=deviationHistory[i];
|
||||
}
|
||||
avgdev/=64;
|
||||
double avgdev=deviationHistory.Average();
|
||||
for(i=0;i<64;i++){
|
||||
double d=(deviationHistory[i]-avgdev);
|
||||
stddev+=(d*d);
|
||||
@ -409,7 +364,7 @@ void JitterBuffer::Tick(){
|
||||
minDelay+=diff;
|
||||
outstandingDelayChange+=diff*60;
|
||||
dontChangeDelay+=32;
|
||||
LOGD("new delay from stddev %f", minDelay);
|
||||
//LOGD("new delay from stddev %f", minDelay);
|
||||
if(diff<0){
|
||||
dontDecMinDelay+=25;
|
||||
}
|
||||
@ -460,18 +415,7 @@ void JitterBuffer::Tick(){
|
||||
|
||||
|
||||
void JitterBuffer::GetAverageLateCount(double *out){
|
||||
double avgLate64=0, avgLate32=0, avgLate16=0;
|
||||
int i;
|
||||
for(i=0;i<64;i++){
|
||||
avgLate64+=lateHistory[i];
|
||||
if(i<32)
|
||||
avgLate32+=lateHistory[i];
|
||||
if(i<16)
|
||||
avgLate16+=lateHistory[i];
|
||||
}
|
||||
avgLate64/=64;
|
||||
avgLate32/=32;
|
||||
avgLate16/=16;
|
||||
double avgLate64=lateHistory.Average(), avgLate32=lateHistory.Average(32), avgLate16=lateHistory.Average(16);
|
||||
out[0]=avgLate16;
|
||||
out[1]=avgLate32;
|
||||
out[2]=avgLate64;
|
||||
|
||||
@ -57,37 +57,36 @@ private:
|
||||
BufferPool bufferPool;
|
||||
Mutex mutex;
|
||||
jitter_packet_t slots[JITTER_SLOT_COUNT];
|
||||
int64_t nextTimestamp;
|
||||
int64_t nextTimestamp=0;
|
||||
uint32_t step;
|
||||
double minDelay;
|
||||
double minDelay=6;
|
||||
uint32_t minMinDelay;
|
||||
uint32_t maxMinDelay;
|
||||
uint32_t maxUsedSlots;
|
||||
uint32_t lastPutTimestamp;
|
||||
uint32_t lossesToReset;
|
||||
double resyncThreshold;
|
||||
unsigned int lostCount;
|
||||
unsigned int lostSinceReset;
|
||||
unsigned int gotSinceReset;
|
||||
bool wasReset;
|
||||
bool needBuffering;
|
||||
int delayHistory[64];
|
||||
int lateHistory[64];
|
||||
bool adjustingDelay;
|
||||
unsigned int tickCount;
|
||||
unsigned int latePacketCount;
|
||||
unsigned int dontIncMinDelay;
|
||||
unsigned int dontDecMinDelay;
|
||||
int lostPackets;
|
||||
double prevRecvTime;
|
||||
double expectNextAtTime;
|
||||
double deviationHistory[64];
|
||||
int deviationPtr;
|
||||
double lastMeasuredJitter;
|
||||
double lastMeasuredDelay;
|
||||
int outstandingDelayChange;
|
||||
unsigned int dontChangeDelay;
|
||||
double avgDelay;
|
||||
unsigned int lostCount=0;
|
||||
unsigned int lostSinceReset=0;
|
||||
unsigned int gotSinceReset=0;
|
||||
bool wasReset=true;
|
||||
bool needBuffering=true;
|
||||
HistoricBuffer<int, 64, double> delayHistory;
|
||||
HistoricBuffer<int, 64, double> lateHistory;
|
||||
bool adjustingDelay=false;
|
||||
unsigned int tickCount=0;
|
||||
unsigned int latePacketCount=0;
|
||||
unsigned int dontIncMinDelay=0;
|
||||
unsigned int dontDecMinDelay=0;
|
||||
int lostPackets=0;
|
||||
double prevRecvTime=0;
|
||||
double expectNextAtTime=0;
|
||||
HistoricBuffer<double, 64> deviationHistory;
|
||||
double lastMeasuredJitter=0;
|
||||
double lastMeasuredDelay=0;
|
||||
int outstandingDelayChange=0;
|
||||
unsigned int dontChangeDelay=0;
|
||||
double avgDelay=0;
|
||||
#ifdef TGVOIP_DUMP_JITTER_STATS
|
||||
FILE* dump;
|
||||
#endif
|
||||
|
||||
268
Makefile.am
Normal file
268
Makefile.am
Normal file
@ -0,0 +1,268 @@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
CFLAGS = -Wall -DHAVE_CONFIG_H -Wno-unknown-pragmas
|
||||
|
||||
lib_LTLIBRARIES = libtgvoip.la
|
||||
|
||||
SRC = VoIPController.cpp \
|
||||
Buffers.cpp \
|
||||
CongestionControl.cpp \
|
||||
EchoCanceller.cpp \
|
||||
JitterBuffer.cpp \
|
||||
logging.cpp \
|
||||
MediaStreamItf.cpp \
|
||||
MessageThread.cpp \
|
||||
NetworkSocket.cpp \
|
||||
OpusDecoder.cpp \
|
||||
OpusEncoder.cpp \
|
||||
PacketReassembler.cpp \
|
||||
VoIPGroupController.cpp \
|
||||
VoIPServerConfig.cpp \
|
||||
audio/AudioIO.cpp \
|
||||
audio/AudioInput.cpp \
|
||||
audio/AudioOutput.cpp \
|
||||
audio/Resampler.cpp \
|
||||
os/posix/NetworkSocketPosix.cpp
|
||||
|
||||
TGVOIP_HDRS = \
|
||||
VoIPController.h \
|
||||
Buffers.h \
|
||||
BlockingQueue.h \
|
||||
PrivateDefines.h \
|
||||
CongestionControl.h \
|
||||
EchoCanceller.h \
|
||||
JitterBuffer.h \
|
||||
logging.h \
|
||||
threading.h \
|
||||
MediaStreamItf.h \
|
||||
MessageThread.h \
|
||||
NetworkSocket.h \
|
||||
OpusDecoder.h \
|
||||
OpusEncoder.h \
|
||||
PacketReassembler.h \
|
||||
VoIPServerConfig.h \
|
||||
audio/AudioIO.h \
|
||||
audio/AudioInput.h \
|
||||
audio/AudioOutput.h \
|
||||
audio/Resampler.h \
|
||||
os/posix/NetworkSocketPosix.h
|
||||
|
||||
if TARGET_OS_OSX
|
||||
|
||||
SRC += \
|
||||
os/darwin/AudioInputAudioUnit.cpp \
|
||||
os/darwin/AudioOutputAudioUnit.cpp \
|
||||
os/darwin/AudioUnitIO.cpp \
|
||||
os/darwin/AudioInputAudioUnitOSX.cpp \
|
||||
os/darwin/AudioOutputAudioUnitOSX.cpp \
|
||||
os/darwin/DarwinSpecific.mm
|
||||
|
||||
TGVOIP_HDRS += \
|
||||
os/darwin/AudioInputAudioUnit.h \
|
||||
os/darwin/AudioOutputAudioUnit.h \
|
||||
os/darwin/AudioUnitIO.h \
|
||||
os/darwin/AudioInputAudioUnitOSX.h \
|
||||
os/darwin/AudioOutputAudioUnitOSX.h \
|
||||
os/darwin/DarwinSpecific.h
|
||||
|
||||
LDFLAGS += -framework Foundation -framework CoreFoundation -framework CoreAudio -framework AudioToolbox
|
||||
|
||||
else
|
||||
# Linux-specific
|
||||
if WITH_ALSA
|
||||
SRC += \
|
||||
os/linux/AudioInputALSA.cpp \
|
||||
os/linux/AudioOutputALSA.cpp
|
||||
TGVOIP_HDRS += \
|
||||
os/linux/AudioInputALSA.h \
|
||||
os/linux/AudioOutputALSA.h
|
||||
endif
|
||||
|
||||
if WITH_PULSE
|
||||
SRC += \
|
||||
os/linux/AudioOutputPulse.cpp \
|
||||
os/linux/AudioInputPulse.cpp \
|
||||
os/linux/AudioPulse.cpp
|
||||
TGVOIP_HDRS += \
|
||||
os/linux/AudioOutputPulse.h \
|
||||
os/linux/AudioInputPulse.h \
|
||||
os/linux/AudioPulse.h \
|
||||
os/linux/PulseFunctions.h
|
||||
endif
|
||||
endif
|
||||
|
||||
if ENABLE_DSP
|
||||
CFLAGS += -DWEBRTC_POSIX -DWEBRTC_APM_DEBUG_DUMP=0 -I$(top_srcdir)/webrtc_dsp
|
||||
CCASFLAGS += -I$(top_srcdir)/webrtc_dsp
|
||||
|
||||
SRC += \
|
||||
webrtc_dsp/webrtc/common_audio/ring_buffer.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/auto_corr_to_refl_coef.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/auto_correlation.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/complex_fft.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/copy_set_operations.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/cross_correlation.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/division_operations.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/dot_product_with_scale.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/downsample_fast.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/energy.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/filter_ar.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/filter_ar_fast_q12.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/filter_ma_fast_q12.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/get_hanning_window.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/get_scaling_square.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/ilbc_specific_functions.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/levinson_durbin.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/lpc_to_refl_coef.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/min_max_operations.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/randomization_functions.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/real_fft.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/refl_coef_to_lpc.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/resample.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/resample_48khz.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/resample_by_2.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/resample_by_2_internal.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/resample_fractional.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/spl_init.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/spl_inl.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/spl_sqrt.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/splitting_filter_impl.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/sqrt_of_one_minus_x_squared.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/vector_scaling_operations.c
|
||||
|
||||
SRC += \
|
||||
webrtc_dsp/webrtc/base/checks.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aecm/aecm_core.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aecm/aecm_core_c.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aecm/echo_control_mobile.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/utility/delay_estimator.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/three_band_filter_bank.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/splitting_filter.cc \
|
||||
webrtc_dsp/webrtc/system_wrappers/source/cpu_features.cc \
|
||||
webrtc_dsp/webrtc/common_audio/sparse_fir_filter.cc \
|
||||
webrtc_dsp/webrtc/common_audio/channel_buffer.cc \
|
||||
webrtc_dsp/webrtc/common_audio/audio_util.cc
|
||||
|
||||
SRC += \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/utility/block_mean_calculator.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/utility/ooura_fft.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/logging/apm_data_dumper.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aec/aec_core.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aec/aec_resampler.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aec/echo_cancellation.cc \
|
||||
webrtc_dsp/webrtc/common_audio/wav_header.cc \
|
||||
webrtc_dsp/webrtc/common_audio/wav_file.cc \
|
||||
webrtc_dsp/webrtc/base/stringutils.cc
|
||||
|
||||
if TARGET_CPU_X86
|
||||
SRC += \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aec/aec_core_sse2.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/utility/ooura_fft_sse2.cc
|
||||
endif
|
||||
|
||||
if TARGET_CPU_ARM
|
||||
SRC += \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/complex_bit_reverse_arm.S \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/spl_sqrt_floor_arm.S
|
||||
if TARGET_CPU_ARMV7
|
||||
CFLAGS += -mfpu=neon -mfloat-abi=hard
|
||||
CCASFLAGS += -mfpu=neon -mfloat-abi=hard
|
||||
SRC += \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/cross_correlation_neon.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/downsample_fast_neon.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/min_max_operations_neon.c \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aec/aec_core_neon.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aecm/aecm_core_neon.cc \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/ns/nsx_core_neon.c \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/utility/ooura_fft_neon.cc
|
||||
# webrtc_dsp/webrtc/common_audio/signal_processing/filter_ar_fast_q12_armv7.S
|
||||
endif
|
||||
else
|
||||
SRC += \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/complex_bit_reverse.c \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/spl_sqrt_floor.c
|
||||
endif
|
||||
|
||||
SRC += \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/ns/noise_suppression_x.c \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/ns/noise_suppression.c \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/ns/ns_core.c \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/ns/nsx_core_c.c \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/ns/nsx_core.c \
|
||||
webrtc_dsp/webrtc/common_audio/fft4g.c
|
||||
|
||||
SRC += \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/agc/legacy/analog_agc.c \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/agc/legacy/digital_agc.c
|
||||
|
||||
# headers
|
||||
SRC += \
|
||||
webrtc_dsp/webrtc/base/array_view.h \
|
||||
webrtc_dsp/webrtc/base/atomicops.h \
|
||||
webrtc_dsp/webrtc/base/basictypes.h \
|
||||
webrtc_dsp/webrtc/base/checks.h \
|
||||
webrtc_dsp/webrtc/base/constructormagic.h \
|
||||
webrtc_dsp/webrtc/base/safe_compare.h \
|
||||
webrtc_dsp/webrtc/base/safe_conversions.h \
|
||||
webrtc_dsp/webrtc/base/safe_conversions_impl.h \
|
||||
webrtc_dsp/webrtc/base/sanitizer.h \
|
||||
webrtc_dsp/webrtc/base/stringutils.h \
|
||||
webrtc_dsp/webrtc/base/type_traits.h \
|
||||
webrtc_dsp/webrtc/common_audio/channel_buffer.h \
|
||||
webrtc_dsp/webrtc/common_audio/fft4g.h \
|
||||
webrtc_dsp/webrtc/common_audio/include/audio_util.h \
|
||||
webrtc_dsp/webrtc/common_audio/ring_buffer.h \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/complex_fft_tables.h \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/include/real_fft.h \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/include/signal_processing_library.h \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/include/spl_inl.h \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/include/spl_inl_armv7.h \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/include/spl_inl_mips.h \
|
||||
webrtc_dsp/webrtc/common_audio/signal_processing/resample_by_2_internal.h \
|
||||
webrtc_dsp/webrtc/common_audio/sparse_fir_filter.h \
|
||||
webrtc_dsp/webrtc/common_audio/wav_file.h \
|
||||
webrtc_dsp/webrtc/common_audio/wav_header.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aec/aec_common.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aec/aec_core.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aec/aec_core_optimized_methods.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aec/aec_resampler.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aec/echo_cancellation.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aecm/aecm_core.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aecm/aecm_defines.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/aecm/echo_control_mobile.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/agc/legacy/analog_agc.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/agc/legacy/digital_agc.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/agc/legacy/gain_control.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/logging/apm_data_dumper.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/ns/defines.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/ns/noise_suppression.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/ns/noise_suppression_x.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/ns/ns_core.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/ns/nsx_core.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/ns/nsx_defines.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/ns/windows_private.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/splitting_filter.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/three_band_filter_bank.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/utility/block_mean_calculator.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/utility/delay_estimator.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/utility/delay_estimator_internal.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/utility/ooura_fft.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/utility/ooura_fft_tables_common.h \
|
||||
webrtc_dsp/webrtc/modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h \
|
||||
webrtc_dsp/webrtc/system_wrappers/include/asm_defines.h \
|
||||
webrtc_dsp/webrtc/system_wrappers/include/compile_assert_c.h \
|
||||
webrtc_dsp/webrtc/system_wrappers/include/cpu_features_wrapper.h \
|
||||
webrtc_dsp/webrtc/system_wrappers/include/metrics.h \
|
||||
webrtc_dsp/webrtc/typedefs.h
|
||||
|
||||
else
|
||||
CFLAGS += -DTGVOIP_NO_DSP
|
||||
endif
|
||||
|
||||
libtgvoip_la_SOURCES = $(SRC) $(TGVOIP_HDRS)
|
||||
tgvoipincludedir = $(includedir)/tgvoip
|
||||
nobase_tgvoipinclude_HEADERS = $(TGVOIP_HDRS)
|
||||
|
||||
CXXFLAGS += -std=gnu++0x $(CFLAGS)
|
||||
2283
Makefile.in
Normal file
2283
Makefile.in
Normal file
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,7 @@ AudioMixer::AudioMixer() : bufferPool(960*2, 16), processedQueue(16), semaphore(
|
||||
AudioMixer::~AudioMixer(){
|
||||
}
|
||||
|
||||
void AudioMixer::SetOutput(const std::unique_ptr<MediaStreamItf>& output){
|
||||
void AudioMixer::SetOutput(MediaStreamItf* output){
|
||||
output->SetCallback(OutputCallback, this);
|
||||
}
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ private:
|
||||
public:
|
||||
AudioMixer();
|
||||
virtual ~AudioMixer();
|
||||
void SetOutput(const std::unique_ptr<MediaStreamItf>& output);
|
||||
void SetOutput(MediaStreamItf* output);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
void AddInput(std::shared_ptr<MediaStreamItf> input);
|
||||
|
||||
170
MessageThread.cpp
Executable file
170
MessageThread.cpp
Executable file
@ -0,0 +1,170 @@
|
||||
//
|
||||
// Created by Grishka on 17.06.2018.
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "MessageThread.h"
|
||||
#include "VoIPController.h"
|
||||
#include "logging.h"
|
||||
|
||||
using namespace tgvoip;
|
||||
|
||||
MessageThread::MessageThread() : Thread(new MethodPointer<MessageThread>(&MessageThread::Run, this), NULL){
|
||||
|
||||
SetName("MessageThread");
|
||||
|
||||
#ifdef _WIN32
|
||||
event=CreateEvent(NULL, false, false, NULL);
|
||||
#else
|
||||
pthread_cond_init(&cond, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
MessageThread::~MessageThread(){
|
||||
Stop();
|
||||
#ifdef _WIN32
|
||||
CloseHandle(event);
|
||||
#else
|
||||
pthread_cond_destroy(&cond);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MessageThread::Stop(){
|
||||
if(running){
|
||||
running=false;
|
||||
#ifdef _WIN32
|
||||
SetEvent(event);
|
||||
#else
|
||||
pthread_cond_signal(&cond);
|
||||
#endif
|
||||
Join();
|
||||
}
|
||||
}
|
||||
|
||||
void MessageThread::Run(void* arg){
|
||||
queueMutex.Lock();
|
||||
while(running){
|
||||
double currentTime=VoIPController::GetCurrentTime();
|
||||
double waitTimeout=queue.empty() ? DBL_MAX : (queue[0].deliverAt-currentTime);
|
||||
//LOGW("MessageThread wait timeout %f", waitTimeout);
|
||||
if(waitTimeout>0.0){
|
||||
#ifdef _WIN32
|
||||
queueMutex.Unlock();
|
||||
DWORD actualWaitTimeout=waitTimeout==DBL_MAX ? INFINITE : ((DWORD)round(waitTimeout*1000.0));
|
||||
WaitForSingleObject(event, actualWaitTimeout);
|
||||
// we don't really care if a context switch happens here and anything gets added to the queue by another thread
|
||||
// since any new no-delay messages will get delivered on this iteration anyway
|
||||
queueMutex.Lock();
|
||||
#else
|
||||
if(waitTimeout!=DBL_MAX){
|
||||
struct timeval now;
|
||||
struct timespec timeout;
|
||||
gettimeofday(&now, NULL);
|
||||
waitTimeout+=now.tv_sec;
|
||||
waitTimeout+=(now.tv_usec/1000000.0);
|
||||
timeout.tv_sec=(time_t)(floor(waitTimeout));
|
||||
timeout.tv_nsec=(long)((waitTimeout-floor(waitTimeout))*1000000000.0);
|
||||
pthread_cond_timedwait(&cond, queueMutex.NativeHandle(), &timeout);
|
||||
}else{
|
||||
pthread_cond_wait(&cond, queueMutex.NativeHandle());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
currentTime=VoIPController::GetCurrentTime();
|
||||
std::vector<Message> msgsToDeliverNow;
|
||||
for(std::vector<Message>::iterator m=queue.begin();m!=queue.end();){
|
||||
if(m->deliverAt==0.0 || currentTime>=m->deliverAt){
|
||||
msgsToDeliverNow.push_back(*m);
|
||||
m=queue.erase(m);
|
||||
continue;
|
||||
}
|
||||
++m;
|
||||
}
|
||||
|
||||
for(Message& m:msgsToDeliverNow){
|
||||
//LOGI("MessageThread delivering %u", m.msg);
|
||||
cancelCurrent=false;
|
||||
if(m.deliverAt==0.0)
|
||||
m.deliverAt=VoIPController::GetCurrentTime();
|
||||
if(m.func!=nullptr){
|
||||
m.func();
|
||||
}
|
||||
if(!cancelCurrent && m.interval>0.0){
|
||||
m.deliverAt+=m.interval;
|
||||
InsertMessageInternal(m);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
queueMutex.Unlock();
|
||||
}
|
||||
|
||||
uint32_t MessageThread::Post(std::function<void()> func, double delay, double interval){
|
||||
assert(delay>=0);
|
||||
//LOGI("MessageThread post [function] delay %f", delay);
|
||||
if(!IsCurrent()){
|
||||
queueMutex.Lock();
|
||||
}
|
||||
double currentTime=VoIPController::GetCurrentTime();
|
||||
Message m{lastMessageID++, delay==0.0 ? 0.0 : (currentTime+delay), interval, func};
|
||||
InsertMessageInternal(m);
|
||||
if(!IsCurrent()){
|
||||
#ifdef _WIN32
|
||||
SetEvent(event);
|
||||
#else
|
||||
pthread_cond_signal(&cond);
|
||||
#endif
|
||||
queueMutex.Unlock();
|
||||
}
|
||||
return m.id;
|
||||
}
|
||||
|
||||
void MessageThread::InsertMessageInternal(MessageThread::Message &m){
|
||||
if(queue.empty()){
|
||||
queue.push_back(m);
|
||||
}else{
|
||||
if(queue[0].deliverAt>m.deliverAt){
|
||||
queue.insert(queue.begin(), m);
|
||||
}else{
|
||||
std::vector<Message>::iterator insertAfter=queue.begin();
|
||||
for(; insertAfter!=queue.end(); ++insertAfter){
|
||||
std::vector<Message>::iterator next=std::next(insertAfter);
|
||||
if(next==queue.end() || (next->deliverAt>m.deliverAt && insertAfter->deliverAt<=m.deliverAt)){
|
||||
queue.insert(next, m);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MessageThread::Cancel(uint32_t id){
|
||||
if(!IsCurrent()){
|
||||
queueMutex.Lock();
|
||||
}
|
||||
|
||||
for(std::vector<Message>::iterator m=queue.begin();m!=queue.end();){
|
||||
if(m->id==id){
|
||||
m=queue.erase(m);
|
||||
}else{
|
||||
++m;
|
||||
}
|
||||
}
|
||||
|
||||
if(!IsCurrent()){
|
||||
queueMutex.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void MessageThread::CancelSelf(){
|
||||
assert(IsCurrent());
|
||||
cancelCurrent=true;
|
||||
}
|
||||
50
MessageThread.h
Executable file
50
MessageThread.h
Executable file
@ -0,0 +1,50 @@
|
||||
//
|
||||
// Created by Grishka on 17.06.2018.
|
||||
//
|
||||
|
||||
#ifndef LIBTGVOIP_MESSAGETHREAD_H
|
||||
#define LIBTGVOIP_MESSAGETHREAD_H
|
||||
|
||||
#include "threading.h"
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
namespace tgvoip{
|
||||
class MessageThread : public Thread{
|
||||
public:
|
||||
MessageThread();
|
||||
virtual ~MessageThread();
|
||||
uint32_t Post(std::function<void()> func, double delay=0, double interval=0);
|
||||
void Cancel(uint32_t id);
|
||||
void CancelSelf();
|
||||
void Stop();
|
||||
|
||||
enum{
|
||||
INVALID_ID=0
|
||||
};
|
||||
private:
|
||||
struct Message{
|
||||
uint32_t id;
|
||||
double deliverAt;
|
||||
double interval;
|
||||
std::function<void()> func;
|
||||
};
|
||||
|
||||
void Run(void* arg);
|
||||
void InsertMessageInternal(Message& m);
|
||||
|
||||
bool running=true;
|
||||
std::vector<Message> queue;
|
||||
Mutex queueMutex;
|
||||
uint32_t lastMessageID=1;
|
||||
bool cancelCurrent=false;
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE event;
|
||||
#else
|
||||
pthread_cond_t cond;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
#endif //LIBTGVOIP_MESSAGETHREAD_H
|
||||
@ -10,6 +10,11 @@
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <opus/opus.h>
|
||||
#else
|
||||
#include "opus.h"
|
||||
#endif
|
||||
|
||||
#include "VoIPController.h"
|
||||
|
||||
@ -27,6 +32,11 @@ tgvoip::OpusDecoder::OpusDecoder(const std::unique_ptr<MediaStreamItf>& dst, boo
|
||||
Initialize(isAsync, needEC);
|
||||
}
|
||||
|
||||
tgvoip::OpusDecoder::OpusDecoder(MediaStreamItf* dst, bool isAsync, bool needEC){
|
||||
dst->SetCallback(OpusDecoder::Callback, this);
|
||||
Initialize(isAsync, needEC);
|
||||
}
|
||||
|
||||
void tgvoip::OpusDecoder::Initialize(bool isAsync, bool needEC){
|
||||
async=isAsync;
|
||||
if(async){
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
|
||||
|
||||
#include "MediaStreamItf.h"
|
||||
#include "opus.h"
|
||||
#include "threading.h"
|
||||
#include "BlockingQueue.h"
|
||||
#include "Buffers.h"
|
||||
@ -19,6 +18,8 @@
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
struct OpusDecoder;
|
||||
|
||||
namespace tgvoip{
|
||||
class OpusDecoder {
|
||||
public:
|
||||
@ -28,6 +29,7 @@ public:
|
||||
|
||||
OpusDecoder(const std::shared_ptr<MediaStreamItf>& dst, bool isAsync, bool needEC);
|
||||
OpusDecoder(const std::unique_ptr<MediaStreamItf>& dst, bool isAsync, bool needEC);
|
||||
OpusDecoder(MediaStreamItf* dst, bool isAsync, bool needEC);
|
||||
virtual ~OpusDecoder();
|
||||
size_t HandleCallback(unsigned char* data, size_t len);
|
||||
void SetEchoCanceller(EchoCanceller* canceller);
|
||||
@ -65,7 +67,6 @@ private:
|
||||
bool async;
|
||||
unsigned char nextBuffer[8192];
|
||||
unsigned char decodeBuffer[8192];
|
||||
bool first;
|
||||
size_t nextLen;
|
||||
unsigned int packetsPerFrame;
|
||||
ptrdiff_t remainingDataLen;
|
||||
|
||||
@ -8,6 +8,11 @@
|
||||
#include <assert.h>
|
||||
#include "logging.h"
|
||||
#include "VoIPServerConfig.h"
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <opus/opus.h>
|
||||
#else
|
||||
#include "opus.h"
|
||||
#endif
|
||||
|
||||
tgvoip::OpusEncoder::OpusEncoder(MediaStreamItf *source, bool needSecondary):queue(11), bufferPool(960*2, 10){
|
||||
this->source=source;
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
|
||||
|
||||
#include "MediaStreamItf.h"
|
||||
#include "opus.h"
|
||||
#include "threading.h"
|
||||
#include "BlockingQueue.h"
|
||||
#include "Buffers.h"
|
||||
@ -17,6 +16,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct OpusEncoder;
|
||||
|
||||
namespace tgvoip{
|
||||
class OpusEncoder{
|
||||
public:
|
||||
|
||||
1096
VoIPController.cpp
1096
VoIPController.cpp
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,7 @@
|
||||
#include "audio/AudioInput.h"
|
||||
#include "BlockingQueue.h"
|
||||
#include "audio/AudioOutput.h"
|
||||
#include "audio/AudioIO.h"
|
||||
#include "JitterBuffer.h"
|
||||
#include "OpusDecoder.h"
|
||||
#include "OpusEncoder.h"
|
||||
@ -31,8 +32,9 @@
|
||||
#include "NetworkSocket.h"
|
||||
#include "Buffers.h"
|
||||
#include "PacketReassembler.h"
|
||||
#include "MessageThread.h"
|
||||
|
||||
#define LIBTGVOIP_VERSION "2.1.1"
|
||||
#define LIBTGVOIP_VERSION "2.2"
|
||||
|
||||
#ifdef _WIN32
|
||||
#undef GetCurrentTime
|
||||
@ -124,7 +126,7 @@ namespace tgvoip{
|
||||
private:
|
||||
double lastPingTime;
|
||||
uint32_t lastPingSeq;
|
||||
double rtts[6];
|
||||
HistoricBuffer<double, 6> rtts;
|
||||
double averageRTT;
|
||||
NetworkSocket* socket;
|
||||
int udpPongCount;
|
||||
@ -251,7 +253,6 @@ namespace tgvoip{
|
||||
* @param cfg
|
||||
*/
|
||||
void SetConfig(const Config& cfg);
|
||||
float GetOutputLevel();
|
||||
void DebugCtl(int request, int param);
|
||||
/**
|
||||
*
|
||||
@ -360,11 +361,15 @@ namespace tgvoip{
|
||||
void (*connectionStateChanged)(VoIPController*, int);
|
||||
void (*signalBarCountChanged)(VoIPController*, int);
|
||||
void (*groupCallKeySent)(VoIPController*);
|
||||
void (*groupCallKeyReceived)(VoIPController*, unsigned char*);
|
||||
void (*groupCallKeyReceived)(VoIPController*, const unsigned char*);
|
||||
void (*upgradeToGroupCallRequested)(VoIPController*);
|
||||
};
|
||||
void SetCallbacks(Callbacks callbacks);
|
||||
|
||||
float GetOutputLevel(){
|
||||
return 0.0f;
|
||||
};
|
||||
|
||||
private:
|
||||
struct Stream;
|
||||
struct UnacknowledgedExtraData;
|
||||
@ -391,7 +396,7 @@ namespace tgvoip{
|
||||
struct QueuedPacket{
|
||||
Buffer data;
|
||||
unsigned char type;
|
||||
uint32_t seqs[16];
|
||||
HistoricBuffer<uint32_t, 16> seqs;
|
||||
double firstSentTime;
|
||||
double lastSentTime;
|
||||
double retryInterval;
|
||||
@ -407,6 +412,7 @@ namespace tgvoip{
|
||||
virtual void OnAudioOutputReady();
|
||||
virtual void SendExtra(Buffer& data, unsigned char type);
|
||||
void SendStreamFlags(Stream& stream);
|
||||
void InitializeTimers();
|
||||
|
||||
private:
|
||||
struct Stream{
|
||||
@ -438,10 +444,9 @@ namespace tgvoip{
|
||||
|
||||
void RunRecvThread(void* arg);
|
||||
void RunSendThread(void* arg);
|
||||
void RunTickThread(void* arg);
|
||||
void HandleAudioInput(unsigned char* data, size_t len, unsigned char* secondaryData, size_t secondaryLen);
|
||||
void HandleVideoInput(EncodedVideoFrame& frame);
|
||||
void UpdateAudioBitrate();
|
||||
void UpdateAudioBitrateLimit();
|
||||
void SetState(int state);
|
||||
void UpdateAudioOutputState();
|
||||
void InitUDPProxy();
|
||||
@ -460,6 +465,17 @@ namespace tgvoip{
|
||||
void StartAudio();
|
||||
void ProcessAcknowledgedOutgoingExtra(UnacknowledgedExtraData& extra);
|
||||
void AddIPv6Relays();
|
||||
void AddTCPRelays();
|
||||
void SendUdpPings();
|
||||
void EvaluateUdpPingResults();
|
||||
void UpdateRTT();
|
||||
void UpdateCongestion();
|
||||
void UpdateAudioBitrate();
|
||||
void UpdateSignalBars();
|
||||
void UpdateQueuedPackets();
|
||||
void SendNopPacket();
|
||||
void TickJitterBufferAngCongestionControl();
|
||||
|
||||
int state;
|
||||
std::vector<std::shared_ptr<Endpoint>> endpoints;
|
||||
std::shared_ptr<Endpoint> currentEndpoint;
|
||||
@ -472,11 +488,12 @@ namespace tgvoip{
|
||||
uint32_t lastSentSeq;
|
||||
std::vector<RecentOutgoingPacket> recentOutgoingPackets;
|
||||
double recvPacketTimes[32];
|
||||
uint32_t sendLossCountHistory[32];
|
||||
HistoricBuffer<uint32_t, 10, double> sendLossCountHistory;
|
||||
uint32_t audioTimestampIn;
|
||||
uint32_t audioTimestampOut;
|
||||
std::shared_ptr<tgvoip::audio::AudioIO> audioIO;
|
||||
tgvoip::audio::AudioInput* audioInput;
|
||||
std::unique_ptr<tgvoip::audio::AudioOutput> audioOutput;
|
||||
tgvoip::audio::AudioOutput* audioOutput;
|
||||
OpusEncoder* encoder;
|
||||
BlockingQueue<PendingOutgoingPacket>* sendQueue;
|
||||
EchoCanceller* echoCanceller;
|
||||
@ -487,12 +504,11 @@ namespace tgvoip{
|
||||
bool audioOutStarted;
|
||||
Thread* recvThread;
|
||||
Thread* sendThread;
|
||||
Thread* tickThread;
|
||||
uint32_t packetsReceived;
|
||||
uint32_t recvLossCount;
|
||||
uint32_t prevSendLossCount;
|
||||
uint32_t firstSentPing;
|
||||
double rttHistory[32];
|
||||
HistoricBuffer<double, 32> rttHistory;
|
||||
bool waitingForAcks;
|
||||
int networkType;
|
||||
int dontSendPackets;
|
||||
@ -532,10 +548,9 @@ namespace tgvoip{
|
||||
bool useTCP;
|
||||
bool useUDP;
|
||||
bool didAddTcpRelays;
|
||||
double setEstablishedAt;
|
||||
SocketSelectCanceller* selectCanceller;
|
||||
NetworkSocket* openingTcpSocket;
|
||||
unsigned char signalBarsHistory[4];
|
||||
HistoricBuffer<unsigned char, 4, int> signalBarsHistory;
|
||||
|
||||
BufferPool outgoingPacketsBufferPool;
|
||||
int udpConnectivityState;
|
||||
@ -550,8 +565,6 @@ namespace tgvoip{
|
||||
std::string proxyPassword;
|
||||
IPv4Address* resolvedProxyAddress;
|
||||
|
||||
int signalBarCount;
|
||||
|
||||
AutomaticGainControl* outputAGC;
|
||||
bool outputAGCEnabled;
|
||||
uint32_t peerCapabilities;
|
||||
@ -576,6 +589,11 @@ namespace tgvoip{
|
||||
bool didAddIPv6Relays;
|
||||
bool didSendIPv6Endpoint;
|
||||
int publicEndpointsReqCount=0;
|
||||
MessageThread messageThread;
|
||||
bool wasEstablished=false;
|
||||
|
||||
uint32_t initTimeoutID=MessageThread::INVALID_ID;
|
||||
uint32_t noStreamsNopID=MessageThread::INVALID_ID;
|
||||
|
||||
/*** server config values ***/
|
||||
uint32_t maxAudioBitrate;
|
||||
@ -594,11 +612,6 @@ namespace tgvoip{
|
||||
double relayToP2pSwitchThreshold;
|
||||
double reconnectingTimeout;
|
||||
|
||||
/*** platform-specific things **/
|
||||
#ifdef __APPLE__
|
||||
audio::AudioUnitIO* appleAudioIO;
|
||||
#endif
|
||||
|
||||
public:
|
||||
#ifdef __APPLE__
|
||||
static double machTimebase;
|
||||
|
||||
@ -467,7 +467,7 @@ void VoIPGroupController::SendUdpPing(shared_ptr<Endpoint> endpoint){
|
||||
void VoIPGroupController::SetNetworkType(int type){
|
||||
networkType=type;
|
||||
UpdateDataSavingState();
|
||||
UpdateAudioBitrate();
|
||||
UpdateAudioBitrateLimit();
|
||||
string itfName=udpSocket->GetLocalInterfaceInfo(NULL, NULL);
|
||||
if(itfName!=activeNetItfName){
|
||||
udpSocket->OnActiveInterfaceChanged();
|
||||
@ -544,7 +544,7 @@ void VoIPGroupController::SendRelayPings(){
|
||||
|
||||
void VoIPGroupController::OnAudioOutputReady(){
|
||||
encoder->SetDTX(true);
|
||||
audioMixer->SetOutput((unique_ptr<MediaStreamItf>&)audioOutput);
|
||||
audioMixer->SetOutput(audioOutput);
|
||||
audioMixer->SetEchoCanceller(echoCanceller);
|
||||
audioMixer->Start();
|
||||
audioOutput->Start();
|
||||
|
||||
10184
aclocal.m4
vendored
Normal file
10184
aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load Diff
88
audio/AudioIO.cpp
Normal file
88
audio/AudioIO.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
//
|
||||
// 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 "AudioIO.h"
|
||||
#include "../logging.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include "../os/android/AudioInputAndroid.h"
|
||||
#include "../os/android/AudioOutputAndroid.h"
|
||||
#elif defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#include "../os/darwin/AudioUnitIO.h"
|
||||
#if TARGET_OS_OSX
|
||||
#include "../os/darwin/AudioInputAudioUnitOSX.h"
|
||||
#include "../os/darwin/AudioOutputAudioUnitOSX.h"
|
||||
#endif
|
||||
#elif defined(_WIN32)
|
||||
#ifdef TGVOIP_WINXP_COMPAT
|
||||
#include "../os/windows/AudioInputWave.h"
|
||||
#include "../os/windows/AudioOutputWave.h"
|
||||
#endif
|
||||
#include "../os/windows/AudioInputWASAPI.h"
|
||||
#include "../os/windows/AudioOutputWASAPI.h"
|
||||
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__gnu_hurd__)
|
||||
#ifndef WITHOUT_ALSA
|
||||
#include "../os/linux/AudioInputALSA.h"
|
||||
#include "../os/linux/AudioOutputALSA.h"
|
||||
#endif
|
||||
#ifndef WITHOUT_PULSE
|
||||
#include "../os/linux/AudioPulse.h"
|
||||
#endif
|
||||
#else
|
||||
#error "Unsupported operating system"
|
||||
#endif
|
||||
|
||||
using namespace tgvoip;
|
||||
using namespace tgvoip::audio;
|
||||
using namespace std;
|
||||
|
||||
shared_ptr<AudioIO> AudioIO::Create(){
|
||||
std::string inputDevice="default", outputDevice="default";
|
||||
#if defined(__ANDROID__)
|
||||
return std::make_shared<ContextlessAudioIO<AudioInputAndroid, AudioOutputAndroid>>();
|
||||
#elif defined(__APPLE__)
|
||||
#if TARGET_OS_OSX
|
||||
if(kCFCoreFoundationVersionNumber<kCFCoreFoundationVersionNumber10_7)
|
||||
return std::make_shared<ContextlessAudioIO<AudioInputAudioUnitLegacy, AudioOutputAudioUnitLegacy>>(inputDevice, outputDevice);
|
||||
|
||||
#endif
|
||||
return std::make_shared<AudioUnitIO>();
|
||||
#elif defined(_WIN32)
|
||||
#ifdef TGVOIP_WINXP_COMPAT
|
||||
if(LOBYTE(LOWORD(GetVersion()))<6)
|
||||
return std::make_shared<ContextlessAudioIO<AudioInputWave, AudioOutputWave>>(inputDevice, outputDevice);
|
||||
#endif
|
||||
return std::make_shared<ContextlessAudioIO<AudioInputWASAPI, AudioOutputWASAPI>>(inputDevice, outputDevice);
|
||||
#elif defined(__linux__)
|
||||
#ifndef WITHOUT_ALSA
|
||||
#ifndef WITHOUT_PULSE
|
||||
if(AudioPulse::Load()){
|
||||
std::shared_ptr<AudioIO> io=std::make_shared<AudioPulse>(inputDevice, outputDevice);
|
||||
if(!io->Failed() && io->GetInput()->IsInitialized() && io->GetOutput()->IsInitialized())
|
||||
return io;
|
||||
LOGW("PulseAudio available but not working; trying ALSA");
|
||||
}
|
||||
#endif
|
||||
return std::make_shared<ContextlessAudioIO<AudioInputALSA, AudioOutputALSA>>(inputDevice, outputDevice);
|
||||
#else
|
||||
return std::make_shared<AudioPulse>(inputDevice, outputDevice);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool AudioIO::Failed(){
|
||||
return failed;
|
||||
}
|
||||
|
||||
std::string AudioIO::GetErrorDescription(){
|
||||
return error;
|
||||
}
|
||||
62
audio/AudioIO.h
Normal file
62
audio/AudioIO.h
Normal file
@ -0,0 +1,62 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
|
||||
#ifndef LIBTGVOIP_AUDIOIO_H
|
||||
#define LIBTGVOIP_AUDIOIO_H
|
||||
|
||||
#include "AudioInput.h"
|
||||
#include "AudioOutput.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace tgvoip{
|
||||
namespace audio {
|
||||
class AudioIO{
|
||||
public:
|
||||
virtual ~AudioIO(){};
|
||||
static std::shared_ptr<AudioIO> Create();
|
||||
virtual AudioInput* GetInput()=0;
|
||||
virtual AudioOutput* GetOutput()=0;
|
||||
bool Failed();
|
||||
std::string GetErrorDescription();
|
||||
protected:
|
||||
bool failed=false;
|
||||
std::string error;
|
||||
};
|
||||
|
||||
template<class I, class O> class ContextlessAudioIO : public AudioIO{
|
||||
public:
|
||||
ContextlessAudioIO(){
|
||||
input=new I();
|
||||
output=new O();
|
||||
}
|
||||
|
||||
ContextlessAudioIO(std::string inputDeviceID, std::string outputDeviceID){
|
||||
input=new I(inputDeviceID);
|
||||
output=new O(outputDeviceID);
|
||||
}
|
||||
|
||||
virtual ~ContextlessAudioIO(){
|
||||
delete input;
|
||||
delete output;
|
||||
}
|
||||
|
||||
virtual AudioInput* GetInput(){
|
||||
return input;
|
||||
}
|
||||
|
||||
virtual AudioOutput* GetOutput(){
|
||||
return output;
|
||||
}
|
||||
private:
|
||||
I* input;
|
||||
O* output;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif //LIBTGVOIP_AUDIOIO_H
|
||||
@ -6,6 +6,11 @@
|
||||
|
||||
#include "AudioInput.h"
|
||||
#include "../logging.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include "../os/android/AudioInputAndroid.h"
|
||||
#elif defined(__APPLE__)
|
||||
@ -20,8 +25,12 @@
|
||||
#endif
|
||||
#include "../os/windows/AudioInputWASAPI.h"
|
||||
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__gnu_hurd__)
|
||||
#ifndef WITHOUT_ALSA
|
||||
#include "../os/linux/AudioInputALSA.h"
|
||||
#include "../os/linux/AudioInputPulse.h"
|
||||
#endif
|
||||
#ifndef WITHOUT_PULSE
|
||||
#include "../os/linux/AudioPulse.h"
|
||||
#endif
|
||||
#else
|
||||
#error "Unsupported operating system"
|
||||
#endif
|
||||
@ -39,7 +48,7 @@ AudioInput::AudioInput(std::string deviceID) : currentDevice(deviceID){
|
||||
failed=false;
|
||||
}
|
||||
|
||||
AudioInput *AudioInput::Create(std::string deviceID, void* platformSpecific){
|
||||
/*AudioInput *AudioInput::Create(std::string deviceID, void* platformSpecific){
|
||||
#if defined(__ANDROID__)
|
||||
return new AudioInputAndroid();
|
||||
#elif defined(__APPLE__)
|
||||
@ -65,7 +74,7 @@ AudioInput *AudioInput::Create(std::string deviceID, void* platformSpecific){
|
||||
}
|
||||
return new AudioInputALSA(deviceID);
|
||||
#endif
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
AudioInput::~AudioInput(){
|
||||
@ -88,8 +97,14 @@ void AudioInput::EnumerateDevices(std::vector<AudioInputDevice>& devs){
|
||||
#endif
|
||||
AudioInputWASAPI::EnumerateDevices(devs);
|
||||
#elif defined(__linux__) && !defined(__ANDROID__)
|
||||
if(!AudioInputPulse::IsAvailable() || !AudioInputPulse::EnumerateDevices(devs))
|
||||
#if !defined(WITHOUT_PULSE) && !defined(WITHOUT_ALSA)
|
||||
if(!AudioInputPulse::EnumerateDevices(devs))
|
||||
AudioInputALSA::EnumerateDevices(devs);
|
||||
#elif defined(WITHOUT_PULSE)
|
||||
AudioInputALSA::EnumerateDevices(devs);
|
||||
#else
|
||||
AudioInputPulse::EnumerateDevices(devs)
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -24,11 +24,10 @@ public:
|
||||
AudioInput(std::string deviceID);
|
||||
virtual ~AudioInput();
|
||||
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels)=0;
|
||||
bool IsInitialized();
|
||||
virtual std::string GetCurrentDevice();
|
||||
virtual void SetCurrentDevice(std::string deviceID);
|
||||
static AudioInput* Create(std::string deviceID, void* platformSpecific);
|
||||
//static AudioInput* Create(std::string deviceID, void* platformSpecific);
|
||||
static void EnumerateDevices(std::vector<AudioInputDevice>& devs);
|
||||
static int32_t GetEstimatedDelay();
|
||||
|
||||
|
||||
@ -7,6 +7,11 @@
|
||||
#include "AudioOutput.h"
|
||||
#include "../logging.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include "../os/android/AudioOutputOpenSLES.h"
|
||||
#include "../os/android/AudioOutputAndroid.h"
|
||||
@ -23,8 +28,13 @@
|
||||
#endif
|
||||
#include "../os/windows/AudioOutputWASAPI.h"
|
||||
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__gnu_hurd__)
|
||||
#ifndef WITHOUT_ALSA
|
||||
#include "../os/linux/AudioOutputALSA.h"
|
||||
#endif
|
||||
#ifndef WITHOUT_PULSE
|
||||
#include "../os/linux/AudioOutputPulse.h"
|
||||
#include "../os/linux/AudioPulse.h"
|
||||
#endif
|
||||
#else
|
||||
#error "Unsupported operating system"
|
||||
#endif
|
||||
@ -34,7 +44,7 @@ using namespace tgvoip::audio;
|
||||
|
||||
int32_t AudioOutput::estimatedDelay=60;
|
||||
|
||||
std::unique_ptr<AudioOutput> AudioOutput::Create(std::string deviceID, void* platformSpecific){
|
||||
/*std::unique_ptr<AudioOutput> AudioOutput::Create(std::string deviceID, void* platformSpecific){
|
||||
#if defined(__ANDROID__)
|
||||
return std::unique_ptr<AudioOutput>(new AudioOutputAndroid());
|
||||
#elif defined(__APPLE__)
|
||||
@ -60,7 +70,7 @@ std::unique_ptr<AudioOutput> AudioOutput::Create(std::string deviceID, void* pla
|
||||
}
|
||||
return std::unique_ptr<AudioOutput>(new AudioOutputALSA(deviceID));
|
||||
#endif
|
||||
}
|
||||
}*/
|
||||
|
||||
AudioOutput::AudioOutput() : currentDevice("default"){
|
||||
failed=false;
|
||||
@ -85,10 +95,6 @@ int32_t AudioOutput::GetEstimatedDelay(){
|
||||
return estimatedDelay;
|
||||
}
|
||||
|
||||
float AudioOutput::GetLevel(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void AudioOutput::EnumerateDevices(std::vector<AudioOutputDevice>& devs){
|
||||
#if defined(__APPLE__) && TARGET_OS_OSX
|
||||
@ -102,8 +108,14 @@ void AudioOutput::EnumerateDevices(std::vector<AudioOutputDevice>& devs){
|
||||
#endif
|
||||
AudioOutputWASAPI::EnumerateDevices(devs);
|
||||
#elif defined(__linux__) && !defined(__ANDROID__)
|
||||
if(!AudioOutputPulse::IsAvailable() || !AudioOutputPulse::EnumerateDevices(devs))
|
||||
#if !defined(WITHOUT_PULSE) && !defined(WITHOUT_ALSA)
|
||||
if(!AudioOutputPulse::EnumerateDevices(devs))
|
||||
AudioOutputALSA::EnumerateDevices(devs);
|
||||
#elif defined(WITHOUT_PULSE)
|
||||
AudioOutputALSA::EnumerateDevices(devs);
|
||||
#else
|
||||
AudioOutputPulse::EnumerateDevices(devs)
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -24,13 +24,11 @@ public:
|
||||
AudioOutput();
|
||||
AudioOutput(std::string deviceID);
|
||||
virtual ~AudioOutput();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels)=0;
|
||||
virtual bool IsPlaying()=0;
|
||||
virtual float GetLevel();
|
||||
static int32_t GetEstimatedDelay();
|
||||
virtual std::string GetCurrentDevice();
|
||||
virtual void SetCurrentDevice(std::string deviceID);
|
||||
static std::unique_ptr<AudioOutput> Create(std::string deviceID, void* platformSpecific);
|
||||
//static std::unique_ptr<AudioOutput> Create(std::string deviceID, void* platformSpecific);
|
||||
static void EnumerateDevices(std::vector<AudioOutputDevice>& devs);
|
||||
bool IsInitialized();
|
||||
|
||||
|
||||
@ -103,7 +103,7 @@ namespace tgvoip {
|
||||
}
|
||||
}
|
||||
|
||||
void groupCallKeyReceived(VoIPController *cntrlr, unsigned char *key){
|
||||
void groupCallKeyReceived(VoIPController *cntrlr, const unsigned char *key){
|
||||
impl_data_android_t *impl=(impl_data_android_t *) cntrlr->implData;
|
||||
if(!impl->javaObject)
|
||||
return;
|
||||
|
||||
348
compile
Executable file
348
compile
Executable file
@ -0,0 +1,348 @@
|
||||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2018-03-07.03; # UTC
|
||||
|
||||
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# We need space, tab and new line, in precisely that order. Quoting is
|
||||
# there to prevent tools from complaining about whitespace usage.
|
||||
IFS=" "" $nl"
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file lazy
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts. If the determined conversion
|
||||
# type is listed in (the comma separated) LAZY, no conversion will
|
||||
# take place.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv/,$2, in
|
||||
*,$file_conv,*)
|
||||
;;
|
||||
mingw/*)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin/*)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine/*)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_cl_dashL linkdir
|
||||
# Make cl look for libraries in LINKDIR
|
||||
func_cl_dashL ()
|
||||
{
|
||||
func_file_conv "$1"
|
||||
if test -z "$lib_path"; then
|
||||
lib_path=$file
|
||||
else
|
||||
lib_path="$lib_path;$file"
|
||||
fi
|
||||
linker_opts="$linker_opts -LIBPATH:$file"
|
||||
}
|
||||
|
||||
# func_cl_dashl library
|
||||
# Do a library search-path lookup for cl
|
||||
func_cl_dashl ()
|
||||
{
|
||||
lib=$1
|
||||
found=no
|
||||
save_IFS=$IFS
|
||||
IFS=';'
|
||||
for dir in $lib_path $LIB
|
||||
do
|
||||
IFS=$save_IFS
|
||||
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.dll.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/$lib.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/lib$lib.a"; then
|
||||
found=yes
|
||||
lib=$dir/lib$lib.a
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS=$save_IFS
|
||||
|
||||
if test "$found" != yes; then
|
||||
lib=$lib.lib
|
||||
fi
|
||||
}
|
||||
|
||||
# func_cl_wrapper cl arg...
|
||||
# Adjust compile command to suit cl
|
||||
func_cl_wrapper ()
|
||||
{
|
||||
# Assume a capable shell
|
||||
lib_path=
|
||||
shared=:
|
||||
linker_opts=
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.[oO][bB][jJ])
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fo"$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fe"$file"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-I)
|
||||
eat=1
|
||||
func_file_conv "$2" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-I*)
|
||||
func_file_conv "${1#-I}" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-l)
|
||||
eat=1
|
||||
func_cl_dashl "$2"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-l*)
|
||||
func_cl_dashl "${1#-l}"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-L)
|
||||
eat=1
|
||||
func_cl_dashL "$2"
|
||||
;;
|
||||
-L*)
|
||||
func_cl_dashL "${1#-L}"
|
||||
;;
|
||||
-static)
|
||||
shared=false
|
||||
;;
|
||||
-Wl,*)
|
||||
arg=${1#-Wl,}
|
||||
save_ifs="$IFS"; IFS=','
|
||||
for flag in $arg; do
|
||||
IFS="$save_ifs"
|
||||
linker_opts="$linker_opts $flag"
|
||||
done
|
||||
IFS="$save_ifs"
|
||||
;;
|
||||
-Xlinker)
|
||||
eat=1
|
||||
linker_opts="$linker_opts $2"
|
||||
;;
|
||||
-*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||
func_file_conv "$1"
|
||||
set x "$@" -Tp"$file"
|
||||
shift
|
||||
;;
|
||||
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||
func_file_conv "$1" mingw
|
||||
set x "$@" "$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if test -n "$linker_opts"; then
|
||||
linker_opts="-link$linker_opts"
|
||||
fi
|
||||
exec "$@" $linker_opts
|
||||
exit 1
|
||||
}
|
||||
|
||||
eat=
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand '-c -o'.
|
||||
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file 'INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
|
||||
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
|
||||
func_cl_wrapper "$@" # Doesn't return...
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
# So we strip '-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no '-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# '.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
1476
config.guess
vendored
Executable file
1476
config.guess
vendored
Executable file
File diff suppressed because it is too large
Load Diff
265
config.h.in
Normal file
265
config.h.in
Normal file
@ -0,0 +1,265 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
|
||||
systems. This function is required for `alloca.c' support on those systems.
|
||||
*/
|
||||
#undef CRAY_STACKSEG_END
|
||||
|
||||
/* Define to 1 if using `alloca.c'. */
|
||||
#undef C_ALLOCA
|
||||
|
||||
/* Define to 1 if you have `alloca', as a function or macro. */
|
||||
#undef HAVE_ALLOCA
|
||||
|
||||
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
|
||||
*/
|
||||
#undef HAVE_ALLOCA_H
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#undef HAVE_ARPA_INET_H
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#undef HAVE_CLOCK_GETTIME
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the <float.h> header file. */
|
||||
#undef HAVE_FLOAT_H
|
||||
|
||||
/* Define to 1 if you have the `floor' function. */
|
||||
#undef HAVE_FLOOR
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#undef HAVE_GETTIMEOFDAY
|
||||
|
||||
/* Define to 1 if you have the `inet_ntoa' function. */
|
||||
#undef HAVE_INET_NTOA
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `crypto' library (-lcrypto). */
|
||||
#undef HAVE_LIBCRYPTO
|
||||
|
||||
/* Define to 1 if you have the `dl' library (-ldl). */
|
||||
#undef HAVE_LIBDL
|
||||
|
||||
/* Define to 1 if you have the `m' library (-lm). */
|
||||
#undef HAVE_LIBM
|
||||
|
||||
/* Define to 1 if you have the `opus' library (-lopus). */
|
||||
#undef HAVE_LIBOPUS
|
||||
|
||||
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
||||
#undef HAVE_LIBPTHREAD
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
|
||||
to 0 otherwise. */
|
||||
#undef HAVE_MALLOC
|
||||
|
||||
/* Define to 1 if you have the <malloc.h> header file. */
|
||||
#undef HAVE_MALLOC_H
|
||||
|
||||
/* Define to 1 if you have the `memmove' function. */
|
||||
#undef HAVE_MEMMOVE
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#undef HAVE_MEMSET
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
#undef HAVE_NETDB_H
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#undef HAVE_NETINET_IN_H
|
||||
|
||||
/* Define to 1 if the system has the type `ptrdiff_t'. */
|
||||
#undef HAVE_PTRDIFF_T
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
|
||||
and to 0 otherwise. */
|
||||
#undef HAVE_REALLOC
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
#undef HAVE_SELECT
|
||||
|
||||
/* Define to 1 if you have the `socket' function. */
|
||||
#undef HAVE_SOCKET
|
||||
|
||||
/* Define to 1 if you have the `sqrt' function. */
|
||||
#undef HAVE_SQRT
|
||||
|
||||
/* Define to 1 if you have the <stddef.h> header file. */
|
||||
#undef HAVE_STDDEF_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the `strcasecmp' function. */
|
||||
#undef HAVE_STRCASECMP
|
||||
|
||||
/* Define to 1 if you have the `strchr' function. */
|
||||
#undef HAVE_STRCHR
|
||||
|
||||
/* Define to 1 if you have the `strerror' function. */
|
||||
#undef HAVE_STRERROR
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `strncasecmp' function. */
|
||||
#undef HAVE_STRNCASECMP
|
||||
|
||||
/* Define to 1 if you have the `strstr' function. */
|
||||
#undef HAVE_STRSTR
|
||||
|
||||
/* Define to 1 if you have the `strtol' function. */
|
||||
#undef HAVE_STRTOL
|
||||
|
||||
/* Define to 1 if you have the `strtoul' function. */
|
||||
#undef HAVE_STRTOUL
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#undef HAVE_SYS_IOCTL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#undef HAVE_SYS_SOCKET_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#undef HAVE_SYS_TIME_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the `uname' function. */
|
||||
#undef HAVE_UNAME
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the <wchar.h> header file. */
|
||||
#undef HAVE_WCHAR_H
|
||||
|
||||
/* Define to 1 if the system has the type `_Bool'. */
|
||||
#undef HAVE__BOOL
|
||||
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* If using the C implementation of alloca, define if you know the
|
||||
direction of stack growth for your system; otherwise it will be
|
||||
automatically deduced at runtime.
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||
#undef STACK_DIRECTION
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Define to disable ALSA support */
|
||||
#undef WITHOUT_ALSA
|
||||
|
||||
/* Define to disable PulseAudio support */
|
||||
#undef WITHOUT_PULSE
|
||||
|
||||
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
|
||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
||||
#define below would cause a syntax error. */
|
||||
#undef _UINT32_T
|
||||
|
||||
/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
|
||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
||||
#define below would cause a syntax error. */
|
||||
#undef _UINT64_T
|
||||
|
||||
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
|
||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
||||
#define below would cause a syntax error. */
|
||||
#undef _UINT8_T
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
#undef inline
|
||||
#endif
|
||||
|
||||
/* Define to the type of a signed integer type of width exactly 16 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
#undef int16_t
|
||||
|
||||
/* Define to the type of a signed integer type of width exactly 32 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
#undef int32_t
|
||||
|
||||
/* Define to the type of a signed integer type of width exactly 64 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
#undef int64_t
|
||||
|
||||
/* Define to the type of a signed integer type of width exactly 8 bits if such
|
||||
a type exists and the standard includes do not define it. */
|
||||
#undef int8_t
|
||||
|
||||
/* Define to rpl_malloc if the replacement function should be used. */
|
||||
#undef malloc
|
||||
|
||||
/* Define to rpl_realloc if the replacement function should be used. */
|
||||
#undef realloc
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef ssize_t
|
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 16 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
#undef uint16_t
|
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 32 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
#undef uint32_t
|
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 64 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
#undef uint64_t
|
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 8 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
#undef uint8_t
|
||||
1801
config.sub
vendored
Executable file
1801
config.sub
vendored
Executable file
File diff suppressed because it is too large
Load Diff
110
configure.ac
Normal file
110
configure.ac
Normal file
@ -0,0 +1,110 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.69])
|
||||
AC_INIT([libtgvoip], [2.2], [https://github.com/grishka/libtgvoip/issues])
|
||||
AC_CONFIG_SRCDIR([config.h.in])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AM_INIT_AUTOMAKE([subdir-objects])
|
||||
AM_SILENT_RULES([yes])
|
||||
LT_INIT
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CC
|
||||
AC_PROG_OBJCXX
|
||||
AM_PROG_AS
|
||||
AC_PROG_RANLIB
|
||||
|
||||
# Checks for libraries.
|
||||
AC_CHECK_LIB([crypto], [SHA1], [], [AC_MSG_FAILURE([libssl-dev is required but not found])])
|
||||
AC_CHECK_LIB([m], [floorf])
|
||||
AC_CHECK_LIB([opus], [opus_decoder_create], [], [AC_MSG_FAILURE([libopus-dev is required but not found])])
|
||||
AC_CHECK_LIB([pthread], [pthread_create])
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
AS_CASE([$host_cpu],
|
||||
[i?86], [cpu_x86=yes],
|
||||
[x86_64], [cpu_x86=yes],
|
||||
[arm*], [cpu_arm=yes],
|
||||
[AS_ECHO("!! WARNING: libtgvoip wasn't tested with your CPU architecture ($host_cpu)")]
|
||||
)
|
||||
AS_CASE([$host_cpu],
|
||||
[armv7*], [cpu_armv7=yes]
|
||||
)
|
||||
AS_ECHO("Detected CPU: $host_cpu")
|
||||
AM_CONDITIONAL(TARGET_CPU_X86, test "x$cpu_x86" == xyes)
|
||||
AM_CONDITIONAL(TARGET_CPU_ARM, test "x$cpu_arm" == xyes)
|
||||
AM_CONDITIONAL(TARGET_CPU_ARMV7, test "x$cpu_armv7" == xyes)
|
||||
AS_ECHO("Detected OS: $host_os")
|
||||
|
||||
AS_CASE([$host_os],
|
||||
[darwin*], [os_osx=yes]
|
||||
)
|
||||
AM_CONDITIONAL(TARGET_OS_OSX, test "x$os_osx" == xyes)
|
||||
|
||||
AS_IF([test "x$os_osx" != xyes], [ # Linux
|
||||
AC_CHECK_LIB([dl], [dlopen])
|
||||
|
||||
AC_ARG_WITH([pulse], [AS_HELP_STRING([--without-pulse], [disable PulseAudio support])], [], [with_pulse=yes])
|
||||
AC_ARG_WITH([alsa], [AS_HELP_STRING([--without-alsa], [disable ALSA support])], [], [with_alsa=yes])
|
||||
|
||||
AS_IF([test "x$with_pulse" == xno && test "x$with_alsa" == xno], [
|
||||
AC_MSG_FAILURE([You can only disable either ALSA or PulseAudio, not both]);
|
||||
])
|
||||
|
||||
AS_IF([test "x$with_pulse" != xno], [
|
||||
AC_CHECK_LIB([pulse], [pa_context_new], [
|
||||
AS_ECHO_N( ) # what is the proper way to check for a library without linking it?
|
||||
], [
|
||||
AC_MSG_FAILURE([libpulse-dev is required during build, but you don't have it installed. Use --without-pulse to disable PulseAudio support.])
|
||||
])
|
||||
], [
|
||||
AC_DEFINE([WITHOUT_PULSE], [1], [Define to disable PulseAudio support])
|
||||
])
|
||||
|
||||
AS_IF([test "x$with_alsa" != xno], [
|
||||
AC_CHECK_LIB([asound], [snd_pcm_open], [
|
||||
AS_ECHO_N( ) # what is the proper way to check for a library without linking it?
|
||||
], [
|
||||
AC_MSG_FAILURE([libasound-dev is required during build, but you don't have it installed. Use --without-alsa to disable ALSA support.])
|
||||
])
|
||||
], [
|
||||
AC_DEFINE([WITHOUT_ALSA], [1], [Define to disable ALSA support])
|
||||
])
|
||||
]);
|
||||
|
||||
AM_CONDITIONAL(WITH_PULSE, test "x$with_pulse" == xyes)
|
||||
AM_CONDITIONAL(WITH_ALSA, test "x$with_alsa" == xyes)
|
||||
|
||||
AC_ARG_ENABLE([dsp], [AS_HELP_STRING([--disable-dsp], [disable signal processing (echo cancellation, noise suppression, and automatic gain control)])], [], [enable_dsp=yes])
|
||||
AM_CONDITIONAL(ENABLE_DSP, test "x$enable_dsp" == xyes)
|
||||
|
||||
# Checks for header files.
|
||||
AC_FUNC_ALLOCA
|
||||
AC_CHECK_HEADERS([arpa/inet.h float.h malloc.h netdb.h netinet/in.h stddef.h stdint.h stdlib.h string.h sys/ioctl.h sys/socket.h sys/time.h unistd.h wchar.h])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_CHECK_HEADER_STDBOOL
|
||||
AC_C_INLINE
|
||||
AC_TYPE_INT16_T
|
||||
AC_TYPE_INT32_T
|
||||
AC_TYPE_INT64_T
|
||||
AC_TYPE_INT8_T
|
||||
AC_TYPE_SIZE_T
|
||||
AC_TYPE_SSIZE_T
|
||||
AC_TYPE_UINT16_T
|
||||
AC_TYPE_UINT32_T
|
||||
AC_TYPE_UINT64_T
|
||||
AC_TYPE_UINT8_T
|
||||
AC_CHECK_TYPES([ptrdiff_t])
|
||||
|
||||
# Checks for library functions.
|
||||
AC_FUNC_ERROR_AT_LINE
|
||||
AC_FUNC_MALLOC
|
||||
AC_FUNC_REALLOC
|
||||
AC_CHECK_FUNCS([clock_gettime floor gettimeofday inet_ntoa memmove memset select socket sqrt strcasecmp strchr strerror strncasecmp strstr strtol strtoul uname])
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
791
depcomp
Executable file
791
depcomp
Executable file
@ -0,0 +1,791 @@
|
||||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2018-03-07.03; # UTC
|
||||
|
||||
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by 'PROGRAMS ARGS'.
|
||||
object Object file output by 'PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputting dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
# Get the directory component of the given path, and save it in the
|
||||
# global variables '$dir'. Note that this directory component will
|
||||
# be either empty or ending with a '/' character. This is deliberate.
|
||||
set_dir_from ()
|
||||
{
|
||||
case $1 in
|
||||
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
|
||||
*) dir=;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get the suffix-stripped basename of the given path, and save it the
|
||||
# global variable '$base'.
|
||||
set_base_from ()
|
||||
{
|
||||
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
|
||||
}
|
||||
|
||||
# If no dependency file was actually created by the compiler invocation,
|
||||
# we still have to create a dummy depfile, to avoid errors with the
|
||||
# Makefile "include basename.Plo" scheme.
|
||||
make_dummy_depfile ()
|
||||
{
|
||||
echo "#dummy" > "$depfile"
|
||||
}
|
||||
|
||||
# Factor out some common post-processing of the generated depfile.
|
||||
# Requires the auxiliary global variable '$tmpdepfile' to be set.
|
||||
aix_post_process_depfile ()
|
||||
{
|
||||
# If the compiler actually managed to produce a dependency file,
|
||||
# post-process it.
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form 'foo.o: dependency.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# $object: dependency.h
|
||||
# and one to simply output
|
||||
# dependency.h:
|
||||
# which is needed to avoid the deleted-header problem.
|
||||
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
|
||||
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
|
||||
} > "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
}
|
||||
|
||||
# A tabulation character.
|
||||
tab=' '
|
||||
# A newline character.
|
||||
nl='
|
||||
'
|
||||
# Character ranges might be problematic outside the C locale.
|
||||
# These definitions help.
|
||||
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
lower=abcdefghijklmnopqrstuvwxyz
|
||||
digits=0123456789
|
||||
alpha=${upper}${lower}
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Avoid interferences from the environment.
|
||||
gccflag= dashmflag=
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
if test "$depmode" = msvc7msys; then
|
||||
# This is just like msvc7 but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvc7
|
||||
fi
|
||||
|
||||
if test "$depmode" = xlc; then
|
||||
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
|
||||
gccflag=-qmakedep=gcc,-MF
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||
## the command line argument order; so add the flags where they
|
||||
## appear in depend2.am. Note that the slowdown incurred here
|
||||
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||
*) set fnord "$@" "$arg" ;;
|
||||
esac
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
|
||||
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
|
||||
## (see the conditional assignment to $gccflag above).
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say). Also, it might not be
|
||||
## supported by the other compilers which use the 'gcc' depmode.
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The second -e expression handles DOS-style file names with drive
|
||||
# letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the "deleted header file" problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
## Some versions of gcc put a space before the ':'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||
## to the object. Take care to not repeat it in the output.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
|
||||
| tr "$nl" ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
xlc)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
tcc)
|
||||
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
|
||||
# FIXME: That version still under development at the moment of writing.
|
||||
# Make that this statement remains true also for stable, released
|
||||
# versions.
|
||||
# It will wrap lines (doesn't matter whether long or short) with a
|
||||
# trailing '\', as in:
|
||||
#
|
||||
# foo.o : \
|
||||
# foo.c \
|
||||
# foo.h \
|
||||
#
|
||||
# It will put a trailing '\' even on the last line, and will use leading
|
||||
# spaces rather than leading tabs (at least since its commit 0394caf7
|
||||
# "Emit spaces for -MD").
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
|
||||
# We have to change lines of the first kind to '$object: \'.
|
||||
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
|
||||
# And for each line of the second kind, we have to emit a 'dep.h:'
|
||||
# dummy dependency, to avoid the deleted-header problem.
|
||||
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
## The order of this option in the case statement is important, since the
|
||||
## shell code in configure will try each of these formats in the order
|
||||
## listed in this file. A plain '-MD' option would be understood by many
|
||||
## compilers, so we must ensure this comes after the gcc and icc options.
|
||||
pgcc)
|
||||
# Portland's C compiler understands '-MD'.
|
||||
# Will always output deps to 'file.d' where file is the root name of the
|
||||
# source file under compilation, even if file resides in a subdirectory.
|
||||
# The object file name does not affect the name of the '.d' file.
|
||||
# pgcc 10.2 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using '\' :
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
set_dir_from "$object"
|
||||
# Use the source, not the object, to determine the base name, since
|
||||
# that's sadly what pgcc will do too.
|
||||
set_base_from "$source"
|
||||
tmpdepfile=$base.d
|
||||
|
||||
# For projects that build the same source file twice into different object
|
||||
# files, the pgcc approach of using the *source* file root name can cause
|
||||
# problems in parallel builds. Use a locking strategy to avoid stomping on
|
||||
# the same $tmpdepfile.
|
||||
lockdir=$base.d-lock
|
||||
trap "
|
||||
echo '$0: caught signal, cleaning up...' >&2
|
||||
rmdir '$lockdir'
|
||||
exit 1
|
||||
" 1 2 13 15
|
||||
numtries=100
|
||||
i=$numtries
|
||||
while test $i -gt 0; do
|
||||
# mkdir is a portable test-and-set.
|
||||
if mkdir "$lockdir" 2>/dev/null; then
|
||||
# This process acquired the lock.
|
||||
"$@" -MD
|
||||
stat=$?
|
||||
# Release the lock.
|
||||
rmdir "$lockdir"
|
||||
break
|
||||
else
|
||||
# If the lock is being held by a different process, wait
|
||||
# until the winning process is done or we timeout.
|
||||
while test -d "$lockdir" && test $i -gt 0; do
|
||||
sleep 1
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
fi
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
trap - 1 2 13 15
|
||||
if test $i -le 0; then
|
||||
echo "$0: failed to acquire lock after $numtries attempts" >&2
|
||||
echo "$0: check lockdir '$lockdir'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form `foo.o: dependent.h',
|
||||
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp2)
|
||||
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||
# compilers, which have integrated preprocessors. The correct option
|
||||
# to use with these is +Maked; it writes dependencies to a file named
|
||||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
"$@" -Wc,+Maked
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add 'dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in 'foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# Libtool generates 2 separate objects for the 2 libraries. These
|
||||
# two compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
|
||||
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
# Same post-processing that is required for AIX mode.
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
msvc7)
|
||||
if test "$libtool" = yes; then
|
||||
showIncludes=-Wc,-showIncludes
|
||||
else
|
||||
showIncludes=-showIncludes
|
||||
fi
|
||||
"$@" $showIncludes > "$tmpdepfile"
|
||||
stat=$?
|
||||
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The first sed program below extracts the file names and escapes
|
||||
# backslashes for cygpath. The second sed program outputs the file
|
||||
# name when reading, but also accumulates all include files in the
|
||||
# hold buffer in order to output them again at the end. This only
|
||||
# works with sed implementations that can handle large buffers.
|
||||
sed < "$tmpdepfile" -n '
|
||||
/^Note: including file: *\(.*\)/ {
|
||||
s//\1/
|
||||
s/\\/\\\\/g
|
||||
p
|
||||
}' | $cygpath_u | sort -u | sed -n '
|
||||
s/ /\\ /g
|
||||
s/\(.*\)/'"$tab"'\1 \\/p
|
||||
s/.\(.*\) \\/\1:/
|
||||
H
|
||||
$ {
|
||||
s/.*/'"$tab"'/
|
||||
G
|
||||
p
|
||||
}' >> "$depfile"
|
||||
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7msys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for ':'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this sed invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
# makedepend may prepend the VPATH from the source file name to the object.
|
||||
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process the last invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed '1,2d' "$tmpdepfile" \
|
||||
| tr ' ' "$nl" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E \
|
||||
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
| sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||
echo "$tab" >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
518
install-sh
Executable file
518
install-sh
Executable file
@ -0,0 +1,518 @@
|
||||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2018-03-11.20; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# 'make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
|
||||
tab=' '
|
||||
nl='
|
||||
'
|
||||
IFS=" $tab$nl"
|
||||
|
||||
# Set DOITPROG to "echo" to test this script.
|
||||
|
||||
doit=${DOITPROG-}
|
||||
doit_exec=${doit:-exec}
|
||||
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
is_target_a_directory=possibly
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve the last data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t)
|
||||
is_target_a_directory=always
|
||||
dst_arg=$2
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-T) is_target_a_directory=never;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# We allow the use of options -d and -T together, by making -d
|
||||
# take the precedence; this is for compatibility with GNU install.
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
if test -n "$dst_arg"; then
|
||||
echo "$0: target directory not allowed when installing a directory." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call 'install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
if test $# -gt 1 || test "$is_target_a_directory" = always; then
|
||||
if test ! -d "$dst_arg"; then
|
||||
echo "$0: $dst_arg: Is not a directory." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
do_exit='(exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $src in
|
||||
-* | [=\(\)!]) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst_arg
|
||||
|
||||
# If destination is a directory, append the input filename.
|
||||
if test -d "$dst"; then
|
||||
if test "$is_target_a_directory" = never; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dstbase=`basename "$src"`
|
||||
case $dst in
|
||||
*/) dst=$dst$dstbase;;
|
||||
*) dst=$dst/$dstbase;;
|
||||
esac
|
||||
dstdir_status=0
|
||||
else
|
||||
dstdir=`dirname "$dst"`
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
case $dstdir in
|
||||
*/) dstdirslash=$dstdir;;
|
||||
*) dstdirslash=$dstdir/;;
|
||||
esac
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
# Note that $RANDOM variable is not portable (e.g. dash); Use it
|
||||
# here however when possible just to lower collision chance.
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
|
||||
trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
# Because "mkdir -p" follows existing symlinks and we likely work
|
||||
# directly in world-writeable /tmp, make sure that the '$tmpdir'
|
||||
# directory is successfully created first before we actually test
|
||||
# 'mkdir -p' feature.
|
||||
if (umask $mkdir_umask &&
|
||||
$mkdirprog $mkdir_mode "$tmpdir" &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
test_tmpdir="$tmpdir/a"
|
||||
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
[-=\(\)!]*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test X"$d" = X && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
if $posix_mkdir; then
|
||||
(umask=$mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=${dstdirslash}_inst.$$_
|
||||
rmtmp=${dstdirslash}_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
set +f &&
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
@ -61,6 +61,10 @@
|
||||
'<(tgvoip_src_loc)/NetworkSocket.h',
|
||||
'<(tgvoip_src_loc)/PacketReassembler.cpp',
|
||||
'<(tgvoip_src_loc)/PacketReassembler.h',
|
||||
'<(tgvoip_src_loc)/MessageThread.cpp',
|
||||
'<(tgvoip_src_loc)/MessageThread.h',
|
||||
'<(tgvoip_src_loc)/audio/AudioIO.cpp',
|
||||
'<(tgvoip_src_loc)/audio/AudioIO.h',
|
||||
|
||||
# Windows
|
||||
'<(tgvoip_src_loc)/os/windows/NetworkSocketWinsock.cpp',
|
||||
@ -97,8 +101,8 @@
|
||||
'<(tgvoip_src_loc)/os/linux/AudioOutputPulse.h',
|
||||
'<(tgvoip_src_loc)/os/linux/AudioInputPulse.cpp',
|
||||
'<(tgvoip_src_loc)/os/linux/AudioInputPulse.h',
|
||||
'<(tgvoip_src_loc)/os/linux/PulseAudioLoader.cpp',
|
||||
'<(tgvoip_src_loc)/os/linux/PulseAudioLoader.h',
|
||||
'<(tgvoip_src_loc)/os/linux/AudioPulse.cpp',
|
||||
'<(tgvoip_src_loc)/os/linux/AudioPulse.h',
|
||||
|
||||
# POSIX
|
||||
'<(tgvoip_src_loc)/os/posix/NetworkSocketPosix.cpp',
|
||||
|
||||
@ -189,6 +189,10 @@
|
||||
69A6DE1C1E95ECF000000E69 /* wav_file.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A6DE181E95ECF000000E69 /* wav_file.h */; };
|
||||
69A6DE1D1E95ECF000000E69 /* wav_header.cc in Sources */ = {isa = PBXBuildFile; fileRef = 69A6DE191E95ECF000000E69 /* wav_header.cc */; };
|
||||
69A6DE1E1E95ECF000000E69 /* wav_header.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A6DE1A1E95ECF000000E69 /* wav_header.h */; };
|
||||
69E357B020F88955002E163B /* AudioIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 69E357A720F88954002E163B /* AudioIO.cpp */; };
|
||||
69E357B120F88955002E163B /* AudioIO.h in Headers */ = {isa = PBXBuildFile; fileRef = 69E357AF20F88954002E163B /* AudioIO.h */; };
|
||||
69FB0B2D20F6860E00827817 /* MessageThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 69FB0B2420F6860D00827817 /* MessageThread.cpp */; };
|
||||
69FB0B2E20F6860E00827817 /* MessageThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 69FB0B2C20F6860D00827817 /* MessageThread.h */; };
|
||||
D00ACA4F20222F5D0045D427 /* SetupLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = D00ACA4D20222F5D0045D427 /* SetupLogging.h */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -429,7 +433,11 @@
|
||||
69A6DE181E95ECF000000E69 /* wav_file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wav_file.h; sourceTree = "<group>"; };
|
||||
69A6DE191E95ECF000000E69 /* wav_header.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wav_header.cc; sourceTree = "<group>"; };
|
||||
69A6DE1A1E95ECF000000E69 /* wav_header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wav_header.h; sourceTree = "<group>"; };
|
||||
69E357A720F88954002E163B /* AudioIO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioIO.cpp; sourceTree = "<group>"; };
|
||||
69E357AF20F88954002E163B /* AudioIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioIO.h; sourceTree = "<group>"; };
|
||||
69F842361E67540700C110F7 /* libtgvoip.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = libtgvoip.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
69FB0B2420F6860D00827817 /* MessageThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MessageThread.cpp; sourceTree = "<group>"; };
|
||||
69FB0B2C20F6860D00827817 /* MessageThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessageThread.h; sourceTree = "<group>"; };
|
||||
D00ACA4D20222F5D0045D427 /* SetupLogging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SetupLogging.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@ -476,6 +484,8 @@
|
||||
692AB8AA1E6759DD00706ACC /* logging.h */,
|
||||
692AB8AB1E6759DD00706ACC /* MediaStreamItf.cpp */,
|
||||
692AB8AC1E6759DD00706ACC /* MediaStreamItf.h */,
|
||||
69FB0B2420F6860D00827817 /* MessageThread.cpp */,
|
||||
69FB0B2C20F6860D00827817 /* MessageThread.h */,
|
||||
69015D921E9D848700AC9763 /* NetworkSocket.cpp */,
|
||||
69015D931E9D848700AC9763 /* NetworkSocket.h */,
|
||||
692AB8AD1E6759DD00706ACC /* OpusDecoder.cpp */,
|
||||
@ -502,6 +512,8 @@
|
||||
692AB8891E6759DD00706ACC /* AudioInput.h */,
|
||||
692AB88A1E6759DD00706ACC /* AudioOutput.cpp */,
|
||||
692AB88B1E6759DD00706ACC /* AudioOutput.h */,
|
||||
69E357A720F88954002E163B /* AudioIO.cpp */,
|
||||
69E357AF20F88954002E163B /* AudioIO.h */,
|
||||
69791A551EE8272A00BB85FB /* Resampler.cpp */,
|
||||
69791A561EE8272A00BB85FB /* Resampler.h */,
|
||||
);
|
||||
@ -910,6 +922,7 @@
|
||||
69A6DDFF1E95EC7700000E69 /* windows_private.h in Headers */,
|
||||
69A6DD961E95EC7700000E69 /* basictypes.h in Headers */,
|
||||
69A6DE161E95EC7800000E69 /* typedefs.h in Headers */,
|
||||
69E357B120F88955002E163B /* AudioIO.h in Headers */,
|
||||
69A6DDE21E95EC7700000E69 /* aec_resampler.h in Headers */,
|
||||
69A6DD9F1E95EC7700000E69 /* stringutils.h in Headers */,
|
||||
69A6DDDB1E95EC7700000E69 /* aec_common.h in Headers */,
|
||||
@ -919,6 +932,7 @@
|
||||
69A6DD991E95EC7700000E69 /* constructormagic.h in Headers */,
|
||||
69A6DDA01E95EC7700000E69 /* type_traits.h in Headers */,
|
||||
69A6DDBE1E95EC7700000E69 /* real_fft.h in Headers */,
|
||||
69FB0B2E20F6860E00827817 /* MessageThread.h in Headers */,
|
||||
692AB8FC1E6759DD00706ACC /* AudioOutputAudioUnit.h in Headers */,
|
||||
69A6DD941E95EC7700000E69 /* array_view.h in Headers */,
|
||||
692AB8D01E6759DD00706ACC /* BlockingQueue.h in Headers */,
|
||||
@ -1151,12 +1165,14 @@
|
||||
69A6DDB41E95EC7700000E69 /* downsample_fast.c in Sources */,
|
||||
69A6DDEA1E95EC7700000E69 /* echo_control_mobile.cc in Sources */,
|
||||
69A6DDF41E95EC7700000E69 /* noise_suppression.c in Sources */,
|
||||
69FB0B2D20F6860E00827817 /* MessageThread.cpp in Sources */,
|
||||
692AB8CF1E6759DD00706ACC /* BlockingQueue.cpp in Sources */,
|
||||
69A6DDC31E95EC7700000E69 /* levinson_durbin.c in Sources */,
|
||||
69A6DDF61E95EC7700000E69 /* noise_suppression_x.c in Sources */,
|
||||
69A6DE1B1E95ECF000000E69 /* wav_file.cc in Sources */,
|
||||
69A6DDCE1E95EC7700000E69 /* resample_by_2_internal.c in Sources */,
|
||||
692AB8CB1E6759DD00706ACC /* AudioInput.cpp in Sources */,
|
||||
69E357B020F88955002E163B /* AudioIO.cpp in Sources */,
|
||||
69A6DDCC1E95EC7700000E69 /* resample_48khz.c in Sources */,
|
||||
69A6DDAC1E95EC7700000E69 /* complex_bit_reverse_arm.S in Sources */,
|
||||
69A6DDD81E95EC7700000E69 /* vector_scaling_operations.c in Sources */,
|
||||
|
||||
@ -46,6 +46,8 @@
|
||||
695B20621EBD39FF00E31757 /* DarwinSpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = 695B20601EBD39FF00E31757 /* DarwinSpecific.h */; };
|
||||
6971220F20C8107F00971C2C /* PacketReassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6971220D20C8107E00971C2C /* PacketReassembler.cpp */; };
|
||||
6971221020C8107F00971C2C /* PacketReassembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 6971220E20C8107F00971C2C /* PacketReassembler.h */; };
|
||||
6976FD0320F6A7060019939E /* MessageThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6976FD0120F6A7050019939E /* MessageThread.cpp */; };
|
||||
6976FD0420F6A7060019939E /* MessageThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 6976FD0220F6A7060019939E /* MessageThread.h */; };
|
||||
698848421F4B39F700076DF0 /* AudioInputAudioUnit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6988483C1F4B39F700076DF0 /* AudioInputAudioUnit.h */; };
|
||||
698848441F4B39F700076DF0 /* AudioOutputAudioUnit.h in Headers */ = {isa = PBXBuildFile; fileRef = 6988483E1F4B39F700076DF0 /* AudioOutputAudioUnit.h */; };
|
||||
698848461F4B39F700076DF0 /* AudioUnitIO.h in Headers */ = {isa = PBXBuildFile; fileRef = 698848401F4B39F700076DF0 /* AudioUnitIO.h */; };
|
||||
@ -186,7 +188,6 @@
|
||||
69A6DF461E9614B700000E69 /* AudioOutputAudioUnitOSX.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A6DF421E9614B700000E69 /* AudioOutputAudioUnitOSX.h */; };
|
||||
69AC14911F4B41CF00AC3173 /* Resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 69AC148F1F4B41CF00AC3173 /* Resampler.h */; };
|
||||
C2A87DD81F4B6A33002D3F73 /* Resampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2A87DD71F4B6A33002D3F73 /* Resampler.cpp */; };
|
||||
C2A87DDA1F4B6A57002D3F73 /* DarwinSpecific.mm in Sources */ = {isa = PBXBuildFile; fileRef = C2A87DD91F4B6A57002D3F73 /* DarwinSpecific.mm */; };
|
||||
C2A87DDF1F4B6A61002D3F73 /* AudioInputAudioUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2A87DDB1F4B6A61002D3F73 /* AudioInputAudioUnit.cpp */; };
|
||||
C2A87DE01F4B6A61002D3F73 /* AudioOutputAudioUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2A87DDD1F4B6A61002D3F73 /* AudioOutputAudioUnit.cpp */; };
|
||||
C2A87DE41F4B6AD3002D3F73 /* AudioUnitIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2A87DE31F4B6AD3002D3F73 /* AudioUnitIO.cpp */; };
|
||||
@ -235,6 +236,13 @@
|
||||
remoteGlobalIDString = D020FB0A1D99637100F279AA;
|
||||
remoteInfo = LegacyDatabase;
|
||||
};
|
||||
6976FCFF20F6A6EF0019939E /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 692AB9071E675E8800706ACC /* Telegraph.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = 099120C01EEAA63400F1366E;
|
||||
remoteInfo = Widget;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@ -280,6 +288,8 @@
|
||||
695B20611EBD39FF00E31757 /* DarwinSpecific.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = DarwinSpecific.mm; path = ../../../../../libtgvoip/os/darwin/DarwinSpecific.mm; sourceTree = "<group>"; };
|
||||
6971220D20C8107E00971C2C /* PacketReassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PacketReassembler.cpp; sourceTree = "<group>"; };
|
||||
6971220E20C8107F00971C2C /* PacketReassembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PacketReassembler.h; sourceTree = "<group>"; };
|
||||
6976FD0120F6A7050019939E /* MessageThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MessageThread.cpp; sourceTree = "<group>"; };
|
||||
6976FD0220F6A7060019939E /* MessageThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessageThread.h; sourceTree = "<group>"; };
|
||||
6988483B1F4B39F700076DF0 /* AudioInputAudioUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AudioInputAudioUnit.cpp; path = ../../../../../libtgvoip/os/darwin/AudioInputAudioUnit.cpp; sourceTree = "<group>"; };
|
||||
6988483C1F4B39F700076DF0 /* AudioInputAudioUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AudioInputAudioUnit.h; path = ../../../../../libtgvoip/os/darwin/AudioInputAudioUnit.h; sourceTree = "<group>"; };
|
||||
6988483D1F4B39F700076DF0 /* AudioOutputAudioUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AudioOutputAudioUnit.cpp; path = ../../../../../libtgvoip/os/darwin/AudioOutputAudioUnit.cpp; sourceTree = "<group>"; };
|
||||
@ -425,7 +435,6 @@
|
||||
69AC148F1F4B41CF00AC3173 /* Resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Resampler.h; path = "../../../../Telegram-iOS/submodules/libtgvoip/audio/Resampler.h"; sourceTree = "<group>"; };
|
||||
69F842361E67540700C110F7 /* libtgvoip.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = libtgvoip.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C2A87DD71F4B6A33002D3F73 /* Resampler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Resampler.cpp; path = audio/Resampler.cpp; sourceTree = "<group>"; };
|
||||
C2A87DD91F4B6A57002D3F73 /* DarwinSpecific.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = DarwinSpecific.mm; path = os/darwin/DarwinSpecific.mm; sourceTree = "<group>"; };
|
||||
C2A87DDB1F4B6A61002D3F73 /* AudioInputAudioUnit.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AudioInputAudioUnit.cpp; path = os/darwin/AudioInputAudioUnit.cpp; sourceTree = "<group>"; };
|
||||
C2A87DDC1F4B6A61002D3F73 /* AudioInputAudioUnitOSX.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AudioInputAudioUnitOSX.cpp; path = os/darwin/AudioInputAudioUnitOSX.cpp; sourceTree = "<group>"; };
|
||||
C2A87DDD1F4B6A61002D3F73 /* AudioOutputAudioUnit.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = AudioOutputAudioUnit.cpp; path = os/darwin/AudioOutputAudioUnit.cpp; sourceTree = "<group>"; };
|
||||
@ -479,6 +488,8 @@
|
||||
692AB8AA1E6759DD00706ACC /* logging.h */,
|
||||
692AB8AB1E6759DD00706ACC /* MediaStreamItf.cpp */,
|
||||
692AB8AC1E6759DD00706ACC /* MediaStreamItf.h */,
|
||||
6976FD0120F6A7050019939E /* MessageThread.cpp */,
|
||||
6976FD0220F6A7060019939E /* MessageThread.h */,
|
||||
690725C01EBBD5F2005D860B /* NetworkSocket.cpp */,
|
||||
690725C11EBBD5F2005D860B /* NetworkSocket.h */,
|
||||
692AB8AD1E6759DD00706ACC /* OpusDecoder.cpp */,
|
||||
@ -559,6 +570,7 @@
|
||||
692AB9171E675E8800706ACC /* watchkitapp Extension.appex */,
|
||||
692AB9191E675E8800706ACC /* SiriIntents.appex */,
|
||||
692AB91B1E675E8800706ACC /* LegacyDatabase.framework */,
|
||||
6976FD0020F6A6EF0019939E /* Widget.appex */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@ -855,7 +867,6 @@
|
||||
C2A87DDC1F4B6A61002D3F73 /* AudioInputAudioUnitOSX.cpp */,
|
||||
C2A87DDD1F4B6A61002D3F73 /* AudioOutputAudioUnit.cpp */,
|
||||
C2A87DDE1F4B6A61002D3F73 /* AudioOutputAudioUnitOSX.cpp */,
|
||||
C2A87DD91F4B6A57002D3F73 /* DarwinSpecific.mm */,
|
||||
C2A87DD71F4B6A33002D3F73 /* Resampler.cpp */,
|
||||
692AB8861E6759BF00706ACC /* libtgvoip */,
|
||||
69F842371E67540700C110F7 /* Products */,
|
||||
@ -900,6 +911,7 @@
|
||||
69A6DF3B1E96149300000E69 /* cpu_features_wrapper.h in Headers */,
|
||||
69A6DF211E96149300000E69 /* ns_core.h in Headers */,
|
||||
69A6DF051E96149300000E69 /* aec_core.h in Headers */,
|
||||
6976FD0420F6A7060019939E /* MessageThread.h in Headers */,
|
||||
69A6DF441E9614B700000E69 /* AudioInputAudioUnitOSX.h in Headers */,
|
||||
692AB8D91E6759DD00706ACC /* CongestionControl.h in Headers */,
|
||||
69A6DF031E96149300000E69 /* aec_common.h in Headers */,
|
||||
@ -1066,6 +1078,13 @@
|
||||
remoteRef = 692AB91A1E675E8800706ACC /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
6976FD0020F6A6EF0019939E /* Widget.appex */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = "wrapper.app-extension";
|
||||
path = Widget.appex;
|
||||
remoteRef = 6976FCFF20F6A6EF0019939E /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
@ -1100,6 +1119,7 @@
|
||||
692AB9041E6759DD00706ACC /* VoIPServerConfig.cpp in Sources */,
|
||||
69A6DF0B1E96149300000E69 /* echo_cancellation.cc in Sources */,
|
||||
69A6DED61E96149300000E69 /* cross_correlation_neon.c in Sources */,
|
||||
6976FD0320F6A7060019939E /* MessageThread.cpp in Sources */,
|
||||
69A6DEF71E96149300000E69 /* spl_sqrt.c in Sources */,
|
||||
69A6DEED1E96149300000E69 /* real_fft.c in Sources */,
|
||||
692AB9021E6759DD00706ACC /* VoIPController.cpp in Sources */,
|
||||
@ -1135,7 +1155,6 @@
|
||||
692AB8E61E6759DD00706ACC /* JitterBuffer.cpp in Sources */,
|
||||
692AB8CB1E6759DD00706ACC /* AudioInput.cpp in Sources */,
|
||||
692AB8CD1E6759DD00706ACC /* AudioOutput.cpp in Sources */,
|
||||
C2A87DDA1F4B6A57002D3F73 /* DarwinSpecific.mm in Sources */,
|
||||
C2A87DD81F4B6A33002D3F73 /* Resampler.cpp in Sources */,
|
||||
69A6DEFA1E96149300000E69 /* splitting_filter_impl.c in Sources */,
|
||||
69A6DEE01E96149300000E69 /* get_hanning_window.c in Sources */,
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -64,8 +64,13 @@ void tgvoip_log_file_write_header(FILE* file){
|
||||
#else
|
||||
struct utsname sysname;
|
||||
uname(&sysname);
|
||||
char systemVersion[128];
|
||||
snprintf(systemVersion, sizeof(systemVersion), "%s %s (%s)", sysname.sysname, sysname.release, sysname.version);
|
||||
std::string sysver(sysname.sysname);
|
||||
sysver+=" ";
|
||||
sysver+=sysname.release;
|
||||
sysver+=" (";
|
||||
sysver+=sysname.version;
|
||||
sysver+=")";
|
||||
const char* systemVersion=sysver.c_str();
|
||||
#endif
|
||||
#elif defined(__APPLE__)
|
||||
char osxVer[128];
|
||||
|
||||
215
missing
Executable file
215
missing
Executable file
@ -0,0 +1,215 @@
|
||||
#! /bin/sh
|
||||
# Common wrapper for a few potentially missing GNU programs.
|
||||
|
||||
scriptversion=2018-03-07.03; # UTC
|
||||
|
||||
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
|
||||
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try '$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case $1 in
|
||||
|
||||
--is-lightweight)
|
||||
# Used by our autoconf macros to check whether the available missing
|
||||
# script is modern enough.
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--run)
|
||||
# Back-compat with the calling convention used by older automake.
|
||||
shift
|
||||
;;
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
|
||||
to PROGRAM being missing or too old.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal autoconf autoheader autom4te automake makeinfo
|
||||
bison yacc flex lex help2man
|
||||
|
||||
Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
|
||||
'g' are ignored when checking the name.
|
||||
|
||||
Send bug reports to <bug-automake@gnu.org>."
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing $scriptversion (GNU Automake)"
|
||||
exit $?
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: unknown '$1' option"
|
||||
echo 1>&2 "Try '$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# Run the given program, remember its exit status.
|
||||
"$@"; st=$?
|
||||
|
||||
# If it succeeded, we are done.
|
||||
test $st -eq 0 && exit 0
|
||||
|
||||
# Also exit now if we it failed (or wasn't found), and '--version' was
|
||||
# passed; such an option is passed most likely to detect whether the
|
||||
# program is present and works.
|
||||
case $2 in --version|--help) exit $st;; esac
|
||||
|
||||
# Exit code 63 means version mismatch. This often happens when the user
|
||||
# tries to use an ancient version of a tool on a file that requires a
|
||||
# minimum version.
|
||||
if test $st -eq 63; then
|
||||
msg="probably too old"
|
||||
elif test $st -eq 127; then
|
||||
# Program was missing.
|
||||
msg="missing on your system"
|
||||
else
|
||||
# Program was found and executed, but failed. Give up.
|
||||
exit $st
|
||||
fi
|
||||
|
||||
perl_URL=https://www.perl.org/
|
||||
flex_URL=https://github.com/westes/flex
|
||||
gnu_software_URL=https://www.gnu.org/software
|
||||
|
||||
program_details ()
|
||||
{
|
||||
case $1 in
|
||||
aclocal|automake)
|
||||
echo "The '$1' program is part of the GNU Automake package:"
|
||||
echo "<$gnu_software_URL/automake>"
|
||||
echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
|
||||
echo "<$gnu_software_URL/autoconf>"
|
||||
echo "<$gnu_software_URL/m4/>"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
autoconf|autom4te|autoheader)
|
||||
echo "The '$1' program is part of the GNU Autoconf package:"
|
||||
echo "<$gnu_software_URL/autoconf/>"
|
||||
echo "It also requires GNU m4 and Perl in order to run:"
|
||||
echo "<$gnu_software_URL/m4/>"
|
||||
echo "<$perl_URL>"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
give_advice ()
|
||||
{
|
||||
# Normalize program name to check for.
|
||||
normalized_program=`echo "$1" | sed '
|
||||
s/^gnu-//; t
|
||||
s/^gnu//; t
|
||||
s/^g//; t'`
|
||||
|
||||
printf '%s\n' "'$1' is $msg."
|
||||
|
||||
configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
|
||||
case $normalized_program in
|
||||
autoconf*)
|
||||
echo "You should only need it if you modified 'configure.ac',"
|
||||
echo "or m4 files included by it."
|
||||
program_details 'autoconf'
|
||||
;;
|
||||
autoheader*)
|
||||
echo "You should only need it if you modified 'acconfig.h' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'autoheader'
|
||||
;;
|
||||
automake*)
|
||||
echo "You should only need it if you modified 'Makefile.am' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'automake'
|
||||
;;
|
||||
aclocal*)
|
||||
echo "You should only need it if you modified 'acinclude.m4' or"
|
||||
echo "$configure_deps."
|
||||
program_details 'aclocal'
|
||||
;;
|
||||
autom4te*)
|
||||
echo "You might have modified some maintainer files that require"
|
||||
echo "the 'autom4te' program to be rebuilt."
|
||||
program_details 'autom4te'
|
||||
;;
|
||||
bison*|yacc*)
|
||||
echo "You should only need it if you modified a '.y' file."
|
||||
echo "You may want to install the GNU Bison package:"
|
||||
echo "<$gnu_software_URL/bison/>"
|
||||
;;
|
||||
lex*|flex*)
|
||||
echo "You should only need it if you modified a '.l' file."
|
||||
echo "You may want to install the Fast Lexical Analyzer package:"
|
||||
echo "<$flex_URL>"
|
||||
;;
|
||||
help2man*)
|
||||
echo "You should only need it if you modified a dependency" \
|
||||
"of a man page."
|
||||
echo "You may want to install the GNU Help2man package:"
|
||||
echo "<$gnu_software_URL/help2man/>"
|
||||
;;
|
||||
makeinfo*)
|
||||
echo "You should only need it if you modified a '.texi' file, or"
|
||||
echo "any other file indirectly affecting the aspect of the manual."
|
||||
echo "You might want to install the Texinfo package:"
|
||||
echo "<$gnu_software_URL/texinfo/>"
|
||||
echo "The spurious makeinfo call might also be the consequence of"
|
||||
echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
|
||||
echo "want to install GNU make:"
|
||||
echo "<$gnu_software_URL/make/>"
|
||||
;;
|
||||
*)
|
||||
echo "You might have modified some files without having the proper"
|
||||
echo "tools for further handling them. Check the 'README' file, it"
|
||||
echo "often tells you about the needed prerequisites for installing"
|
||||
echo "this package. You may also peek at any GNU archive site, in"
|
||||
echo "case some other package contains this missing '$1' program."
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
give_advice "$1" | sed -e '1s/^/WARNING: /' \
|
||||
-e '2,$s/^/ /' >&2
|
||||
|
||||
# Propagate the correct exit status (expected to be 127 for a program
|
||||
# not found, 63 for a program that failed due to version mismatch).
|
||||
exit $st
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
@ -32,6 +32,8 @@ AudioInputAndroid::AudioInputAndroid(){
|
||||
jobject obj=env->NewObject(jniClass, ctor, (jlong)(intptr_t)this);
|
||||
javaObject=env->NewGlobalRef(obj);
|
||||
|
||||
env->CallVoidMethod(javaObject, initMethod, 48000, 16, 1, 960*2);
|
||||
|
||||
if(didAttach){
|
||||
sharedJVM->DetachCurrentThread();
|
||||
}
|
||||
@ -59,23 +61,6 @@ AudioInputAndroid::~AudioInputAndroid(){
|
||||
}
|
||||
}
|
||||
|
||||
void AudioInputAndroid::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
MutexGuard guard(mutex);
|
||||
JNIEnv* env=NULL;
|
||||
bool didAttach=false;
|
||||
sharedJVM->GetEnv((void**) &env, JNI_VERSION_1_6);
|
||||
if(!env){
|
||||
sharedJVM->AttachCurrentThread(&env, NULL);
|
||||
didAttach=true;
|
||||
}
|
||||
|
||||
env->CallVoidMethod(javaObject, initMethod, sampleRate, bitsPerSample, channels, 960*2);
|
||||
|
||||
if(didAttach){
|
||||
sharedJVM->DetachCurrentThread();
|
||||
}
|
||||
}
|
||||
|
||||
void AudioInputAndroid::Start(){
|
||||
MutexGuard guard(mutex);
|
||||
JNIEnv* env=NULL;
|
||||
|
||||
@ -17,7 +17,6 @@ class AudioInputAndroid : public AudioInput{
|
||||
public:
|
||||
AudioInputAndroid();
|
||||
virtual ~AudioInputAndroid();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
void HandleCallback(JNIEnv* env, jobject buffer);
|
||||
|
||||
@ -32,6 +32,8 @@ AudioOutputAndroid::AudioOutputAndroid(){
|
||||
jobject obj=env->NewObject(jniClass, ctor, (jlong)(intptr_t)this);
|
||||
javaObject=env->NewGlobalRef(obj);
|
||||
|
||||
env->CallVoidMethod(javaObject, initMethod, 48000, 16, 1, 960*2);
|
||||
|
||||
if(didAttach){
|
||||
sharedJVM->DetachCurrentThread();
|
||||
}
|
||||
@ -56,22 +58,6 @@ AudioOutputAndroid::~AudioOutputAndroid(){
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOutputAndroid::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
JNIEnv* env=NULL;
|
||||
bool didAttach=false;
|
||||
sharedJVM->GetEnv((void**) &env, JNI_VERSION_1_6);
|
||||
if(!env){
|
||||
sharedJVM->AttachCurrentThread(&env, NULL);
|
||||
didAttach=true;
|
||||
}
|
||||
|
||||
env->CallVoidMethod(javaObject, initMethod, sampleRate, bitsPerSample, channels, 960*2);
|
||||
|
||||
if(didAttach){
|
||||
sharedJVM->DetachCurrentThread();
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOutputAndroid::Start(){
|
||||
JNIEnv* env=NULL;
|
||||
bool didAttach=false;
|
||||
@ -119,7 +105,3 @@ void AudioOutputAndroid::HandleCallback(JNIEnv* env, jbyteArray buffer){
|
||||
bool AudioOutputAndroid::IsPlaying(){
|
||||
return false;
|
||||
}
|
||||
|
||||
float AudioOutputAndroid::GetLevel(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -17,11 +17,9 @@ public:
|
||||
|
||||
AudioOutputAndroid();
|
||||
virtual ~AudioOutputAndroid();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
virtual bool IsPlaying() override;
|
||||
virtual float GetLevel() override;
|
||||
void HandleCallback(JNIEnv* env, jbyteArray buffer);
|
||||
static jmethodID initMethod;
|
||||
static jmethodID releaseMethod;
|
||||
|
||||
@ -23,22 +23,15 @@ AudioInputAudioUnit::AudioInputAudioUnit(std::string deviceID, AudioUnitIO* io){
|
||||
#if TARGET_OS_OSX
|
||||
io->SetCurrentDevice(true, deviceID);
|
||||
#endif
|
||||
io->AttachInput(this);
|
||||
failed=io->IsFailed();
|
||||
}
|
||||
|
||||
AudioInputAudioUnit::~AudioInputAudioUnit(){
|
||||
io->DetachInput();
|
||||
}
|
||||
|
||||
void AudioInputAudioUnit::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
io->Configure(sampleRate, bitsPerSample, channels);
|
||||
}
|
||||
|
||||
void AudioInputAudioUnit::Start(){
|
||||
isRecording=true;
|
||||
io->EnableInput(true);
|
||||
failed=io->IsFailed();
|
||||
}
|
||||
|
||||
void AudioInputAudioUnit::Stop(){
|
||||
|
||||
@ -18,7 +18,6 @@ class AudioInputAudioUnit : public AudioInput{
|
||||
public:
|
||||
AudioInputAudioUnit(std::string deviceID, AudioUnitIO* io);
|
||||
virtual ~AudioInputAudioUnit();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
void HandleBufferCallback(AudioBufferList* ioData);
|
||||
|
||||
@ -78,9 +78,6 @@ AudioInputAudioUnitLegacy::~AudioInputAudioUnitLegacy(){
|
||||
free(inBufferList.mBuffers[0].mData);
|
||||
}
|
||||
|
||||
void AudioInputAudioUnitLegacy::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
}
|
||||
|
||||
void AudioInputAudioUnitLegacy::Start(){
|
||||
isRecording=true;
|
||||
OSStatus status=AudioOutputUnitStart(unit);
|
||||
@ -96,7 +93,7 @@ void AudioInputAudioUnitLegacy::Stop(){
|
||||
OSStatus AudioInputAudioUnitLegacy::BufferCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData){
|
||||
AudioInputAudioUnitLegacy* input=(AudioInputAudioUnitLegacy*) inRefCon;
|
||||
input->inBufferList.mBuffers[0].mDataByteSize=10240;
|
||||
OSStatus res=AudioUnitRender(input->unit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &input->inBufferList);
|
||||
AudioUnitRender(input->unit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &input->inBufferList);
|
||||
input->HandleBufferCallback(&input->inBufferList);
|
||||
return noErr;
|
||||
}
|
||||
@ -213,7 +210,7 @@ void AudioInputAudioUnitLegacy::EnumerateDevices(std::vector<AudioInputDevice>&
|
||||
|
||||
void AudioInputAudioUnitLegacy::SetCurrentDevice(std::string deviceID){
|
||||
UInt32 size=sizeof(AudioDeviceID);
|
||||
AudioDeviceID inputDevice=NULL;
|
||||
AudioDeviceID inputDevice=0;
|
||||
OSStatus status;
|
||||
|
||||
if(deviceID=="default"){
|
||||
|
||||
@ -18,7 +18,6 @@ class AudioInputAudioUnitLegacy : public AudioInput{
|
||||
public:
|
||||
AudioInputAudioUnitLegacy(std::string deviceID);
|
||||
virtual ~AudioInputAudioUnitLegacy();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
void HandleBufferCallback(AudioBufferList* ioData);
|
||||
|
||||
@ -19,35 +19,18 @@ using namespace tgvoip::audio;
|
||||
AudioOutputAudioUnit::AudioOutputAudioUnit(std::string deviceID, AudioUnitIO* io){
|
||||
isPlaying=false;
|
||||
remainingDataSize=0;
|
||||
level=0.0;
|
||||
this->io=io;
|
||||
#if TARGET_OS_OSX
|
||||
io->SetCurrentDevice(false, deviceID);
|
||||
#endif
|
||||
io->AttachOutput(this);
|
||||
failed=io->IsFailed();
|
||||
}
|
||||
|
||||
AudioOutputAudioUnit::~AudioOutputAudioUnit(){
|
||||
io->DetachOutput();
|
||||
}
|
||||
|
||||
void AudioOutputAudioUnit::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
io->Configure(sampleRate, bitsPerSample, channels);
|
||||
}
|
||||
|
||||
bool AudioOutputAudioUnit::IsPhone(){
|
||||
return false;
|
||||
}
|
||||
|
||||
void AudioOutputAudioUnit::EnableLoudspeaker(bool enabled){
|
||||
|
||||
}
|
||||
|
||||
void AudioOutputAudioUnit::Start(){
|
||||
isPlaying=true;
|
||||
io->EnableOutput(true);
|
||||
failed=io->IsFailed();
|
||||
}
|
||||
|
||||
void AudioOutputAudioUnit::Stop(){
|
||||
@ -59,10 +42,6 @@ bool AudioOutputAudioUnit::IsPlaying(){
|
||||
return isPlaying;
|
||||
}
|
||||
|
||||
float AudioOutputAudioUnit::GetLevel(){
|
||||
return level / 9.0;
|
||||
}
|
||||
|
||||
void AudioOutputAudioUnit::HandleBufferCallback(AudioBufferList *ioData){
|
||||
int i;
|
||||
for(i=0;i<ioData->mNumberBuffers;i++){
|
||||
|
||||
@ -17,13 +17,9 @@ class AudioOutputAudioUnit : public AudioOutput{
|
||||
public:
|
||||
AudioOutputAudioUnit(std::string deviceID, AudioUnitIO* io);
|
||||
virtual ~AudioOutputAudioUnit();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual bool IsPhone();
|
||||
virtual void EnableLoudspeaker(bool enabled);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
virtual bool IsPlaying();
|
||||
virtual float GetLevel();
|
||||
void HandleBufferCallback(AudioBufferList* ioData);
|
||||
#if TARGET_OS_OSX
|
||||
virtual void SetCurrentDevice(std::string deviceID);
|
||||
@ -34,9 +30,6 @@ private:
|
||||
unsigned char remainingData[10240];
|
||||
size_t remainingDataSize;
|
||||
AudioUnitIO* io;
|
||||
float level;
|
||||
int16_t absMax;
|
||||
int count;
|
||||
};
|
||||
}}
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ using namespace tgvoip::audio;
|
||||
AudioOutputAudioUnitLegacy::AudioOutputAudioUnitLegacy(std::string deviceID){
|
||||
remainingDataSize=0;
|
||||
isPlaying=false;
|
||||
sysDevID=NULL;
|
||||
sysDevID=0;
|
||||
|
||||
OSStatus status;
|
||||
AudioComponentDescription inputDesc={
|
||||
@ -100,9 +100,6 @@ AudioOutputAudioUnitLegacy::~AudioOutputAudioUnitLegacy(){
|
||||
AudioComponentInstanceDispose(unit);
|
||||
}
|
||||
|
||||
void AudioOutputAudioUnitLegacy::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
}
|
||||
|
||||
void AudioOutputAudioUnitLegacy::Start(){
|
||||
isPlaying=true;
|
||||
OSStatus status=AudioOutputUnitStart(unit);
|
||||
@ -127,8 +124,6 @@ bool AudioOutputAudioUnitLegacy::IsPlaying(){
|
||||
|
||||
void AudioOutputAudioUnitLegacy::HandleBufferCallback(AudioBufferList *ioData){
|
||||
int i;
|
||||
unsigned int k;
|
||||
int16_t absVal=0;
|
||||
for(i=0;i<ioData->mNumberBuffers;i++){
|
||||
AudioBuffer buf=ioData->mBuffers[i];
|
||||
if(!isPlaying){
|
||||
@ -236,7 +231,7 @@ void AudioOutputAudioUnitLegacy::EnumerateDevices(std::vector<AudioOutputDevice>
|
||||
|
||||
void AudioOutputAudioUnitLegacy::SetCurrentDevice(std::string deviceID){
|
||||
UInt32 size=sizeof(AudioDeviceID);
|
||||
AudioDeviceID outputDevice=NULL;
|
||||
AudioDeviceID outputDevice=0;
|
||||
OSStatus status;
|
||||
AudioObjectPropertyAddress dataSourceProp={
|
||||
kAudioDevicePropertyDataSource,
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
// you should have received with this source code distribution.
|
||||
//
|
||||
|
||||
#ifndef LIBTGVOIP_AUDIOINPUTAUDIOUNIT_OSX_H
|
||||
#define LIBTGVOIP_AUDIOINPUTAUDIOUNIT_OSX_H
|
||||
#ifndef LIBTGVOIP_AUDIOOUTPUTAUDIOUNIT_OSX_H
|
||||
#define LIBTGVOIP_AUDIOOUTPUTAUDIOUNIT_OSX_H
|
||||
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
#import <AudioToolbox/AudioToolbox.h>
|
||||
@ -18,7 +18,6 @@ class AudioOutputAudioUnitLegacy : public AudioOutput{
|
||||
public:
|
||||
AudioOutputAudioUnitLegacy(std::string deviceID);
|
||||
virtual ~AudioOutputAudioUnitLegacy();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
virtual bool IsPlaying();
|
||||
@ -40,4 +39,4 @@ private:
|
||||
};
|
||||
}}
|
||||
|
||||
#endif //LIBTGVOIP_AUDIOINPUTAUDIOUNIT_OSX_H
|
||||
#endif //LIBTGVOIP_AUDIOOUTPUTAUDIOUNIT_OSX_H
|
||||
|
||||
@ -109,6 +109,10 @@ AudioUnitIO::AudioUnitIO(){
|
||||
propertyAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
|
||||
AudioObjectAddPropertyListener(kAudioObjectSystemObject, &propertyAddress, AudioUnitIO::DefaultDeviceChangedCallback, this);
|
||||
#endif
|
||||
|
||||
|
||||
input=new AudioInputAudioUnit("default", this);
|
||||
output=new AudioOutputAudioUnit("default", this);
|
||||
}
|
||||
|
||||
AudioUnitIO::~AudioUnitIO(){
|
||||
@ -121,16 +125,14 @@ AudioUnitIO::~AudioUnitIO(){
|
||||
propertyAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
|
||||
AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &propertyAddress, AudioUnitIO::DefaultDeviceChangedCallback, this);
|
||||
#endif
|
||||
delete input;
|
||||
delete output;
|
||||
AudioOutputUnitStop(unit);
|
||||
AudioUnitUninitialize(unit);
|
||||
AudioComponentInstanceDispose(unit);
|
||||
free(inBufferList.mBuffers[0].mData);
|
||||
}
|
||||
|
||||
void AudioUnitIO::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
|
||||
}
|
||||
|
||||
OSStatus AudioUnitIO::BufferCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData){
|
||||
((AudioUnitIO*)inRefCon)->BufferCallback(ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
|
||||
return noErr;
|
||||
@ -152,28 +154,6 @@ void AudioUnitIO::BufferCallback(AudioUnitRenderActionFlags *ioActionFlags, cons
|
||||
}
|
||||
}
|
||||
|
||||
void AudioUnitIO::AttachInput(AudioInputAudioUnit *i){
|
||||
assert(input==NULL);
|
||||
input=i;
|
||||
}
|
||||
|
||||
void AudioUnitIO::AttachOutput(AudioOutputAudioUnit *o){
|
||||
assert(output==NULL);
|
||||
output=o;
|
||||
}
|
||||
|
||||
void AudioUnitIO::DetachInput(){
|
||||
assert(input!=NULL);
|
||||
input=NULL;
|
||||
inputEnabled=false;
|
||||
}
|
||||
|
||||
void AudioUnitIO::DetachOutput(){
|
||||
assert(output!=NULL);
|
||||
output=NULL;
|
||||
outputEnabled=false;
|
||||
}
|
||||
|
||||
void AudioUnitIO::EnableInput(bool enabled){
|
||||
inputEnabled=enabled;
|
||||
StartIfNeeded();
|
||||
@ -194,8 +174,12 @@ void AudioUnitIO::StartIfNeeded(){
|
||||
CHECK_AU_ERROR(status, "Error starting AudioUnit");
|
||||
}
|
||||
|
||||
bool AudioUnitIO::IsFailed(){
|
||||
return failed;
|
||||
AudioInput* AudioUnitIO::GetInput(){
|
||||
return input;
|
||||
}
|
||||
|
||||
AudioOutput* AudioUnitIO::GetOutput(){
|
||||
return output;
|
||||
}
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
@ -221,7 +205,7 @@ void AudioUnitIO::SetCurrentDevice(bool input, std::string deviceID){
|
||||
AudioUnitUninitialize(unit);
|
||||
}
|
||||
UInt32 size=sizeof(AudioDeviceID);
|
||||
AudioDeviceID device=NULL;
|
||||
AudioDeviceID device=0;
|
||||
OSStatus status;
|
||||
|
||||
if(deviceID=="default"){
|
||||
|
||||
@ -11,23 +11,20 @@
|
||||
#include <AudioToolbox/AudioToolbox.h>
|
||||
#include "../../threading.h"
|
||||
#include <string>
|
||||
#include "../../audio/AudioIO.h"
|
||||
|
||||
namespace tgvoip{ namespace audio{
|
||||
class AudioInputAudioUnit;
|
||||
class AudioOutputAudioUnit;
|
||||
|
||||
class AudioUnitIO{
|
||||
class AudioUnitIO : public AudioIO{
|
||||
public:
|
||||
AudioUnitIO();
|
||||
~AudioUnitIO();
|
||||
void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
void AttachInput(AudioInputAudioUnit* i);
|
||||
void AttachOutput(AudioOutputAudioUnit* o);
|
||||
void DetachInput();
|
||||
void DetachOutput();
|
||||
void EnableInput(bool enabled);
|
||||
void EnableOutput(bool enabled);
|
||||
bool IsFailed();
|
||||
virtual AudioInput* GetInput();
|
||||
virtual AudioOutput* GetOutput();
|
||||
#if TARGET_OS_OSX
|
||||
void SetCurrentDevice(bool input, std::string deviceID);
|
||||
#endif
|
||||
@ -47,7 +44,6 @@ private:
|
||||
AudioBufferList inBufferList;
|
||||
bool inputEnabled;
|
||||
bool outputEnabled;
|
||||
bool failed;
|
||||
bool started;
|
||||
};
|
||||
}}
|
||||
|
||||
@ -12,7 +12,15 @@
|
||||
namespace tgvoip {
|
||||
class DarwinSpecific{
|
||||
public:
|
||||
enum{
|
||||
THREAD_PRIO_USER_INTERACTIVE,
|
||||
THREAD_PRIO_USER_INITIATED,
|
||||
THREAD_PRIO_UTILITY,
|
||||
THREAD_PRIO_BACKGROUND,
|
||||
THREAD_PRIO_DEFAULT
|
||||
};
|
||||
static void GetSystemName(char* buf, size_t len);
|
||||
static void SetCurrentThreadPriority(int priority);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -15,3 +15,50 @@ void DarwinSpecific::GetSystemName(char* buf, size_t len){
|
||||
strcpy(buf, [v UTF8String]);
|
||||
//[v getCString:buf maxLength:sizeof(buf) encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
void DarwinSpecific::SetCurrentThreadPriority(int priority){
|
||||
NSThread* thread=[NSThread currentThread];
|
||||
if([thread respondsToSelector:@selector(setQualityOfService:)]){
|
||||
NSQualityOfService qos;
|
||||
switch(priority){
|
||||
case THREAD_PRIO_USER_INTERACTIVE:
|
||||
qos=NSQualityOfServiceUserInteractive;
|
||||
break;
|
||||
case THREAD_PRIO_USER_INITIATED:
|
||||
qos=NSQualityOfServiceUserInitiated;
|
||||
break;
|
||||
case THREAD_PRIO_UTILITY:
|
||||
qos=NSQualityOfServiceUtility;
|
||||
break;
|
||||
case THREAD_PRIO_BACKGROUND:
|
||||
qos=NSQualityOfServiceBackground;
|
||||
break;
|
||||
case THREAD_PRIO_DEFAULT:
|
||||
default:
|
||||
qos=NSQualityOfServiceDefault;
|
||||
break;
|
||||
}
|
||||
[thread setQualityOfService:qos];
|
||||
}else{
|
||||
double p;
|
||||
switch(priority){
|
||||
case THREAD_PRIO_USER_INTERACTIVE:
|
||||
p=1.0;
|
||||
break;
|
||||
case THREAD_PRIO_USER_INITIATED:
|
||||
p=0.8;
|
||||
break;
|
||||
case THREAD_PRIO_UTILITY:
|
||||
p=0.4;
|
||||
break;
|
||||
case THREAD_PRIO_BACKGROUND:
|
||||
p=0.2;
|
||||
break;
|
||||
case THREAD_PRIO_DEFAULT:
|
||||
default:
|
||||
p=0.5;
|
||||
break;
|
||||
}
|
||||
[NSThread setThreadPriority:p];
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,10 +49,6 @@ AudioInputALSA::~AudioInputALSA(){
|
||||
dlclose(lib);
|
||||
}
|
||||
|
||||
void AudioInputALSA::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
|
||||
}
|
||||
|
||||
void AudioInputALSA::Start(){
|
||||
if(failed || isRecording)
|
||||
return;
|
||||
|
||||
@ -19,7 +19,6 @@ class AudioInputALSA : public AudioInput{
|
||||
public:
|
||||
AudioInputALSA(std::string devID);
|
||||
virtual ~AudioInputALSA();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
virtual void SetCurrentDevice(std::string devID);
|
||||
|
||||
@ -11,9 +11,8 @@
|
||||
#include "AudioInputPulse.h"
|
||||
#include "../../logging.h"
|
||||
#include "../../VoIPController.h"
|
||||
#define TGVOIP_IN_AUDIO_IO
|
||||
#include "PulseAudioLoader.h"
|
||||
#undef TGVOIP_IN_AUDIO_IO
|
||||
#include "AudioPulse.h"
|
||||
#include "PulseFunctions.h"
|
||||
#if !defined(__GLIBC__)
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
@ -23,74 +22,17 @@
|
||||
|
||||
using namespace tgvoip::audio;
|
||||
|
||||
AudioInputPulse::AudioInputPulse(std::string devID){
|
||||
AudioInputPulse::AudioInputPulse(pa_context* context, pa_threaded_mainloop* mainloop, std::string devID){
|
||||
isRecording=false;
|
||||
isConnected=false;
|
||||
didStart=false;
|
||||
|
||||
mainloop=NULL;
|
||||
mainloopApi=NULL;
|
||||
context=NULL;
|
||||
this->mainloop=mainloop;
|
||||
this->context=context;
|
||||
stream=NULL;
|
||||
remainingDataSize=0;
|
||||
|
||||
if(!PulseAudioLoader::IncRef()){
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
|
||||
mainloop=pa_threaded_mainloop_new();
|
||||
if(!mainloop){
|
||||
LOGE("Error initializing PulseAudio (pa_threaded_mainloop_new)");
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
mainloopApi=pa_threaded_mainloop_get_api(mainloop);
|
||||
#ifndef MAXPATHLEN
|
||||
char exeName[20];
|
||||
#else
|
||||
char exePath[MAXPATHLEN];
|
||||
char exeName[MAXPATHLEN];
|
||||
ssize_t lres=readlink("/proc/self/exe", exePath, sizeof(exePath));
|
||||
if(lres==-1)
|
||||
lres=readlink("/proc/curproc/file", exePath, sizeof(exePath));
|
||||
if(lres==-1)
|
||||
lres=readlink("/proc/curproc/exe", exePath, sizeof(exePath));
|
||||
if(lres>0){
|
||||
strcpy(exeName, basename(exePath));
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
snprintf(exeName, sizeof(exeName), "Process %d", getpid());
|
||||
}
|
||||
context=pa_context_new(mainloopApi, exeName);
|
||||
if(!context){
|
||||
LOGE("Error initializing PulseAudio (pa_context_new)");
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
pa_context_set_state_callback(context, AudioInputPulse::ContextStateCallback, this);
|
||||
isLocked=true;
|
||||
pa_threaded_mainloop_lock(mainloop);
|
||||
int err=pa_threaded_mainloop_start(mainloop);
|
||||
CHECK_ERROR(err, "pa_threaded_mainloop_start");
|
||||
didStart=true;
|
||||
|
||||
err=pa_context_connect(context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL);
|
||||
CHECK_ERROR(err, "pa_context_connect");
|
||||
|
||||
while(true){
|
||||
pa_context_state_t contextState=pa_context_get_state(context);
|
||||
if(!PA_CONTEXT_IS_GOOD(contextState)){
|
||||
LOGE("Error initializing PulseAudio (PA_CONTEXT_IS_GOOD)");
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
if(contextState==PA_CONTEXT_READY)
|
||||
break;
|
||||
pa_threaded_mainloop_wait(mainloop);
|
||||
}
|
||||
|
||||
pa_sample_spec sample_specifications{
|
||||
.format=PA_SAMPLE_S16LE,
|
||||
.rate=48000,
|
||||
@ -112,38 +54,10 @@ AudioInputPulse::AudioInputPulse(std::string devID){
|
||||
}
|
||||
|
||||
AudioInputPulse::~AudioInputPulse(){
|
||||
if(mainloop && didStart){
|
||||
if(isLocked)
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
pa_threaded_mainloop_stop(mainloop);
|
||||
}
|
||||
if(stream){
|
||||
pa_stream_disconnect(stream);
|
||||
pa_stream_unref(stream);
|
||||
}
|
||||
if(context){
|
||||
pa_context_disconnect(context);
|
||||
pa_context_unref(context);
|
||||
}
|
||||
if(mainloop)
|
||||
pa_threaded_mainloop_free(mainloop);
|
||||
|
||||
PulseAudioLoader::DecRef();
|
||||
}
|
||||
|
||||
bool AudioInputPulse::IsAvailable(){
|
||||
void* lib=dlopen("libpulse.so.0", RTLD_LAZY);
|
||||
if(!lib)
|
||||
lib=dlopen("libpulse.so", RTLD_LAZY);
|
||||
if(lib){
|
||||
dlclose(lib);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AudioInputPulse::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
|
||||
}
|
||||
|
||||
void AudioInputPulse::Start(){
|
||||
@ -152,7 +66,7 @@ void AudioInputPulse::Start(){
|
||||
|
||||
pa_threaded_mainloop_lock(mainloop);
|
||||
isRecording=true;
|
||||
pa_operation_unref(pa_stream_cork(stream, 0, AudioInputPulse::StreamSuccessCallback, NULL));
|
||||
pa_operation_unref(pa_stream_cork(stream, 0, NULL, NULL));
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
}
|
||||
|
||||
@ -162,7 +76,7 @@ void AudioInputPulse::Stop(){
|
||||
|
||||
isRecording=false;
|
||||
pa_threaded_mainloop_lock(mainloop);
|
||||
pa_operation_unref(pa_stream_cork(stream, 1, AudioInputPulse::StreamSuccessCallback, NULL));
|
||||
pa_operation_unref(pa_stream_cork(stream, 1, NULL, NULL));
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
}
|
||||
|
||||
@ -209,60 +123,23 @@ void AudioInputPulse::SetCurrentDevice(std::string devID){
|
||||
isConnected=true;
|
||||
|
||||
if(isRecording){
|
||||
pa_operation_unref(pa_stream_cork(stream, 0, AudioInputPulse::StreamSuccessCallback, mainloop));
|
||||
pa_operation_unref(pa_stream_cork(stream, 0, NULL, NULL));
|
||||
}
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
}
|
||||
|
||||
bool AudioInputPulse::EnumerateDevices(std::vector<AudioInputDevice>& devs){
|
||||
if(!PulseAudioLoader::IncRef())
|
||||
return false;
|
||||
|
||||
pa_mainloop* ml;
|
||||
pa_mainloop_api* mlAPI;
|
||||
pa_context* ctx;
|
||||
pa_operation* op=NULL;
|
||||
int state=0;
|
||||
int paReady=0;
|
||||
|
||||
ml=pa_mainloop_new();
|
||||
mlAPI=pa_mainloop_get_api(ml);
|
||||
ctx=pa_context_new(mlAPI, "libtgvoip");
|
||||
|
||||
pa_context_connect(ctx, NULL, PA_CONTEXT_NOFLAGS, NULL);
|
||||
pa_context_set_state_callback(ctx, AudioInputPulse::ContextStateCallbackEnum, &paReady);
|
||||
|
||||
while(true){
|
||||
if(paReady==0){
|
||||
pa_mainloop_iterate(ml, 1, NULL);
|
||||
continue;
|
||||
}
|
||||
if(paReady==2){
|
||||
pa_context_disconnect(ctx);
|
||||
pa_context_unref(ctx);
|
||||
pa_mainloop_free(ml);
|
||||
PulseAudioLoader::DecRef();
|
||||
return false;
|
||||
}
|
||||
if(!op){
|
||||
op=pa_context_get_source_info_list(ctx, AudioInputPulse::DeviceEnumCallback, &devs);
|
||||
continue;
|
||||
}
|
||||
if(pa_operation_get_state(op)==PA_OPERATION_DONE){
|
||||
pa_operation_unref(op);
|
||||
pa_context_disconnect(ctx);
|
||||
pa_context_unref(ctx);
|
||||
pa_mainloop_free(ml);
|
||||
PulseAudioLoader::DecRef();
|
||||
return true;
|
||||
}
|
||||
pa_mainloop_iterate(ml, 1, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioInputPulse::ContextStateCallback(pa_context* context, void* arg) {
|
||||
AudioInputPulse* self=(AudioInputPulse*) arg;
|
||||
pa_threaded_mainloop_signal(self->mainloop, 0);
|
||||
return AudioPulse::DoOneOperation([&](pa_context* ctx){
|
||||
return pa_context_get_source_info_list(ctx, [](pa_context* ctx, const pa_source_info* info, int eol, void* userdata){
|
||||
if(eol>0)
|
||||
return;
|
||||
std::vector<AudioInputDevice>* devs=(std::vector<AudioInputDevice>*)userdata;
|
||||
AudioInputDevice dev;
|
||||
dev.id=std::string(info->name);
|
||||
dev.displayName=std::string(info->description);
|
||||
devs->push_back(dev);
|
||||
}, &devs);
|
||||
});
|
||||
}
|
||||
|
||||
void AudioInputPulse::StreamStateCallback(pa_stream *s, void* arg) {
|
||||
@ -275,11 +152,10 @@ void AudioInputPulse::StreamReadCallback(pa_stream *stream, size_t requestedByte
|
||||
}
|
||||
|
||||
void AudioInputPulse::StreamReadCallback(pa_stream *stream, size_t requestedBytes) {
|
||||
int bytesRemaining = requestedBytes;
|
||||
size_t bytesRemaining = requestedBytes;
|
||||
uint8_t *buffer = NULL;
|
||||
while (bytesRemaining > 0) {
|
||||
size_t bytesToFill = 102400;
|
||||
size_t i;
|
||||
|
||||
if (bytesToFill > bytesRemaining) bytesToFill = bytesRemaining;
|
||||
|
||||
@ -305,39 +181,3 @@ void AudioInputPulse::StreamReadCallback(pa_stream *stream, size_t requestedByte
|
||||
bytesRemaining -= bytesToFill;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioInputPulse::StreamSuccessCallback(pa_stream *stream, int success, void *userdata) {
|
||||
return;
|
||||
}
|
||||
|
||||
void AudioInputPulse::ContextStateCallbackEnum(pa_context* context, void* arg){
|
||||
pa_context_state_t state;
|
||||
int* pa_ready=(int*)arg;
|
||||
|
||||
state=pa_context_get_state(context);
|
||||
switch(state){
|
||||
case PA_CONTEXT_UNCONNECTED:
|
||||
case PA_CONTEXT_CONNECTING:
|
||||
case PA_CONTEXT_AUTHORIZING:
|
||||
case PA_CONTEXT_SETTING_NAME:
|
||||
default:
|
||||
break;
|
||||
case PA_CONTEXT_FAILED:
|
||||
case PA_CONTEXT_TERMINATED:
|
||||
*pa_ready=2;
|
||||
break;
|
||||
case PA_CONTEXT_READY:
|
||||
*pa_ready=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioInputPulse::DeviceEnumCallback(pa_context* ctx, const pa_source_info* info, int eol, void* userdata){
|
||||
if(eol>0)
|
||||
return;
|
||||
std::vector<AudioInputDevice>* devs=(std::vector<AudioInputDevice>*)userdata;
|
||||
AudioInputDevice dev;
|
||||
dev.id=std::string(info->name);
|
||||
dev.displayName=std::string(info->description);
|
||||
devs->push_back(dev);
|
||||
}
|
||||
|
||||
@ -18,27 +18,20 @@ namespace audio{
|
||||
|
||||
class AudioInputPulse : public AudioInput{
|
||||
public:
|
||||
AudioInputPulse(std::string devID);
|
||||
AudioInputPulse(pa_context* context, pa_threaded_mainloop* mainloop, std::string devID);
|
||||
virtual ~AudioInputPulse();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
virtual bool IsRecording();
|
||||
virtual void SetCurrentDevice(std::string devID);
|
||||
static bool EnumerateDevices(std::vector<AudioInputDevice>& devs);
|
||||
static bool IsAvailable();
|
||||
|
||||
private:
|
||||
static void ContextStateCallback(pa_context* context, void* arg);
|
||||
static void ContextStateCallbackEnum(pa_context* context, void* arg);
|
||||
static void StreamStateCallback(pa_stream* s, void* arg);
|
||||
static void StreamSuccessCallback(pa_stream* stream, int success, void* userdata);
|
||||
static void StreamReadCallback(pa_stream* stream, size_t requested_bytes, void* userdata);
|
||||
static void DeviceEnumCallback(pa_context* ctx, const pa_source_info* info, int eol, void* userdata);
|
||||
void StreamReadCallback(pa_stream* stream, size_t requestedBytes);
|
||||
|
||||
pa_threaded_mainloop* mainloop;
|
||||
pa_mainloop_api* mainloopApi;
|
||||
pa_context* context;
|
||||
pa_stream* stream;
|
||||
|
||||
|
||||
@ -48,10 +48,6 @@ AudioOutputALSA::~AudioOutputALSA(){
|
||||
dlclose(lib);
|
||||
}
|
||||
|
||||
void AudioOutputALSA::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
|
||||
}
|
||||
|
||||
void AudioOutputALSA::Start(){
|
||||
if(failed || isPlaying)
|
||||
return;
|
||||
|
||||
@ -18,7 +18,6 @@ class AudioOutputALSA : public AudioOutput{
|
||||
public:
|
||||
AudioOutputALSA(std::string devID);
|
||||
virtual ~AudioOutputALSA();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
virtual bool IsPlaying();
|
||||
|
||||
@ -11,9 +11,8 @@
|
||||
#include "AudioOutputPulse.h"
|
||||
#include "../../logging.h"
|
||||
#include "../../VoIPController.h"
|
||||
#define TGVOIP_IN_AUDIO_IO
|
||||
#include "PulseAudioLoader.h"
|
||||
#undef TGVOIP_IN_AUDIO_IO
|
||||
#include "AudioPulse.h"
|
||||
#include "PulseFunctions.h"
|
||||
#if !defined(__GLIBC__)
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
@ -24,130 +23,43 @@
|
||||
using namespace tgvoip;
|
||||
using namespace tgvoip::audio;
|
||||
|
||||
using tgvoip::PulseAudioLoader;
|
||||
|
||||
AudioOutputPulse::AudioOutputPulse(std::string devID){
|
||||
AudioOutputPulse::AudioOutputPulse(pa_context* context, pa_threaded_mainloop* mainloop, std::string devID){
|
||||
isPlaying=false;
|
||||
isConnected=false;
|
||||
didStart=false;
|
||||
isLocked=false;
|
||||
|
||||
mainloop=NULL;
|
||||
mainloopApi=NULL;
|
||||
context=NULL;
|
||||
this->mainloop=mainloop;
|
||||
this->context=context;
|
||||
stream=NULL;
|
||||
remainingDataSize=0;
|
||||
|
||||
if(!PulseAudioLoader::IncRef()){
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
|
||||
mainloop=pa_threaded_mainloop_new();
|
||||
if(!mainloop){
|
||||
LOGE("Error initializing PulseAudio (pa_threaded_mainloop_new)");
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
mainloopApi=pa_threaded_mainloop_get_api(mainloop);
|
||||
#ifndef MAXPATHLEN
|
||||
char exeName[20];
|
||||
#else
|
||||
char exePath[MAXPATHLEN];
|
||||
char exeName[MAXPATHLEN];
|
||||
ssize_t lres=readlink("/proc/self/exe", exePath, sizeof(exePath));
|
||||
if(lres==-1)
|
||||
lres=readlink("/proc/curproc/file", exePath, sizeof(exePath));
|
||||
if(lres==-1)
|
||||
lres=readlink("/proc/curproc/exe", exePath, sizeof(exePath));
|
||||
if(lres>0){
|
||||
strcpy(exeName, basename(exePath));
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
snprintf(exeName, sizeof(exeName), "Process %d", getpid());
|
||||
}
|
||||
context=pa_context_new(mainloopApi, exeName);
|
||||
if(!context){
|
||||
LOGE("Error initializing PulseAudio (pa_context_new)");
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
pa_context_set_state_callback(context, AudioOutputPulse::ContextStateCallback, this);
|
||||
pa_threaded_mainloop_lock(mainloop);
|
||||
isLocked=true;
|
||||
int err=pa_threaded_mainloop_start(mainloop);
|
||||
CHECK_ERROR(err, "pa_threaded_mainloop_start");
|
||||
didStart=true;
|
||||
|
||||
err=pa_context_connect(context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL);
|
||||
CHECK_ERROR(err, "pa_context_connect");
|
||||
|
||||
while(true){
|
||||
pa_context_state_t contextState=pa_context_get_state(context);
|
||||
if(!PA_CONTEXT_IS_GOOD(contextState)){
|
||||
LOGE("Error initializing PulseAudio (PA_CONTEXT_IS_GOOD)");
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
if(contextState==PA_CONTEXT_READY)
|
||||
break;
|
||||
pa_threaded_mainloop_wait(mainloop);
|
||||
}
|
||||
|
||||
pa_sample_spec sample_specifications{
|
||||
.format=PA_SAMPLE_S16LE,
|
||||
.rate=48000,
|
||||
.channels=1
|
||||
};
|
||||
|
||||
pa_threaded_mainloop_lock(mainloop);
|
||||
stream=pa_stream_new(context, "libtgvoip playback", &sample_specifications, NULL);
|
||||
if(!stream){
|
||||
LOGE("Error initializing PulseAudio (pa_stream_new)");
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
pa_stream_set_state_callback(stream, AudioOutputPulse::StreamStateCallback, this);
|
||||
pa_stream_set_write_callback(stream, AudioOutputPulse::StreamWriteCallback, this);
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
isLocked=false;
|
||||
|
||||
SetCurrentDevice(devID);
|
||||
}
|
||||
|
||||
AudioOutputPulse::~AudioOutputPulse(){
|
||||
if(mainloop && didStart){
|
||||
if(isLocked)
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
pa_threaded_mainloop_stop(mainloop);
|
||||
}
|
||||
if(stream){
|
||||
pa_stream_disconnect(stream);
|
||||
pa_stream_unref(stream);
|
||||
}
|
||||
if(context){
|
||||
pa_context_disconnect(context);
|
||||
pa_context_unref(context);
|
||||
}
|
||||
if(mainloop)
|
||||
pa_threaded_mainloop_free(mainloop);
|
||||
|
||||
PulseAudioLoader::DecRef();
|
||||
}
|
||||
|
||||
bool AudioOutputPulse::IsAvailable(){
|
||||
void* lib=dlopen("libpulse.so.0", RTLD_LAZY);
|
||||
if(!lib)
|
||||
lib=dlopen("libpulse.so", RTLD_LAZY);
|
||||
if(lib){
|
||||
dlclose(lib);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AudioOutputPulse::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
|
||||
}
|
||||
|
||||
void AudioOutputPulse::Start(){
|
||||
@ -156,7 +68,7 @@ void AudioOutputPulse::Start(){
|
||||
|
||||
isPlaying=true;
|
||||
pa_threaded_mainloop_lock(mainloop);
|
||||
pa_operation_unref(pa_stream_cork(stream, 0, AudioOutputPulse::StreamSuccessCallback, NULL));
|
||||
pa_operation_unref(pa_stream_cork(stream, 0, NULL, NULL));
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
}
|
||||
|
||||
@ -166,7 +78,7 @@ void AudioOutputPulse::Stop(){
|
||||
|
||||
isPlaying=false;
|
||||
pa_threaded_mainloop_lock(mainloop);
|
||||
pa_operation_unref(pa_stream_cork(stream, 1, AudioOutputPulse::StreamSuccessCallback, NULL));
|
||||
pa_operation_unref(pa_stream_cork(stream, 1, NULL, NULL));
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
}
|
||||
|
||||
@ -213,60 +125,23 @@ void AudioOutputPulse::SetCurrentDevice(std::string devID){
|
||||
isConnected=true;
|
||||
|
||||
if(isPlaying){
|
||||
pa_operation_unref(pa_stream_cork(stream, 0, AudioOutputPulse::StreamSuccessCallback, mainloop));
|
||||
pa_operation_unref(pa_stream_cork(stream, 0, NULL, NULL));
|
||||
}
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
}
|
||||
|
||||
bool AudioOutputPulse::EnumerateDevices(std::vector<AudioOutputDevice>& devs){
|
||||
if(!PulseAudioLoader::IncRef())
|
||||
return false;
|
||||
|
||||
pa_mainloop* ml;
|
||||
pa_mainloop_api* mlAPI;
|
||||
pa_context* ctx;
|
||||
pa_operation* op=NULL;
|
||||
int state=0;
|
||||
int paReady=0;
|
||||
|
||||
ml=pa_mainloop_new();
|
||||
mlAPI=pa_mainloop_get_api(ml);
|
||||
ctx=pa_context_new(mlAPI, "libtgvoip");
|
||||
|
||||
pa_context_connect(ctx, NULL, PA_CONTEXT_NOFLAGS, NULL);
|
||||
pa_context_set_state_callback(ctx, AudioOutputPulse::ContextStateCallbackEnum, &paReady);
|
||||
|
||||
while(true){
|
||||
if(paReady==0){
|
||||
pa_mainloop_iterate(ml, 1, NULL);
|
||||
continue;
|
||||
}
|
||||
if(paReady==2){
|
||||
pa_context_disconnect(ctx);
|
||||
pa_context_unref(ctx);
|
||||
pa_mainloop_free(ml);
|
||||
PulseAudioLoader::DecRef();
|
||||
return false;
|
||||
}
|
||||
if(!op){
|
||||
op=pa_context_get_sink_info_list(ctx, AudioOutputPulse::DeviceEnumCallback, &devs);
|
||||
continue;
|
||||
}
|
||||
if(pa_operation_get_state(op)==PA_OPERATION_DONE){
|
||||
pa_operation_unref(op);
|
||||
pa_context_disconnect(ctx);
|
||||
pa_context_unref(ctx);
|
||||
pa_mainloop_free(ml);
|
||||
PulseAudioLoader::DecRef();
|
||||
return true;
|
||||
}
|
||||
pa_mainloop_iterate(ml, 1, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOutputPulse::ContextStateCallback(pa_context* context, void* arg) {
|
||||
AudioOutputPulse* self=(AudioOutputPulse*) arg;
|
||||
pa_threaded_mainloop_signal(self->mainloop, 0);
|
||||
return AudioPulse::DoOneOperation([&](pa_context* ctx){
|
||||
return pa_context_get_sink_info_list(ctx, [](pa_context* ctx, const pa_sink_info* info, int eol, void* userdata){
|
||||
if(eol>0)
|
||||
return;
|
||||
std::vector<AudioOutputDevice>* devs=(std::vector<AudioOutputDevice>*)userdata;
|
||||
AudioOutputDevice dev;
|
||||
dev.id=std::string(info->name);
|
||||
dev.displayName=std::string(info->description);
|
||||
devs->push_back(dev);
|
||||
}, &devs);
|
||||
});
|
||||
}
|
||||
|
||||
void AudioOutputPulse::StreamStateCallback(pa_stream *s, void* arg) {
|
||||
@ -295,39 +170,3 @@ void AudioOutputPulse::StreamWriteCallback(pa_stream *stream, size_t requestedBy
|
||||
if(remainingDataSize>0)
|
||||
memmove(remainingData, remainingData+requestedBytes, remainingDataSize);
|
||||
}
|
||||
|
||||
void AudioOutputPulse::StreamSuccessCallback(pa_stream *stream, int success, void *userdata) {
|
||||
return;
|
||||
}
|
||||
|
||||
void AudioOutputPulse::ContextStateCallbackEnum(pa_context* context, void* arg){
|
||||
pa_context_state_t state;
|
||||
int* pa_ready=(int*)arg;
|
||||
|
||||
state=pa_context_get_state(context);
|
||||
switch(state){
|
||||
case PA_CONTEXT_UNCONNECTED:
|
||||
case PA_CONTEXT_CONNECTING:
|
||||
case PA_CONTEXT_AUTHORIZING:
|
||||
case PA_CONTEXT_SETTING_NAME:
|
||||
default:
|
||||
break;
|
||||
case PA_CONTEXT_FAILED:
|
||||
case PA_CONTEXT_TERMINATED:
|
||||
*pa_ready=2;
|
||||
break;
|
||||
case PA_CONTEXT_READY:
|
||||
*pa_ready=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOutputPulse::DeviceEnumCallback(pa_context* ctx, const pa_sink_info* info, int eol, void* userdata){
|
||||
if(eol>0)
|
||||
return;
|
||||
std::vector<AudioOutputDevice>* devs=(std::vector<AudioOutputDevice>*)userdata;
|
||||
AudioOutputDevice dev;
|
||||
dev.id=std::string(info->name);
|
||||
dev.displayName=std::string(info->description);
|
||||
devs->push_back(dev);
|
||||
}
|
||||
|
||||
@ -16,27 +16,20 @@ namespace audio{
|
||||
|
||||
class AudioOutputPulse : public AudioOutput{
|
||||
public:
|
||||
AudioOutputPulse(std::string devID);
|
||||
AudioOutputPulse(pa_context* context, pa_threaded_mainloop* mainloop, std::string devID);
|
||||
virtual ~AudioOutputPulse();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
virtual bool IsPlaying();
|
||||
virtual void SetCurrentDevice(std::string devID);
|
||||
static bool EnumerateDevices(std::vector<AudioOutputDevice>& devs);
|
||||
static bool IsAvailable();
|
||||
|
||||
private:
|
||||
static void ContextStateCallback(pa_context* context, void* arg);
|
||||
static void ContextStateCallbackEnum(pa_context* context, void* arg);
|
||||
static void StreamStateCallback(pa_stream* s, void* arg);
|
||||
static void StreamSuccessCallback(pa_stream* stream, int success, void* userdata);
|
||||
static void StreamWriteCallback(pa_stream* stream, size_t requested_bytes, void* userdata);
|
||||
static void DeviceEnumCallback(pa_context* ctx, const pa_sink_info* info, int eol, void* userdata);
|
||||
void StreamWriteCallback(pa_stream* stream, size_t requestedBytes);
|
||||
|
||||
pa_threaded_mainloop* mainloop;
|
||||
pa_mainloop_api* mainloopApi;
|
||||
pa_context* context;
|
||||
pa_stream* stream;
|
||||
|
||||
|
||||
275
os/linux/AudioPulse.cpp
Normal file
275
os/linux/AudioPulse.cpp
Normal file
@ -0,0 +1,275 @@
|
||||
//
|
||||
// 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 "AudioPulse.h"
|
||||
#include <dlfcn.h>
|
||||
#include "../../logging.h"
|
||||
|
||||
#define DECLARE_DL_FUNCTION(name) typeof(name)* AudioPulse::_import_##name=NULL
|
||||
#define CHECK_DL_ERROR(res, msg) if(!res){LOGE(msg ": %s", dlerror()); return false;}
|
||||
#define LOAD_DL_FUNCTION(name) {_import_##name=(typeof(_import_##name))dlsym(lib, #name); CHECK_DL_ERROR(_import_##name, "Error getting entry point for " #name);}
|
||||
#define CHECK_ERROR(res, msg) if(res!=0){LOGE(msg " failed: %s", pa_strerror(res)); failed=true; return;}
|
||||
|
||||
using namespace tgvoip;
|
||||
using namespace tgvoip::audio;
|
||||
|
||||
bool AudioPulse::loaded=false;
|
||||
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_set_state_callback);
|
||||
DECLARE_DL_FUNCTION(pa_threaded_mainloop_lock);
|
||||
DECLARE_DL_FUNCTION(pa_threaded_mainloop_unlock);
|
||||
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_set_state_callback);
|
||||
DECLARE_DL_FUNCTION(pa_stream_set_write_callback);
|
||||
DECLARE_DL_FUNCTION(pa_stream_connect_playback);
|
||||
DECLARE_DL_FUNCTION(pa_operation_unref);
|
||||
DECLARE_DL_FUNCTION(pa_stream_cork);
|
||||
DECLARE_DL_FUNCTION(pa_threaded_mainloop_stop);
|
||||
DECLARE_DL_FUNCTION(pa_stream_disconnect);
|
||||
DECLARE_DL_FUNCTION(pa_stream_unref);
|
||||
DECLARE_DL_FUNCTION(pa_context_disconnect);
|
||||
DECLARE_DL_FUNCTION(pa_context_unref);
|
||||
DECLARE_DL_FUNCTION(pa_threaded_mainloop_free);
|
||||
DECLARE_DL_FUNCTION(pa_threaded_mainloop_signal);
|
||||
DECLARE_DL_FUNCTION(pa_stream_begin_write);
|
||||
DECLARE_DL_FUNCTION(pa_stream_write);
|
||||
DECLARE_DL_FUNCTION(pa_stream_get_state);
|
||||
DECLARE_DL_FUNCTION(pa_strerror);
|
||||
DECLARE_DL_FUNCTION(pa_stream_set_read_callback);
|
||||
DECLARE_DL_FUNCTION(pa_stream_connect_record);
|
||||
DECLARE_DL_FUNCTION(pa_stream_peek);
|
||||
DECLARE_DL_FUNCTION(pa_stream_drop);
|
||||
DECLARE_DL_FUNCTION(pa_mainloop_new);
|
||||
DECLARE_DL_FUNCTION(pa_mainloop_get_api);
|
||||
DECLARE_DL_FUNCTION(pa_mainloop_iterate);
|
||||
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);
|
||||
|
||||
#include "PulseFunctions.h"
|
||||
|
||||
bool AudioPulse::Load(){
|
||||
if(loaded)
|
||||
return true;
|
||||
|
||||
lib=dlopen("libpulse.so.0", RTLD_LAZY);
|
||||
if(!lib)
|
||||
lib=dlopen("libpulse.so", RTLD_LAZY);
|
||||
if(!lib){
|
||||
LOGE("Error loading libpulse: %s", dlerror());
|
||||
return false;
|
||||
}
|
||||
|
||||
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_set_state_callback);
|
||||
LOAD_DL_FUNCTION(pa_threaded_mainloop_lock);
|
||||
LOAD_DL_FUNCTION(pa_threaded_mainloop_unlock);
|
||||
LOAD_DL_FUNCTION(pa_threaded_mainloop_start);
|
||||
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_set_state_callback);
|
||||
LOAD_DL_FUNCTION(pa_stream_set_write_callback);
|
||||
LOAD_DL_FUNCTION(pa_stream_connect_playback);
|
||||
LOAD_DL_FUNCTION(pa_operation_unref);
|
||||
LOAD_DL_FUNCTION(pa_stream_cork);
|
||||
LOAD_DL_FUNCTION(pa_threaded_mainloop_stop);
|
||||
LOAD_DL_FUNCTION(pa_stream_disconnect);
|
||||
LOAD_DL_FUNCTION(pa_stream_unref);
|
||||
LOAD_DL_FUNCTION(pa_context_disconnect);
|
||||
LOAD_DL_FUNCTION(pa_context_unref);
|
||||
LOAD_DL_FUNCTION(pa_threaded_mainloop_free);
|
||||
LOAD_DL_FUNCTION(pa_threaded_mainloop_signal);
|
||||
LOAD_DL_FUNCTION(pa_stream_begin_write);
|
||||
LOAD_DL_FUNCTION(pa_stream_write);
|
||||
LOAD_DL_FUNCTION(pa_stream_get_state);
|
||||
LOAD_DL_FUNCTION(pa_strerror);
|
||||
LOAD_DL_FUNCTION(pa_stream_set_read_callback);
|
||||
LOAD_DL_FUNCTION(pa_stream_connect_record);
|
||||
LOAD_DL_FUNCTION(pa_stream_peek);
|
||||
LOAD_DL_FUNCTION(pa_stream_drop);
|
||||
LOAD_DL_FUNCTION(pa_mainloop_new);
|
||||
LOAD_DL_FUNCTION(pa_mainloop_get_api);
|
||||
LOAD_DL_FUNCTION(pa_mainloop_iterate);
|
||||
LOAD_DL_FUNCTION(pa_mainloop_free);
|
||||
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);
|
||||
|
||||
loaded=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
AudioPulse::AudioPulse(std::string inputDevice, std::string outputDevice){
|
||||
if(!Load()){
|
||||
failed=true;
|
||||
LOGE("Failed to load libpulse");
|
||||
return;
|
||||
}
|
||||
|
||||
mainloop=pa_threaded_mainloop_new();
|
||||
if(!mainloop){
|
||||
LOGE("Error initializing PulseAudio (pa_threaded_mainloop_new)");
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
mainloopApi=pa_threaded_mainloop_get_api(mainloop);
|
||||
#ifndef MAXPATHLEN
|
||||
char exeName[20];
|
||||
#else
|
||||
char exePath[MAXPATHLEN];
|
||||
char exeName[MAXPATHLEN];
|
||||
ssize_t lres=readlink("/proc/self/exe", exePath, sizeof(exePath));
|
||||
if(lres==-1)
|
||||
lres=readlink("/proc/curproc/file", exePath, sizeof(exePath));
|
||||
if(lres==-1)
|
||||
lres=readlink("/proc/curproc/exe", exePath, sizeof(exePath));
|
||||
if(lres>0){
|
||||
strcpy(exeName, basename(exePath));
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
snprintf(exeName, sizeof(exeName), "Process %d", getpid());
|
||||
}
|
||||
context=pa_context_new(mainloopApi, exeName);
|
||||
if(!context){
|
||||
LOGE("Error initializing PulseAudio (pa_context_new)");
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
pa_context_set_state_callback(context, [](pa_context* context, void* arg){
|
||||
AudioPulse* self=reinterpret_cast<AudioPulse*>(arg);
|
||||
pa_threaded_mainloop_signal(self->mainloop, 0);
|
||||
}, this);
|
||||
pa_threaded_mainloop_lock(mainloop);
|
||||
isLocked=true;
|
||||
int err=pa_threaded_mainloop_start(mainloop);
|
||||
CHECK_ERROR(err, "pa_threaded_mainloop_start");
|
||||
didStart=true;
|
||||
|
||||
err=pa_context_connect(context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL);
|
||||
CHECK_ERROR(err, "pa_context_connect");
|
||||
|
||||
while(true){
|
||||
pa_context_state_t contextState=pa_context_get_state(context);
|
||||
if(!PA_CONTEXT_IS_GOOD(contextState)){
|
||||
LOGE("Error initializing PulseAudio (PA_CONTEXT_IS_GOOD)");
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
if(contextState==PA_CONTEXT_READY)
|
||||
break;
|
||||
pa_threaded_mainloop_wait(mainloop);
|
||||
}
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
isLocked=false;
|
||||
|
||||
output=new AudioOutputPulse(context, mainloop, outputDevice);
|
||||
input=new AudioInputPulse(context, mainloop, outputDevice);
|
||||
}
|
||||
|
||||
AudioPulse::~AudioPulse(){
|
||||
if(mainloop && didStart){
|
||||
if(isLocked)
|
||||
pa_threaded_mainloop_unlock(mainloop);
|
||||
pa_threaded_mainloop_stop(mainloop);
|
||||
}
|
||||
|
||||
if(input)
|
||||
delete input;
|
||||
if(output)
|
||||
delete output;
|
||||
|
||||
if(context){
|
||||
pa_context_disconnect(context);
|
||||
pa_context_unref(context);
|
||||
}
|
||||
if(mainloop)
|
||||
pa_threaded_mainloop_free(mainloop);
|
||||
}
|
||||
|
||||
AudioOutput* AudioPulse::GetOutput(){
|
||||
return output;
|
||||
}
|
||||
|
||||
AudioInput* AudioPulse::GetInput(){
|
||||
return input;
|
||||
}
|
||||
|
||||
bool AudioPulse::DoOneOperation(std::function<pa_operation*(pa_context*)> f){
|
||||
if(!Load())
|
||||
return false;
|
||||
|
||||
pa_mainloop* ml;
|
||||
pa_mainloop_api* mlAPI;
|
||||
pa_context* ctx;
|
||||
pa_operation* op=NULL;
|
||||
int paReady=0;
|
||||
|
||||
ml=pa_mainloop_new();
|
||||
mlAPI=pa_mainloop_get_api(ml);
|
||||
ctx=pa_context_new(mlAPI, "libtgvoip");
|
||||
|
||||
pa_context_connect(ctx, NULL, PA_CONTEXT_NOFLAGS, NULL);
|
||||
pa_context_set_state_callback(ctx, [](pa_context* context, void* arg){
|
||||
pa_context_state_t state;
|
||||
int* pa_ready=(int*)arg;
|
||||
|
||||
state=pa_context_get_state(context);
|
||||
switch(state){
|
||||
case PA_CONTEXT_UNCONNECTED:
|
||||
case PA_CONTEXT_CONNECTING:
|
||||
case PA_CONTEXT_AUTHORIZING:
|
||||
case PA_CONTEXT_SETTING_NAME:
|
||||
default:
|
||||
break;
|
||||
case PA_CONTEXT_FAILED:
|
||||
case PA_CONTEXT_TERMINATED:
|
||||
*pa_ready=2;
|
||||
break;
|
||||
case PA_CONTEXT_READY:
|
||||
*pa_ready=1;
|
||||
break;
|
||||
}
|
||||
}, &paReady);
|
||||
|
||||
while(true){
|
||||
if(paReady==0){
|
||||
pa_mainloop_iterate(ml, 1, NULL);
|
||||
continue;
|
||||
}
|
||||
if(paReady==2){
|
||||
pa_context_disconnect(ctx);
|
||||
pa_context_unref(ctx);
|
||||
pa_mainloop_free(ml);
|
||||
return false;
|
||||
}
|
||||
if(!op){
|
||||
op=f(ctx);
|
||||
continue;
|
||||
}
|
||||
if(pa_operation_get_state(op)==PA_OPERATION_DONE){
|
||||
pa_operation_unref(op);
|
||||
pa_context_disconnect(ctx);
|
||||
pa_context_unref(ctx);
|
||||
pa_mainloop_free(ml);
|
||||
return true;
|
||||
}
|
||||
pa_mainloop_iterate(ml, 1, NULL);
|
||||
}
|
||||
}
|
||||
88
os/linux/AudioPulse.h
Normal file
88
os/linux/AudioPulse.h
Normal file
@ -0,0 +1,88 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef LIBTGVOIP_PULSEAUDIOLOADER_H
|
||||
#define LIBTGVOIP_PULSEAUDIOLOADER_H
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <pulse/pulseaudio.h>
|
||||
#include "../../audio/AudioIO.h"
|
||||
#include "AudioInputPulse.h"
|
||||
#include "AudioOutputPulse.h"
|
||||
|
||||
#define DECLARE_DL_FUNCTION(name) static typeof(name)* _import_##name
|
||||
|
||||
namespace tgvoip{
|
||||
namespace audio{
|
||||
class AudioPulse : public AudioIO{
|
||||
public:
|
||||
AudioPulse(std::string inputDevice, std::string outputDevice);
|
||||
virtual ~AudioPulse();
|
||||
virtual AudioInput* GetInput();
|
||||
virtual AudioOutput* GetOutput();
|
||||
|
||||
static bool Load();
|
||||
static bool DoOneOperation(std::function<pa_operation*(pa_context*)> f);
|
||||
|
||||
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_set_state_callback);
|
||||
DECLARE_DL_FUNCTION(pa_threaded_mainloop_lock);
|
||||
DECLARE_DL_FUNCTION(pa_threaded_mainloop_unlock);
|
||||
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_set_state_callback);
|
||||
DECLARE_DL_FUNCTION(pa_stream_set_write_callback);
|
||||
DECLARE_DL_FUNCTION(pa_stream_connect_playback);
|
||||
DECLARE_DL_FUNCTION(pa_operation_unref);
|
||||
DECLARE_DL_FUNCTION(pa_stream_cork);
|
||||
DECLARE_DL_FUNCTION(pa_threaded_mainloop_stop);
|
||||
DECLARE_DL_FUNCTION(pa_stream_disconnect);
|
||||
DECLARE_DL_FUNCTION(pa_stream_unref);
|
||||
DECLARE_DL_FUNCTION(pa_context_disconnect);
|
||||
DECLARE_DL_FUNCTION(pa_context_unref);
|
||||
DECLARE_DL_FUNCTION(pa_threaded_mainloop_free);
|
||||
DECLARE_DL_FUNCTION(pa_threaded_mainloop_signal);
|
||||
DECLARE_DL_FUNCTION(pa_stream_begin_write);
|
||||
DECLARE_DL_FUNCTION(pa_stream_write);
|
||||
DECLARE_DL_FUNCTION(pa_stream_get_state);
|
||||
DECLARE_DL_FUNCTION(pa_strerror);
|
||||
DECLARE_DL_FUNCTION(pa_stream_set_read_callback);
|
||||
DECLARE_DL_FUNCTION(pa_stream_connect_record);
|
||||
DECLARE_DL_FUNCTION(pa_stream_peek);
|
||||
DECLARE_DL_FUNCTION(pa_stream_drop);
|
||||
|
||||
DECLARE_DL_FUNCTION(pa_mainloop_new);
|
||||
DECLARE_DL_FUNCTION(pa_mainloop_get_api);
|
||||
DECLARE_DL_FUNCTION(pa_mainloop_iterate);
|
||||
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);
|
||||
|
||||
private:
|
||||
static void* lib;
|
||||
static bool loaded;
|
||||
AudioInputPulse* input=NULL;
|
||||
AudioOutputPulse* output=NULL;
|
||||
|
||||
pa_threaded_mainloop* mainloop;
|
||||
pa_mainloop_api* mainloopApi;
|
||||
pa_context* context;
|
||||
bool isLocked=false;
|
||||
bool didStart=false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#undef DECLARE_DL_FUNCTION
|
||||
|
||||
#endif // LIBTGVOIP_PULSEAUDIOLOADER_H
|
||||
43
os/linux/PulseFunctions.h
Normal file
43
os/linux/PulseFunctions.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef LIBTGVOIP_PULSE_FUNCTIONS_H
|
||||
#define LIBTGVOIP_PULSE_FUNCTIONS_H
|
||||
|
||||
#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_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
|
||||
#define pa_threaded_mainloop_start AudioPulse::_import_pa_threaded_mainloop_start
|
||||
#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_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
|
||||
#define pa_operation_unref AudioPulse::_import_pa_operation_unref
|
||||
#define pa_stream_cork AudioPulse::_import_pa_stream_cork
|
||||
#define pa_threaded_mainloop_stop AudioPulse::_import_pa_threaded_mainloop_stop
|
||||
#define pa_stream_disconnect AudioPulse::_import_pa_stream_disconnect
|
||||
#define pa_stream_unref AudioPulse::_import_pa_stream_unref
|
||||
#define pa_context_disconnect AudioPulse::_import_pa_context_disconnect
|
||||
#define pa_context_unref AudioPulse::_import_pa_context_unref
|
||||
#define pa_threaded_mainloop_free AudioPulse::_import_pa_threaded_mainloop_free
|
||||
#define pa_threaded_mainloop_signal AudioPulse::_import_pa_threaded_mainloop_signal
|
||||
#define pa_stream_begin_write AudioPulse::_import_pa_stream_begin_write
|
||||
#define pa_stream_write AudioPulse::_import_pa_stream_write
|
||||
#define pa_strerror AudioPulse::_import_pa_strerror
|
||||
#define pa_stream_get_state AudioPulse::_import_pa_stream_get_state
|
||||
#define pa_stream_set_read_callback AudioPulse::_import_pa_stream_set_read_callback
|
||||
#define pa_stream_connect_record AudioPulse::_import_pa_stream_connect_record
|
||||
#define pa_stream_peek AudioPulse::_import_pa_stream_peek
|
||||
#define pa_stream_drop AudioPulse::_import_pa_stream_drop
|
||||
#define pa_mainloop_new AudioPulse::_import_pa_mainloop_new
|
||||
#define pa_mainloop_get_api AudioPulse::_import_pa_mainloop_get_api
|
||||
#define pa_mainloop_iterate AudioPulse::_import_pa_mainloop_iterate
|
||||
#define pa_mainloop_free AudioPulse::_import_pa_mainloop_free
|
||||
#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
|
||||
|
||||
#endif //LIBTGVOIP_PULSE_FUNCTIONS_H
|
||||
@ -490,7 +490,7 @@ bool NetworkSocketPosix::Select(std::vector<NetworkSocket *> &readFds, std::vect
|
||||
|
||||
if(canceller && FD_ISSET(canceller->pipeRead, &readSet) && !anyFailed){
|
||||
char c;
|
||||
read(canceller->pipeRead, &c, 1);
|
||||
(void) read(canceller->pipeRead, &c, 1);
|
||||
return false;
|
||||
}else if(anyFailed){
|
||||
FD_ZERO(&readSet);
|
||||
@ -539,7 +539,7 @@ SocketSelectCancellerPosix::~SocketSelectCancellerPosix(){
|
||||
|
||||
void SocketSelectCancellerPosix::CancelSelect(){
|
||||
char c=1;
|
||||
write(pipeWrite, &c, 1);
|
||||
(void) write(pipeWrite, &c, 1);
|
||||
}
|
||||
|
||||
int NetworkSocketPosix::GetDescriptorFromSocket(NetworkSocket *socket){
|
||||
|
||||
@ -99,11 +99,6 @@ AudioInputWASAPI::~AudioInputWASAPI(){
|
||||
SafeRelease(&enumerator);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioInputWASAPI::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
|
||||
}
|
||||
|
||||
void AudioInputWASAPI::Start(){
|
||||
isRecording=true;
|
||||
if(!thread){
|
||||
|
||||
@ -44,7 +44,6 @@ class AudioInputWASAPI : public AudioInput{
|
||||
public:
|
||||
AudioInputWASAPI(std::string deviceID);
|
||||
virtual ~AudioInputWASAPI();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
virtual bool IsRecording();
|
||||
|
||||
@ -37,10 +37,6 @@ AudioInputWave::~AudioInputWave(){
|
||||
waveInClose(hWaveIn);
|
||||
}
|
||||
|
||||
void AudioInputWave::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
|
||||
}
|
||||
|
||||
void AudioInputWave::Start(){
|
||||
if(!isRecording){
|
||||
isRecording=true;
|
||||
|
||||
@ -20,7 +20,6 @@ class AudioInputWave : public AudioInput{
|
||||
public:
|
||||
AudioInputWave(std::string deviceID);
|
||||
virtual ~AudioInputWave();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
virtual void SetCurrentDevice(std::string deviceID);
|
||||
|
||||
@ -101,10 +101,6 @@ AudioOutputWASAPI::~AudioOutputWASAPI(){
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioOutputWASAPI::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
|
||||
}
|
||||
|
||||
void AudioOutputWASAPI::Start(){
|
||||
isPlaying=true;
|
||||
if(!thread){
|
||||
|
||||
@ -43,7 +43,6 @@ class AudioOutputWASAPI : public AudioOutput{
|
||||
public:
|
||||
AudioOutputWASAPI(std::string deviceID);
|
||||
virtual ~AudioOutputWASAPI();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
virtual bool IsPlaying();
|
||||
|
||||
@ -35,10 +35,6 @@ AudioOutputWave::~AudioOutputWave(){
|
||||
waveOutClose(hWaveOut);
|
||||
}
|
||||
|
||||
void AudioOutputWave::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
|
||||
}
|
||||
|
||||
void AudioOutputWave::Start(){
|
||||
if(!isPlaying){
|
||||
isPlaying=true;
|
||||
|
||||
@ -19,7 +19,6 @@ class AudioOutputWave : public AudioOutput{
|
||||
public:
|
||||
AudioOutputWave(std::string deviceID);
|
||||
virtual ~AudioOutputWave();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
virtual bool IsPlaying();
|
||||
|
||||
35
threading.h
35
threading.h
@ -38,6 +38,10 @@ namespace tgvoip{
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#ifdef __APPLE__
|
||||
#include "os/darwin/DarwinSpecific.h"
|
||||
#endif
|
||||
|
||||
namespace tgvoip{
|
||||
class Mutex{
|
||||
@ -58,6 +62,10 @@ namespace tgvoip{
|
||||
pthread_mutex_unlock(&mtx);
|
||||
}
|
||||
|
||||
pthread_mutex_t* NativeHandle(){
|
||||
return &mtx;
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex(const Mutex& other);
|
||||
pthread_mutex_t mtx;
|
||||
@ -69,7 +77,7 @@ namespace tgvoip{
|
||||
name=NULL;
|
||||
}
|
||||
|
||||
~Thread(){
|
||||
virtual ~Thread(){
|
||||
delete entry;
|
||||
}
|
||||
|
||||
@ -87,7 +95,17 @@ namespace tgvoip{
|
||||
|
||||
|
||||
void SetMaxPriority(){
|
||||
#ifdef __APPLE__
|
||||
maxPriority=true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void Sleep(double seconds){
|
||||
usleep((useconds_t)(seconds*1000000000));
|
||||
}
|
||||
|
||||
bool IsCurrent(){
|
||||
return thread==pthread_self();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -98,6 +116,9 @@ namespace tgvoip{
|
||||
pthread_setname_np(self->thread, self->name);
|
||||
#elif !defined(__gnu_hurd__)
|
||||
pthread_setname_np(self->name);
|
||||
if(self->maxPriority){
|
||||
DarwinSpecific::SetCurrentThreadPriority(DarwinSpecific::THREAD_PRIO_USER_INTERACTIVE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
self->entry->Invoke(self->arg);
|
||||
@ -107,6 +128,7 @@ namespace tgvoip{
|
||||
void* arg;
|
||||
pthread_t thread;
|
||||
const char* name;
|
||||
bool maxPriority=false;
|
||||
};
|
||||
}
|
||||
|
||||
@ -227,7 +249,7 @@ namespace tgvoip{
|
||||
}
|
||||
|
||||
void Start(){
|
||||
thread=CreateThread(NULL, 0, Thread::ActualEntryPoint, this, 0, NULL);
|
||||
thread=CreateThread(NULL, 0, Thread::ActualEntryPoint, this, 0, &id);
|
||||
}
|
||||
|
||||
void Join(){
|
||||
@ -247,6 +269,14 @@ namespace tgvoip{
|
||||
SetThreadPriority(thread, THREAD_PRIORITY_HIGHEST);
|
||||
}
|
||||
|
||||
static void Sleep(double seconds){
|
||||
::Sleep((DWORD)(seconds*1000));
|
||||
}
|
||||
|
||||
bool IsCurrent(){
|
||||
return id==GetCurrentThreadId();
|
||||
}
|
||||
|
||||
private:
|
||||
static const DWORD MS_VC_EXCEPTION=0x406D1388;
|
||||
|
||||
@ -278,6 +308,7 @@ namespace tgvoip{
|
||||
MethodPointerBase* entry;
|
||||
void* arg;
|
||||
HANDLE thread;
|
||||
DWORD id;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user