mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-29 17:10:31 +00:00
Update to v0.4
Moved public API classes into namespace tgvoip (CVoIPController -> tgvoip::VoIPController, CVoIPServerConfig -> tgvoip::ServerConfig) Endpoint is now a class instead of a struct; also, IP addresses are now wrapped into objects instead of relying on in_addr and in6_addr Full Windows port (Win32 threading + Winsock + WaveOut/WaveIn) Added support for ALSA audio I/O on Linux (closes #2) Abstracted away low-level networking to make it more portable Minor bugfixes
This commit is contained in:
parent
88d22e82cf
commit
bfde1a4be3
68
Android.mk
68
Android.mk
@ -1,16 +1,24 @@
|
||||
LOCAL_MODULE := WebRtcAec
|
||||
|
||||
LOCAL_SRC_FILES := ./libtgvoip/external/libWebRtcAec_android_$(TARGET_ARCH_ABI).a
|
||||
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := voip
|
||||
LOCAL_CPPFLAGS := -Wall -std=c++11 -DANDROID -finline-functions -ffast-math -Os -fno-strict-aliasing -O3
|
||||
LOCAL_CFLAGS := -O3 -DUSE_KISS_FFT -DFIXED_POINT
|
||||
LOCAL_CFLAGS := -O3 -DUSE_KISS_FFT -fexceptions
|
||||
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
LOCAL_CPPFLAGS += -mfloat-abi=softfp -mfpu=neon
|
||||
LOCAL_CFLAGS += -mfloat-abi=softfp -mfpu=neon
|
||||
# LOCAL_CPPFLAGS += -mfloat-abi=softfp -mfpu=neon
|
||||
# LOCAL_CFLAGS += -mfloat-abi=softfp -mfpu=neon -DFLOATING_POINT
|
||||
# LOCAL_ARM_NEON := true
|
||||
else
|
||||
LOCAL_CFLAGS += -DFIXED_POINT
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi)
|
||||
LOCAL_CPPFLAGS += -mfloat-abi=softfp -mfpu=neon
|
||||
LOCAL_CFLAGS += -mfloat-abi=softfp -mfpu=neon
|
||||
# LOCAL_CPPFLAGS += -mfloat-abi=softfp -mfpu=neon
|
||||
# LOCAL_CFLAGS += -mfloat-abi=softfp -mfpu=neon
|
||||
else
|
||||
ifeq ($(TARGET_ARCH_ABI),x86)
|
||||
|
||||
@ -23,32 +31,28 @@ MY_DIR := libtgvoip
|
||||
LOCAL_C_INCLUDES := jni/opus/include jni/boringssl/include/
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
$(MY_DIR)/external/speex_dsp/buffer.c \
|
||||
$(MY_DIR)/external/speex_dsp/fftwrap.c \
|
||||
$(MY_DIR)/external/speex_dsp/filterbank.c \
|
||||
$(MY_DIR)/external/speex_dsp/kiss_fft.c \
|
||||
$(MY_DIR)/external/speex_dsp/kiss_fftr.c \
|
||||
$(MY_DIR)/external/speex_dsp/mdf.c \
|
||||
$(MY_DIR)/external/speex_dsp/preprocess.c \
|
||||
$(MY_DIR)/external/speex_dsp/resample.c \
|
||||
$(MY_DIR)/external/speex_dsp/scal.c \
|
||||
$(MY_DIR)/external/speex_dsp/smallft.c \
|
||||
$(MY_DIR)/VoIPController.cpp \
|
||||
$(MY_DIR)/BufferInputStream.cpp \
|
||||
$(MY_DIR)/BufferOutputStream.cpp \
|
||||
$(MY_DIR)/BlockingQueue.cpp \
|
||||
$(MY_DIR)/audio/AudioInput.cpp \
|
||||
$(MY_DIR)/os/android/AudioInputOpenSLES.cpp \
|
||||
$(MY_DIR)/MediaStreamItf.cpp \
|
||||
$(MY_DIR)/audio/AudioOutput.cpp \
|
||||
$(MY_DIR)/OpusEncoder.cpp \
|
||||
$(MY_DIR)/os/android/AudioOutputOpenSLES.cpp \
|
||||
$(MY_DIR)/JitterBuffer.cpp \
|
||||
$(MY_DIR)/OpusDecoder.cpp \
|
||||
$(MY_DIR)/BufferPool.cpp \
|
||||
$(MY_DIR)/os/android/OpenSLEngineWrapper.cpp \
|
||||
$(MY_DIR)/os/android/AudioInputAndroid.cpp \
|
||||
$(MY_DIR)/EchoCanceller.cpp \
|
||||
./libtgvoip/logging.cpp \
|
||||
./libtgvoip/VoIPController.cpp \
|
||||
./libtgvoip/BufferInputStream.cpp \
|
||||
./libtgvoip/BufferOutputStream.cpp \
|
||||
./libtgvoip/BlockingQueue.cpp \
|
||||
./libtgvoip/audio/AudioInput.cpp \
|
||||
./libtgvoip/os/android/AudioInputOpenSLES.cpp \
|
||||
./libtgvoip/MediaStreamItf.cpp \
|
||||
./libtgvoip/audio/AudioOutput.cpp \
|
||||
./libtgvoip/OpusEncoder.cpp \
|
||||
./libtgvoip/os/android/AudioOutputOpenSLES.cpp \
|
||||
./libtgvoip/JitterBuffer.cpp \
|
||||
./libtgvoip/OpusDecoder.cpp \
|
||||
./libtgvoip/BufferPool.cpp \
|
||||
./libtgvoip/os/android/OpenSLEngineWrapper.cpp \
|
||||
./libtgvoip/os/android/AudioInputAndroid.cpp \
|
||||
./libtgvoip/os/android/AudioOutputAndroid.cpp \
|
||||
./libtgvoip/EchoCanceller.cpp \
|
||||
./libtgvoip/CongestionControl.cpp \
|
||||
./libtgvoip/VoIPServerConfig.cpp \
|
||||
./libtgvoip/NetworkSocket.cpp
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define LIBTGVOIP_BUFFEROUTPUTSTREAM_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
class CBufferOutputStream{
|
||||
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace tgvoip;
|
||||
|
||||
CCongestionControl::CCongestionControl(){
|
||||
memset(rttHistory, 0, 100*sizeof(double));
|
||||
memset(inflightPackets, 0, 100*sizeof(tgvoip_congestionctl_packet_t));
|
||||
@ -27,7 +29,7 @@ CCongestionControl::CCongestionControl(){
|
||||
stateTransitionTime=0;
|
||||
inflightDataSize=0;
|
||||
lossCount=0;
|
||||
cwnd=(size_t) CVoIPServerConfig::GetSharedInstance()->GetInt("audio_congestion_window", 1024);
|
||||
cwnd=(size_t) ServerConfig::GetSharedInstance()->GetInt("audio_congestion_window", 1024);
|
||||
init_mutex(mutex);
|
||||
}
|
||||
|
||||
@ -81,7 +83,7 @@ void CCongestionControl::PacketAcknowledged(uint32_t seq){
|
||||
int i;
|
||||
for(i=0;i<100;i++){
|
||||
if(inflightPackets[i].seq==seq && inflightPackets[i].sendTime>0){
|
||||
tmpRtt+=(CVoIPController::GetCurrentTime()-inflightPackets[i].sendTime);
|
||||
tmpRtt+=(VoIPController::GetCurrentTime()-inflightPackets[i].sendTime);
|
||||
tmpRttCount++;
|
||||
inflightPackets[i].sendTime=0;
|
||||
inflightDataSize-=inflightPackets[i].size;
|
||||
@ -119,7 +121,7 @@ void CCongestionControl::PacketSent(uint32_t seq, size_t size){
|
||||
}
|
||||
slot->seq=seq;
|
||||
slot->size=size;
|
||||
slot->sendTime=CVoIPController::GetCurrentTime();
|
||||
slot->sendTime=VoIPController::GetCurrentTime();
|
||||
inflightDataSize+=size;
|
||||
unlock_mutex(mutex);
|
||||
}
|
||||
@ -138,7 +140,7 @@ void CCongestionControl::Tick(){
|
||||
}
|
||||
int i;
|
||||
for(i=0;i<100;i++){
|
||||
if(inflightPackets[i].sendTime!=0 && CVoIPController::GetCurrentTime()-inflightPackets[i].sendTime>2){
|
||||
if(inflightPackets[i].sendTime!=0 && VoIPController::GetCurrentTime()-inflightPackets[i].sendTime>2){
|
||||
inflightPackets[i].sendTime=0;
|
||||
inflightDataSize-=inflightPackets[i].size;
|
||||
lossCount++;
|
||||
@ -152,17 +154,17 @@ void CCongestionControl::Tick(){
|
||||
|
||||
|
||||
int CCongestionControl::GetBandwidthControlAction(){
|
||||
if(CVoIPController::GetCurrentTime()-lastActionTime<1)
|
||||
if(VoIPController::GetCurrentTime()-lastActionTime<1)
|
||||
return TGVOIP_CONCTL_ACT_NONE;
|
||||
size_t inflightAvg=GetInflightDataSize();
|
||||
size_t max=cwnd+cwnd/10;
|
||||
size_t min=cwnd-cwnd/10;
|
||||
if(inflightAvg<min){
|
||||
lastActionTime=CVoIPController::GetCurrentTime();
|
||||
lastActionTime=VoIPController::GetCurrentTime();
|
||||
return TGVOIP_CONCTL_ACT_INCREASE;
|
||||
}
|
||||
if(inflightAvg>max){
|
||||
lastActionTime=CVoIPController::GetCurrentTime();
|
||||
lastActionTime=VoIPController::GetCurrentTime();
|
||||
return TGVOIP_CONCTL_ACT_DECREASE;
|
||||
}
|
||||
return TGVOIP_CONCTL_ACT_NONE;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define LIBTGVOIP_CONGESTIONCONTROL_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "threading.h"
|
||||
|
||||
#define TGVOIP_CONCTL_STARTUP 0
|
||||
|
@ -10,12 +10,17 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef TGVOIP_NO_AEC
|
||||
#ifndef TGVOIP_NO_DSP
|
||||
#ifndef TGVOIP_USE_DESKTOP_DSP
|
||||
#include "webrtc/modules/audio_processing/aecm/echo_control_mobile.h"
|
||||
//#include "external/include/webrtc/echo_cancellation.h"
|
||||
#include "webrtc/modules/audio_processing/ns/noise_suppression_x.h"
|
||||
#else
|
||||
#include "webrtc/modules/audio_processing/aec/echo_cancellation.h"
|
||||
//#include "webrtc/modules/audio_processing/ns/noise_suppression.h"
|
||||
#include "webrtc/modules/audio_processing/ns/noise_suppression_x.h"
|
||||
#endif
|
||||
#include "webrtc/modules/audio_processing/splitting_filter.h"
|
||||
#include "webrtc/common_audio/channel_buffer.h"
|
||||
#include "webrtc/modules/audio_processing/ns/noise_suppression_x.h"
|
||||
#include "webrtc/modules/audio_processing/agc/legacy/gain_control.h"
|
||||
#endif
|
||||
|
||||
@ -25,9 +30,11 @@
|
||||
//#define CLAMP(x, min, max) (x<max ? (x>min ? x : min) : max)
|
||||
#define CLAMP(x, min, max) x
|
||||
|
||||
/*namespace webrtc{
|
||||
#ifdef TGVOIP_USE_DESKTOP_DSP
|
||||
namespace webrtc{
|
||||
void WebRtcAec_enable_delay_agnostic(AecCore* self, int enable);
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
|
||||
CEchoCanceller::CEchoCanceller(bool enableAEC, bool enableNS, bool enableAGC){
|
||||
this->enableAEC=enableAEC;
|
||||
@ -46,12 +53,24 @@ CEchoCanceller::CEchoCanceller(bool enableAEC, bool enableNS, bool enableAGC){
|
||||
|
||||
if(enableAEC){
|
||||
init_mutex(aecMutex);
|
||||
#ifndef TGVOIP_USE_DESKTOP_DSP
|
||||
aec=WebRtcAecm_Create();
|
||||
WebRtcAecm_Init(aec, 16000);
|
||||
AecmConfig cfg;
|
||||
cfg.cngMode=AecmFalse;
|
||||
cfg.echoMode=1;
|
||||
WebRtcAecm_set_config(aec, cfg);
|
||||
#else
|
||||
aec=webrtc::WebRtcAec_Create();
|
||||
webrtc::WebRtcAec_Init(aec, 48000, 48000);
|
||||
webrtc::WebRtcAec_enable_delay_agnostic(webrtc::WebRtcAec_aec_core(aec), 1);
|
||||
webrtc::AecConfig config;
|
||||
config.metricsMode=webrtc::kAecFalse;
|
||||
config.nlpMode=webrtc::kAecNlpAggressive;
|
||||
config.skewMode=webrtc::kAecFalse;
|
||||
config.delay_logging=webrtc::kAecFalse;
|
||||
webrtc::WebRtcAec_set_config(aec, config);
|
||||
#endif
|
||||
|
||||
farendQueue=new CBlockingQueue(11);
|
||||
farendBufferPool=new CBufferPool(960*2, 10);
|
||||
@ -61,9 +80,15 @@ CEchoCanceller::CEchoCanceller(bool enableAEC, bool enableNS, bool enableAGC){
|
||||
}
|
||||
|
||||
if(enableNS){
|
||||
//#ifndef TGVOIP_USE_DESKTOP_DSP
|
||||
ns=WebRtcNsx_Create();
|
||||
WebRtcNsx_Init((NsxHandle*)ns, 48000);
|
||||
WebRtcNsx_set_policy((NsxHandle*)ns, 2);
|
||||
/*#else
|
||||
ns=WebRtcNs_Create();
|
||||
WebRtcNs_Init((NsHandle*)ns, 48000);
|
||||
WebRtcNs_set_policy((NsHandle*)ns, 1);
|
||||
#endif*/
|
||||
}
|
||||
|
||||
if(enableAGC){
|
||||
@ -90,10 +115,18 @@ CEchoCanceller::~CEchoCanceller(){
|
||||
join_thread(bufferFarendThread);
|
||||
delete farendQueue;
|
||||
delete farendBufferPool;
|
||||
#ifndef TGVOIP_USE_DESKTOP_DSP
|
||||
WebRtcAecm_Free(aec);
|
||||
#else
|
||||
webrtc::WebRtcAec_Free(aec);
|
||||
#endif
|
||||
}
|
||||
if(enableNS){
|
||||
//#ifndef TGVOIP_USE_DESKTOP_DSP
|
||||
WebRtcNsx_Free((NsxHandle*)ns);
|
||||
/*#else
|
||||
WebRtcNs_Free((NsHandle*)ns);
|
||||
#endif*/
|
||||
}
|
||||
if(enableAGC){
|
||||
WebRtcAgc_Free(agc);
|
||||
@ -152,10 +185,13 @@ void CEchoCanceller::RunBufferFarendThread(){
|
||||
farendBufferPool->Reuse((unsigned char *) samplesIn);
|
||||
((webrtc::SplittingFilter*)splittingFilterFarend)->Analysis(bufIn, bufOut);
|
||||
lock_mutex(aecMutex);
|
||||
//webrtc::WebRtcAec_BufferFarend(state, splittingFilterFarend->bufferOut[0], 160);
|
||||
//webrtc::WebRtcAec_BufferFarend(state, &splittingFilterFarend->bufferOut[0][160], 160);
|
||||
#ifndef TGVOIP_USE_DESKTOP_DSP
|
||||
WebRtcAecm_BufferFarend(aec, bufOut->ibuf_const()->bands(0)[0], 160);
|
||||
WebRtcAecm_BufferFarend(aec, bufOut->ibuf_const()->bands(0)[0]+160, 160);
|
||||
#else
|
||||
webrtc::WebRtcAec_BufferFarend(aec, bufOut->fbuf_const()->bands(0)[0], 160);
|
||||
webrtc::WebRtcAec_BufferFarend(aec, bufOut->fbuf_const()->bands(0)[0]+160, 160);
|
||||
#endif
|
||||
unlock_mutex(aecMutex);
|
||||
didBufferFarend=true;
|
||||
}
|
||||
@ -175,8 +211,8 @@ void CEchoCanceller::ProcessInput(unsigned char* data, unsigned char* out, size_
|
||||
int16_t* samplesIn=(int16_t*)data;
|
||||
int16_t* samplesOut=(int16_t*)out;
|
||||
|
||||
webrtc::IFChannelBuffer* bufIn=(webrtc::IFChannelBuffer*) splittingFilterFarendIn;
|
||||
webrtc::IFChannelBuffer* bufOut=(webrtc::IFChannelBuffer*) splittingFilterFarendOut;
|
||||
webrtc::IFChannelBuffer* bufIn=(webrtc::IFChannelBuffer*) splittingFilterIn;
|
||||
webrtc::IFChannelBuffer* bufOut=(webrtc::IFChannelBuffer*) splittingFilterOut;
|
||||
|
||||
memcpy(bufIn->ibuf()->bands(0)[0], samplesIn, 960*2);
|
||||
|
||||
@ -205,6 +241,7 @@ void CEchoCanceller::ProcessInput(unsigned char* data, unsigned char* out, size_
|
||||
memcpy(bufOut->ibuf()->bands(0)[2], _agcOut[2], 320*2);
|
||||
}
|
||||
|
||||
#ifndef TGVOIP_USE_DESKTOP_DSP
|
||||
if(enableAEC && enableNS){
|
||||
int16_t _nsOut[3][320];
|
||||
int16_t* nsIn[3];
|
||||
@ -252,9 +289,69 @@ void CEchoCanceller::ProcessInput(unsigned char* data, unsigned char* out, size_
|
||||
memcpy(bufOut->ibuf()->bands(0)[1], _nsOut[1], 320*2);
|
||||
memcpy(bufOut->ibuf()->bands(0)[2], _nsOut[2], 320*2);
|
||||
}
|
||||
#else
|
||||
/*if(enableNS){
|
||||
float _nsOut[3][320];
|
||||
const float* nsIn[3];
|
||||
float* nsOut[3];
|
||||
for(i=0;i<3;i++){
|
||||
nsIn[i]=bufOut->fbuf_const()->bands(0)[i];
|
||||
nsOut[i]=_nsOut[i];
|
||||
}
|
||||
WebRtcNs_Process((NsHandle*)ns, nsIn, 3, nsOut);
|
||||
for(i=0;i<3;i++){
|
||||
nsOut[i]+=160;
|
||||
nsIn[i]+=160;
|
||||
}
|
||||
WebRtcNs_Process((NsHandle*)ns, nsIn, 3, nsOut);
|
||||
|
||||
memcpy(bufOut->fbuf()->bands(0)[0], _nsOut[0], 320*4);
|
||||
memcpy(bufOut->fbuf()->bands(0)[1], _nsOut[1], 320*4);
|
||||
memcpy(bufOut->fbuf()->bands(0)[2], _nsOut[2], 320*4);
|
||||
}*/
|
||||
if(enableNS){
|
||||
int16_t _nsOut[3][320];
|
||||
int16_t* nsIn[3];
|
||||
int16_t* nsOut[3];
|
||||
for(i=0;i<3;i++){
|
||||
nsIn[i]=(int16_t*)bufOut->ibuf_const()->bands(0)[i];
|
||||
nsOut[i]=_nsOut[i];
|
||||
}
|
||||
WebRtcNsx_Process((NsxHandle*)ns, (const short *const *)nsIn, 3, nsOut);
|
||||
for(i=0;i<3;i++){
|
||||
nsOut[i]+=160;
|
||||
nsIn[i]+=160;
|
||||
}
|
||||
WebRtcNsx_Process((NsxHandle*)ns, (const short *const *)nsIn, 3, nsOut);
|
||||
|
||||
memcpy(bufOut->ibuf()->bands(0)[0], _nsOut[0], 320*2);
|
||||
memcpy(bufOut->ibuf()->bands(0)[1], _nsOut[1], 320*2);
|
||||
memcpy(bufOut->ibuf()->bands(0)[2], _nsOut[2], 320*2);
|
||||
}
|
||||
|
||||
if(enableAEC){
|
||||
const float* aecIn[3];
|
||||
float* aecOut[3];
|
||||
float _aecOut[3][320];
|
||||
for(i=0;i<3;i++){
|
||||
aecIn[i]=bufOut->fbuf_const()->bands(0)[i];
|
||||
aecOut[i]=_aecOut[i];
|
||||
}
|
||||
webrtc::WebRtcAec_Process(aec, aecIn, 3, aecOut, AEC_FRAME_SIZE, CAudioOutput::GetEstimatedDelay(), 0);
|
||||
for(i=0;i<3;i++){
|
||||
aecOut[i]+=160;
|
||||
aecIn[i]+=160;
|
||||
}
|
||||
webrtc::WebRtcAec_Process(aec, aecIn, 3, aecOut, AEC_FRAME_SIZE, CAudioOutput::GetEstimatedDelay(), 0);
|
||||
|
||||
memcpy(bufOut->fbuf()->bands(0)[0], _aecOut[0], 320*4);
|
||||
memcpy(bufOut->fbuf()->bands(0)[1], _aecOut[1], 320*4);
|
||||
memcpy(bufOut->fbuf()->bands(0)[2], _aecOut[2], 320*4);
|
||||
}
|
||||
#endif
|
||||
|
||||
((webrtc::SplittingFilter*)splittingFilter)->Synthesis(bufOut, bufIn);
|
||||
|
||||
memcpy(samplesOut, bufIn->ibuf()->bands(0)[0], 960*2);
|
||||
memcpy(samplesOut, bufIn->ibuf_const()->bands(0)[0], 960*2);
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include "VoIPServerConfig.h"
|
||||
#include <math.h>
|
||||
|
||||
using namespace tgvoip;
|
||||
|
||||
CJitterBuffer::CJitterBuffer(CMediaStreamItf *out, uint32_t step):bufferPool(JITTER_SLOT_SIZE, JITTER_SLOT_COUNT){
|
||||
if(out)
|
||||
out->SetCallback(CJitterBuffer::CallbackOut, this);
|
||||
@ -23,20 +25,20 @@ CJitterBuffer::CJitterBuffer(CMediaStreamItf *out, uint32_t step):bufferPool(JIT
|
||||
dontDecMinDelay=0;
|
||||
lostPackets=0;
|
||||
if(step<30){
|
||||
minMinDelay=(uint32_t) CVoIPServerConfig::GetSharedInstance()->GetInt("jitter_min_delay_20", 6);
|
||||
maxMinDelay=(uint32_t) CVoIPServerConfig::GetSharedInstance()->GetInt("jitter_max_delay_20", 25);
|
||||
maxUsedSlots=(uint32_t) CVoIPServerConfig::GetSharedInstance()->GetInt("jitter_max_slots_20", 50);
|
||||
minMinDelay=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_min_delay_20", 6);
|
||||
maxMinDelay=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_max_delay_20", 25);
|
||||
maxUsedSlots=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_max_slots_20", 50);
|
||||
}else if(step<50){
|
||||
minMinDelay=(uint32_t) CVoIPServerConfig::GetSharedInstance()->GetInt("jitter_min_delay_40", 4);
|
||||
maxMinDelay=(uint32_t) CVoIPServerConfig::GetSharedInstance()->GetInt("jitter_max_delay_40", 15);
|
||||
maxUsedSlots=(uint32_t) CVoIPServerConfig::GetSharedInstance()->GetInt("jitter_max_slots_40", 30);
|
||||
minMinDelay=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_min_delay_40", 4);
|
||||
maxMinDelay=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_max_delay_40", 15);
|
||||
maxUsedSlots=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_max_slots_40", 30);
|
||||
}else{
|
||||
minMinDelay=(uint32_t) CVoIPServerConfig::GetSharedInstance()->GetInt("jitter_min_delay_60", 1);
|
||||
maxMinDelay=(uint32_t) CVoIPServerConfig::GetSharedInstance()->GetInt("jitter_max_delay_60", 10);
|
||||
maxUsedSlots=(uint32_t) CVoIPServerConfig::GetSharedInstance()->GetInt("jitter_max_slots_60", 20);
|
||||
minMinDelay=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_min_delay_60", 1);
|
||||
maxMinDelay=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_max_delay_60", 10);
|
||||
maxUsedSlots=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_max_slots_60", 20);
|
||||
}
|
||||
lossesToReset=(uint32_t) CVoIPServerConfig::GetSharedInstance()->GetInt("jitter_losses_to_reset", 20);
|
||||
resyncThreshold=CVoIPServerConfig::GetSharedInstance()->GetDouble("jitter_resync_threshold", 1.0);
|
||||
lossesToReset=(uint32_t) ServerConfig::GetSharedInstance()->GetInt("jitter_losses_to_reset", 20);
|
||||
resyncThreshold=ServerConfig::GetSharedInstance()->GetDouble("jitter_resync_threshold", 1.0);
|
||||
Reset();
|
||||
init_mutex(mutex);
|
||||
}
|
||||
@ -208,7 +210,7 @@ void CJitterBuffer::PutInternal(jitter_packet_t* pkt){
|
||||
prevTime=slots[i].recvTime;
|
||||
}
|
||||
}*/
|
||||
double time=CVoIPController::GetCurrentTime();
|
||||
double time=VoIPController::GetCurrentTime();
|
||||
if(expectNextAtTime!=0){
|
||||
double dev=expectNextAtTime-time;
|
||||
//LOGV("packet dev %f", dev);
|
||||
|
142
NetworkSocket.cpp
Normal file
142
NetworkSocket.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
//
|
||||
// Created by Grishka on 29.03.17.
|
||||
//
|
||||
|
||||
#include "NetworkSocket.h"
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if defined(_WIN32)
|
||||
#include "os/windows/NetworkSocketWinsock.h"
|
||||
#else
|
||||
#include "os/posix/NetworkSocketPosix.h"
|
||||
#endif
|
||||
#include "logging.h"
|
||||
#include "VoIPServerConfig.h"
|
||||
|
||||
#define MIN_UDP_PORT 16384
|
||||
#define MAX_UDP_PORT 32768
|
||||
|
||||
namespace tgvoip {
|
||||
|
||||
#pragma mark - NetworkSocket
|
||||
|
||||
NetworkSocket::NetworkSocket(){
|
||||
ipv6Timeout=ServerConfig::GetSharedInstance()->GetDouble("nat64_fallback_timeout", 3);
|
||||
failed=false;
|
||||
}
|
||||
|
||||
NetworkSocket::~NetworkSocket(){
|
||||
|
||||
}
|
||||
|
||||
std::string NetworkSocket::GetLocalInterfaceInfo(IPv4Address *inet4addr, IPv6Address *inet6addr){
|
||||
std::string r="not implemented";
|
||||
return r;
|
||||
}
|
||||
|
||||
uint16_t NetworkSocket::GenerateLocalPort(){
|
||||
return (uint16_t) ((rand()%(MAX_UDP_PORT-MIN_UDP_PORT))+MIN_UDP_PORT);
|
||||
}
|
||||
|
||||
void NetworkSocket::SetMaxPriority(){
|
||||
}
|
||||
|
||||
bool NetworkSocket::IsFailed(){
|
||||
return failed;
|
||||
}
|
||||
|
||||
NetworkSocket *NetworkSocket::Create(){
|
||||
#ifndef _WIN32
|
||||
return new NetworkSocketPosix();
|
||||
#else
|
||||
return new NetworkSocketWinsock();
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma mark - NetworkAddress
|
||||
|
||||
bool NetworkAddress::operator==(const NetworkAddress &other){
|
||||
IPv4Address* self4=dynamic_cast<IPv4Address*>(this);
|
||||
IPv4Address* other4=dynamic_cast<IPv4Address*>((NetworkAddress*)&other);
|
||||
if(self4 && other4){
|
||||
return self4->GetAddress()==other4->GetAddress();
|
||||
}
|
||||
IPv6Address* self6=dynamic_cast<IPv6Address*>(this);
|
||||
IPv6Address* other6=dynamic_cast<IPv6Address*>((NetworkAddress*)&other);
|
||||
if(self6 && other6){
|
||||
return memcmp(self6->GetAddress(), other6->GetAddress(), 16)==0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetworkAddress::operator!=(const NetworkAddress &other){
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
#pragma mark - IPv4Address
|
||||
|
||||
IPv4Address::IPv4Address(std::string addr){
|
||||
#ifndef _WIN32
|
||||
this->address=NetworkSocketPosix::StringToV4Address(addr);
|
||||
#else
|
||||
this->address=NetworkSocketWinsock::StringToV4Address(addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
IPv4Address::IPv4Address(uint32_t addr){
|
||||
this->address=addr;
|
||||
}
|
||||
|
||||
|
||||
std::string IPv4Address::ToString(){
|
||||
#ifndef _WIN32
|
||||
return NetworkSocketPosix::V4AddressToString(address);
|
||||
#else
|
||||
return NetworkSocketWinsock::V4AddressToString(address);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*sockaddr &IPv4Address::ToSockAddr(uint16_t port){
|
||||
sockaddr_in sa;
|
||||
sa.sin_family=AF_INET;
|
||||
sa.sin_addr=addr;
|
||||
sa.sin_port=port;
|
||||
return *((sockaddr *) &sa);
|
||||
}*/
|
||||
|
||||
uint32_t IPv4Address::GetAddress(){
|
||||
return address;
|
||||
}
|
||||
|
||||
#pragma mark - IPv6Address
|
||||
|
||||
IPv6Address::IPv6Address(std::string addr){
|
||||
#ifndef _WIN32
|
||||
NetworkSocketPosix::StringToV6Address(addr, this->address);
|
||||
#else
|
||||
NetworkSocketWinsock::StringToV6Address(addr, this->address);
|
||||
#endif
|
||||
}
|
||||
|
||||
IPv6Address::IPv6Address(uint8_t addr[16]){
|
||||
memcpy(address, addr, 16);
|
||||
}
|
||||
|
||||
std::string IPv6Address::ToString(){
|
||||
return "";
|
||||
}
|
||||
|
||||
/*sockaddr &IPv6Address::ToSockAddr(uint16_t port){
|
||||
sockaddr_in6 sa;
|
||||
sa.sin6_family=AF_INET6;
|
||||
sa.sin6_addr=addr;
|
||||
sa.sin6_port=port;
|
||||
return *((sockaddr *) &sa);
|
||||
}*/
|
||||
|
||||
const uint8_t *IPv6Address::GetAddress(){
|
||||
return address;
|
||||
}
|
||||
|
||||
}
|
76
NetworkSocket.h
Normal file
76
NetworkSocket.h
Normal file
@ -0,0 +1,76 @@
|
||||
//
|
||||
// Created by Grishka on 29.03.17.
|
||||
//
|
||||
|
||||
#ifndef LIBTGVOIP_NETWORKSOCKET_H
|
||||
#define LIBTGVOIP_NETWORKSOCKET_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
namespace tgvoip {
|
||||
class NetworkAddress{
|
||||
public:
|
||||
virtual std::string ToString()=0;
|
||||
//virtual sockaddr& ToSockAddr(uint16_t port)=0;
|
||||
bool operator==(const NetworkAddress& other);
|
||||
bool operator!=(const NetworkAddress& other);
|
||||
};
|
||||
|
||||
class IPv4Address : public NetworkAddress{
|
||||
public:
|
||||
IPv4Address(std::string addr);
|
||||
IPv4Address(uint32_t addr);
|
||||
virtual std::string ToString();
|
||||
//virtual sockaddr& ToSockAddr(uint16_t port);
|
||||
uint32_t GetAddress();
|
||||
|
||||
private:
|
||||
uint32_t address;
|
||||
};
|
||||
|
||||
class IPv6Address : public NetworkAddress{
|
||||
public:
|
||||
IPv6Address(std::string addr);
|
||||
IPv6Address(uint8_t addr[16]);
|
||||
virtual std::string ToString();
|
||||
//virtual sockaddr& ToSockAddr(uint16_t port);
|
||||
const uint8_t* GetAddress();
|
||||
private:
|
||||
uint8_t address[16];
|
||||
};
|
||||
|
||||
struct NetworkPacket{
|
||||
unsigned char* data;
|
||||
size_t length;
|
||||
NetworkAddress* address;
|
||||
uint16_t port;
|
||||
};
|
||||
typedef struct NetworkPacket NetworkPacket;
|
||||
|
||||
class NetworkSocket{
|
||||
public:
|
||||
NetworkSocket();
|
||||
virtual ~NetworkSocket();
|
||||
virtual void Send(NetworkPacket* packet)=0;
|
||||
virtual void Receive(NetworkPacket* packet)=0;
|
||||
virtual void Open()=0;
|
||||
virtual void Close()=0;
|
||||
virtual uint16_t GetLocalPort()=0;
|
||||
virtual std::string GetLocalInterfaceInfo(IPv4Address* inet4addr, IPv6Address* inet6addr);
|
||||
virtual void OnActiveInterfaceChanged()=0;
|
||||
bool IsFailed();
|
||||
|
||||
static NetworkSocket* Create();
|
||||
|
||||
protected:
|
||||
virtual uint16_t GenerateLocalPort();
|
||||
virtual void SetMaxPriority();
|
||||
double ipv6Timeout;
|
||||
unsigned char nat64Prefix[12];
|
||||
bool failed;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //LIBTGVOIP_NETWORKSOCKET_H
|
@ -9,6 +9,8 @@
|
||||
#include "logging.h"
|
||||
#include "VoIPServerConfig.h"
|
||||
|
||||
using namespace tgvoip;
|
||||
|
||||
COpusEncoder::COpusEncoder(CMediaStreamItf *source):queue(11), bufferPool(960*2, 10){
|
||||
this->source=source;
|
||||
source->SetCallback(COpusEncoder::Callback, this);
|
||||
@ -24,10 +26,10 @@ COpusEncoder::COpusEncoder(CMediaStreamItf *source):queue(11), bufferPool(960*2,
|
||||
echoCanceller=NULL;
|
||||
complexity=10;
|
||||
frameDuration=20;
|
||||
mediumCorrectionBitrate=CVoIPServerConfig::GetSharedInstance()->GetInt("audio_medium_fec_bitrate", 10000);
|
||||
strongCorrectionBitrate=CVoIPServerConfig::GetSharedInstance()->GetInt("audio_strong_fec_bitrate", 8000);
|
||||
mediumCorrectionMultiplier=CVoIPServerConfig::GetSharedInstance()->GetDouble("audio_medium_fec_multiplier", 1.5);
|
||||
strongCorrectionMultiplier=CVoIPServerConfig::GetSharedInstance()->GetDouble("audio_strong_fec_multiplier", 2.0);
|
||||
mediumCorrectionBitrate=ServerConfig::GetSharedInstance()->GetInt("audio_medium_fec_bitrate", 10000);
|
||||
strongCorrectionBitrate=ServerConfig::GetSharedInstance()->GetInt("audio_strong_fec_bitrate", 8000);
|
||||
mediumCorrectionMultiplier=ServerConfig::GetSharedInstance()->GetDouble("audio_medium_fec_multiplier", 1.5);
|
||||
strongCorrectionMultiplier=ServerConfig::GetSharedInstance()->GetDouble("audio_strong_fec_multiplier", 2.0);
|
||||
}
|
||||
|
||||
COpusEncoder::~COpusEncoder(){
|
||||
|
File diff suppressed because it is too large
Load Diff
137
VoIPController.h
137
VoIPController.h
@ -1,8 +1,19 @@
|
||||
//
|
||||
// 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 __VOIPCONTROLLER_H
|
||||
#define __VOIPCONTROLLER_H
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@ -16,8 +27,9 @@
|
||||
#include "OpusEncoder.h"
|
||||
#include "EchoCanceller.h"
|
||||
#include "CongestionControl.h"
|
||||
#include "NetworkSocket.h"
|
||||
|
||||
#define LIBTGVOIP_VERSION "0.3.2"
|
||||
#define LIBTGVOIP_VERSION "0.4"
|
||||
|
||||
#define PKT_INIT 1
|
||||
#define PKT_INIT_ACK 2
|
||||
@ -39,10 +51,10 @@
|
||||
#define STATE_ESTABLISHED 3
|
||||
#define STATE_FAILED 4
|
||||
|
||||
#define ERROR_UNKNOWN 0
|
||||
#define ERROR_INCOMPATIBLE 1
|
||||
#define ERROR_TIMEOUT 2
|
||||
#define ERROR_AUDIO_IO 3
|
||||
#define TGVOIP_ERROR_UNKNOWN 0
|
||||
#define TGVOIP_ERROR_INCOMPATIBLE 1
|
||||
#define TGVOIP_ERROR_TIMEOUT 2
|
||||
#define TGVOIP_ERROR_AUDIO_IO 3
|
||||
|
||||
#define NET_TYPE_UNKNOWN 0
|
||||
#define NET_TYPE_GPRS 1
|
||||
@ -62,8 +74,6 @@
|
||||
#define PROTOCOL_NAME 0x50567247 // "GrVP" in little endian (reversed here)
|
||||
#define PROTOCOL_VERSION 3
|
||||
#define MIN_PROTOCOL_VERSION 3
|
||||
#define MIN_UDP_PORT 16384
|
||||
#define MAX_UDP_PORT 32768
|
||||
|
||||
#define STREAM_DATA_FLAG_LEN16 0x40
|
||||
#define STREAM_DATA_FLAG_HAS_MORE_FLAGS 0x80
|
||||
@ -98,6 +108,10 @@
|
||||
#define TLID_UDP_REFLECTOR_PEER_INFO 0x27D9371C
|
||||
#define PAD4(x) (4-(x+(x<=253 ? 1 : 0))%4)
|
||||
|
||||
#ifdef _WIN32
|
||||
#undef GetCurrentTime
|
||||
#endif
|
||||
|
||||
inline int pad4(int x){
|
||||
int r=PAD4(x);
|
||||
if(r==4)
|
||||
@ -105,21 +119,6 @@ inline int pad4(int x){
|
||||
return r;
|
||||
}
|
||||
|
||||
struct voip_endpoint_t{ // make this a class maybe?
|
||||
int64_t id;
|
||||
uint32_t port;
|
||||
in_addr address;
|
||||
in6_addr address6;
|
||||
char type;
|
||||
unsigned char peerTag[16];
|
||||
|
||||
double _lastPingTime;
|
||||
uint32_t _lastPingSeq;
|
||||
double _rtts[6];
|
||||
double _averageRtt;
|
||||
};
|
||||
typedef struct voip_endpoint_t voip_endpoint_t;
|
||||
|
||||
struct voip_stream_t{
|
||||
int32_t userID;
|
||||
unsigned char id;
|
||||
@ -154,6 +153,18 @@ struct voip_config_t{
|
||||
};
|
||||
typedef struct voip_config_t voip_config_t;
|
||||
|
||||
#if defined(__APPLE__) && TARGET_OS_IPHONE
|
||||
// temporary fix for nasty linking errors
|
||||
struct voip_legacy_endpoint_t{
|
||||
const char* address;
|
||||
const char* address6;
|
||||
uint16_t port;
|
||||
int64_t id;
|
||||
unsigned char peerTag[16];
|
||||
};
|
||||
typedef struct voip_legacy_endpoint_t voip_legacy_endpoint_t;
|
||||
#endif
|
||||
|
||||
struct voip_stats_t{
|
||||
uint64_t bytesSentWifi;
|
||||
uint64_t bytesRecvdWifi;
|
||||
@ -177,20 +188,41 @@ inline bool seqgt(uint32_t s1, uint32_t s2){
|
||||
return ((s1>s2) && (s1-s2<=SEQ_MAX/2)) || ((s1<s2) && (s2-s1>SEQ_MAX/2));
|
||||
}
|
||||
|
||||
class CVoIPController
|
||||
namespace tgvoip{
|
||||
|
||||
class Endpoint{
|
||||
friend class VoIPController;
|
||||
public:
|
||||
Endpoint(int64_t id, uint16_t port, IPv4Address& address, IPv6Address& v6address, char type, unsigned char* peerTag);
|
||||
Endpoint();
|
||||
int64_t id;
|
||||
uint16_t port;
|
||||
IPv4Address address;
|
||||
IPv6Address v6address;
|
||||
char type;
|
||||
unsigned char peerTag[16];
|
||||
|
||||
private:
|
||||
double lastPingTime;
|
||||
uint32_t lastPingSeq;
|
||||
double rtts[6];
|
||||
double averageRTT;
|
||||
};
|
||||
|
||||
class VoIPController
|
||||
{
|
||||
public:
|
||||
CVoIPController();
|
||||
~CVoIPController();
|
||||
VoIPController();
|
||||
~VoIPController();
|
||||
|
||||
void SetRemoteEndpoints(voip_endpoint_t* endpoints, size_t count, bool allowP2p);
|
||||
void SetRemoteEndpoints(std::vector<Endpoint> endpoints, bool allowP2p);
|
||||
void Start();
|
||||
void Connect();
|
||||
voip_endpoint_t* GetRemoteEndpoint();
|
||||
Endpoint& GetRemoteEndpoint();
|
||||
void GetDebugString(char* buffer, size_t len);
|
||||
void SetNetworkType(int type);
|
||||
double GetAverageRTT();
|
||||
void SetStateCallback(void (*f)(CVoIPController*, int));
|
||||
void SetStateCallback(void (*f)(VoIPController*, int));
|
||||
static double GetCurrentTime();
|
||||
void* implData;
|
||||
void SetMicMute(bool mute);
|
||||
@ -218,7 +250,7 @@ private:
|
||||
void RunRecvThread();
|
||||
void RunSendThread();
|
||||
void RunTickThread();
|
||||
void SendPacket(unsigned char* data, size_t len, voip_endpoint_t* ep);
|
||||
void SendPacket(unsigned char* data, size_t len, Endpoint* ep);
|
||||
void HandleAudioInput(unsigned char* data, size_t len);
|
||||
void UpdateAudioBitrate();
|
||||
void SetState(int state);
|
||||
@ -226,25 +258,20 @@ private:
|
||||
void SendInit();
|
||||
void SendInitAck();
|
||||
void UpdateDataSavingState();
|
||||
void SendP2pPing(int endpointType);
|
||||
void KDF(unsigned char* msgKey, size_t x, unsigned char* aesKey, unsigned char* aesIv);
|
||||
void GetLocalNetworkItfInfo(in_addr *addr, char *outName);
|
||||
uint16_t GenerateLocalUDPPort();
|
||||
CBufferOutputStream* GetOutgoingPacketBuffer();
|
||||
uint32_t WritePacketHeader(CBufferOutputStream* s, unsigned char type, uint32_t length);
|
||||
static size_t AudioInputCallback(unsigned char* data, size_t length, void* param);
|
||||
void SendPublicEndpointsRequest();
|
||||
void SendPublicEndpointsRequest(voip_endpoint_t* relay);
|
||||
voip_endpoint_t* GetEndpointByType(int type);
|
||||
void SendPublicEndpointsRequest(Endpoint& relay);
|
||||
Endpoint* GetEndpointByType(int type);
|
||||
void SendPacketReliably(unsigned char type, unsigned char* data, size_t len, double retryInterval, double timeout);
|
||||
void LogDebugInfo();
|
||||
sockaddr_in6 MakeInetAddress(in_addr addr, uint16_t port);
|
||||
int state;
|
||||
int udpSocket;
|
||||
std::vector<voip_endpoint_t*> endpoints;
|
||||
voip_endpoint_t* currentEndpoint;
|
||||
voip_endpoint_t* preferredRelay;
|
||||
voip_endpoint_t* peerPreferredRelay;
|
||||
std::vector<Endpoint*> endpoints;
|
||||
Endpoint* currentEndpoint;
|
||||
Endpoint* preferredRelay;
|
||||
Endpoint* peerPreferredRelay;
|
||||
bool runReceiver;
|
||||
uint32_t seq;
|
||||
uint32_t lastRemoteSeq;
|
||||
@ -265,6 +292,7 @@ private:
|
||||
CEchoCanceller* echoCanceller;
|
||||
std::vector<CBufferOutputStream*> emptySendBuffers;
|
||||
tgvoip_mutex_t sendBufferMutex;
|
||||
tgvoip_mutex_t endpointsMutex;
|
||||
bool stopping;
|
||||
bool audioOutStarted;
|
||||
tgvoip_thread_t recvThread;
|
||||
@ -284,23 +312,18 @@ private:
|
||||
bool micMuted;
|
||||
uint32_t maxBitrate;
|
||||
CBufferOutputStream* currentAudioPacket;
|
||||
void (*stateCallback)(CVoIPController*, int);
|
||||
void (*stateCallback)(VoIPController*, int);
|
||||
std::vector<voip_stream_t*> outgoingStreams;
|
||||
std::vector<voip_stream_t*> incomingStreams;
|
||||
unsigned char encryptionKey[256];
|
||||
unsigned char keyFingerprint[8];
|
||||
unsigned char callID[16];
|
||||
double stateChangeTime;
|
||||
bool needSendP2pPing;
|
||||
bool waitingForRelayPeerInfo;
|
||||
double relayPeerInfoReqTime;
|
||||
double lastP2pPingTime;
|
||||
int p2pPingCount;
|
||||
uint16_t localUdpPort;
|
||||
bool allowP2p;
|
||||
bool dataSavingMode;
|
||||
bool dataSavingRequestedByPeer;
|
||||
char activeNetItfName[32];
|
||||
std::string activeNetItfName;
|
||||
double publicEndpointsReqTime;
|
||||
std::vector<voip_queued_packet_t*> queuedPackets;
|
||||
tgvoip_mutex_t queuedPacketsMutex;
|
||||
@ -314,13 +337,8 @@ private:
|
||||
bool receivedInitAck;
|
||||
std::vector<std::string> debugLogs;
|
||||
bool isOutgoing;
|
||||
tgvoip::NetworkSocket* socket;
|
||||
|
||||
unsigned char nat64Prefix[12];
|
||||
bool needUpdateNat64Prefix;
|
||||
bool nat64Present;
|
||||
double switchToV6at;
|
||||
bool isV4Available;
|
||||
|
||||
/*** server config values ***/
|
||||
uint32_t maxAudioBitrate;
|
||||
uint32_t maxAudioBitrateEDGE;
|
||||
@ -336,18 +354,27 @@ private:
|
||||
double relaySwitchThreshold;
|
||||
double p2pToRelaySwitchThreshold;
|
||||
double relayToP2pSwitchThreshold;
|
||||
double ipv6Timeout;
|
||||
|
||||
#ifdef TGVOIP_USE_AUDIO_SESSION
|
||||
void (^acquireAudioSession)(void (^)());
|
||||
bool needNotifyAcquiredAudioSession;
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
public:
|
||||
#ifdef __APPLE__
|
||||
static double machTimebase;
|
||||
static uint64_t machTimestart;
|
||||
#if TARGET_OS_IPHONE
|
||||
// temporary fix for nasty linking errors
|
||||
void SetRemoteEndpoints(voip_legacy_endpoint_t* buffer, size_t count, bool allowP2P);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
static int64_t win32TimeScale;
|
||||
static bool didInitWin32TimeScale;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -8,23 +8,25 @@
|
||||
#include <stdlib.h>
|
||||
#include "logging.h"
|
||||
|
||||
CVoIPServerConfig* CVoIPServerConfig::sharedInstance=NULL;
|
||||
using namespace tgvoip;
|
||||
|
||||
CVoIPServerConfig::CVoIPServerConfig(){
|
||||
ServerConfig* ServerConfig::sharedInstance=NULL;
|
||||
|
||||
ServerConfig::ServerConfig(){
|
||||
init_mutex(mutex);
|
||||
}
|
||||
|
||||
CVoIPServerConfig::~CVoIPServerConfig(){
|
||||
ServerConfig::~ServerConfig(){
|
||||
free_mutex(mutex);
|
||||
}
|
||||
|
||||
CVoIPServerConfig *CVoIPServerConfig::GetSharedInstance(){
|
||||
ServerConfig *ServerConfig::GetSharedInstance(){
|
||||
if(!sharedInstance)
|
||||
sharedInstance=new CVoIPServerConfig();
|
||||
sharedInstance=new ServerConfig();
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
bool CVoIPServerConfig::GetBoolean(std::string name, bool fallback){
|
||||
bool ServerConfig::GetBoolean(std::string name, bool fallback){
|
||||
CMutexGuard sync(mutex);
|
||||
if(ContainsKey(name)){
|
||||
std::string val=config[name];
|
||||
@ -36,7 +38,7 @@ bool CVoIPServerConfig::GetBoolean(std::string name, bool fallback){
|
||||
return fallback;
|
||||
}
|
||||
|
||||
double CVoIPServerConfig::GetDouble(std::string name, double fallback){
|
||||
double ServerConfig::GetDouble(std::string name, double fallback){
|
||||
CMutexGuard sync(mutex);
|
||||
if(ContainsKey(name)){
|
||||
std::string val=config[name];
|
||||
@ -50,7 +52,7 @@ double CVoIPServerConfig::GetDouble(std::string name, double fallback){
|
||||
return fallback;
|
||||
}
|
||||
|
||||
int32_t CVoIPServerConfig::GetInt(std::string name, int32_t fallback){
|
||||
int32_t ServerConfig::GetInt(std::string name, int32_t fallback){
|
||||
CMutexGuard sync(mutex);
|
||||
if(ContainsKey(name)){
|
||||
std::string val=config[name];
|
||||
@ -64,14 +66,14 @@ int32_t CVoIPServerConfig::GetInt(std::string name, int32_t fallback){
|
||||
return fallback;
|
||||
}
|
||||
|
||||
std::string CVoIPServerConfig::GetString(std::string name, std::string fallback){
|
||||
std::string ServerConfig::GetString(std::string name, std::string fallback){
|
||||
CMutexGuard sync(mutex);
|
||||
if(ContainsKey(name))
|
||||
return config[name];
|
||||
return fallback;
|
||||
}
|
||||
|
||||
void CVoIPServerConfig::Update(std::map<std::string, std::string> newValues){
|
||||
void ServerConfig::Update(std::map<std::string, std::string> newValues){
|
||||
CMutexGuard sync(mutex);
|
||||
LOGD("=== Updating voip config ===");
|
||||
config.clear();
|
||||
@ -83,7 +85,7 @@ void CVoIPServerConfig::Update(std::map<std::string, std::string> newValues){
|
||||
}
|
||||
}
|
||||
|
||||
void CVoIPServerConfig::Update(const char **values, int count) {
|
||||
void ServerConfig::Update(const char **values, int count) {
|
||||
std::map<std::string, std::string> result;
|
||||
for (int i = 0; i < count / 2; i++) {
|
||||
result[values[i * 2 + 0]] = std::string(values[i * 2 + 1]);
|
||||
@ -92,7 +94,7 @@ void CVoIPServerConfig::Update(const char **values, int count) {
|
||||
}
|
||||
|
||||
|
||||
bool CVoIPServerConfig::ContainsKey(std::string key){
|
||||
bool ServerConfig::ContainsKey(std::string key){
|
||||
return config.find(key)!=config.end();
|
||||
}
|
||||
|
||||
|
@ -11,12 +11,13 @@
|
||||
#include <string>
|
||||
#include "threading.h"
|
||||
|
||||
namespace tgvoip{
|
||||
|
||||
class CVoIPServerConfig{
|
||||
class ServerConfig{
|
||||
public:
|
||||
CVoIPServerConfig();
|
||||
~CVoIPServerConfig();
|
||||
static CVoIPServerConfig* GetSharedInstance();
|
||||
ServerConfig();
|
||||
~ServerConfig();
|
||||
static ServerConfig* GetSharedInstance();
|
||||
int32_t GetInt(std::string name, int32_t fallback);
|
||||
double GetDouble(std::string name, double fallback);
|
||||
std::string GetString(std::string name, std::string fallback);
|
||||
@ -25,11 +26,11 @@ public:
|
||||
void Update(const char **values, int count);
|
||||
|
||||
private:
|
||||
static CVoIPServerConfig* sharedInstance;
|
||||
static ServerConfig* sharedInstance;
|
||||
bool ContainsKey(std::string key);
|
||||
std::map<std::string, std::string> config;
|
||||
tgvoip_mutex_t mutex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //TGVOIP_VOIPSERVERCONFIG_H
|
||||
|
@ -14,6 +14,10 @@
|
||||
#else
|
||||
#include "../os/darwin/AudioInputAudioUnitOSX.h"
|
||||
#endif
|
||||
#elif defined(_WIN32)
|
||||
#include "../os/windows/AudioInputWave.h"
|
||||
#elif defined(__linux__)
|
||||
#include "../os/linux/AudioInputALSA.h"
|
||||
#else
|
||||
#error "Unsupported operating system"
|
||||
#endif
|
||||
@ -27,6 +31,10 @@ CAudioInput *CAudioInput::Create(){
|
||||
return new CAudioInputAndroid();
|
||||
#elif defined(__APPLE__)
|
||||
return new CAudioInputAudioUnit();
|
||||
#elif defined(_WIN32)
|
||||
return new tgvoip::audio::AudioInputWave();
|
||||
#elif defined(__linux__)
|
||||
return new tgvoip::audio::AudioInputALSA();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,10 @@
|
||||
#else
|
||||
#include "../os/darwin/AudioOutputAudioUnitOSX.h"
|
||||
#endif
|
||||
#elif defined(_WIN32)
|
||||
#include "../os/windows/AudioOutputWave.h"
|
||||
#elif defined(__linux__)
|
||||
#include "../os/linux/AudioOutputALSA.h"
|
||||
#else
|
||||
#error "Unsupported operating system"
|
||||
#endif
|
||||
@ -30,9 +34,16 @@ CAudioOutput *CAudioOutput::Create(){
|
||||
return new CAudioOutputOpenSLES();
|
||||
#elif defined(__APPLE__)
|
||||
return new CAudioOutputAudioUnit();
|
||||
#elif defined(_WIN32)
|
||||
return new tgvoip::audio::AudioOutputWave();
|
||||
#elif defined(__linux__)
|
||||
return new tgvoip::audio::AudioOutputALSA();
|
||||
#endif
|
||||
}
|
||||
|
||||
CAudioOutput::CAudioOutput(){
|
||||
failed=false;
|
||||
}
|
||||
|
||||
CAudioOutput::~CAudioOutput(){
|
||||
|
||||
@ -43,7 +54,7 @@ int32_t CAudioOutput::GetEstimatedDelay(){
|
||||
#if defined(__ANDROID__)
|
||||
return systemVersion<21 ? 150 : 50;
|
||||
#endif
|
||||
return 0;
|
||||
return 60;
|
||||
}
|
||||
|
||||
float CAudioOutput::GetLevel(){
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
class CAudioOutput : public CMediaStreamItf{
|
||||
public:
|
||||
CAudioOutput();
|
||||
virtual ~CAudioOutput();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels)=0;
|
||||
virtual bool IsPlaying()=0;
|
||||
@ -22,6 +23,9 @@ public:
|
||||
#if defined(__ANDROID__)
|
||||
static int systemVersion;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool failed;
|
||||
};
|
||||
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <wchar.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <libtgvoip/VoIPServerConfig.h>
|
||||
#include "../../VoIPController.h"
|
||||
#include "../../os/android/AudioOutputOpenSLES.h"
|
||||
@ -26,7 +27,9 @@ struct impl_data_android_t{
|
||||
jobject javaObject;
|
||||
};
|
||||
|
||||
void updateConnectionState(CVoIPController* cntrlr, int state){
|
||||
using namespace tgvoip;
|
||||
|
||||
void updateConnectionState(VoIPController* cntrlr, int state){
|
||||
impl_data_android_t* impl=(impl_data_android_t*) cntrlr->implData;
|
||||
if(!impl->javaObject)
|
||||
return;
|
||||
@ -70,29 +73,30 @@ extern "C" JNIEXPORT jlong Java_org_telegram_messenger_voip_VoIPController_nativ
|
||||
|
||||
impl_data_android_t* impl=(impl_data_android_t*) malloc(sizeof(impl_data_android_t));
|
||||
impl->javaObject=env->NewGlobalRef(thiz);
|
||||
CVoIPController* cntrlr=new CVoIPController();
|
||||
VoIPController* cntrlr=new VoIPController();
|
||||
cntrlr->implData=impl;
|
||||
cntrlr->SetStateCallback(updateConnectionState);
|
||||
return (jlong)(intptr_t)cntrlr;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPController_nativeStart(JNIEnv* env, jobject thiz, jlong inst){
|
||||
((CVoIPController*)(intptr_t)inst)->Start();
|
||||
((VoIPController*)(intptr_t)inst)->Start();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPController_nativeConnect(JNIEnv* env, jobject thiz, jlong inst){
|
||||
((CVoIPController*)(intptr_t)inst)->Connect();
|
||||
((VoIPController*)(intptr_t)inst)->Connect();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPController_nativeSetEncryptionKey(JNIEnv* env, jobject thiz, jlong inst, jbyteArray key, jboolean isOutgoing){
|
||||
jbyte* akey=env->GetByteArrayElements(key, NULL);
|
||||
((CVoIPController*)(intptr_t)inst)->SetEncryptionKey((char *) akey, isOutgoing);
|
||||
((VoIPController*)(intptr_t)inst)->SetEncryptionKey((char *) akey, isOutgoing);
|
||||
env->ReleaseByteArrayElements(key, akey, JNI_ABORT);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPController_nativeSetRemoteEndpoints(JNIEnv* env, jobject thiz, jlong inst, jobjectArray endpoints, jboolean allowP2p){
|
||||
size_t len=(size_t) env->GetArrayLength(endpoints);
|
||||
voip_endpoint_t* eps=(voip_endpoint_t *) malloc(sizeof(voip_endpoint_t)*len);
|
||||
// voip_endpoint_t* eps=(voip_endpoint_t *) malloc(sizeof(voip_endpoint_t)*len);
|
||||
std::vector<Endpoint> eps;
|
||||
/*public String ip;
|
||||
public String ipv6;
|
||||
public int port;
|
||||
@ -111,25 +115,25 @@ extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPController_native
|
||||
jint port=env->GetIntField(endpoint, portFld);
|
||||
jlong id=env->GetLongField(endpoint, idFld);
|
||||
jbyteArray peerTag=(jbyteArray) env->GetObjectField(endpoint, peerTagFld);
|
||||
eps[i].id=id;
|
||||
eps[i].port=(uint32_t) port;
|
||||
const char* ipChars=env->GetStringUTFChars(ip, NULL);
|
||||
inet_aton(ipChars, &eps[i].address);
|
||||
std::string ipLiteral(ipChars);
|
||||
IPv4Address v4addr(ipLiteral);
|
||||
IPv6Address v6addr("::0");
|
||||
env->ReleaseStringUTFChars(ip, ipChars);
|
||||
if(ipv6 && env->GetStringLength(ipv6)){
|
||||
const char* ipv6Chars=env->GetStringUTFChars(ipv6, NULL);
|
||||
inet_pton(AF_INET6, ipv6Chars, &eps[i].address6);
|
||||
v6addr=IPv6Address(ipv6Chars);
|
||||
env->ReleaseStringUTFChars(ipv6, ipv6Chars);
|
||||
}
|
||||
unsigned char pTag[16];
|
||||
if(peerTag && env->GetArrayLength(peerTag)){
|
||||
jbyte* peerTagBytes=env->GetByteArrayElements(peerTag, NULL);
|
||||
memcpy(eps[i].peerTag, peerTagBytes, 16);
|
||||
memcpy(pTag, peerTagBytes, 16);
|
||||
env->ReleaseByteArrayElements(peerTag, peerTagBytes, JNI_ABORT);
|
||||
}
|
||||
eps[i].type=EP_TYPE_UDP_RELAY;
|
||||
eps.push_back(Endpoint((int64_t)id, (uint16_t)port, v4addr, v6addr, EP_TYPE_UDP_RELAY, pTag));
|
||||
}
|
||||
((CVoIPController*)(intptr_t)inst)->SetRemoteEndpoints(eps, len, allowP2p);
|
||||
free(eps);
|
||||
((VoIPController*)(intptr_t)inst)->SetRemoteEndpoints(eps, allowP2p);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPController_nativeSetNativeBufferSize(JNIEnv* env, jclass thiz, jint size){
|
||||
@ -140,7 +144,7 @@ extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPController_native
|
||||
extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPController_nativeRelease(JNIEnv* env, jobject thiz, jlong inst){
|
||||
//env->DeleteGlobalRef(CAudioInputAndroid::jniClass);
|
||||
|
||||
CVoIPController* ctlr=((CVoIPController*)(intptr_t)inst);
|
||||
VoIPController* ctlr=((VoIPController*)(intptr_t)inst);
|
||||
impl_data_android_t* impl=(impl_data_android_t*)ctlr->implData;
|
||||
delete ctlr;
|
||||
env->DeleteGlobalRef(impl->javaObject);
|
||||
@ -169,16 +173,16 @@ extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_AudioTrackJNI_nativeC
|
||||
|
||||
extern "C" JNIEXPORT jstring Java_org_telegram_messenger_voip_VoIPController_nativeGetDebugString(JNIEnv* env, jobject thiz, jlong inst){
|
||||
char buf[10240];
|
||||
((CVoIPController*)(intptr_t)inst)->GetDebugString(buf, 10240);
|
||||
((VoIPController*)(intptr_t)inst)->GetDebugString(buf, 10240);
|
||||
return env->NewStringUTF(buf);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPController_nativeSetNetworkType(JNIEnv* env, jobject thiz, jlong inst, jint type){
|
||||
((CVoIPController*)(intptr_t)inst)->SetNetworkType(type);
|
||||
((VoIPController*)(intptr_t)inst)->SetNetworkType(type);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPController_nativeSetMicMute(JNIEnv* env, jobject thiz, jlong inst, jboolean mute){
|
||||
((CVoIPController*)(intptr_t)inst)->SetMicMute(mute);
|
||||
((VoIPController*)(intptr_t)inst)->SetMicMute(mute);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPController_nativeSetConfig(JNIEnv* env, jobject thiz, jlong inst, jdouble recvTimeout, jdouble initTimeout, jint dataSavingMode, jboolean enableAEC, jboolean enableNS, jboolean enableAGC, jstring logFilePath){
|
||||
@ -197,28 +201,28 @@ extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPController_native
|
||||
}else{
|
||||
memset(cfg.logFilePath, 0, sizeof(cfg.logFilePath));
|
||||
}
|
||||
((CVoIPController*)(intptr_t)inst)->SetConfig(&cfg);
|
||||
((VoIPController*)(intptr_t)inst)->SetConfig(&cfg);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPController_nativeDebugCtl(JNIEnv* env, jobject thiz, jlong inst, jint request, jint param){
|
||||
((CVoIPController*)(intptr_t)inst)->DebugCtl(request, param);
|
||||
((VoIPController*)(intptr_t)inst)->DebugCtl(request, param);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jstring Java_org_telegram_messenger_voip_VoIPController_nativeGetVersion(JNIEnv* env, jclass clasz){
|
||||
return env->NewStringUTF(CVoIPController::GetVersion());
|
||||
return env->NewStringUTF(VoIPController::GetVersion());
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong Java_org_telegram_messenger_voip_VoIPController_nativeGetPreferredRelayID(JNIEnv* env, jclass clasz, jlong inst){
|
||||
return ((CVoIPController*)(intptr_t)inst)->GetPreferredRelayID();
|
||||
return ((VoIPController*)(intptr_t)inst)->GetPreferredRelayID();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint Java_org_telegram_messenger_voip_VoIPController_nativeGetLastError(JNIEnv* env, jclass clasz, jlong inst){
|
||||
return ((CVoIPController*)(intptr_t)inst)->GetLastError();
|
||||
return ((VoIPController*)(intptr_t)inst)->GetLastError();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPController_nativeGetStats(JNIEnv* env, jclass clasz, jlong inst, jobject stats){
|
||||
voip_stats_t _stats;
|
||||
((CVoIPController*)(intptr_t)inst)->GetStats(&_stats);
|
||||
((VoIPController*)(intptr_t)inst)->GetStats(&_stats);
|
||||
jclass cls=env->GetObjectClass(stats);
|
||||
env->SetLongField(stats, env->GetFieldID(cls, "bytesSentWifi", "J"), _stats.bytesSentWifi);
|
||||
env->SetLongField(stats, env->GetFieldID(cls, "bytesSentMobile", "J"), _stats.bytesSentMobile);
|
||||
@ -243,11 +247,11 @@ extern "C" JNIEXPORT void Java_org_telegram_messenger_voip_VoIPServerConfig_nati
|
||||
env->ReleaseStringUTFChars(jval, cval);
|
||||
config[key]=val;
|
||||
}
|
||||
CVoIPServerConfig::GetSharedInstance()->Update(config);
|
||||
ServerConfig::GetSharedInstance()->Update(config);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jstring Java_org_telegram_messenger_voip_VoIPController_nativeGetDebugLog(JNIEnv* env, jobject thiz, jlong inst){
|
||||
CVoIPController* ctlr=((CVoIPController*)(intptr_t)inst);
|
||||
VoIPController* ctlr=((VoIPController*)(intptr_t)inst);
|
||||
std::string log=ctlr->GetDebugLog();
|
||||
return env->NewStringUTF(log.c_str());
|
||||
}
|
||||
|
333
libtgvoip.gyp
Normal file
333
libtgvoip.gyp
Normal file
@ -0,0 +1,333 @@
|
||||
# GYP project file for TDesktop
|
||||
|
||||
{
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'libtgvoip',
|
||||
'type': 'static_library',
|
||||
'dependencies': [],
|
||||
'defines': [
|
||||
'WEBRTC_APM_DEBUG_DUMP=0',
|
||||
'TGVOIP_USE_DESKTOP_DSP'
|
||||
],
|
||||
'variables': {
|
||||
'tgvoip_src_loc': '../../third_party/libtgvoip',
|
||||
},
|
||||
'include_dirs': [
|
||||
'<(tgvoip_src_loc)/webrtc_dsp',
|
||||
'../../../Libraries/opus/include',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'<(tgvoip_src_loc)',
|
||||
],
|
||||
},
|
||||
'export_dependent_settings': [],
|
||||
'sources': [
|
||||
'<(tgvoip_src_loc)/BlockingQueue.cpp',
|
||||
'<(tgvoip_src_loc)/BlockingQueue.h',
|
||||
'<(tgvoip_src_loc)/BufferInputStream.cpp',
|
||||
'<(tgvoip_src_loc)/BufferInputStream.h',
|
||||
'<(tgvoip_src_loc)/BufferOutputStream.cpp',
|
||||
'<(tgvoip_src_loc)/BufferOutputStream.h',
|
||||
'<(tgvoip_src_loc)/BufferPool.cpp',
|
||||
'<(tgvoip_src_loc)/BufferPool.h',
|
||||
'<(tgvoip_src_loc)/CongestionControl.cpp',
|
||||
'<(tgvoip_src_loc)/CongestionControl.h',
|
||||
'<(tgvoip_src_loc)/EchoCanceller.cpp',
|
||||
'<(tgvoip_src_loc)/EchoCanceller.h',
|
||||
'<(tgvoip_src_loc)/JitterBuffer.cpp',
|
||||
'<(tgvoip_src_loc)/JitterBuffer.h',
|
||||
'<(tgvoip_src_loc)/logging.cpp',
|
||||
'<(tgvoip_src_loc)/logging.h',
|
||||
'<(tgvoip_src_loc)/MediaStreamItf.cpp',
|
||||
'<(tgvoip_src_loc)/MediaStreamItf.h',
|
||||
'<(tgvoip_src_loc)/OpusDecoder.cpp',
|
||||
'<(tgvoip_src_loc)/OpusDecoder.h',
|
||||
'<(tgvoip_src_loc)/OpusEncoder.cpp',
|
||||
'<(tgvoip_src_loc)/OpusEncoder.h',
|
||||
'<(tgvoip_src_loc)/threading.h',
|
||||
'<(tgvoip_src_loc)/VoIPController.cpp',
|
||||
'<(tgvoip_src_loc)/VoIPController.h',
|
||||
'<(tgvoip_src_loc)/VoIPServerConfig.cpp',
|
||||
'<(tgvoip_src_loc)/VoIPServerConfig.h',
|
||||
'<(tgvoip_src_loc)/audio/AudioInput.cpp',
|
||||
'<(tgvoip_src_loc)/audio/AudioInput.h',
|
||||
'<(tgvoip_src_loc)/audio/AudioOutput.cpp',
|
||||
'<(tgvoip_src_loc)/audio/AudioOutput.h',
|
||||
'<(tgvoip_src_loc)/audio/Resampler.cpp',
|
||||
'<(tgvoip_src_loc)/audio/Resampler.h',
|
||||
'<(tgvoip_src_loc)/NetworkSocket.cpp',
|
||||
'<(tgvoip_src_loc)/NetworkSocket.h',
|
||||
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/base/array_view.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/base/atomicops.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/base/basictypes.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/base/checks.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/base/checks.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/base/constructormagic.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/base/safe_compare.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/base/safe_conversions.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/base/safe_conversions_impl.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/base/sanitizer.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/base/stringutils.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/base/stringutils.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/base/type_traits.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/audio_util.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/channel_buffer.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/channel_buffer.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/fft4g.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/fft4g.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/include/audio_util.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/ring_buffer.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/ring_buffer.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/auto_corr_to_refl_coef.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/auto_correlation.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/complex_bit_reverse.c',
|
||||
# 'webrtc_dsp/webrtc/common_audio/signal_processing/complex_bit_reverse_arm.S',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/complex_fft.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/complex_fft_tables.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/copy_set_operations.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/cross_correlation.c',
|
||||
# '<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/cross_correlation_neon.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/division_operations.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/dot_product_with_scale.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/downsample_fast.c',
|
||||
# '<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/downsample_fast_neon.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/energy.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/filter_ar.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/filter_ar_fast_q12.c',
|
||||
# 'webrtc_dsp/webrtc/common_audio/signal_processing/filter_ar_fast_q12_armv7.S',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/filter_ma_fast_q12.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/get_hanning_window.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/get_scaling_square.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/ilbc_specific_functions.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/include/real_fft.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/include/signal_processing_library.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/include/spl_inl.h',
|
||||
# '<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/include/spl_inl_armv7.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/include/spl_inl_mips.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/levinson_durbin.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/lpc_to_refl_coef.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/min_max_operations.c',
|
||||
# '<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/min_max_operations_neon.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/randomization_functions.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/real_fft.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/refl_coef_to_lpc.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/resample.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/resample_48khz.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/resample_by_2.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/resample_by_2_internal.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/resample_by_2_internal.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/resample_fractional.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/spl_init.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/spl_inl.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/spl_sqrt.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/spl_sqrt_floor.c',
|
||||
#'webrtc_dsp/webrtc/common_audio/signal_processing/spl_sqrt_floor_arm.S',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/splitting_filter_impl.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/sqrt_of_one_minus_x_squared.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/signal_processing/vector_scaling_operations.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/sparse_fir_filter.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/sparse_fir_filter.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/wav_file.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/wav_file.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/wav_header.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/common_audio/wav_header.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aec/aec_common.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aec/aec_core.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aec/aec_core.h',
|
||||
# '<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aec/aec_core_neon.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aec/aec_core_optimized_methods.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aec/aec_core_sse2.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aec/aec_resampler.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aec/aec_resampler.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aec/echo_cancellation.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aec/echo_cancellation.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aecm/aecm_core.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aecm/aecm_core.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aecm/aecm_core_c.cc',
|
||||
# '<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aecm/aecm_core_neon.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aecm/aecm_defines.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aecm/echo_control_mobile.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/aecm/echo_control_mobile.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/agc/legacy/analog_agc.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/agc/legacy/analog_agc.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/agc/legacy/digital_agc.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/agc/legacy/digital_agc.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/agc/legacy/gain_control.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/logging/apm_data_dumper.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/logging/apm_data_dumper.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/ns/defines.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/ns/noise_suppression.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/ns/noise_suppression.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/ns/noise_suppression_x.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/ns/noise_suppression_x.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/ns/ns_core.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/ns/ns_core.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/ns/nsx_core.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/ns/nsx_core.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/ns/nsx_core_c.c',
|
||||
# '<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/ns/nsx_core_neon.c',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/ns/nsx_defines.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/ns/windows_private.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/splitting_filter.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/splitting_filter.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/three_band_filter_bank.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/three_band_filter_bank.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/utility/block_mean_calculator.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/utility/block_mean_calculator.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/utility/delay_estimator.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/utility/delay_estimator.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/utility/delay_estimator_internal.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/utility/ooura_fft.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/utility/ooura_fft.h',
|
||||
# '<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/utility/ooura_fft_neon.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/utility/ooura_fft_sse2.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/utility/ooura_fft_tables_common.h',
|
||||
# '<(tgvoip_src_loc)/webrtc_dsp/webrtc/modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/system_wrappers/include/asm_defines.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/system_wrappers/include/compile_assert_c.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/system_wrappers/include/cpu_features_wrapper.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/system_wrappers/include/metrics.h',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/system_wrappers/source/cpu_features.cc',
|
||||
'<(tgvoip_src_loc)/webrtc_dsp/webrtc/typedefs.h',
|
||||
|
||||
],
|
||||
'libraries': [],
|
||||
'configurations': {
|
||||
'Debug': {},
|
||||
'Release': {},
|
||||
},
|
||||
'conditions': [
|
||||
[
|
||||
'"<(OS)" == "mac"', {
|
||||
'sources': [
|
||||
'<(tgvoip_src_loc)/os/darwin/AudioInputAudioUnitOSX.cpp',
|
||||
'<(tgvoip_src_loc)/os/darwin/AudioInputAudioUnitOSX.h',
|
||||
'<(tgvoip_src_loc)/os/darwin/AudioOutputAudioUnitOSX.cpp',
|
||||
'<(tgvoip_src_loc)/os/darwin/AudioOutputAudioUnitOSX.h',
|
||||
'<(tgvoip_src_loc)/os/posix/NetworkSocketPosix.cpp',
|
||||
'<(tgvoip_src_loc)/os/posix/NetworkSocketPosix.h',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../../../Libraries/openssl-xcode/include',
|
||||
],
|
||||
'xcode_settings': {
|
||||
'CLANG_CXX_LANGUAGE_STANDARD': 'c++1z',
|
||||
},
|
||||
'defines': [
|
||||
'WEBRTC_POSIX',
|
||||
],
|
||||
},
|
||||
],
|
||||
[
|
||||
'"<(OS)" == "win"', {
|
||||
'msbuild_toolset': 'v140',
|
||||
'defines': [
|
||||
'NOMINMAX',
|
||||
'_USING_V110_SDK71_',
|
||||
],
|
||||
'sources': [
|
||||
'<(tgvoip_src_loc)/os/windows/NetworkSocketWinsock.cpp',
|
||||
'<(tgvoip_src_loc)/os/windows/NetworkSocketWinsock.h',
|
||||
'<(tgvoip_src_loc)/os/windows/AudioInputWave.cpp',
|
||||
'<(tgvoip_src_loc)/os/windows/AudioInputWave.h',
|
||||
'<(tgvoip_src_loc)/os/windows/AudioOutputWave.cpp',
|
||||
'<(tgvoip_src_loc)/os/windows/AudioOutputWave.h',
|
||||
],
|
||||
'libraries': [
|
||||
'winmm',
|
||||
'ws2_32',
|
||||
'kernel32',
|
||||
'user32',
|
||||
],
|
||||
'msvs_cygwin_shell': 0,
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'ProgramDataBaseFileName': '$(OutDir)\\$(ProjectName).pdb',
|
||||
'DebugInformationFormat': '3', # Program Database (/Zi)
|
||||
'AdditionalOptions': [
|
||||
'/MP', # Enable multi process build.
|
||||
'/EHsc', # Catch C++ exceptions only, extern C functions never throw a C++ exception.
|
||||
],
|
||||
'TreatWChar_tAsBuiltInType': 'false',
|
||||
},
|
||||
},
|
||||
'msvs_external_builder_build_cmd': [
|
||||
'ninja.exe',
|
||||
'-C',
|
||||
'$(OutDir)',
|
||||
'-k0',
|
||||
'$(ProjectName)',
|
||||
],
|
||||
'configurations': {
|
||||
'Debug': {
|
||||
'defines': [
|
||||
'_DEBUG',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../../../Libraries/openssl_debug/Debug/include',
|
||||
],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'Optimization': '0', # Disabled (/Od)
|
||||
'RuntimeLibrary': '1', # Multi-threaded Debug (/MTd)
|
||||
'RuntimeTypeInfo': 'true',
|
||||
},
|
||||
'VCLibrarianTool': {
|
||||
'AdditionalOptions': [
|
||||
'/NODEFAULTLIB:LIBCMT'
|
||||
]
|
||||
}
|
||||
},
|
||||
},
|
||||
'Release': {
|
||||
'defines': [
|
||||
'NDEBUG',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../../../Libraries/openssl/Release/include',
|
||||
],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'Optimization': '2', # Maximize Speed (/O2)
|
||||
'InlineFunctionExpansion': '2', # Any suitable (/Ob2)
|
||||
'EnableIntrinsicFunctions': 'true', # Yes (/Oi)
|
||||
'FavorSizeOrSpeed': '1', # Favor fast code (/Ot)
|
||||
'RuntimeLibrary': '0', # Multi-threaded (/MT)
|
||||
'EnableEnhancedInstructionSet': '2', # Streaming SIMD Extensions 2 (/arch:SSE2)
|
||||
'WholeProgramOptimization': 'true', # /GL
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
'"<(OS)" == "linux"', {
|
||||
'sources': [
|
||||
'<(tgvoip_src_loc)/os/posix/NetworkSocketPosix.cpp',
|
||||
'<(tgvoip_src_loc)/os/posix/NetworkSocketPosix.h',
|
||||
|
||||
'<(tgvoip_src_loc)/os/linux/AudioInputALSA.cpp',
|
||||
'<(tgvoip_src_loc)/os/linux/AudioInputALSA.h',
|
||||
'<(tgvoip_src_loc)/os/linux/AudioOutputALSA.cpp',
|
||||
'<(tgvoip_src_loc)/os/linux/AudioOutputALSA.h',
|
||||
],
|
||||
'defines': [
|
||||
'WEBRTC_POSIX',
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'libraries': [
|
||||
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
@ -7,6 +7,10 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
69015D8A1E9D846F00AC9763 /* NetworkSocketPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 69015D881E9D846F00AC9763 /* NetworkSocketPosix.cpp */; };
|
||||
69015D8B1E9D846F00AC9763 /* NetworkSocketPosix.h in Headers */ = {isa = PBXBuildFile; fileRef = 69015D891E9D846F00AC9763 /* NetworkSocketPosix.h */; };
|
||||
69015D941E9D848700AC9763 /* NetworkSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 69015D921E9D848700AC9763 /* NetworkSocket.cpp */; };
|
||||
69015D951E9D848700AC9763 /* NetworkSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 69015D931E9D848700AC9763 /* NetworkSocket.h */; };
|
||||
6915307B1E6B5BAB004F643F /* logging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6915307A1E6B5BAB004F643F /* logging.cpp */; };
|
||||
692AB8CB1E6759DD00706ACC /* AudioInput.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 692AB8881E6759DD00706ACC /* AudioInput.cpp */; };
|
||||
692AB8CC1E6759DD00706ACC /* AudioInput.h in Headers */ = {isa = PBXBuildFile; fileRef = 692AB8891E6759DD00706ACC /* AudioInput.h */; };
|
||||
@ -232,6 +236,10 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
69015D881E9D846F00AC9763 /* NetworkSocketPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkSocketPosix.cpp; sourceTree = "<group>"; };
|
||||
69015D891E9D846F00AC9763 /* NetworkSocketPosix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkSocketPosix.h; sourceTree = "<group>"; };
|
||||
69015D921E9D848700AC9763 /* NetworkSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkSocket.cpp; sourceTree = "<group>"; };
|
||||
69015D931E9D848700AC9763 /* NetworkSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkSocket.h; sourceTree = "<group>"; };
|
||||
6915307A1E6B5BAB004F643F /* logging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = logging.cpp; sourceTree = "<group>"; };
|
||||
692AB8881E6759DD00706ACC /* AudioInput.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AudioInput.cpp; sourceTree = "<group>"; };
|
||||
692AB8891E6759DD00706ACC /* AudioInput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioInput.h; sourceTree = "<group>"; };
|
||||
@ -427,6 +435,16 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
69015D871E9D846F00AC9763 /* posix */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
69015D881E9D846F00AC9763 /* NetworkSocketPosix.cpp */,
|
||||
69015D891E9D846F00AC9763 /* NetworkSocketPosix.h */,
|
||||
);
|
||||
name = posix;
|
||||
path = ../../../../TDesktop/TBuild/tdesktop/third_party/libtgvoip/os/posix;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
692AB8861E6759BF00706ACC /* libtgvoip */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -450,6 +468,8 @@
|
||||
692AB8AA1E6759DD00706ACC /* logging.h */,
|
||||
692AB8AB1E6759DD00706ACC /* MediaStreamItf.cpp */,
|
||||
692AB8AC1E6759DD00706ACC /* MediaStreamItf.h */,
|
||||
69015D921E9D848700AC9763 /* NetworkSocket.cpp */,
|
||||
69015D931E9D848700AC9763 /* NetworkSocket.h */,
|
||||
692AB8AD1E6759DD00706ACC /* OpusDecoder.cpp */,
|
||||
692AB8AE1E6759DD00706ACC /* OpusDecoder.h */,
|
||||
692AB8AF1E6759DD00706ACC /* OpusEncoder.cpp */,
|
||||
@ -479,6 +499,7 @@
|
||||
692AB8B11E6759DD00706ACC /* os */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
69015D871E9D846F00AC9763 /* posix */,
|
||||
692AB8BD1E6759DD00706ACC /* darwin */,
|
||||
);
|
||||
path = os;
|
||||
@ -875,6 +896,7 @@
|
||||
69A6DDDB1E95EC7700000E69 /* aec_common.h in Headers */,
|
||||
69A6DDDD1E95EC7700000E69 /* aec_core.h in Headers */,
|
||||
69A6DE051E95EC7800000E69 /* block_mean_calculator.h in Headers */,
|
||||
69015D8B1E9D846F00AC9763 /* NetworkSocketPosix.h in Headers */,
|
||||
69A6DD951E95EC7700000E69 /* atomicops.h in Headers */,
|
||||
69A6DD991E95EC7700000E69 /* constructormagic.h in Headers */,
|
||||
69A6DDA01E95EC7700000E69 /* type_traits.h in Headers */,
|
||||
@ -887,6 +909,7 @@
|
||||
69A6DE0A1E95EC7800000E69 /* delay_estimator_wrapper.h in Headers */,
|
||||
69A6DE141E95EC7800000E69 /* metrics.h in Headers */,
|
||||
692AB8FE1E6759DD00706ACC /* AudioUnitIO.h in Headers */,
|
||||
69015D951E9D848700AC9763 /* NetworkSocket.h in Headers */,
|
||||
69A6DE131E95EC7800000E69 /* cpu_features_wrapper.h in Headers */,
|
||||
69A6DDDF1E95EC7700000E69 /* aec_core_optimized_methods.h in Headers */,
|
||||
69A6DE101E95EC7800000E69 /* ooura_fft_tables_neon_sse2.h in Headers */,
|
||||
@ -1055,6 +1078,7 @@
|
||||
69A6DDE81E95EC7700000E69 /* aecm_core_neon.cc in Sources */,
|
||||
69A6DDBB1E95EC7700000E69 /* get_hanning_window.c in Sources */,
|
||||
69A6DDB51E95EC7700000E69 /* downsample_fast_neon.c in Sources */,
|
||||
69015D941E9D848700AC9763 /* NetworkSocket.cpp in Sources */,
|
||||
69A6DDC41E95EC7700000E69 /* lpc_to_refl_coef.c in Sources */,
|
||||
69A6DDEC1E95EC7700000E69 /* analog_agc.c in Sources */,
|
||||
69A6DDA71E95EC7700000E69 /* ring_buffer.c in Sources */,
|
||||
@ -1110,6 +1134,7 @@
|
||||
692AB8CB1E6759DD00706ACC /* AudioInput.cpp in Sources */,
|
||||
69A6DDCC1E95EC7700000E69 /* resample_48khz.c in Sources */,
|
||||
69A6DDAC1E95EC7700000E69 /* complex_bit_reverse_arm.S in Sources */,
|
||||
69015D8A1E9D846F00AC9763 /* NetworkSocketPosix.cpp in Sources */,
|
||||
69A6DDD81E95EC7700000E69 /* vector_scaling_operations.c in Sources */,
|
||||
69A6DE0D1E95EC7800000E69 /* ooura_fft_neon.cc in Sources */,
|
||||
692AB8FD1E6759DD00706ACC /* AudioUnitIO.cpp in Sources */,
|
||||
@ -1241,12 +1266,10 @@
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
../../Telegraph/thirdparty/opus/include/opus,
|
||||
"$(PROJECT_DIR)/../../Telegraph/thirdparty/opus/include/opus",
|
||||
"$(inherited)",
|
||||
../../Telegraph,
|
||||
"$(PROJECT_DIR)/../../Telegraph",
|
||||
webrtc_dsp,
|
||||
"../Telegram-iOS/Telegraph/thirdparty/opus/include/opus",
|
||||
"../Telegram-iOS/Telegraph",
|
||||
);
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
@ -1278,12 +1301,10 @@
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
../../Telegraph/thirdparty/opus/include/opus,
|
||||
"$(PROJECT_DIR)/../../Telegraph/thirdparty/opus/include/opus",
|
||||
"$(inherited)",
|
||||
../../Telegraph,
|
||||
"$(PROJECT_DIR)/../../Telegraph",
|
||||
webrtc_dsp,
|
||||
"../Telegram-iOS/Telegraph/thirdparty/opus/include/opus",
|
||||
"../Telegram-iOS/Telegraph",
|
||||
);
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
@ -1366,12 +1387,10 @@
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
../../Telegraph/thirdparty/opus/include/opus,
|
||||
"$(PROJECT_DIR)/../../Telegraph/thirdparty/opus/include/opus",
|
||||
"$(inherited)",
|
||||
../../Telegraph,
|
||||
"$(PROJECT_DIR)/../../Telegraph",
|
||||
webrtc_dsp,
|
||||
"../Telegram-iOS/Telegraph/thirdparty/opus/include/opus",
|
||||
"../Telegram-iOS/Telegraph",
|
||||
);
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
@ -1448,12 +1467,10 @@
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
../../Telegraph/thirdparty/opus/include/opus,
|
||||
"$(PROJECT_DIR)/../../Telegraph/thirdparty/opus/include/opus",
|
||||
"$(inherited)",
|
||||
../../Telegraph,
|
||||
"$(PROJECT_DIR)/../../Telegraph",
|
||||
webrtc_dsp,
|
||||
"../Telegram-iOS/Telegraph/thirdparty/opus/include/opus",
|
||||
"../Telegram-iOS/Telegraph",
|
||||
);
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
|
13
logging.h
13
logging.h
@ -38,6 +38,19 @@ void tgvoip_log_file_printf(char level, const char* msg, ...);
|
||||
#define LOGW(msg, ...) __tgvoip_call_tglog("W/tgvoip: " msg, ##__VA_ARGS__)
|
||||
#define LOGE(msg, ...) __tgvoip_call_tglog("E/tgvoip: " msg, ##__VA_ARGS__)
|
||||
|
||||
#elif defined(_WIN32) && defined(_DEBUG)
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define _TGVOIP_W32_LOG_PRINT(msg, ...){ char __log_buf[1024]; snprintf(__log_buf, 1024, msg, ##__VA_ARGS__); OutputDebugStringA(__log_buf); }
|
||||
|
||||
#define LOGV(msg, ...) _TGVOIP_W32_LOG_PRINT("V/tgvoip: " msg "\n", ##__VA_ARGS__)
|
||||
#define LOGD(msg, ...) _TGVOIP_W32_LOG_PRINT("D/tgvoip: " msg "\n", ##__VA_ARGS__)
|
||||
#define LOGI(msg, ...) _TGVOIP_W32_LOG_PRINT("I/tgvoip: " msg "\n", ##__VA_ARGS__)
|
||||
#define LOGW(msg, ...) _TGVOIP_W32_LOG_PRINT("W/tgvoip: " msg "\n", ##__VA_ARGS__)
|
||||
#define LOGE(msg, ...) _TGVOIP_W32_LOG_PRINT("E/tgvoip: " msg "\n", ##__VA_ARGS__)
|
||||
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -17,6 +17,8 @@
|
||||
#define kOutputBus 0
|
||||
#define kInputBus 1
|
||||
|
||||
using namespace tgvoip;
|
||||
|
||||
int CAudioUnitIO::refCount=0;
|
||||
CAudioUnitIO* CAudioUnitIO::sharedInstance=NULL;
|
||||
bool CAudioUnitIO::haveAudioSession=false;
|
||||
@ -210,9 +212,9 @@ void* CAudioUnitIO::StartFakeIOThread(void *arg){
|
||||
|
||||
void CAudioUnitIO::RunFakeIOThread(){
|
||||
double neededDataDuration=0;
|
||||
double prevTime=CVoIPController::GetCurrentTime();
|
||||
double prevTime=VoIPController::GetCurrentTime();
|
||||
while(runFakeIO){
|
||||
double t=CVoIPController::GetCurrentTime();
|
||||
double t=VoIPController::GetCurrentTime();
|
||||
neededDataDuration+=t-prevTime;
|
||||
prevTime=t;
|
||||
while(neededDataDuration>=0.020){
|
||||
|
@ -1,6 +1,6 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "ASCommon.h"
|
||||
#import <ASCommon.h>
|
||||
|
||||
void __tgvoip_call_tglog(char* format, ...){
|
||||
va_list args;
|
||||
|
88
os/linux/AudioInputALSA.cpp
Normal file
88
os/linux/AudioInputALSA.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
//
|
||||
// libtgvoip is free and unencumbered public domain software.
|
||||
// For more information, see http://unlicense.org or the UNLICENSE file
|
||||
// you should have received with this source code distribution.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include "AudioInputALSA.h"
|
||||
#include "../../logging.h"
|
||||
|
||||
using namespace tgvoip::audio;
|
||||
|
||||
#define BUFFER_SIZE 960
|
||||
#define CHECK_ERROR(res, msg) if(res<0){LOGE(msg ": %s", _snd_strerror(res));}
|
||||
#define CHECK_DL_ERROR(res, msg) if(!res){LOGE(msg ": %s", dlerror()); failed=true; return;}
|
||||
#define LOAD_FUNCTION(lib, name, ref) {ref=(typeof(ref))dlsym(lib, name); CHECK_DL_ERROR(ref, "Error getting entry point for " name);}
|
||||
|
||||
AudioInputALSA::AudioInputALSA(){
|
||||
isRecording=false;
|
||||
|
||||
lib=dlopen("libasound.so", RTLD_LAZY);
|
||||
if(!lib){
|
||||
LOGE("Error loading libasound: %s", dlerror());
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
|
||||
LOAD_FUNCTION(lib, "snd_pcm_open", _snd_pcm_open);
|
||||
LOAD_FUNCTION(lib, "snd_pcm_set_params", _snd_pcm_set_params);
|
||||
LOAD_FUNCTION(lib, "snd_pcm_close", _snd_pcm_close);
|
||||
LOAD_FUNCTION(lib, "snd_pcm_readi", _snd_pcm_readi);
|
||||
LOAD_FUNCTION(lib, "snd_pcm_recover", _snd_pcm_recover);
|
||||
LOAD_FUNCTION(lib, "snd_strerror", _snd_strerror);
|
||||
|
||||
int res=_snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0);
|
||||
CHECK_ERROR(res, "snd_pcm_open failed");
|
||||
|
||||
res=_snd_pcm_set_params(handle, SND_PCM_FORMAT_S16, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 48000, 1, 100000);
|
||||
CHECK_ERROR(res, "snd_pcm_set_params failed");
|
||||
}
|
||||
|
||||
AudioInputALSA::~AudioInputALSA(){
|
||||
_snd_pcm_close(handle);
|
||||
dlclose(lib);
|
||||
}
|
||||
|
||||
void AudioInputALSA::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
|
||||
}
|
||||
|
||||
void AudioInputALSA::Start(){
|
||||
if(failed || isRecording)
|
||||
return;
|
||||
|
||||
isRecording=true;
|
||||
start_thread(thread, AudioInputALSA::StartThread, this);
|
||||
}
|
||||
|
||||
void AudioInputALSA::Stop(){
|
||||
if(!isRecording)
|
||||
return;
|
||||
|
||||
isRecording=false;
|
||||
join_thread(thread);
|
||||
}
|
||||
|
||||
void* AudioInputALSA::StartThread(void* arg){
|
||||
((AudioInputALSA*)arg)->RunThread();
|
||||
}
|
||||
|
||||
void AudioInputALSA::RunThread(){
|
||||
unsigned char buffer[BUFFER_SIZE*2];
|
||||
snd_pcm_sframes_t frames;
|
||||
while(isRecording){
|
||||
frames=_snd_pcm_readi(handle, buffer, BUFFER_SIZE);
|
||||
if (frames < 0){
|
||||
frames = _snd_pcm_recover(handle, frames, 0);
|
||||
}
|
||||
if (frames < 0) {
|
||||
LOGE("snd_pcm_readi failed: %s\n", _snd_strerror(frames));
|
||||
break;
|
||||
}
|
||||
InvokeCallback(buffer, sizeof(buffer));
|
||||
}
|
||||
}
|
46
os/linux/AudioInputALSA.h
Normal file
46
os/linux/AudioInputALSA.h
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// 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_AUDIOINPUTALSA_H
|
||||
#define LIBTGVOIP_AUDIOINPUTALSA_H
|
||||
|
||||
#include "../../audio/AudioInput.h"
|
||||
#include "../../threading.h"
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
namespace tgvoip{
|
||||
namespace audio{
|
||||
|
||||
class AudioInputALSA : public CAudioInput{
|
||||
|
||||
public:
|
||||
AudioInputALSA();
|
||||
virtual ~AudioInputALSA();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
|
||||
private:
|
||||
static void* StartThread(void* arg);
|
||||
void RunThread();
|
||||
|
||||
int (*_snd_pcm_open)(snd_pcm_t** pcm, const char* name, snd_pcm_stream_t stream, int mode);
|
||||
int (*_snd_pcm_set_params)(snd_pcm_t* pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, unsigned int rate, int soft_resample, unsigned int latency);
|
||||
int (*_snd_pcm_close)(snd_pcm_t* pcm);
|
||||
snd_pcm_sframes_t (*_snd_pcm_readi)(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
|
||||
int (*_snd_pcm_recover)(snd_pcm_t* pcm, int err, int silent);
|
||||
const char* (*_snd_strerror)(int errnum);
|
||||
void* lib;
|
||||
|
||||
snd_pcm_t* handle;
|
||||
tgvoip_thread_t thread;
|
||||
bool isRecording;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //LIBTGVOIP_AUDIOINPUTALSA_H
|
91
os/linux/AudioOutputALSA.cpp
Normal file
91
os/linux/AudioOutputALSA.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
//
|
||||
// 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 <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include "AudioOutputALSA.h"
|
||||
#include "../../logging.h"
|
||||
|
||||
#define BUFFER_SIZE 960
|
||||
#define CHECK_ERROR(res, msg) if(res<0){LOGE(msg ": %s", _snd_strerror(res));}
|
||||
#define CHECK_DL_ERROR(res, msg) if(!res){LOGE(msg ": %s", dlerror()); failed=true; return;}
|
||||
#define LOAD_FUNCTION(lib, name, ref) {ref=(typeof(ref))dlsym(lib, name); CHECK_DL_ERROR(ref, "Error getting entry point for " name);}
|
||||
|
||||
using namespace tgvoip::audio;
|
||||
|
||||
AudioOutputALSA::AudioOutputALSA(){
|
||||
isPlaying=false;
|
||||
|
||||
lib=dlopen("libasound.so", RTLD_LAZY);
|
||||
if(!lib){
|
||||
LOGE("Error loading libasound: %s", dlerror());
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
|
||||
LOAD_FUNCTION(lib, "snd_pcm_open", _snd_pcm_open);
|
||||
LOAD_FUNCTION(lib, "snd_pcm_set_params", _snd_pcm_set_params);
|
||||
LOAD_FUNCTION(lib, "snd_pcm_close", _snd_pcm_close);
|
||||
LOAD_FUNCTION(lib, "snd_pcm_writei", _snd_pcm_writei);
|
||||
LOAD_FUNCTION(lib, "snd_pcm_recover", _snd_pcm_recover);
|
||||
LOAD_FUNCTION(lib, "snd_strerror", _snd_strerror);
|
||||
|
||||
int res=_snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
|
||||
CHECK_ERROR(res, "snd_pcm_open failed");
|
||||
|
||||
res=_snd_pcm_set_params(handle, SND_PCM_FORMAT_S16, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 48000, 1, 100000);
|
||||
CHECK_ERROR(res, "snd_pcm_set_params failed");
|
||||
}
|
||||
|
||||
AudioOutputALSA::~AudioOutputALSA(){
|
||||
_snd_pcm_close(handle);
|
||||
dlclose(lib);
|
||||
}
|
||||
|
||||
void AudioOutputALSA::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
|
||||
}
|
||||
|
||||
void AudioOutputALSA::Start(){
|
||||
if(failed || isPlaying)
|
||||
return;
|
||||
|
||||
isPlaying=true;
|
||||
start_thread(thread, AudioOutputALSA::StartThread, this);
|
||||
}
|
||||
|
||||
void AudioOutputALSA::Stop(){
|
||||
if(!isPlaying)
|
||||
return;
|
||||
|
||||
isPlaying=false;
|
||||
join_thread(thread);
|
||||
}
|
||||
|
||||
bool AudioOutputALSA::IsPlaying(){
|
||||
return isPlaying;
|
||||
}
|
||||
|
||||
void* AudioOutputALSA::StartThread(void* arg){
|
||||
((AudioOutputALSA*)arg)->RunThread();
|
||||
}
|
||||
|
||||
void AudioOutputALSA::RunThread(){
|
||||
unsigned char buffer[BUFFER_SIZE*2];
|
||||
snd_pcm_sframes_t frames;
|
||||
while(isPlaying){
|
||||
InvokeCallback(buffer, sizeof(buffer));
|
||||
frames=_snd_pcm_writei(handle, buffer, BUFFER_SIZE);
|
||||
if (frames < 0){
|
||||
frames = _snd_pcm_recover(handle, frames, 0);
|
||||
}
|
||||
if (frames < 0) {
|
||||
LOGE("snd_pcm_writei failed: %s\n", _snd_strerror(frames));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
46
os/linux/AudioOutputALSA.h
Normal file
46
os/linux/AudioOutputALSA.h
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// 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_AUDIOOUTPUTALSA_H
|
||||
#define LIBTGVOIP_AUDIOOUTPUTALSA_H
|
||||
|
||||
#include "../../audio/AudioOutput.h"
|
||||
#include "../../threading.h"
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
namespace tgvoip{
|
||||
namespace audio{
|
||||
|
||||
class AudioOutputALSA : public CAudioOutput{
|
||||
public:
|
||||
AudioOutputALSA();
|
||||
virtual ~AudioOutputALSA();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
virtual bool IsPlaying();
|
||||
|
||||
private:
|
||||
static void* StartThread(void* arg);
|
||||
void RunThread();
|
||||
|
||||
int (*_snd_pcm_open)(snd_pcm_t** pcm, const char* name, snd_pcm_stream_t stream, int mode);
|
||||
int (*_snd_pcm_set_params)(snd_pcm_t* pcm, snd_pcm_format_t format, snd_pcm_access_t access, unsigned int channels, unsigned int rate, int soft_resample, unsigned int latency);
|
||||
int (*_snd_pcm_close)(snd_pcm_t* pcm);
|
||||
snd_pcm_sframes_t (*_snd_pcm_writei)(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);
|
||||
int (*_snd_pcm_recover)(snd_pcm_t* pcm, int err, int silent);
|
||||
const char* (*_snd_strerror)(int errnum);
|
||||
void* lib;
|
||||
|
||||
snd_pcm_t* handle;
|
||||
tgvoip_thread_t thread;
|
||||
bool isPlaying;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //LIBTGVOIP_AUDIOOUTPUTALSA_H
|
282
os/posix/NetworkSocketPosix.cpp
Normal file
282
os/posix/NetworkSocketPosix.cpp
Normal file
@ -0,0 +1,282 @@
|
||||
//
|
||||
// Created by Grishka on 10.04.17.
|
||||
//
|
||||
|
||||
#include "NetworkSocketPosix.h"
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include "../../logging.h"
|
||||
#include "../../VoIPController.h"
|
||||
|
||||
using namespace tgvoip;
|
||||
|
||||
NetworkSocketPosix::NetworkSocketPosix() : lastRecvdV4(0){
|
||||
needUpdateNat64Prefix=true;
|
||||
nat64Present=false;
|
||||
switchToV6at=0;
|
||||
isV4Available=false;
|
||||
}
|
||||
|
||||
NetworkSocketPosix::~NetworkSocketPosix(){
|
||||
|
||||
}
|
||||
|
||||
void NetworkSocketPosix::SetMaxPriority(){
|
||||
#ifdef __APPLE__
|
||||
int prio=NET_SERVICE_TYPE_VO;
|
||||
int res=setsockopt(fd, SOL_SOCKET, SO_NET_SERVICE_TYPE, &prio, sizeof(prio));
|
||||
if(res<0){
|
||||
LOGE("error setting darwin-specific net priority: %d / %s", errno, strerror(errno));
|
||||
}
|
||||
#else
|
||||
int prio=5;
|
||||
int res=setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio));
|
||||
if(res<0){
|
||||
LOGE("error setting priority: %d / %s", errno, strerror(errno));
|
||||
}
|
||||
prio=6 << 5;
|
||||
res=setsockopt(fd, SOL_IP, IP_TOS, &prio, sizeof(prio));
|
||||
if(res<0){
|
||||
LOGE("error setting ip tos: %d / %s", errno, strerror(errno));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void NetworkSocketPosix::Send(NetworkPacket *packet){
|
||||
sockaddr_in6 addr;
|
||||
IPv4Address* v4addr=dynamic_cast<IPv4Address*>(packet->address);
|
||||
if(v4addr){
|
||||
if(needUpdateNat64Prefix && !isV4Available && VoIPController::GetCurrentTime()>switchToV6at && switchToV6at!=0){
|
||||
LOGV("Updating NAT64 prefix");
|
||||
nat64Present=false;
|
||||
addrinfo* addr0;
|
||||
int res=getaddrinfo("ipv4only.arpa", NULL, NULL, &addr0);
|
||||
if(res!=0){
|
||||
LOGW("Error updating NAT64 prefix: %d / %s", res, gai_strerror(res));
|
||||
}else{
|
||||
addrinfo* addrPtr;
|
||||
unsigned char* addr170=NULL;
|
||||
unsigned char* addr171=NULL;
|
||||
for(addrPtr=addr0;addrPtr;addrPtr=addrPtr->ai_next){
|
||||
if(addrPtr->ai_family==AF_INET6){
|
||||
sockaddr_in6* translatedAddr=(sockaddr_in6*)addrPtr->ai_addr;
|
||||
uint32_t v4part=*((uint32_t*)&translatedAddr->sin6_addr.s6_addr[12]);
|
||||
if(v4part==0xAA0000C0 && !addr170){
|
||||
addr170=translatedAddr->sin6_addr.s6_addr;
|
||||
}
|
||||
if(v4part==0xAB0000C0 && !addr171){
|
||||
addr171=translatedAddr->sin6_addr.s6_addr;
|
||||
}
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
LOGV("Got translated address: %s", inet_ntop(AF_INET6, &translatedAddr->sin6_addr, buf, sizeof(buf)));
|
||||
}
|
||||
}
|
||||
if(addr170 && addr171 && memcmp(addr170, addr171, 12)==0){
|
||||
nat64Present=true;
|
||||
memcpy(nat64Prefix, addr170, 12);
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
LOGV("Found nat64 prefix from %s", inet_ntop(AF_INET6, addr170, buf, sizeof(buf)));
|
||||
}else{
|
||||
LOGV("Didn't find nat64");
|
||||
}
|
||||
freeaddrinfo(addr0);
|
||||
}
|
||||
needUpdateNat64Prefix=false;
|
||||
}
|
||||
memset(&addr, 0, sizeof(sockaddr_in6));
|
||||
addr.sin6_family=AF_INET6;
|
||||
*((uint32_t*)&addr.sin6_addr.s6_addr[12])=v4addr->GetAddress();
|
||||
if(nat64Present)
|
||||
memcpy(addr.sin6_addr.s6_addr, nat64Prefix, 12);
|
||||
else
|
||||
addr.sin6_addr.s6_addr[11]=addr.sin6_addr.s6_addr[10]=0xFF;
|
||||
|
||||
}else{
|
||||
IPv6Address* v6addr=dynamic_cast<IPv6Address*>(packet->address);
|
||||
assert(v6addr!=NULL);
|
||||
}
|
||||
addr.sin6_port=htons(packet->port);
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, &addr.sin6_addr, buf, sizeof(buf));
|
||||
int res=sendto(fd, packet->data, packet->length, 0, (const sockaddr *) &addr, sizeof(addr));
|
||||
if(res<0){
|
||||
LOGE("error sending: %d / %s", errno, strerror(errno));
|
||||
if(errno==ENETUNREACH && !isV4Available && VoIPController::GetCurrentTime()<switchToV6at){
|
||||
switchToV6at=VoIPController::GetCurrentTime();
|
||||
LOGI("Network unreachable, trying NAT64");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkSocketPosix::Receive(NetworkPacket *packet){
|
||||
int addrLen=sizeof(sockaddr_in6);
|
||||
sockaddr_in6 srcAddr;
|
||||
ssize_t len=recvfrom(fd, packet->data, packet->length, 0, (sockaddr *) &srcAddr, (socklen_t *) &addrLen);
|
||||
if(len>0)
|
||||
packet->length=(size_t) len;
|
||||
else{
|
||||
packet->length=0;
|
||||
return;
|
||||
}
|
||||
//LOGV("Received %d bytes from %s:%d at %.5lf", len, inet_ntoa(srcAddr.sin_addr), ntohs(srcAddr.sin_port), GetCurrentTime());
|
||||
if(!isV4Available && IN6_IS_ADDR_V4MAPPED(&srcAddr.sin6_addr)){
|
||||
isV4Available=true;
|
||||
LOGI("Detected IPv4 connectivity, will not try IPv6");
|
||||
}
|
||||
if(IN6_IS_ADDR_V4MAPPED(&srcAddr.sin6_addr) || (nat64Present && memcmp(nat64Prefix, srcAddr.sin6_addr.s6_addr, 12)==0)){
|
||||
in_addr v4addr=*((in_addr *) &srcAddr.sin6_addr.s6_addr[12]);
|
||||
lastRecvdV4=IPv4Address(v4addr.s_addr);
|
||||
packet->address=&lastRecvdV4;
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkSocketPosix::Open(){
|
||||
fd=socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if(fd<0){
|
||||
LOGE("error creating socket: %d / %s", errno, strerror(errno));
|
||||
}
|
||||
int flag=0;
|
||||
int res=setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag));
|
||||
if(res<0){
|
||||
LOGE("error enabling dual stack socket: %d / %s", errno, strerror(errno));
|
||||
}
|
||||
|
||||
SetMaxPriority();
|
||||
|
||||
int tries=0;
|
||||
sockaddr_in6 addr;
|
||||
//addr.sin6_addr.s_addr=0;
|
||||
memset(&addr, 0, sizeof(sockaddr_in6));
|
||||
//addr.sin6_len=sizeof(sa_family_t);
|
||||
addr.sin6_family=AF_INET6;
|
||||
for(tries=0;tries<10;tries++){
|
||||
addr.sin6_port=htons(GenerateLocalPort());
|
||||
res=::bind(fd, (sockaddr *) &addr, sizeof(sockaddr_in6));
|
||||
LOGV("trying bind to port %u", ntohs(addr.sin6_port));
|
||||
if(res<0){
|
||||
LOGE("error binding to port %u: %d / %s", ntohs(addr.sin6_port), errno, strerror(errno));
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(tries==10){
|
||||
addr.sin6_port=0;
|
||||
res=::bind(fd, (sockaddr *) &addr, sizeof(sockaddr_in6));
|
||||
if(res<0){
|
||||
LOGE("error binding to port %u: %d / %s", ntohs(addr.sin6_port), errno, strerror(errno));
|
||||
//SetState(STATE_FAILED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
size_t addrLen=sizeof(sockaddr_in6);
|
||||
getsockname(fd, (sockaddr*)&addr, (socklen_t*) &addrLen);
|
||||
uint16_t localUdpPort=ntohs(addr.sin6_port);
|
||||
LOGD("Bound to local UDP port %u", ntohs(addr.sin6_port));
|
||||
|
||||
needUpdateNat64Prefix=true;
|
||||
isV4Available=false;
|
||||
switchToV6at=VoIPController::GetCurrentTime()+ipv6Timeout;
|
||||
}
|
||||
|
||||
void NetworkSocketPosix::Close(){
|
||||
shutdown(fd, SHUT_RDWR);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void NetworkSocketPosix::OnActiveInterfaceChanged(){
|
||||
needUpdateNat64Prefix=true;
|
||||
isV4Available=false;
|
||||
switchToV6at=VoIPController::GetCurrentTime()+ipv6Timeout;
|
||||
}
|
||||
|
||||
std::string NetworkSocketPosix::GetLocalInterfaceInfo(IPv4Address *v4addr, IPv6Address *v6addr){
|
||||
struct ifconf ifc;
|
||||
struct ifreq* ifr;
|
||||
char buf[16384];
|
||||
int sd;
|
||||
std::string name="";
|
||||
sd=socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if(sd>0){
|
||||
ifc.ifc_len=sizeof(buf);
|
||||
ifc.ifc_ifcu.ifcu_buf=buf;
|
||||
if(ioctl(sd, SIOCGIFCONF, &ifc)==0){
|
||||
ifr=ifc.ifc_req;
|
||||
int len;
|
||||
int i;
|
||||
for(i=0;i<ifc.ifc_len;){
|
||||
#ifndef __linux__
|
||||
len=IFNAMSIZ + ifr->ifr_addr.sa_len;
|
||||
#else
|
||||
len=sizeof(*ifr);
|
||||
#endif
|
||||
if(ifr->ifr_addr.sa_family==AF_INET){
|
||||
if(ioctl(sd, SIOCGIFADDR, ifr)==0){
|
||||
struct sockaddr_in* addr=(struct sockaddr_in *)(&ifr->ifr_addr);
|
||||
LOGI("Interface %s, address %s\n", ifr->ifr_name, inet_ntoa(addr->sin_addr));
|
||||
if(ioctl(sd, SIOCGIFFLAGS, ifr)==0){
|
||||
if(!(ifr->ifr_flags & IFF_LOOPBACK) && (ifr->ifr_flags & IFF_UP) && (ifr->ifr_flags & IFF_RUNNING)){
|
||||
//LOGV("flags = %08X", ifr->ifr_flags);
|
||||
if((ntohl(addr->sin_addr.s_addr) & 0xFFFF0000)==0xA9FE0000){
|
||||
LOGV("skipping link-local");
|
||||
continue;
|
||||
}
|
||||
if(v4addr){
|
||||
*v4addr=IPv4Address(addr->sin_addr.s_addr);
|
||||
}
|
||||
name=ifr->ifr_name;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
LOGE("Error getting address for %s: %d\n", ifr->ifr_name, errno);
|
||||
}
|
||||
}
|
||||
ifr=(struct ifreq*)((char*)ifr+len);
|
||||
i+=len;
|
||||
}
|
||||
}else{
|
||||
LOGE("Error getting LAN address: %d", errno);
|
||||
}
|
||||
}
|
||||
close(sd);
|
||||
return name;
|
||||
}
|
||||
|
||||
uint16_t NetworkSocketPosix::GetLocalPort(){
|
||||
sockaddr_in6 addr;
|
||||
size_t addrLen=sizeof(sockaddr_in6);
|
||||
getsockname(fd, (sockaddr*)&addr, (socklen_t*) &addrLen);
|
||||
return ntohs(addr.sin6_port);
|
||||
}
|
||||
|
||||
std::string NetworkSocketPosix::V4AddressToString(uint32_t address){
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
in_addr addr;
|
||||
addr.s_addr=address;
|
||||
inet_ntop(AF_INET, &addr, buf, sizeof(buf));
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
std::string NetworkSocketPosix::V6AddressToString(unsigned char *address){
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
in6_addr addr;
|
||||
memcpy(addr.s6_addr, address, 16);
|
||||
inet_ntop(AF_INET6, &addr, buf, sizeof(buf));
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
uint32_t NetworkSocketPosix::StringToV4Address(std::string address){
|
||||
in_addr addr;
|
||||
inet_pton(AF_INET, address.c_str(), &addr);
|
||||
return addr.s_addr;
|
||||
}
|
||||
|
||||
void NetworkSocketPosix::StringToV6Address(std::string address, unsigned char *out){
|
||||
in6_addr addr;
|
||||
inet_pton(AF_INET6, address.c_str(), &addr);
|
||||
memcpy(out, addr.s6_addr, 16);
|
||||
}
|
44
os/posix/NetworkSocketPosix.h
Normal file
44
os/posix/NetworkSocketPosix.h
Normal file
@ -0,0 +1,44 @@
|
||||
//
|
||||
// Created by Grishka on 10.04.17.
|
||||
//
|
||||
|
||||
#ifndef LIBTGVOIP_NETWORKSOCKETPOSIX_H
|
||||
#define LIBTGVOIP_NETWORKSOCKETPOSIX_H
|
||||
|
||||
#include "../../NetworkSocket.h"
|
||||
|
||||
namespace tgvoip {
|
||||
|
||||
class NetworkSocketPosix : public NetworkSocket{
|
||||
public:
|
||||
NetworkSocketPosix();
|
||||
virtual ~NetworkSocketPosix();
|
||||
virtual void Send(NetworkPacket* packet);
|
||||
virtual void Receive(NetworkPacket* packet);
|
||||
virtual void Open();
|
||||
virtual void Close();
|
||||
virtual std::string GetLocalInterfaceInfo(IPv4Address* v4addr, IPv6Address* v6addr);
|
||||
virtual void OnActiveInterfaceChanged();
|
||||
virtual uint16_t GetLocalPort();
|
||||
|
||||
static std::string V4AddressToString(uint32_t address);
|
||||
static std::string V6AddressToString(unsigned char address[16]);
|
||||
static uint32_t StringToV4Address(std::string address);
|
||||
static void StringToV6Address(std::string address, unsigned char* out);
|
||||
|
||||
protected:
|
||||
virtual void SetMaxPriority();
|
||||
|
||||
private:
|
||||
int fd;
|
||||
bool needUpdateNat64Prefix;
|
||||
bool nat64Present;
|
||||
double switchToV6at;
|
||||
bool isV4Available;
|
||||
IPv4Address lastRecvdV4;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //LIBTGVOIP_NETWORKSOCKETPOSIX_H
|
91
os/windows/AudioInputWave.cpp
Normal file
91
os/windows/AudioInputWave.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
//
|
||||
// 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "AudioInputWave.h"
|
||||
#include "../../logging.h"
|
||||
|
||||
using namespace tgvoip::audio;
|
||||
|
||||
#define BUFFER_SIZE 960
|
||||
#define CHECK_ERROR(res, msg) if(res!=MMSYSERR_NOERROR){wchar_t _buf[1024]; waveInGetErrorTextW(res, _buf, 1024); LOGE(msg ": %ws (MMRESULT=0x08X)", _buf, res); failed=true;}
|
||||
|
||||
AudioInputWave::AudioInputWave(){
|
||||
isRecording=false;
|
||||
|
||||
for(int i=0;i<4;i++){
|
||||
ZeroMemory(&buffers[i], sizeof(WAVEHDR));
|
||||
buffers[i].dwBufferLength=960*2;
|
||||
buffers[i].lpData=(char*)malloc(960*2);
|
||||
}
|
||||
|
||||
ZeroMemory(&format, sizeof(format));
|
||||
format.cbSize=0;
|
||||
format.wFormatTag=WAVE_FORMAT_PCM;
|
||||
format.nSamplesPerSec=48000;
|
||||
format.wBitsPerSample=16;
|
||||
format.nChannels=1;
|
||||
format.nBlockAlign=2;
|
||||
|
||||
MMRESULT res=waveInOpen(&hWaveIn, WAVE_MAPPER, &format, (DWORD_PTR)AudioInputWave::WaveInProc, (DWORD_PTR)this, CALLBACK_FUNCTION);
|
||||
CHECK_ERROR(res, "waveInOpen failed");
|
||||
}
|
||||
|
||||
AudioInputWave::~AudioInputWave(){
|
||||
for(int i=0;i<4;i++){
|
||||
free(buffers[i].lpData);
|
||||
}
|
||||
waveInClose(hWaveIn);
|
||||
}
|
||||
|
||||
void AudioInputWave::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
|
||||
}
|
||||
|
||||
void AudioInputWave::Start(){
|
||||
isRecording=true;
|
||||
|
||||
MMRESULT res;
|
||||
for(int i=0;i<4;i++){
|
||||
res=waveInPrepareHeader(hWaveIn, &buffers[i], sizeof(WAVEHDR));
|
||||
CHECK_ERROR(res, "waveInPrepareHeader failed");
|
||||
res=waveInAddBuffer(hWaveIn, &buffers[i], sizeof(WAVEHDR));
|
||||
CHECK_ERROR(res, "waveInAddBuffer failed");
|
||||
}
|
||||
res=waveInStart(hWaveIn);
|
||||
CHECK_ERROR(res, "waveInStart failed");
|
||||
}
|
||||
|
||||
void AudioInputWave::Stop(){
|
||||
isRecording=false;
|
||||
|
||||
MMRESULT res=waveInStop(hWaveIn);
|
||||
CHECK_ERROR(res, "waveInStop failed");
|
||||
res=waveInReset(hWaveIn);
|
||||
CHECK_ERROR(res, "waveInReset failed");
|
||||
for(int i=0;i<4;i++){
|
||||
res=waveInUnprepareHeader(hWaveIn, &buffers[i], sizeof(WAVEHDR));
|
||||
CHECK_ERROR(res, "waveInUnprepareHeader failed");
|
||||
}
|
||||
}
|
||||
|
||||
void AudioInputWave::WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2){
|
||||
if(uMsg==WIM_DATA){
|
||||
((AudioInputWave*)dwInstance)->OnData((WAVEHDR*)dwParam1);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioInputWave::OnData(WAVEHDR* hdr){
|
||||
if(!isRecording)
|
||||
return;
|
||||
|
||||
InvokeCallback((unsigned char*)hdr->lpData, hdr->dwBufferLength);
|
||||
hdr->dwFlags&= ~WHDR_DONE;
|
||||
MMRESULT res=waveInAddBuffer(hWaveIn, hdr, sizeof(WAVEHDR));
|
||||
CHECK_ERROR(res, "waveInAddBuffer failed");
|
||||
}
|
37
os/windows/AudioInputWave.h
Normal file
37
os/windows/AudioInputWave.h
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// 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_AUDIOINPUTWAVE_H
|
||||
#define LIBTGVOIP_AUDIOINPUTWAVE_H
|
||||
|
||||
#include <windows.h>
|
||||
#include "../../audio/AudioInput.h"
|
||||
|
||||
namespace tgvoip{
|
||||
namespace audio{
|
||||
|
||||
class AudioInputWave : public CAudioInput{
|
||||
|
||||
public:
|
||||
AudioInputWave();
|
||||
virtual ~AudioInputWave();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
|
||||
private:
|
||||
static void CALLBACK WaveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
|
||||
void OnData(WAVEHDR* hdr);
|
||||
HWAVEIN hWaveIn;
|
||||
WAVEFORMATEX format;
|
||||
WAVEHDR buffers[4];
|
||||
bool isRecording;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //LIBTGVOIP_AUDIOINPUTWAVE_H
|
90
os/windows/AudioOutputWave.cpp
Normal file
90
os/windows/AudioOutputWave.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
//
|
||||
// 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 <assert.h>
|
||||
#include "AudioOutputWave.h"
|
||||
#include "../../logging.h"
|
||||
|
||||
#define BUFFER_SIZE 960
|
||||
#define CHECK_ERROR(res, msg) if(res!=MMSYSERR_NOERROR){wchar_t _buf[1024]; waveOutGetErrorTextW(res, _buf, 1024); LOGE(msg ": %ws (MMRESULT=0x08X)", _buf, res); failed=true;}
|
||||
|
||||
using namespace tgvoip::audio;
|
||||
|
||||
AudioOutputWave::AudioOutputWave(){
|
||||
isPlaying=false;
|
||||
|
||||
for(int i=0;i<4;i++){
|
||||
ZeroMemory(&buffers[i], sizeof(WAVEHDR));
|
||||
buffers[i].dwBufferLength=960*2;
|
||||
buffers[i].lpData=(char*)malloc(960*2);
|
||||
}
|
||||
|
||||
ZeroMemory(&format, sizeof(format));
|
||||
format.cbSize=0;
|
||||
format.wFormatTag=WAVE_FORMAT_PCM;
|
||||
format.nSamplesPerSec=48000;
|
||||
format.wBitsPerSample=16;
|
||||
format.nChannels=1;
|
||||
format.nBlockAlign=2;
|
||||
|
||||
MMRESULT res=waveOutOpen(&hWaveOut, WAVE_MAPPER, &format, (DWORD_PTR)AudioOutputWave::WaveOutProc, (DWORD_PTR)this, CALLBACK_FUNCTION);
|
||||
CHECK_ERROR(res, "waveOutOpen failed");
|
||||
}
|
||||
|
||||
AudioOutputWave::~AudioOutputWave(){
|
||||
for(int i=0;i<4;i++){
|
||||
free(buffers[i].lpData);
|
||||
}
|
||||
waveOutClose(hWaveOut);
|
||||
}
|
||||
|
||||
void AudioOutputWave::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
|
||||
|
||||
}
|
||||
|
||||
void AudioOutputWave::Start(){
|
||||
isPlaying=true;
|
||||
|
||||
for(int i=0;i<4;i++){
|
||||
MMRESULT res=waveOutPrepareHeader(hWaveOut, &buffers[i], sizeof(WAVEHDR));
|
||||
CHECK_ERROR(res, "waveOutPrepareHeader failed");
|
||||
//InvokeCallback((unsigned char*)buffers[i].lpData, buffers[i].dwBufferLength);
|
||||
ZeroMemory(buffers[i].lpData, buffers[i].dwBufferLength);
|
||||
res=waveOutWrite(hWaveOut, &buffers[i], sizeof(WAVEHDR));
|
||||
CHECK_ERROR(res, "waveOutWrite failed");
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOutputWave::Stop(){
|
||||
isPlaying=false;
|
||||
|
||||
MMRESULT res=waveOutReset(hWaveOut);
|
||||
CHECK_ERROR(res, "waveOutReset failed");
|
||||
for(int i=0;i<4;i++){
|
||||
res=waveOutUnprepareHeader(hWaveOut, &buffers[i], sizeof(WAVEHDR));
|
||||
CHECK_ERROR(res, "waveOutUnprepareHeader failed");
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioOutputWave::IsPlaying(){
|
||||
return isPlaying;
|
||||
}
|
||||
|
||||
void AudioOutputWave::WaveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) {
|
||||
if(uMsg==WOM_DONE){
|
||||
((AudioOutputWave*)dwInstance)->OnBufferDone((WAVEHDR*)dwParam1);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOutputWave::OnBufferDone(WAVEHDR* hdr){
|
||||
if(!isPlaying)
|
||||
return;
|
||||
|
||||
InvokeCallback((unsigned char*)hdr->lpData, hdr->dwBufferLength);
|
||||
hdr->dwFlags&= ~WHDR_DONE;
|
||||
MMRESULT res=waveOutWrite(hWaveOut, hdr, sizeof(WAVEHDR));
|
||||
}
|
37
os/windows/AudioOutputWave.h
Normal file
37
os/windows/AudioOutputWave.h
Normal file
@ -0,0 +1,37 @@
|
||||
//
|
||||
// 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_AUDIOOUTPUTWAVE_H
|
||||
#define LIBTGVOIP_AUDIOOUTPUTWAVE_H
|
||||
|
||||
#include <windows.h>
|
||||
#include "../../audio/AudioOutput.h"
|
||||
|
||||
namespace tgvoip{
|
||||
namespace audio{
|
||||
|
||||
class AudioOutputWave : public CAudioOutput{
|
||||
public:
|
||||
AudioOutputWave();
|
||||
virtual ~AudioOutputWave();
|
||||
virtual void Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels);
|
||||
virtual void Start();
|
||||
virtual void Stop();
|
||||
virtual bool IsPlaying();
|
||||
|
||||
private:
|
||||
HWAVEOUT hWaveOut;
|
||||
WAVEFORMATEX format;
|
||||
WAVEHDR buffers[4];
|
||||
static void CALLBACK WaveOutProc(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
|
||||
void OnBufferDone(WAVEHDR* hdr);
|
||||
bool isPlaying;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif //LIBTGVOIP_AUDIOOUTPUTWAVE_H
|
375
os/windows/NetworkSocketWinsock.cpp
Normal file
375
os/windows/NetworkSocketWinsock.cpp
Normal file
@ -0,0 +1,375 @@
|
||||
//
|
||||
// Created by Grishka on 10.04.17.
|
||||
//
|
||||
|
||||
#include "NetworkSocketWinsock.h"
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <IPHlpApi.h>
|
||||
#include <assert.h>
|
||||
#include "../../logging.h"
|
||||
#include "../../VoIPController.h"
|
||||
|
||||
using namespace tgvoip;
|
||||
|
||||
NetworkSocketWinsock::NetworkSocketWinsock() : lastRecvdV4(0){
|
||||
needUpdateNat64Prefix=true;
|
||||
nat64Present=false;
|
||||
switchToV6at=0;
|
||||
isV4Available=false;
|
||||
|
||||
DWORD version=GetVersion();
|
||||
isAtLeastVista=LOBYTE(LOWORD(version))>=6; // Vista is 6.0, XP is 5.1 and 5.2
|
||||
|
||||
WSADATA wsaData;
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
LOGD("Initialized winsock, version %d.%d", wsaData.wHighVersion, wsaData.wVersion);
|
||||
}
|
||||
|
||||
NetworkSocketWinsock::~NetworkSocketWinsock(){
|
||||
|
||||
}
|
||||
|
||||
void NetworkSocketWinsock::SetMaxPriority(){
|
||||
|
||||
}
|
||||
|
||||
void NetworkSocketWinsock::Send(NetworkPacket *packet){
|
||||
sockaddr_in6 addr;
|
||||
IPv4Address* v4addr=dynamic_cast<IPv4Address*>(packet->address);
|
||||
if(v4addr){
|
||||
if(!isAtLeastVista){
|
||||
sockaddr_in _addr;
|
||||
_addr.sin_family=AF_INET;
|
||||
_addr.sin_addr.s_addr=v4addr->GetAddress();
|
||||
_addr.sin_port=htons(packet->port);
|
||||
int res=sendto(fd, (char*)packet->data, packet->length, 0, (sockaddr*)&_addr, sizeof(_addr));
|
||||
if(res==SOCKET_ERROR){
|
||||
int error=WSAGetLastError();
|
||||
LOGE("error sending: %d", error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(needUpdateNat64Prefix && !isV4Available && VoIPController::GetCurrentTime()>switchToV6at && switchToV6at!=0){
|
||||
LOGV("Updating NAT64 prefix");
|
||||
nat64Present=false;
|
||||
addrinfo* addr0;
|
||||
int res=getaddrinfo("ipv4only.arpa", NULL, NULL, &addr0);
|
||||
if(res!=0){
|
||||
LOGW("Error updating NAT64 prefix: %d / %s", res, gai_strerror(res));
|
||||
}else{
|
||||
addrinfo* addrPtr;
|
||||
unsigned char* addr170=NULL;
|
||||
unsigned char* addr171=NULL;
|
||||
for(addrPtr=addr0;addrPtr;addrPtr=addrPtr->ai_next){
|
||||
if(addrPtr->ai_family==AF_INET6){
|
||||
sockaddr_in6* translatedAddr=(sockaddr_in6*)addrPtr->ai_addr;
|
||||
uint32_t v4part=*((uint32_t*)&translatedAddr->sin6_addr.s6_addr[12]);
|
||||
if(v4part==0xAA0000C0 && !addr170){
|
||||
addr170=translatedAddr->sin6_addr.s6_addr;
|
||||
}
|
||||
if(v4part==0xAB0000C0 && !addr171){
|
||||
addr171=translatedAddr->sin6_addr.s6_addr;
|
||||
}
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
//LOGV("Got translated address: %s", inet_ntop(AF_INET6, &translatedAddr->sin6_addr, buf, sizeof(buf)));
|
||||
}
|
||||
}
|
||||
if(addr170 && addr171 && memcmp(addr170, addr171, 12)==0){
|
||||
nat64Present=true;
|
||||
memcpy(nat64Prefix, addr170, 12);
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
//LOGV("Found nat64 prefix from %s", inet_ntop(AF_INET6, addr170, buf, sizeof(buf)));
|
||||
}else{
|
||||
LOGV("Didn't find nat64");
|
||||
}
|
||||
freeaddrinfo(addr0);
|
||||
}
|
||||
needUpdateNat64Prefix=false;
|
||||
}
|
||||
memset(&addr, 0, sizeof(sockaddr_in6));
|
||||
addr.sin6_family=AF_INET6;
|
||||
*((uint32_t*)&addr.sin6_addr.s6_addr[12])=v4addr->GetAddress();
|
||||
if(nat64Present)
|
||||
memcpy(addr.sin6_addr.s6_addr, nat64Prefix, 12);
|
||||
else
|
||||
addr.sin6_addr.s6_addr[11]=addr.sin6_addr.s6_addr[10]=0xFF;
|
||||
|
||||
}else{
|
||||
IPv6Address* v6addr=dynamic_cast<IPv6Address*>(packet->address);
|
||||
assert(v6addr!=NULL);
|
||||
if(!isAtLeastVista){
|
||||
return;
|
||||
}
|
||||
}
|
||||
addr.sin6_port=htons(packet->port);
|
||||
|
||||
//WSABUF wsaBuf;
|
||||
//wsaBuf.buf=(char*) packet->data;
|
||||
//wsaBuf.len=packet->length;
|
||||
//int res=WSASendTo(fd, &wsaBuf, 1, NULL, 0, (const sockaddr*)&addr, sizeof(addr), NULL, NULL);
|
||||
int res=sendto(fd, (char*)packet->data, packet->length, 0, (sockaddr*)&addr, sizeof(addr));
|
||||
if(res==SOCKET_ERROR){
|
||||
int error=WSAGetLastError();
|
||||
LOGE("error sending: %d", error);
|
||||
if(error==WSAENETUNREACH && !isV4Available && VoIPController::GetCurrentTime()<switchToV6at){
|
||||
switchToV6at=VoIPController::GetCurrentTime();
|
||||
LOGI("Network unreachable, trying NAT64");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkSocketWinsock::Receive(NetworkPacket *packet){
|
||||
sockaddr_in6 srcAddr;
|
||||
sockaddr_in srcAddr4;
|
||||
sockaddr* addr;
|
||||
int addrLen;
|
||||
if(isAtLeastVista){
|
||||
addr=(sockaddr*)&srcAddr;
|
||||
addrLen=sizeof(srcAddr);
|
||||
}else{
|
||||
addr=(sockaddr*)&srcAddr4;
|
||||
addrLen=sizeof(srcAddr4);
|
||||
}
|
||||
//DWORD len;
|
||||
//WSABUF buf;
|
||||
//buf.buf=(char*) packet->data;
|
||||
//buf.len=packet->length;
|
||||
//int res=WSARecvFrom(fd, &buf, 1, &len, 0, (sockaddr*) &srcAddr, &addrLen, NULL, NULL);
|
||||
int res=recvfrom(fd, (char*)packet->data, packet->length, 0, addr, &addrLen);
|
||||
if(res!=SOCKET_ERROR)
|
||||
packet->length=(size_t) res;
|
||||
else{
|
||||
packet->length=0;
|
||||
int error=WSAGetLastError();
|
||||
LOGE("error receiving: %d", error);
|
||||
return;
|
||||
}
|
||||
//LOGV("Received %d bytes from %s:%d at %.5lf", len, inet_ntoa(srcAddr.sin_addr), ntohs(srcAddr.sin_port), GetCurrentTime());
|
||||
if(addr->sa_family==AF_INET){
|
||||
packet->port=srcAddr4.sin_port;
|
||||
lastRecvdV4=IPv4Address(srcAddr4.sin_addr.s_addr);
|
||||
packet->address=&lastRecvdV4;
|
||||
}else{
|
||||
packet->port=srcAddr.sin6_port;
|
||||
if(!isV4Available && IN6_IS_ADDR_V4MAPPED(&srcAddr.sin6_addr)){
|
||||
isV4Available=true;
|
||||
LOGI("Detected IPv4 connectivity, will not try IPv6");
|
||||
}
|
||||
if(IN6_IS_ADDR_V4MAPPED(&srcAddr.sin6_addr) || (nat64Present && memcmp(nat64Prefix, srcAddr.sin6_addr.s6_addr, 12)==0)){
|
||||
in_addr v4addr=*((in_addr *)&srcAddr.sin6_addr.s6_addr[12]);
|
||||
lastRecvdV4=IPv4Address(v4addr.s_addr);
|
||||
packet->address=&lastRecvdV4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkSocketWinsock::Open(){
|
||||
fd=socket(isAtLeastVista ? AF_INET6 : AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if(fd==INVALID_SOCKET){
|
||||
int error=WSAGetLastError();
|
||||
LOGE("error creating socket: %d", error);
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
|
||||
int res;
|
||||
if(isAtLeastVista){
|
||||
DWORD flag=0;
|
||||
res=setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&flag, sizeof(flag));
|
||||
if(res==SOCKET_ERROR){
|
||||
LOGE("error enabling dual stack socket: %d", WSAGetLastError());
|
||||
failed=true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetMaxPriority();
|
||||
|
||||
int tries=0;
|
||||
sockaddr* addr;
|
||||
sockaddr_in addr4;
|
||||
sockaddr_in6 addr6;
|
||||
int addrLen;
|
||||
if(isAtLeastVista){
|
||||
//addr.sin6_addr.s_addr=0;
|
||||
memset(&addr6, 0, sizeof(sockaddr_in6));
|
||||
//addr.sin6_len=sizeof(sa_family_t);
|
||||
addr6.sin6_family=AF_INET6;
|
||||
addr=(sockaddr*)&addr6;
|
||||
addrLen=sizeof(addr6);
|
||||
}else{
|
||||
sockaddr_in addr4;
|
||||
addr4.sin_addr.s_addr=0;
|
||||
addr4.sin_family=AF_INET;
|
||||
addr=(sockaddr*)&addr4;
|
||||
addrLen=sizeof(addr4);
|
||||
}
|
||||
for(tries=0;tries<10;tries++){
|
||||
uint16_t port=htons(GenerateLocalPort());
|
||||
if(isAtLeastVista)
|
||||
((sockaddr_in6*)addr)->sin6_port=port;
|
||||
else
|
||||
((sockaddr_in*)addr)->sin_port=port;
|
||||
res=::bind(fd, addr, addrLen);
|
||||
LOGV("trying bind to port %u", ntohs(port));
|
||||
if(res<0){
|
||||
LOGE("error binding to port %u: %d / %s", ntohs(port), errno, strerror(errno));
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(tries==10){
|
||||
if(isAtLeastVista)
|
||||
((sockaddr_in6*)addr)->sin6_port=0;
|
||||
else
|
||||
((sockaddr_in*)addr)->sin_port=0;
|
||||
res=::bind(fd, addr, addrLen);
|
||||
if(res<0){
|
||||
LOGE("error binding to port %u: %d / %s", 0, errno, strerror(errno));
|
||||
//SetState(STATE_FAILED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
getsockname(fd, addr, (socklen_t*) &addrLen);
|
||||
uint16_t localUdpPort;
|
||||
if(isAtLeastVista)
|
||||
localUdpPort=ntohs(((sockaddr_in6*)addr)->sin6_port);
|
||||
else
|
||||
localUdpPort=ntohs(((sockaddr_in*)addr)->sin_port);
|
||||
LOGD("Bound to local UDP port %u", ntohs(localUdpPort));
|
||||
|
||||
needUpdateNat64Prefix=true;
|
||||
isV4Available=false;
|
||||
switchToV6at=VoIPController::GetCurrentTime()+ipv6Timeout;
|
||||
}
|
||||
|
||||
void NetworkSocketWinsock::Close(){
|
||||
closesocket(fd);
|
||||
}
|
||||
|
||||
void NetworkSocketWinsock::OnActiveInterfaceChanged(){
|
||||
needUpdateNat64Prefix=true;
|
||||
isV4Available=false;
|
||||
switchToV6at=VoIPController::GetCurrentTime()+ipv6Timeout;
|
||||
}
|
||||
|
||||
std::string NetworkSocketWinsock::GetLocalInterfaceInfo(IPv4Address *v4addr, IPv6Address *v6addr){
|
||||
IP_ADAPTER_ADDRESSES* addrs=(IP_ADAPTER_ADDRESSES*)malloc(15*1024);
|
||||
ULONG size=15*1024;
|
||||
ULONG flags=GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME;
|
||||
|
||||
ULONG res=GetAdaptersAddresses(AF_UNSPEC, flags, NULL, addrs, &size);
|
||||
if(res==ERROR_BUFFER_OVERFLOW){
|
||||
addrs=(IP_ADAPTER_ADDRESSES*)realloc(addrs, size);
|
||||
res=GetAdaptersAddresses(AF_UNSPEC, flags, NULL, addrs, &size);
|
||||
}
|
||||
|
||||
ULONG bestMetric=0;
|
||||
std::string bestName("");
|
||||
|
||||
if(res==ERROR_SUCCESS){
|
||||
IP_ADAPTER_ADDRESSES* current=addrs;
|
||||
while(current){
|
||||
char* name=current->AdapterName;
|
||||
LOGV("Adapter '%s':", name);
|
||||
IP_ADAPTER_UNICAST_ADDRESS* curAddr=current->FirstUnicastAddress;
|
||||
if(current->OperStatus!=IfOperStatusUp){
|
||||
LOGV("-> (down)");
|
||||
current=current->Next;
|
||||
continue;
|
||||
}
|
||||
if(current->IfType==IF_TYPE_SOFTWARE_LOOPBACK){
|
||||
LOGV("-> (loopback)");
|
||||
current=current->Next;
|
||||
continue;
|
||||
}
|
||||
if(isAtLeastVista)
|
||||
LOGV("v4 metric: %u, v6 metric: %u", current->Ipv4Metric, current->Ipv6Metric);
|
||||
while(curAddr){
|
||||
sockaddr* addr=curAddr->Address.lpSockaddr;
|
||||
if(addr->sa_family==AF_INET && v4addr){
|
||||
sockaddr_in* ipv4=(sockaddr_in*)addr;
|
||||
LOGV("-> V4: %s", V4AddressToString(ipv4->sin_addr.s_addr).c_str());
|
||||
uint32_t ip=ntohl(ipv4->sin_addr.s_addr);
|
||||
if((ip & 0xFFFF0000)!=0xA9FE0000){
|
||||
if(isAtLeastVista){
|
||||
if(current->Ipv4Metric>bestMetric){
|
||||
bestMetric=current->Ipv4Metric;
|
||||
bestName=std::string(current->AdapterName);
|
||||
*v4addr=IPv4Address(ipv4->sin_addr.s_addr);
|
||||
}
|
||||
}else{
|
||||
bestName=std::string(current->AdapterName);
|
||||
*v4addr=IPv4Address(ipv4->sin_addr.s_addr);
|
||||
}
|
||||
}
|
||||
}else if(addr->sa_family==AF_INET6 && v6addr){
|
||||
sockaddr_in6* ipv6=(sockaddr_in6*)addr;
|
||||
LOGV("-> V6: %s", V6AddressToString(ipv6->sin6_addr.s6_addr).c_str());
|
||||
if(!IN6_IS_ADDR_LINKLOCAL(&ipv6->sin6_addr)){
|
||||
*v6addr=IPv6Address(ipv6->sin6_addr.s6_addr);
|
||||
}
|
||||
}
|
||||
curAddr=curAddr->Next;
|
||||
}
|
||||
current=current->Next;
|
||||
}
|
||||
}
|
||||
|
||||
free(addrs);
|
||||
return bestName;
|
||||
}
|
||||
|
||||
uint16_t NetworkSocketWinsock::GetLocalPort(){
|
||||
if(!isAtLeastVista){
|
||||
sockaddr_in addr;
|
||||
size_t addrLen=sizeof(sockaddr_in);
|
||||
getsockname(fd, (sockaddr*)&addr, (socklen_t*)&addrLen);
|
||||
return ntohs(addr.sin_port);
|
||||
}
|
||||
sockaddr_in6 addr;
|
||||
size_t addrLen=sizeof(sockaddr_in6);
|
||||
getsockname(fd, (sockaddr*)&addr, (socklen_t*) &addrLen);
|
||||
return ntohs(addr.sin6_port);
|
||||
}
|
||||
|
||||
std::string NetworkSocketWinsock::V4AddressToString(uint32_t address){
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
sockaddr_in addr;
|
||||
ZeroMemory(&addr, sizeof(addr));
|
||||
addr.sin_family=AF_INET;
|
||||
addr.sin_addr.s_addr=address;
|
||||
DWORD len=sizeof(buf);
|
||||
WSAAddressToStringA((sockaddr*)&addr, sizeof(addr), NULL, buf, &len);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
std::string NetworkSocketWinsock::V6AddressToString(unsigned char *address){
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
sockaddr_in6 addr;
|
||||
ZeroMemory(&addr, sizeof(addr));
|
||||
addr.sin6_family=AF_INET6;
|
||||
memcpy(addr.sin6_addr.s6_addr, address, 16);
|
||||
DWORD len=sizeof(buf);
|
||||
WSAAddressToStringA((sockaddr*)&addr, sizeof(addr), NULL, buf, &len);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
uint32_t NetworkSocketWinsock::StringToV4Address(std::string address){
|
||||
sockaddr_in addr;
|
||||
ZeroMemory(&addr, sizeof(addr));
|
||||
addr.sin_family=AF_INET;
|
||||
int size=sizeof(addr);
|
||||
WSAStringToAddressA((char*)address.c_str(), AF_INET, NULL, (sockaddr*)&addr, &size);
|
||||
return addr.sin_addr.s_addr;
|
||||
}
|
||||
|
||||
void NetworkSocketWinsock::StringToV6Address(std::string address, unsigned char *out){
|
||||
sockaddr_in6 addr;
|
||||
ZeroMemory(&addr, sizeof(addr));
|
||||
addr.sin6_family=AF_INET6;
|
||||
int size=sizeof(addr);
|
||||
WSAStringToAddressA((char*)address.c_str(), AF_INET6, NULL, (sockaddr*)&addr, &size);
|
||||
memcpy(out, addr.sin6_addr.s6_addr, 16);
|
||||
}
|
46
os/windows/NetworkSocketWinsock.h
Normal file
46
os/windows/NetworkSocketWinsock.h
Normal file
@ -0,0 +1,46 @@
|
||||
//
|
||||
// Created by Grishka on 10.04.17.
|
||||
//
|
||||
|
||||
#ifndef LIBTGVOIP_NETWORKSOCKETWINSOCK_H
|
||||
#define LIBTGVOIP_NETWORKSOCKETWINSOCK_H
|
||||
|
||||
#include "../../NetworkSocket.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace tgvoip {
|
||||
|
||||
class NetworkSocketWinsock : public NetworkSocket{
|
||||
public:
|
||||
NetworkSocketWinsock();
|
||||
virtual ~NetworkSocketWinsock();
|
||||
virtual void Send(NetworkPacket* packet);
|
||||
virtual void Receive(NetworkPacket* packet);
|
||||
virtual void Open();
|
||||
virtual void Close();
|
||||
virtual std::string GetLocalInterfaceInfo(IPv4Address* v4addr, IPv6Address* v6addr);
|
||||
virtual void OnActiveInterfaceChanged();
|
||||
virtual uint16_t GetLocalPort();
|
||||
|
||||
static std::string V4AddressToString(uint32_t address);
|
||||
static std::string V6AddressToString(unsigned char address[16]);
|
||||
static uint32_t StringToV4Address(std::string address);
|
||||
static void StringToV6Address(std::string address, unsigned char* out);
|
||||
|
||||
protected:
|
||||
virtual void SetMaxPriority();
|
||||
|
||||
private:
|
||||
uintptr_t fd;
|
||||
bool needUpdateNat64Prefix;
|
||||
bool nat64Present;
|
||||
double switchToV6at;
|
||||
bool isV4Available;
|
||||
IPv4Address lastRecvdV4;
|
||||
bool isAtLeastVista;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //LIBTGVOIP_NETWORKSOCKETWINSOCK_H
|
27
threading.h
27
threading.h
@ -35,6 +35,33 @@ typedef pthread_cond_t tgvoip_lock_t;
|
||||
#define wait_lock(lock, mutex) pthread_cond_wait(&lock, &mutex)
|
||||
#define notify_lock(lock) pthread_cond_broadcast(&lock)
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
#include <Windows.h>
|
||||
typedef HANDLE tgvoip_thread_t;
|
||||
typedef CRITICAL_SECTION tgvoip_mutex_t;
|
||||
typedef HANDLE tgvoip_lock_t; // uncomment for XP compatibility
|
||||
//typedef CONDITION_VARIABLE tgvoip_lock_t;
|
||||
|
||||
#define start_thread(ref, entry, arg) (ref=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)entry, arg, 0, NULL))
|
||||
#define join_thread(thread) {WaitForSingleObject(thread, INFINITE); CloseHandle(thread);}
|
||||
#define set_thread_name(thread, name) // threads in Windows don't have names
|
||||
#define set_thread_priority(thread, priority) SetThreadPriority(thread, priority)
|
||||
#define get_thread_max_priority() THREAD_PRIORITY_HIGHEST
|
||||
#define get_thread_min_priority() THREAD_PRIORITY_LOWEST
|
||||
#define init_mutex(mutex) InitializeCriticalSection(&mutex)
|
||||
#define free_mutex(mutex) DeleteCriticalSection(&mutex)
|
||||
#define lock_mutex(mutex) EnterCriticalSection(&mutex)
|
||||
#define unlock_mutex(mutex) LeaveCriticalSection(&mutex)
|
||||
#define init_lock(lock) (lock=CreateEvent(NULL, false, false, NULL))
|
||||
#define free_lock(lock) CloseHandle(lock)
|
||||
#define wait_lock(lock, mutex) {LeaveCriticalSection(&mutex); WaitForSingleObject(lock, INFINITE); EnterCriticalSection(&mutex);}
|
||||
#define notify_lock(lock) PulseEvent(lock)
|
||||
//#define init_lock(lock) InitializeConditionVariable(&lock)
|
||||
//#define free_lock(lock) // ?
|
||||
//#define wait_lock(lock, mutex) SleepConditionVariableCS(&lock, &mutex, INFINITE)
|
||||
//#define notify_lock(lock) WakeAllConditionVariable(&lock)
|
||||
|
||||
#else
|
||||
#error "No threading implementation for your operating system"
|
||||
#endif
|
||||
|
@ -11,7 +11,6 @@
|
||||
/*
|
||||
* The core AEC algorithm, SSE2 version of speed-critical functions.
|
||||
*/
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
#include <emmintrin.h>
|
||||
#include <math.h>
|
||||
#include <string.h> // memset
|
||||
@ -23,6 +22,8 @@ extern "C" {
|
||||
#include "webrtc/modules/audio_processing/aec/aec_core_optimized_methods.h"
|
||||
#include "webrtc/modules/audio_processing/utility/ooura_fft.h"
|
||||
|
||||
#if defined(WEBRTC_ARCH_X86_FAMILY)
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
__inline static float MulRe(float aRe, float aIm, float bRe, float bIm) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user