Add interface for changing ggwave's internal logging (#52)

* ggwave : add interface for changing ggwave's internal logging

Using GGWave::setLogFile() it is now possible to change the log file
used internally by ggwave, or disable it all together.

* ggwave : add comments about thread-safety of setLogFile
This commit is contained in:
Georgi Gerganov
2021-09-21 06:48:16 +03:00
committed by GitHub
parent 1a0af88ed6
commit 9cf2d476b8
3 changed files with 62 additions and 20 deletions

View File

@@ -15,14 +15,23 @@
#define M_PI 3.14159265358979323846
#endif
#define ggprintf(...) \
g_fptr && fprintf(g_fptr, __VA_ARGS__)
//
// C interface
//
namespace {
FILE * g_fptr = stderr;
std::map<ggwave_Instance, GGWave *> g_instances;
}
extern "C"
void ggwave_setLogFile(void * fptr) {
GGWave::setLogFile((FILE *) fptr);
}
extern "C"
ggwave_Parameters ggwave_getDefaultParameters(void) {
return GGWave::getDefaultParameters();
@@ -62,12 +71,12 @@ int ggwave_encode(
GGWave * ggWave = (GGWave *) g_instances[instance];
if (ggWave == nullptr) {
fprintf(stderr, "Invalid GGWave instance %d\n", instance);
ggprintf("Invalid GGWave instance %d\n", instance);
return -1;
}
if (ggWave->init(dataSize, dataBuffer, ggWave->getTxProtocol(txProtocolId), volume) == false) {
fprintf(stderr, "Failed to initialize GGWave instance %d\n", instance);
ggprintf("Failed to initialize GGWave instance %d\n", instance);
return -1;
}
@@ -89,7 +98,7 @@ int ggwave_encode(
};
if (ggWave->encode(cbWaveformOut) == false) {
fprintf(stderr, "Failed to encode data - GGWave instance %d\n", instance);
ggprintf("Failed to encode data - GGWave instance %d\n", instance);
return -1;
}
@@ -263,7 +272,7 @@ int bytesForSampleFormat(GGWave::SampleFormat sampleFormat) {
case GGWAVE_SAMPLE_FORMAT_F32: return sizeof(float); break;
};
fprintf(stderr, "Invalid sample format: %d\n", (int) sampleFormat);
ggprintf("Invalid sample format: %d\n", (int) sampleFormat);
return 0;
}
@@ -274,6 +283,10 @@ struct GGWave::Impl {
Resampler resampler;
};
void GGWave::setLogFile(FILE * fptr) {
g_fptr = fptr;
}
const GGWave::Parameters & GGWave::getDefaultParameters() {
static ggwave_Parameters result {
-1, // vaiable payload length
@@ -370,12 +383,12 @@ GGWave::GGWave(const Parameters & parameters) :
}
if (m_sampleRateInp < kSampleRateMin) {
fprintf(stderr, "Error: capture sample rate (%g Hz) must be >= %g Hz\n", m_sampleRateInp, kSampleRateMin);
ggprintf("Error: capture sample rate (%g Hz) must be >= %g Hz\n", m_sampleRateInp, kSampleRateMin);
throw std::runtime_error("Invalid capture/playback sample rate");
}
if (m_sampleRateInp > kSampleRateMax) {
fprintf(stderr, "Error: capture sample rate (%g Hz) must be <= %g Hz\n", m_sampleRateInp, kSampleRateMax);
ggprintf("Error: capture sample rate (%g Hz) must be <= %g Hz\n", m_sampleRateInp, kSampleRateMax);
throw std::runtime_error("Invalid capture/playback sample rate");
}
@@ -399,18 +412,18 @@ bool GGWave::init(int dataSize, const char * dataBuffer, const int volume) {
bool GGWave::init(int dataSize, const char * dataBuffer, const TxProtocol & txProtocol, const int volume) {
if (dataSize < 0) {
fprintf(stderr, "Negative data size: %d\n", dataSize);
ggprintf("Negative data size: %d\n", dataSize);
return false;
}
auto maxLength = m_isFixedPayloadLength ? m_payloadLength : kMaxLengthVarible;
if (dataSize > maxLength) {
fprintf(stderr, "Truncating data from %d to %d bytes\n", dataSize, maxLength);
ggprintf("Truncating data from %d to %d bytes\n", dataSize, maxLength);
dataSize = maxLength;
}
if (volume < 0 || volume > 100) {
fprintf(stderr, "Invalid volume: %d\n", volume);
ggprintf("Invalid volume: %d\n", volume);
return false;
}
@@ -740,14 +753,14 @@ void GGWave::decode(const CBWaveformInp & cbWaveformInp) {
}
if (nBytesRecorded % m_sampleSizeBytesInp != 0) {
fprintf(stderr, "Failure during capture - provided bytes (%d) are not multiple of sample size (%d)\n",
ggprintf("Failure during capture - provided bytes (%d) are not multiple of sample size (%d)\n",
nBytesRecorded, m_sampleSizeBytesInp);
m_samplesNeeded = m_samplesPerFrame;
break;
}
if (nBytesRecorded > nBytesNeeded) {
fprintf(stderr, "Failure during capture - more samples were provided (%d) than requested (%d)\n",
ggprintf("Failure during capture - more samples were provided (%d) than requested (%d)\n",
nBytesRecorded/m_sampleSizeBytesInp, nBytesNeeded/m_sampleSizeBytesInp);
m_samplesNeeded = m_samplesPerFrame;
break;
@@ -891,7 +904,7 @@ bool GGWave::takeRxAmplitude(AmplitudeData & dst) {
bool GGWave::computeFFTR(const float * src, float * dst, int N, float d) {
if (N > kMaxSamplesPerFrame) {
fprintf(stderr, "computeFFTR: N (%d) must be <= %d\n", N, GGWave::kMaxSamplesPerFrame);
ggprintf("computeFFTR: N (%d) must be <= %d\n", N, GGWave::kMaxSamplesPerFrame);
return false;
}
@@ -948,7 +961,7 @@ void GGWave::decode_variable() {
}
if (m_analyzingData) {
fprintf(stderr, "Analyzing captured data ..\n");
ggprintf("Analyzing captured data ..\n");
auto tStart = std::chrono::high_resolution_clock::now();
const int stepsPerFrame = 16;
@@ -1057,8 +1070,8 @@ void GGWave::decode_variable() {
if (m_rxData[0] != 0) {
std::string s((char *) m_rxData.data(), decodedLength);
fprintf(stderr, "Decoded length = %d, protocol = '%s' (%d)\n", decodedLength, rxProtocol.name, rxProtocolId);
fprintf(stderr, "Received sound data successfully: '%s'\n", s.c_str());
ggprintf("Decoded length = %d, protocol = '%s' (%d)\n", decodedLength, rxProtocol.name, rxProtocolId);
ggprintf("Received sound data successfully: '%s'\n", s.c_str());
isValid = true;
m_hasNewRxData = true;
@@ -1081,7 +1094,7 @@ void GGWave::decode_variable() {
m_framesToRecord = 0;
if (isValid == false) {
fprintf(stderr, "Failed to capture sound data. Please try again (length = %d)\n", m_rxData[0]);
ggprintf("Failed to capture sound data. Please try again (length = %d)\n", m_rxData[0]);
m_lastRxDataLength = -1;
m_framesToRecord = -1;
}
@@ -1095,7 +1108,7 @@ void GGWave::decode_variable() {
m_framesLeftToAnalyze = 0;
auto tEnd = std::chrono::high_resolution_clock::now();
fprintf(stderr, "Time to analyze: %g ms\n", getTime_ms(tStart, tEnd));
ggprintf("Time to analyze: %g ms\n", getTime_ms(tStart, tEnd));
}
// check if receiving data
@@ -1134,7 +1147,7 @@ void GGWave::decode_variable() {
if (isReceiving) {
std::time_t timestamp = std::time(nullptr);
fprintf(stderr, "%sReceiving sound data ...\n", std::asctime(std::localtime(&timestamp)));
ggprintf("%sReceiving sound data ...\n", std::asctime(std::localtime(&timestamp)));
m_receivingData = true;
std::fill(m_rxData.begin(), m_rxData.end(), 0);
@@ -1183,7 +1196,7 @@ void GGWave::decode_variable() {
if (isEnded && m_framesToRecord > 1) {
std::time_t timestamp = std::time(nullptr);
m_recvDuration_frames -= m_framesLeftToRecord - 1;
fprintf(stderr, "%sReceived end marker. Frames left = %d, recorded = %d\n", std::asctime(std::localtime(&timestamp)), m_framesLeftToRecord, m_recvDuration_frames);
ggprintf("%sReceived end marker. Frames left = %d, recorded = %d\n", std::asctime(std::localtime(&timestamp)), m_framesLeftToRecord, m_recvDuration_frames);
m_nMarkersSuccess = 0;
m_framesLeftToRecord = 1;
}
@@ -1321,7 +1334,7 @@ void GGWave::decode_fixed() {
if (rsData.Decode(m_txDataEncoded.data(), m_rxData.data()) == 0) {
if (m_rxData[0] != 0) {
fprintf(stderr, "Received sound data successfully: '%s'\n", m_rxData.data());
ggprintf("Received sound data successfully: '%s'\n", m_rxData.data());
isValid = true;
m_hasNewRxData = true;