- 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:
Grishka 2018-07-17 19:48:21 +03:00
parent dacde29548
commit 5380aaba0d
79 changed files with 52442 additions and 1444 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

File diff suppressed because it is too large Load Diff

88
audio/AudioIO.cpp Normal file
View 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
View 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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

265
config.h.in Normal file
View 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

File diff suppressed because it is too large Load Diff

21128
configure vendored Executable file

File diff suppressed because it is too large Load Diff

110
configure.ac Normal file
View 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
View 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
View 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:

View File

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

View File

@ -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 */,

View File

@ -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 */,

View File

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

View File

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

11147
ltmain.sh Normal file

File diff suppressed because it is too large Load Diff

215
missing Executable file
View 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:

View File

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

View File

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

View File

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

View File

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

View File

@ -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(){

View File

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

View File

@ -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"){

View File

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

View File

@ -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++){

View File

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

View File

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

View File

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

View File

@ -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"){

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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