1
0
mirror of https://github.com/danog/libtgvoip.git synced 2024-11-30 04:39:03 +01:00

Logging to file(s) now works on all systems and logs now contain OS version in their header

On OS X, audio now plays only out of the right speaker on MacBook Pro's to avoid insane echo when using built-in speakers
Fixed crash on Linux
This commit is contained in:
Grishka 2017-05-06 02:18:34 +03:00
parent 510a977ff0
commit 5109903e02
13 changed files with 250 additions and 30 deletions

View File

@ -1854,8 +1854,10 @@ void VoIPController::SetConfig(voip_config_t *cfg){
if(tgvoipLogFile){ if(tgvoipLogFile){
fclose(tgvoipLogFile); fclose(tgvoipLogFile);
} }
if(strlen(cfg->logFilePath)) if(strlen(cfg->logFilePath)){
tgvoipLogFile=fopen(cfg->logFilePath, "w"); tgvoipLogFile=fopen(cfg->logFilePath, "a");
tgvoip_log_file_write_header();
}
if(statsDump) if(statsDump)
fclose(statsDump); fclose(statsDump);
if(strlen(cfg->statsDumpFilePath)){ if(strlen(cfg->statsDumpFilePath)){

View File

@ -30,6 +30,7 @@ using namespace tgvoip::audio;
#if defined(__ANDROID__) #if defined(__ANDROID__)
int AudioOutput::systemVersion; int AudioOutput::systemVersion;
#endif #endif
int32_t AudioOutput::estimatedDelay=60;
AudioOutput *AudioOutput::Create(std::string deviceID){ AudioOutput *AudioOutput::Create(std::string deviceID){
#if defined(__ANDROID__) #if defined(__ANDROID__)
@ -70,7 +71,7 @@ int32_t AudioOutput::GetEstimatedDelay(){
#if defined(__ANDROID__) #if defined(__ANDROID__)
return systemVersion<21 ? 150 : 50; return systemVersion<21 ? 150 : 50;
#endif #endif
return 60; return estimatedDelay;
} }
float AudioOutput::GetLevel(){ float AudioOutput::GetLevel(){

View File

@ -40,6 +40,7 @@ public:
protected: protected:
std::string currentDevice; std::string currentDevice;
bool failed; bool failed;
static int32_t estimatedDelay;
}; };
}} }}

View File

@ -209,6 +209,8 @@
'<(tgvoip_src_loc)/os/darwin/AudioInputAudioUnitOSX.h', '<(tgvoip_src_loc)/os/darwin/AudioInputAudioUnitOSX.h',
'<(tgvoip_src_loc)/os/darwin/AudioOutputAudioUnitOSX.cpp', '<(tgvoip_src_loc)/os/darwin/AudioOutputAudioUnitOSX.cpp',
'<(tgvoip_src_loc)/os/darwin/AudioOutputAudioUnitOSX.h', '<(tgvoip_src_loc)/os/darwin/AudioOutputAudioUnitOSX.h',
'<(tgvoip_src_loc)/os/darwin/DarwinSpecific.mm',
'<(tgvoip_src_loc)/os/darwin/DarwinSpecific.h',
'<(tgvoip_src_loc)/os/posix/NetworkSocketPosix.cpp', '<(tgvoip_src_loc)/os/posix/NetworkSocketPosix.cpp',
'<(tgvoip_src_loc)/os/posix/NetworkSocketPosix.h', '<(tgvoip_src_loc)/os/posix/NetworkSocketPosix.h',
], ],

View File

@ -46,6 +46,8 @@
692AB91F1E675F7000706ACC /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 692AB91C1E675F7000706ACC /* AudioToolbox.framework */; }; 692AB91F1E675F7000706ACC /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 692AB91C1E675F7000706ACC /* AudioToolbox.framework */; };
692AB9201E675F7000706ACC /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 692AB91D1E675F7000706ACC /* AudioUnit.framework */; }; 692AB9201E675F7000706ACC /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 692AB91D1E675F7000706ACC /* AudioUnit.framework */; };
692AB9211E675F7000706ACC /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 692AB91E1E675F7000706ACC /* CoreAudio.framework */; }; 692AB9211E675F7000706ACC /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 692AB91E1E675F7000706ACC /* CoreAudio.framework */; };
695B20621EBD39FF00E31757 /* DarwinSpecific.h in Headers */ = {isa = PBXBuildFile; fileRef = 695B20601EBD39FF00E31757 /* DarwinSpecific.h */; };
695B20631EBD39FF00E31757 /* DarwinSpecific.mm in Sources */ = {isa = PBXBuildFile; fileRef = 695B20611EBD39FF00E31757 /* DarwinSpecific.mm */; };
69A6DEB91E96149300000E69 /* array_view.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A6DE231E96149300000E69 /* array_view.h */; }; 69A6DEB91E96149300000E69 /* array_view.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A6DE231E96149300000E69 /* array_view.h */; };
69A6DEBA1E96149300000E69 /* atomicops.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A6DE241E96149300000E69 /* atomicops.h */; }; 69A6DEBA1E96149300000E69 /* atomicops.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A6DE241E96149300000E69 /* atomicops.h */; };
69A6DEBB1E96149300000E69 /* basictypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A6DE251E96149300000E69 /* basictypes.h */; }; 69A6DEBB1E96149300000E69 /* basictypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 69A6DE251E96149300000E69 /* basictypes.h */; };
@ -269,6 +271,8 @@
692AB91C1E675F7000706ACC /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; 692AB91C1E675F7000706ACC /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
692AB91D1E675F7000706ACC /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; }; 692AB91D1E675F7000706ACC /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = System/Library/Frameworks/AudioUnit.framework; sourceTree = SDKROOT; };
692AB91E1E675F7000706ACC /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; }; 692AB91E1E675F7000706ACC /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
695B20601EBD39FF00E31757 /* DarwinSpecific.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DarwinSpecific.h; path = ../../../../../TDesktop/TBuild/tdesktop/third_party/libtgvoip/os/darwin/DarwinSpecific.h; sourceTree = "<group>"; };
695B20611EBD39FF00E31757 /* DarwinSpecific.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = DarwinSpecific.mm; path = ../../../../../TDesktop/TBuild/tdesktop/third_party/libtgvoip/os/darwin/DarwinSpecific.mm; sourceTree = "<group>"; };
69A6DE231E96149300000E69 /* array_view.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = array_view.h; sourceTree = "<group>"; }; 69A6DE231E96149300000E69 /* array_view.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = array_view.h; sourceTree = "<group>"; };
69A6DE241E96149300000E69 /* atomicops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = atomicops.h; sourceTree = "<group>"; }; 69A6DE241E96149300000E69 /* atomicops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = atomicops.h; sourceTree = "<group>"; };
69A6DE251E96149300000E69 /* basictypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = basictypes.h; sourceTree = "<group>"; }; 69A6DE251E96149300000E69 /* basictypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = basictypes.h; sourceTree = "<group>"; };
@ -497,6 +501,8 @@
69A6DF401E9614B700000E69 /* AudioInputAudioUnitOSX.h */, 69A6DF401E9614B700000E69 /* AudioInputAudioUnitOSX.h */,
69A6DF411E9614B700000E69 /* AudioOutputAudioUnitOSX.cpp */, 69A6DF411E9614B700000E69 /* AudioOutputAudioUnitOSX.cpp */,
69A6DF421E9614B700000E69 /* AudioOutputAudioUnitOSX.h */, 69A6DF421E9614B700000E69 /* AudioOutputAudioUnitOSX.h */,
695B20601EBD39FF00E31757 /* DarwinSpecific.h */,
695B20611EBD39FF00E31757 /* DarwinSpecific.mm */,
); );
path = darwin; path = darwin;
sourceTree = "<group>"; sourceTree = "<group>";
@ -847,6 +853,7 @@
69A6DF341E96149300000E69 /* ooura_fft.h in Headers */, 69A6DF341E96149300000E69 /* ooura_fft.h in Headers */,
69A6DEBA1E96149300000E69 /* atomicops.h in Headers */, 69A6DEBA1E96149300000E69 /* atomicops.h in Headers */,
69A6DF0A1E96149300000E69 /* aec_resampler.h in Headers */, 69A6DF0A1E96149300000E69 /* aec_resampler.h in Headers */,
695B20621EBD39FF00E31757 /* DarwinSpecific.h in Headers */,
69A6DEE51E96149300000E69 /* spl_inl.h in Headers */, 69A6DEE51E96149300000E69 /* spl_inl.h in Headers */,
69A6DF3B1E96149300000E69 /* cpu_features_wrapper.h in Headers */, 69A6DF3B1E96149300000E69 /* cpu_features_wrapper.h in Headers */,
69A6DF211E96149300000E69 /* ns_core.h in Headers */, 69A6DF211E96149300000E69 /* ns_core.h in Headers */,
@ -1056,6 +1063,7 @@
69A6DF101E96149300000E69 /* aecm_core_neon.cc in Sources */, 69A6DF101E96149300000E69 /* aecm_core_neon.cc in Sources */,
69A6DED71E96149300000E69 /* division_operations.c in Sources */, 69A6DED71E96149300000E69 /* division_operations.c in Sources */,
69A6DEDB1E96149300000E69 /* energy.c in Sources */, 69A6DEDB1E96149300000E69 /* energy.c in Sources */,
695B20631EBD39FF00E31757 /* DarwinSpecific.mm in Sources */,
69A6DEC61E96149300000E69 /* audio_util.cc in Sources */, 69A6DEC61E96149300000E69 /* audio_util.cc in Sources */,
69A6DF141E96149300000E69 /* analog_agc.c in Sources */, 69A6DF141E96149300000E69 /* analog_agc.c in Sources */,
69A6DEF81E96149300000E69 /* spl_sqrt_floor.c in Sources */, 69A6DEF81E96149300000E69 /* spl_sqrt_floor.c in Sources */,

View File

@ -9,6 +9,21 @@
#include <stdarg.h> #include <stdarg.h>
#include <time.h> #include <time.h>
#include "VoIPController.h"
#ifdef __ANDROID__
#include <sys/system_properties.h>
#elif defined(__linux__)
#include <sys/utsname.h>
#endif
#ifdef __APPLE__
#include <TargetConditionals.h>
#if TARGET_OS_OSX
#include "os/darwin/DarwinSpecific.h"
#endif
#endif
FILE* tgvoipLogFile=NULL; FILE* tgvoipLogFile=NULL;
void tgvoip_log_file_printf(char level, const char* msg, ...){ void tgvoip_log_file_printf(char level, const char* msg, ...){
@ -23,3 +38,58 @@ void tgvoip_log_file_printf(char level, const char* msg, ...){
fflush(tgvoipLogFile); fflush(tgvoipLogFile);
} }
} }
void tgvoip_log_file_write_header(){
if(tgvoipLogFile){
time_t t = time(0);
struct tm *now = localtime(&t);
#if defined(_WIN32)
#if WINAPI_PARTITION_DESKTOP
char systemVersion[64];
OSVERSIONINFOA vInfo;
vInfo.dwOSVersionInfoSize=sizeof(vInfo);
GetVersionExA(&vInfo);
snprintf(systemVersion, sizeof(systemVersion), "Windows %d.%d.%d %s", vInfo.dwMajorVersion, vInfo.dwMinorVersion, vInfo.dwBuildNumber, vInfo.szCSDVersion);
#else
char* systemVersion="Windows RT";
#endif
#elif defined(__linux__)
#ifdef __ANDROID__
char systemVersion[128];
char sysRel[PROP_VALUE_MAX];
char deviceVendor[PROP_VALUE_MAX];
char deviceModel[PROP_VALUE_MAX];
__system_property_get("ro.build.version.release", sysRel);
__system_property_get("ro.product.manufacturer", deviceVendor);
__system_property_get("ro.product.model", deviceModel);
snprintf(systemVersion, sizeof(systemVersion), "Android %s (%s %s)", sysRel, deviceVendor, deviceModel);
#else
struct utsname sysname;
uname(&sysname);
char systemVersion[128];
snprintf(systemVersion, sizeof(systemVersion), "%s %s (%s)", sysname.sysname, sysname.release, sysname.version);
#endif
#elif defined(__APPLE__) && TARGET_OS_OSX
char osxVer[128];
tgvoip::DarwinSpecific::GetSystemName(osxVer, sizeof(osxVer));
char systemVersion[128];
snprintf(systemVersion, sizeof(systemVersion), "OS X %s", osxVer);
#else
const char* systemVersion="Unknown OS";
#endif
#if defined(__aarch64__)
const char* cpuArch="ARM64";
#elif defined(__arm__) || defined(_M_ARM)
const char* cpuArch="ARM";
#elif defined(_M_X64) || defined(__x86_64__)
const char* cpuArch="x86_64";
#elif defined(_M_IX86) || defined(__i386__)
const char* cpuArch="x86";
#else
const char* cpuArch="Unknown CPU";
#endif
fprintf(tgvoipLogFile, "---------------\nlibtgvoip v" LIBTGVOIP_VERSION " on %s %s\nLog started on %d/%02d/%d at %d:%02d:%02d\n---------------\n", systemVersion, cpuArch, now->tm_mday, now->tm_mon+1, now->tm_year+1900, now->tm_hour, now->tm_min, now->tm_sec);
}
}

View File

@ -14,6 +14,7 @@
#endif #endif
void tgvoip_log_file_printf(char level, const char* msg, ...); void tgvoip_log_file_printf(char level, const char* msg, ...);
void tgvoip_log_file_write_header();
#if defined(__ANDROID__) #if defined(__ANDROID__)
@ -43,24 +44,49 @@ void tgvoip_log_file_printf(char level, const char* msg, ...);
#include <windows.h> #include <windows.h>
#include <stdio.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 _TGVOIP_W32_LOG_PRINT(verb, msg, ...){ char __log_buf[1024]; snprintf(__log_buf, 1024, "%c/tgvoip: " msg "\n", verb, ##__VA_ARGS__); OutputDebugStringA(__log_buf); tgvoip_log_file_printf((char)verb, msg, __VA_ARGS__);}
#define LOGV(msg, ...) _TGVOIP_W32_LOG_PRINT("V/tgvoip: " msg "\n", ##__VA_ARGS__) #define LOGV(msg, ...) _TGVOIP_W32_LOG_PRINT('V', msg, ##__VA_ARGS__)
#define LOGD(msg, ...) _TGVOIP_W32_LOG_PRINT("D/tgvoip: " msg "\n", ##__VA_ARGS__) #define LOGD(msg, ...) _TGVOIP_W32_LOG_PRINT('D', msg, ##__VA_ARGS__)
#define LOGI(msg, ...) _TGVOIP_W32_LOG_PRINT("I/tgvoip: " msg "\n", ##__VA_ARGS__) #define LOGI(msg, ...) _TGVOIP_W32_LOG_PRINT('I', msg, ##__VA_ARGS__)
#define LOGW(msg, ...) _TGVOIP_W32_LOG_PRINT("W/tgvoip: " msg "\n", ##__VA_ARGS__) #define LOGW(msg, ...) _TGVOIP_W32_LOG_PRINT('W', msg, ##__VA_ARGS__)
#define LOGE(msg, ...) _TGVOIP_W32_LOG_PRINT("E/tgvoip: " msg "\n", ##__VA_ARGS__) #define LOGE(msg, ...) _TGVOIP_W32_LOG_PRINT('E', msg, ##__VA_ARGS__)
#else #else
#include <stdio.h> #include <stdio.h>
#define LOGV(msg, ...) printf("V/tgvoip: " msg "\n", ##__VA_ARGS__) #define _TGVOIP_LOG_PRINT(verb, msg, ...) {printf("%c/tgvoip: " msg "\n", verb, ##__VA_ARGS__); tgvoip_log_file_printf(verb, msg, ##__VA_ARGS__);}
#define LOGD(msg, ...) printf("D/tgvoip: " msg "\n", ##__VA_ARGS__)
#define LOGI(msg, ...) printf("I/tgvoip: " msg "\n", ##__VA_ARGS__) #define LOGV(msg, ...) _TGVOIP_LOG_PRINT('V', msg, ##__VA_ARGS__)
#define LOGW(msg, ...) printf("W/tgvoip: " msg "\n", ##__VA_ARGS__) #define LOGD(msg, ...) _TGVOIP_LOG_PRINT('D', msg, ##__VA_ARGS__)
#define LOGE(msg, ...) printf("E/tgvoip: " msg "\n", ##__VA_ARGS__) #define LOGI(msg, ...) _TGVOIP_LOG_PRINT('I', msg, ##__VA_ARGS__)
#define LOGW(msg, ...) _TGVOIP_LOG_PRINT('W', msg, ##__VA_ARGS__)
#define LOGE(msg, ...) _TGVOIP_LOG_PRINT('E', msg, ##__VA_ARGS__)
#endif #endif
#ifdef TGVOIP_LOG_VERBOSITY
#if TGVOIP_LOG_VERBOSITY<5
#undef LOGV
#define LOGV(msg, ...)
#endif
#if TGVOIP_LOG_VERBOSITY<4
#undef LOGD
#define LOGD(msg, ...)
#endif
#if TGVOIP_LOG_VERBOSITY<3
#undef LOGI
#define LOGI(msg, ...)
#endif
#if TGVOIP_LOG_VERBOSITY<2
#undef LOGW
#define LOGW(msg, ...)
#endif
#if TGVOIP_LOG_VERBOSITY<1
#undef LOGE
#define LOGE(msg, ...)
#endif
#endif
#endif //__LOGGING_H #endif //__LOGGING_H

View File

@ -6,6 +6,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <sys/sysctl.h>
#include "AudioOutputAudioUnitOSX.h" #include "AudioOutputAudioUnitOSX.h"
#include "../../logging.h" #include "../../logging.h"
#include "../../VoIPController.h" #include "../../VoIPController.h"
@ -22,6 +23,7 @@ using namespace tgvoip::audio;
AudioOutputAudioUnit::AudioOutputAudioUnit(std::string deviceID){ AudioOutputAudioUnit::AudioOutputAudioUnit(std::string deviceID){
remainingDataSize=0; remainingDataSize=0;
isPlaying=false; isPlaying=false;
sysDevID=NULL;
OSStatus status; OSStatus status;
AudioComponentDescription inputDesc={ AudioComponentDescription inputDesc={
@ -39,6 +41,15 @@ AudioOutputAudioUnit::AudioOutputAudioUnit(std::string deviceID){
status = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag)); status = AudioUnitSetProperty(unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag));
CHECK_AU_ERROR(status, "Error enabling AudioUnit input"); CHECK_AU_ERROR(status, "Error enabling AudioUnit input");
char model[128];
memset(model, 0, sizeof(model));
size_t msize=sizeof(model);
int mres=sysctlbyname("hw.model", model, &msize, NULL, 0);
if(mres==0){
LOGV("Mac model: %s", model);
isMacBookPro=(strncmp("MacBookPro", model, 10)==0);
}
SetCurrentDevice(deviceID); SetCurrentDevice(deviceID);
CFRunLoopRef theRunLoop = NULL; CFRunLoopRef theRunLoop = NULL;
@ -76,6 +87,15 @@ AudioOutputAudioUnit::~AudioOutputAudioUnit(){
propertyAddress.mElement = kAudioObjectPropertyElementMaster; propertyAddress.mElement = kAudioObjectPropertyElementMaster;
AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &propertyAddress, AudioOutputAudioUnit::DefaultDeviceChangedCallback, this); AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &propertyAddress, AudioOutputAudioUnit::DefaultDeviceChangedCallback, this);
AudioObjectPropertyAddress dataSourceProp={
kAudioDevicePropertyDataSource,
kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMaster
};
if(isMacBookPro && sysDevID && AudioObjectHasProperty(sysDevID, &dataSourceProp)){
AudioObjectRemovePropertyListener(sysDevID, &dataSourceProp, AudioOutputAudioUnit::DefaultDeviceChangedCallback, this);
}
AudioUnitUninitialize(unit); AudioUnitUninitialize(unit);
AudioComponentInstanceDispose(unit); AudioComponentInstanceDispose(unit);
} }
@ -216,8 +236,17 @@ void AudioOutputAudioUnit::EnumerateDevices(std::vector<AudioOutputDevice>& devs
void AudioOutputAudioUnit::SetCurrentDevice(std::string deviceID){ void AudioOutputAudioUnit::SetCurrentDevice(std::string deviceID){
UInt32 size=sizeof(AudioDeviceID); UInt32 size=sizeof(AudioDeviceID);
AudioDeviceID inputDevice=NULL; AudioDeviceID outputDevice=NULL;
OSStatus status; OSStatus status;
AudioObjectPropertyAddress dataSourceProp={
kAudioDevicePropertyDataSource,
kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMaster
};
if(isMacBookPro && sysDevID && AudioObjectHasProperty(sysDevID, &dataSourceProp)){
AudioObjectRemovePropertyListener(sysDevID, &dataSourceProp, AudioOutputAudioUnit::DefaultDeviceChangedCallback, this);
}
if(deviceID=="default"){ if(deviceID=="default"){
AudioObjectPropertyAddress propertyAddress; AudioObjectPropertyAddress propertyAddress;
@ -225,7 +254,7 @@ void AudioOutputAudioUnit::SetCurrentDevice(std::string deviceID){
propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
propertyAddress.mElement = kAudioObjectPropertyElementMaster; propertyAddress.mElement = kAudioObjectPropertyElementMaster;
UInt32 propsize = sizeof(AudioDeviceID); UInt32 propsize = sizeof(AudioDeviceID);
status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &propsize, &inputDevice); status = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &propsize, &outputDevice);
CHECK_AU_ERROR(status, "Error getting default input device"); CHECK_AU_ERROR(status, "Error getting default input device");
}else{ }else{
AudioObjectPropertyAddress propertyAddress = { AudioObjectPropertyAddress propertyAddress = {
@ -251,11 +280,11 @@ void AudioOutputAudioUnit::SetCurrentDevice(std::string deviceID){
CFStringGetCString(deviceUID, buf, 1024, kCFStringEncodingUTF8); CFStringGetCString(deviceUID, buf, 1024, kCFStringEncodingUTF8);
if(deviceID==buf){ if(deviceID==buf){
LOGV("Found device for id %s", buf); LOGV("Found device for id %s", buf);
inputDevice=audioDevices[i]; outputDevice=audioDevices[i];
break; break;
} }
} }
if(!inputDevice){ if(!outputDevice){
LOGW("Requested device not found, using default"); LOGW("Requested device not found, using default");
SetCurrentDevice("default"); SetCurrentDevice("default");
return; return;
@ -266,7 +295,7 @@ void AudioOutputAudioUnit::SetCurrentDevice(std::string deviceID){
kAudioOutputUnitProperty_CurrentDevice, kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Global, kAudioUnitScope_Global,
kOutputBus, kOutputBus,
&inputDevice, &outputDevice,
size); size);
CHECK_AU_ERROR(status, "Error setting output device"); CHECK_AU_ERROR(status, "Error setting output device");
@ -287,13 +316,53 @@ void AudioOutputAudioUnit::SetCurrentDevice(std::string deviceID){
LOGD("Switched playback device, new sample rate %d", hardwareSampleRate); LOGD("Switched playback device, new sample rate %d", hardwareSampleRate);
this->currentDevice=deviceID; this->currentDevice=deviceID;
sysDevID=outputDevice;
AudioObjectPropertyAddress propertyAddress = {
kAudioDevicePropertyBufferFrameSize,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
size=4;
UInt32 bufferFrameSize;
status=AudioObjectGetPropertyData(outputDevice, &propertyAddress, 0, NULL, &size, &bufferFrameSize);
if(status==noErr){
estimatedDelay=bufferFrameSize/48;
LOGD("CoreAudio buffer size for output device is %u frames (%u ms)", bufferFrameSize, estimatedDelay);
}
if(isMacBookPro){
if(AudioObjectHasProperty(outputDevice, &dataSourceProp)){
UInt32 dataSource;
size=4;
AudioObjectGetPropertyData(outputDevice, &dataSourceProp, 0, NULL, &size, &dataSource);
SetPanRight(dataSource=='ispk');
AudioObjectAddPropertyListener(outputDevice, &dataSourceProp, AudioOutputAudioUnit::DefaultDeviceChangedCallback, this);
}else{
SetPanRight(false);
}
}
}
void AudioOutputAudioUnit::SetPanRight(bool panRight){
LOGI("%sabling pan right on macbook pro", panRight ? "En" : "Dis");
int32_t channelMap[]={panRight ? -1 : 0, 0};
OSStatus status=AudioUnitSetProperty(unit, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Global, kOutputBus, channelMap, sizeof(channelMap));
CHECK_AU_ERROR(status, "Error setting channel map");
} }
OSStatus AudioOutputAudioUnit::DefaultDeviceChangedCallback(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inClientData){ OSStatus AudioOutputAudioUnit::DefaultDeviceChangedCallback(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inClientData){
LOGV("System default input device changed");
AudioOutputAudioUnit* self=(AudioOutputAudioUnit*)inClientData; AudioOutputAudioUnit* self=(AudioOutputAudioUnit*)inClientData;
if(inAddresses[0].mSelector==kAudioHardwarePropertyDefaultOutputDevice){
LOGV("System default input device changed");
if(self->currentDevice=="default"){ if(self->currentDevice=="default"){
self->SetCurrentDevice(self->currentDevice); self->SetCurrentDevice(self->currentDevice);
} }
}else if(inAddresses[0].mSelector==kAudioDevicePropertyDataSource){
UInt32 dataSource;
UInt32 size=4;
AudioObjectGetPropertyData(inObjectID, inAddresses, 0, NULL, &size, &dataSource);
self->SetPanRight(dataSource=='ispk');
}
return noErr; return noErr;
} }

View File

@ -29,11 +29,14 @@ public:
private: private:
static OSStatus BufferCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); static OSStatus BufferCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData);
static OSStatus DefaultDeviceChangedCallback(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inClientData); static OSStatus DefaultDeviceChangedCallback(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inClientData);
void SetPanRight(bool panRight);
unsigned char remainingData[10240]; unsigned char remainingData[10240];
size_t remainingDataSize; size_t remainingDataSize;
bool isPlaying; bool isPlaying;
AudioUnit unit; AudioUnit unit;
int hardwareSampleRate; int hardwareSampleRate;
bool isMacBookPro;
AudioDeviceID sysDevID;
}; };
}} }}

View File

@ -0,0 +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 TGVOIP_DARWINSPECIFIC_H
#define TGVOIP_DARWINSPECIFIC_H
#include <string>
namespace tgvoip {
class DarwinSpecific{
public:
static void GetSystemName(char* buf, size_t len);
};
}
#endif //TGVOIP_DARWINSPECIFIC_H

View File

@ -0,0 +1,17 @@
//
// 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 "DarwinSpecific.h"
#import <Foundation/Foundation.h>
using namespace tgvoip;
void DarwinSpecific::GetSystemName(char* buf, size_t len){
NSString* v=[[NSProcessInfo processInfo] operatingSystemVersionString];
strcpy(buf, [v UTF8String]);
//[v getCString:buf maxLength:sizeof(buf) encoding:NSUTF8StringEncoding];
}

View File

@ -21,6 +21,7 @@ using namespace tgvoip::audio;
AudioInputALSA::AudioInputALSA(std::string devID){ AudioInputALSA::AudioInputALSA(std::string devID){
isRecording=false; isRecording=false;
handle=NULL;
lib=dlopen("libasound.so", RTLD_LAZY); lib=dlopen("libasound.so", RTLD_LAZY);
if(!lib){ if(!lib){
@ -36,13 +37,13 @@ AudioInputALSA::AudioInputALSA(std::string devID){
LOAD_FUNCTION(lib, "snd_pcm_recover", _snd_pcm_recover); LOAD_FUNCTION(lib, "snd_pcm_recover", _snd_pcm_recover);
LOAD_FUNCTION(lib, "snd_strerror", _snd_strerror); LOAD_FUNCTION(lib, "snd_strerror", _snd_strerror);
handle=NULL;
SetCurrentDevice(devID); SetCurrentDevice(devID);
} }
AudioInputALSA::~AudioInputALSA(){ AudioInputALSA::~AudioInputALSA(){
if(handle)
_snd_pcm_close(handle); _snd_pcm_close(handle);
if(lib)
dlclose(lib); dlclose(lib);
} }

View File

@ -20,6 +20,7 @@ using namespace tgvoip::audio;
AudioOutputALSA::AudioOutputALSA(std::string devID){ AudioOutputALSA::AudioOutputALSA(std::string devID){
isPlaying=false; isPlaying=false;
handle=NULL;
lib=dlopen("libasound.so", RTLD_LAZY); lib=dlopen("libasound.so", RTLD_LAZY);
if(!lib){ if(!lib){
@ -35,13 +36,13 @@ AudioOutputALSA::AudioOutputALSA(std::string devID){
LOAD_FUNCTION(lib, "snd_pcm_recover", _snd_pcm_recover); LOAD_FUNCTION(lib, "snd_pcm_recover", _snd_pcm_recover);
LOAD_FUNCTION(lib, "snd_strerror", _snd_strerror); LOAD_FUNCTION(lib, "snd_strerror", _snd_strerror);
handle=NULL;
SetCurrentDevice(devID); SetCurrentDevice(devID);
} }
AudioOutputALSA::~AudioOutputALSA(){ AudioOutputALSA::~AudioOutputALSA(){
if(handle)
_snd_pcm_close(handle); _snd_pcm_close(handle);
if(lib)
dlclose(lib); dlclose(lib);
} }