Merge branch 'master' into audio_recording

This commit is contained in:
Charles J. Cliffe 2017-11-01 22:34:28 -04:00
commit 6af64752be
42 changed files with 10381 additions and 9845 deletions

View File

@ -324,7 +324,7 @@ namespace CubicVR {
};
static vec3 unProject(mat4 pMatrix, mat4 mvMatrix, float width, float height, float winx, float winy, float /* winz */) {
vec4 p(((winx / width) * 2.0f) - 1.0, -(((winy / height) * 2.0f) - 1.0), 1.0, 1.0);
vec4 p(((winx / width) * 2.0f) - 1.0f, -(((winy / height) * 2.0f) - 1.0f), 1.0f, 1.0f);
vec4 invp = mat4::vec4_multiply(mat4::vec4_multiply(p, mat4::inverse(pMatrix)), mat4::inverse(mvMatrix));

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -43,7 +43,7 @@
# autoconf initialization macros
NAME := liquid-dsp
VERSION := 1.3.0
VERSION := 1.3.1
BUGREPORT := support@liquidsdr.org
# paths
@ -64,17 +64,13 @@ RANLIB := ranlib
# flags
INCLUDE_CFLAGS = $(addprefix -I ,$(include_dirs))
#MINGW: optimizations goes here
CONFIG_CFLAGS = -m32 -O3 -msse3 -ffast-math
# -g : debugging info
CFLAGS += $(INCLUDE_CFLAGS) -Wall -fPIC $(CONFIG_CFLAGS)
#LDFLAGS += -lm -lc
CPPFLAGS = $(INCLUDE_CFLAGS)
CFLAGS = $(CONFIG_CFLAGS) -Wall -fPIC
LDFLAGS =
#MINGW:
LDFLAGS += -lmsvcrt
LIBS += -lmsvcrt
ARFLAGS = r
PATHSEP = /
@ -347,8 +343,8 @@ src/fft/src/dct.o : %.o : %.c $(include_headers)
src/fft/src/fftf.o : %.o : %.c $(include_headers)
src/fft/src/fft_utilities.o : %.o : %.c $(include_headers)
src/fft/src/mdct.o : %.o : %.c $(include_headers)
src/fft/src/spgramcf.o : %.o : %.c $(include_headers) src/fft/src/asgram.c src/fft/src/spgram.c
src/fft/src/spgramf.o : %.o : %.c $(include_headers) src/fft/src/asgram.c src/fft/src/spgram.c
src/fft/src/spgramcf.o : %.o : %.c $(include_headers) src/fft/src/asgram.c src/fft/src/spgram.c src/fft/src/spwaterfall.c
src/fft/src/spgramf.o : %.o : %.c $(include_headers) src/fft/src/asgram.c src/fft/src/spgram.c src/fft/src/spwaterfall.c
# fft autotest scripts
fft_autotests := \
@ -657,6 +653,7 @@ framing_benchmarks := \
src/framing/bench/flexframesync_benchmark.c \
src/framing/bench/framesync64_benchmark.c \
src/framing/bench/gmskframesync_benchmark.c \
src/framing/bench/qdetector_benchmark.c \
#
@ -1158,8 +1155,6 @@ benchmark_sources := \
.PHONY: all
# Shared library
#SHARED_LIB = libliquid.so
#MINGW:
SHARED_LIB = libliquid.dll
@ -1172,15 +1167,14 @@ libliquid.a: $(objects)
#
# gcc -dynamiclib -install_name libliquid.dylib -o libliquid.dylib libmodem.a libutility.a
libliquid.dylib: $(objects)
$(CC) -dynamiclib -install_name $@ -o $@ $^ $(LDFLAGS)
$(CC) -dynamiclib -install_name $@ -o $@ $^ $(LDFLAGS) $(LIBS)
# linux, et al
libliquid.so: libliquid.a
$(CC) -shared -Xlinker -soname=$@ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive $(LDFLAGS)
# MINGW*
$(CC) $(CFLAGS) $(LDFLAGS) -shared -Xlinker -soname=$@ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive $(LIBS)
#MINGW:
libliquid.dll: libliquid.a
$(CC) -shared -Xlinker -soname=$@ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive -Wl,--output-def,libliquid.def -Wl,--out-implib,libliquid.lib $(LDFLAGS)
$(CC) -shared -Xlinker -soname=$@ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive -Wl,--output-def,libliquid.def -Wl,--out-implib,libliquid.lib $(LIBS)
all: libliquid.a $(SHARED_LIB)
@ -1236,10 +1230,10 @@ uninstall:
autoscript : scripts/autoscript
scripts/autoscript.o scripts/main.o : %.o : %.c
$(CC) $(CFLAGS) -c -o $@ $<
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
scripts/autoscript : scripts/autoscript.o scripts/main.o
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
clean-autoscript :
$(RM) scripts/autoscript.o scripts/main.o scripts/autoscript
@ -1265,23 +1259,23 @@ autotest_include.h : scripts/autoscript $(autotest_sources) $(include_headers)
# the '-x c' flag
autotest_obj = $(patsubst %.c,%.o,$(autotest_sources))
$(autotest_obj) : %.o : %.c $(include_headers)
$(CC) $(CFLAGS) $< -c -o $@
$(CC) $(CPPFLAGS) $(CFLAGS) $< -c -o $@
# additional autotest objects
$(autotest_extra_obj) : %.o : %.c $(include_headers)
# compile the autotest internal library functions without linking
autotest/autotestlib.o : autotest/autotestlib.c autotest/autotest.h
$(CC) $(CFLAGS) $< -c -o $@
$(CC) $(CPPFLAGS) $(CFLAGS) $< -c -o $@
# compile the autotest program without linking
$(autotest_prog).o : autotest/autotest.c autotest/autotest.h autotest_include.h
$(CC) $(CFLAGS) $< -c -o $@
$(CC) $(CPPFLAGS) $(CFLAGS) $< -c -o $@
# link the autotest program with the objects
# NOTE: linked libraries must come _after_ the target program
$(autotest_prog): $(autotest_prog).o $(autotest_obj) $(autotest_extra_obj) autotest/autotestlib.o libliquid.a
$(CC) $^ -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)
# run the autotest program
check: $(autotest_prog)
@ -1306,8 +1300,10 @@ clean-check:
# on the target platform.
.PHONY: bench
bench_prog = benchmark
BENCH_CFLAGS = -Wall $(INCLUDE_CFLAGS) $(CONFIG_CFLAGS)
BENCH_CPPFLAGS = $(CPPFLAGS)
BENCH_CFLAGS = -Wall $(CFLAGS)
BENCH_LDFLAGS = $(LDFLAGS)
BENCH_LIBS = $(LIBS)
# run the benchmark generator script to create benchmark_include.h
benchmark_include.h : scripts/autoscript $(benchmark_sources) $(include_headers)
@ -1319,19 +1315,19 @@ benchmark_include.h : scripts/autoscript $(benchmark_sources) $(include_headers)
# the '-x c' flag
benchmark_obj = $(patsubst %.c,%.o,$(benchmark_sources))
$(benchmark_obj) : %.o : %.c $(include_headers)
$(CC) $(BENCH_CFLAGS) $< -c -o $@
$(CC) $(BENCH_CPPFLAGS) $(BENCH_CFLAGS) $< -c -o $@
# additional benchmark objects
$(benchmark_extra_obj) : %.o : %.c $(include_headers)
# compile the benchmark program without linking
$(bench_prog).o: bench/bench.c benchmark_include.h bench/bench.c
$(CC) $(BENCH_CFLAGS) $< -c -o $(bench_prog).o
$(CC) $(BENCH_CPPFLAGS) $(BENCH_CFLAGS) $< -c -o $(bench_prog).o
# link the benchmark program with the library objects
# NOTE: linked libraries must come _after_ the target program
$(bench_prog): $(bench_prog).o $(benchmark_obj) $(benchmark_extra_obj) libliquid.a
$(CC) $^ -o $(bench_prog) $(BENCH_LDFLAGS)
$(CC) $(BENCH_CFLAGS) $(BENCH_LDFLAGS) $^ -o $(bench_prog) $(BENCH_LIBS)
# run the benchmark program
bench: $(bench_prog)
@ -1339,14 +1335,14 @@ bench: $(bench_prog)
# benchmark compare script
scripts/benchmark_compare : % : %.c
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS)
# fftbench program
bench/fftbench.o : %.o : %.c
$(CC) $(BENCH_CFLAGS) $< -c -o $@
$(CC) $(BENCH_CPPFLAGS) $(BENCH_CFLAGS) $< -c -o $@
bench/fftbench : % : %.o libliquid.a
$(CC) $^ -o $@ $(BENCH_LDFLAGS)
$(CC) $(BENCH_CFLAGS) $(BENCH_LDFLAGS) $^ -o $@ $(BENCH_LIBS)
# clean up the generated files
clean-bench:
@ -1364,6 +1360,7 @@ clean-bench:
.PHONY: examples
example_programs := \
examples/agc_crcf_example \
examples/agc_crcf_squelch_example \
examples/agc_crcf_qpsk_example \
examples/agc_rrrf_example \
examples/ampmodem_example \
@ -1403,7 +1400,9 @@ example_programs := \
examples/firfilt_crcf_example \
examples/firfilt_rrrf_example \
examples/firdes_kaiser_example \
examples/firdespm_callback_example \
examples/firdespm_example \
examples/firdespm_lowpass_example \
examples/firhilb_example \
examples/firhilb_decim_example \
examples/firhilb_interp_example \
@ -1480,6 +1479,7 @@ example_programs := \
examples/spgramcf_example \
examples/spgramcf_waterfall_example \
examples/spgramf_example \
examples/spwaterfallcf_example \
examples/symsync_crcf_example \
examples/symsync_crcf_full_example \
examples/symsync_crcf_kaiser_example \
@ -1496,13 +1496,11 @@ example_programs := \
example_objects = $(patsubst %,%.o,$(example_programs))
examples: $(example_programs)
EXAMPLES_LDFLAGS = $(LDFLAGS)
# NOTE: linked libraries must come _after_ the target program
$(example_objects): %.o : %.c
$(example_programs): % : %.o libliquid.a
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)
# clean examples
clean-examples:
@ -1624,7 +1622,7 @@ SANDBOX_LDFLAGS = $(LDFLAGS) -lfftw3f
$(sandbox_objects): %.o : %.c
$(sandbox_programs): % : %.o libliquid.a
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) $(LIBS)
# clean sandbox
clean-sandbox:

View File

@ -43,7 +43,7 @@
# autoconf initialization macros
NAME := liquid-dsp
VERSION := 1.3.0
VERSION := 1.3.1
BUGREPORT := support@liquidsdr.org
# paths
@ -64,17 +64,13 @@ RANLIB := ranlib
# flags
INCLUDE_CFLAGS = $(addprefix -I ,$(include_dirs))
#MINGW: optimizations goes here
CONFIG_CFLAGS = -O3 -msse3 -ffast-math -static-libgcc -static-libstdc++
# -g : debugging info
CFLAGS += $(INCLUDE_CFLAGS) -Wall -fPIC $(CONFIG_CFLAGS)
#LDFLAGS += -lm -lc
CPPFLAGS = $(INCLUDE_CFLAGS)
CFLAGS = $(CONFIG_CFLAGS) -Wall -fPIC
LDFLAGS =
#MINGW:
LDFLAGS += -static-libgcc -static-libstdc++
LIBS += -static-libgcc -static-libstdc++
ARFLAGS = r
PATHSEP = /
@ -347,8 +343,8 @@ src/fft/src/dct.o : %.o : %.c $(include_headers)
src/fft/src/fftf.o : %.o : %.c $(include_headers)
src/fft/src/fft_utilities.o : %.o : %.c $(include_headers)
src/fft/src/mdct.o : %.o : %.c $(include_headers)
src/fft/src/spgramcf.o : %.o : %.c $(include_headers) src/fft/src/asgram.c src/fft/src/spgram.c
src/fft/src/spgramf.o : %.o : %.c $(include_headers) src/fft/src/asgram.c src/fft/src/spgram.c
src/fft/src/spgramcf.o : %.o : %.c $(include_headers) src/fft/src/asgram.c src/fft/src/spgram.c src/fft/src/spwaterfall.c
src/fft/src/spgramf.o : %.o : %.c $(include_headers) src/fft/src/asgram.c src/fft/src/spgram.c src/fft/src/spwaterfall.c
# fft autotest scripts
fft_autotests := \
@ -657,6 +653,7 @@ framing_benchmarks := \
src/framing/bench/flexframesync_benchmark.c \
src/framing/bench/framesync64_benchmark.c \
src/framing/bench/gmskframesync_benchmark.c \
src/framing/bench/qdetector_benchmark.c \
#
@ -1158,8 +1155,6 @@ benchmark_sources := \
.PHONY: all
# Shared library
#SHARED_LIB = libliquid.so
#MINGW:
SHARED_LIB = libliquid.dll
@ -1172,15 +1167,14 @@ libliquid.a: $(objects)
#
# gcc -dynamiclib -install_name libliquid.dylib -o libliquid.dylib libmodem.a libutility.a
libliquid.dylib: $(objects)
$(CC) -dynamiclib -install_name $@ -o $@ $^ $(LDFLAGS)
$(CC) -dynamiclib -install_name $@ -o $@ $^ $(LDFLAGS) $(LIBS)
# linux, et al
libliquid.so: libliquid.a
$(CC) -shared -Xlinker -soname=$@ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive $(LDFLAGS)
# MINGW*
$(CC) $(CFLAGS) $(LDFLAGS) -shared -Xlinker -soname=$@ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive $(LIBS)
#MINGW:
libliquid.dll: libliquid.a
$(CC) -shared -Xlinker -soname=$@ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive -Wl,--output-def,libliquid.def -Wl,--out-implib,libliquid.lib $(LDFLAGS)
$(CC) -shared -Xlinker -soname=$@ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive -Wl,--output-def,libliquid.def -Wl,--out-implib,libliquid.lib $(LIBS)
all: libliquid.a $(SHARED_LIB)
@ -1236,10 +1230,10 @@ uninstall:
autoscript : scripts/autoscript
scripts/autoscript.o scripts/main.o : %.o : %.c
$(CC) $(CFLAGS) -c -o $@ $<
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
scripts/autoscript : scripts/autoscript.o scripts/main.o
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
clean-autoscript :
$(RM) scripts/autoscript.o scripts/main.o scripts/autoscript
@ -1265,23 +1259,23 @@ autotest_include.h : scripts/autoscript $(autotest_sources) $(include_headers)
# the '-x c' flag
autotest_obj = $(patsubst %.c,%.o,$(autotest_sources))
$(autotest_obj) : %.o : %.c $(include_headers)
$(CC) $(CFLAGS) $< -c -o $@
$(CC) $(CPPFLAGS) $(CFLAGS) $< -c -o $@
# additional autotest objects
$(autotest_extra_obj) : %.o : %.c $(include_headers)
# compile the autotest internal library functions without linking
autotest/autotestlib.o : autotest/autotestlib.c autotest/autotest.h
$(CC) $(CFLAGS) $< -c -o $@
$(CC) $(CPPFLAGS) $(CFLAGS) $< -c -o $@
# compile the autotest program without linking
$(autotest_prog).o : autotest/autotest.c autotest/autotest.h autotest_include.h
$(CC) $(CFLAGS) $< -c -o $@
$(CC) $(CPPFLAGS) $(CFLAGS) $< -c -o $@
# link the autotest program with the objects
# NOTE: linked libraries must come _after_ the target program
$(autotest_prog): $(autotest_prog).o $(autotest_obj) $(autotest_extra_obj) autotest/autotestlib.o libliquid.a
$(CC) $^ -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)
# run the autotest program
check: $(autotest_prog)
@ -1306,8 +1300,10 @@ clean-check:
# on the target platform.
.PHONY: bench
bench_prog = benchmark
BENCH_CFLAGS = -Wall $(INCLUDE_CFLAGS) $(CONFIG_CFLAGS)
BENCH_CPPFLAGS = $(CPPFLAGS)
BENCH_CFLAGS = -Wall $(CFLAGS)
BENCH_LDFLAGS = $(LDFLAGS)
BENCH_LIBS = $(LIBS)
# run the benchmark generator script to create benchmark_include.h
benchmark_include.h : scripts/autoscript $(benchmark_sources) $(include_headers)
@ -1319,19 +1315,19 @@ benchmark_include.h : scripts/autoscript $(benchmark_sources) $(include_headers)
# the '-x c' flag
benchmark_obj = $(patsubst %.c,%.o,$(benchmark_sources))
$(benchmark_obj) : %.o : %.c $(include_headers)
$(CC) $(BENCH_CFLAGS) $< -c -o $@
$(CC) $(BENCH_CPPFLAGS) $(BENCH_CFLAGS) $< -c -o $@
# additional benchmark objects
$(benchmark_extra_obj) : %.o : %.c $(include_headers)
# compile the benchmark program without linking
$(bench_prog).o: bench/bench.c benchmark_include.h bench/bench.c
$(CC) $(BENCH_CFLAGS) $< -c -o $(bench_prog).o
$(CC) $(BENCH_CPPFLAGS) $(BENCH_CFLAGS) $< -c -o $(bench_prog).o
# link the benchmark program with the library objects
# NOTE: linked libraries must come _after_ the target program
$(bench_prog): $(bench_prog).o $(benchmark_obj) $(benchmark_extra_obj) libliquid.a
$(CC) $^ -o $(bench_prog) $(BENCH_LDFLAGS)
$(CC) $(BENCH_CFLAGS) $(BENCH_LDFLAGS) $^ -o $(bench_prog) $(BENCH_LIBS)
# run the benchmark program
bench: $(bench_prog)
@ -1339,14 +1335,14 @@ bench: $(bench_prog)
# benchmark compare script
scripts/benchmark_compare : % : %.c
$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS)
# fftbench program
bench/fftbench.o : %.o : %.c
$(CC) $(BENCH_CFLAGS) $< -c -o $@
$(CC) $(BENCH_CPPFLAGS) $(BENCH_CFLAGS) $< -c -o $@
bench/fftbench : % : %.o libliquid.a
$(CC) $^ -o $@ $(BENCH_LDFLAGS)
$(CC) $(BENCH_CFLAGS) $(BENCH_LDFLAGS) $^ -o $@ $(BENCH_LIBS)
# clean up the generated files
clean-bench:
@ -1364,6 +1360,7 @@ clean-bench:
.PHONY: examples
example_programs := \
examples/agc_crcf_example \
examples/agc_crcf_squelch_example \
examples/agc_crcf_qpsk_example \
examples/agc_rrrf_example \
examples/ampmodem_example \
@ -1403,7 +1400,9 @@ example_programs := \
examples/firfilt_crcf_example \
examples/firfilt_rrrf_example \
examples/firdes_kaiser_example \
examples/firdespm_callback_example \
examples/firdespm_example \
examples/firdespm_lowpass_example \
examples/firhilb_example \
examples/firhilb_decim_example \
examples/firhilb_interp_example \
@ -1480,6 +1479,7 @@ example_programs := \
examples/spgramcf_example \
examples/spgramcf_waterfall_example \
examples/spgramf_example \
examples/spwaterfallcf_example \
examples/symsync_crcf_example \
examples/symsync_crcf_full_example \
examples/symsync_crcf_kaiser_example \
@ -1496,13 +1496,11 @@ example_programs := \
example_objects = $(patsubst %,%.o,$(example_programs))
examples: $(example_programs)
EXAMPLES_LDFLAGS = $(LDFLAGS)
# NOTE: linked libraries must come _after_ the target program
$(example_objects): %.o : %.c
$(example_programs): % : %.o libliquid.a
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS)
# clean examples
clean-examples:
@ -1624,7 +1622,7 @@ SANDBOX_LDFLAGS = $(LDFLAGS) -lfftw3f
$(sandbox_objects): %.o : %.c
$(sandbox_programs): % : %.o libliquid.a
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) $(LIBS)
# clean sandbox
clean-sandbox:

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@ -1366,7 +1366,6 @@ bool AppFrame::actionOnMenuAudioSampleRate(wxCommandEvent& event) {
}
i++;
}
}
return false;

View File

@ -205,12 +205,12 @@ private:
SpectrumVisualDataThread *spectrumVisualThread = nullptr;
SpectrumVisualDataThread *demodVisualThread = nullptr;
SDRThreadIQDataQueuePtr pipeSDRIQData = nullptr;
DemodulatorThreadInputQueuePtr pipeIQVisualData = nullptr;
DemodulatorThreadOutputQueuePtr pipeAudioVisualData = nullptr;
DemodulatorThreadInputQueuePtr pipeDemodIQVisualData = nullptr;
DemodulatorThreadInputQueuePtr pipeWaterfallIQVisualData = nullptr;
DemodulatorThreadInputQueuePtr pipeActiveDemodIQVisualData = nullptr;
SDRThreadIQDataQueuePtr pipeSDRIQData;
DemodulatorThreadInputQueuePtr pipeIQVisualData;
DemodulatorThreadOutputQueuePtr pipeAudioVisualData;
DemodulatorThreadInputQueuePtr pipeDemodIQVisualData;
DemodulatorThreadInputQueuePtr pipeWaterfallIQVisualData;
DemodulatorThreadInputQueuePtr pipeActiveDemodIQVisualData;
ScopeVisualProcessor scopeProcessor;

View File

@ -59,3 +59,7 @@ const char filePathSeparator =
//Represents the amount of time to process in the FFT distributor.
#define FFT_DISTRIBUTOR_BUFFER_IN_SECONDS 0.250
//The maximum number of listed sample rates for a device, to be able to handle
//devices returning an insane amount because they have quasi-continuous ranges (UHD...)
#define DEVICE_SAMPLE_RATES_MAX_NB 25

View File

@ -18,8 +18,9 @@ std::map<int, AudioThread *> AudioThread::deviceController;
std::map<int, int> AudioThread::deviceSampleRate;
std::map<int, std::thread *> AudioThread::deviceThread;
AudioThread::AudioThread() : IOThread(),
currentInput(nullptr), inputQueue(nullptr), nBufferFrames(1024), sampleRate(0) {
std::recursive_mutex AudioThread::m_device_mutex;
AudioThread::AudioThread() : IOThread(), nBufferFrames(1024), sampleRate(0) {
audioQueuePtr = 0;
underflowCount = 0;
@ -29,7 +30,7 @@ AudioThread::AudioThread() : IOThread(),
}
AudioThread::~AudioThread() {
std::lock_guard<std::recursive_mutex> lock(m_mutex);
}
std::recursive_mutex & AudioThread::getMutex()
@ -50,8 +51,8 @@ void AudioThread::removeThread(AudioThread *other) {
std::lock_guard<std::recursive_mutex> lock(m_mutex);
std::vector<AudioThread *>::iterator i;
i = std::find(boundThreads.begin(), boundThreads.end(), other);
auto i = std::find(boundThreads.begin(), boundThreads.end(), other);
if (i != boundThreads.end()) {
boundThreads.erase(i);
}
@ -59,9 +60,9 @@ void AudioThread::removeThread(AudioThread *other) {
void AudioThread::deviceCleanup() {
std::map<int, AudioThread *>::iterator i;
std::lock_guard<std::recursive_mutex> lock(m_device_mutex);
for (i = deviceController.begin(); i != deviceController.end(); i++) {
for (auto i = deviceController.begin(); i != deviceController.end(); i++) {
i->second->terminate();
}
}
@ -279,22 +280,46 @@ void AudioThread::enumerateDevices(std::vector<RtAudio::DeviceInfo> &devs) {
void AudioThread::setDeviceSampleRate(int deviceId, int sampleRate) {
AudioThread* matchingAudioThread = nullptr;
//scope lock here to minimize the common unique static lock contention
{
std::lock_guard<std::recursive_mutex> lock(m_device_mutex);
if (deviceController.find(deviceId) != deviceController.end()) {
matchingAudioThread = deviceController[deviceId];
}
}
//out-of-lock test
if (matchingAudioThread != nullptr) {
AudioThreadCommand refreshDevice;
refreshDevice.cmd = AudioThreadCommand::AUDIO_THREAD_CMD_SET_SAMPLE_RATE;
refreshDevice.int_value = sampleRate;
//VSO : blocking push !
deviceController[deviceId]->getCommandQueue()->push(refreshDevice);
matchingAudioThread->getCommandQueue()->push(refreshDevice);
}
}
void AudioThread::setSampleRate(int sampleRate) {
std::lock_guard<std::recursive_mutex> lock(m_mutex);
bool outputIsThis = false;
//scope lock here to minimize the common unique static lock contention
{
std::lock_guard<std::recursive_mutex> lock(m_device_mutex);
if (deviceController[outputDevice.load()] == this) {
outputIsThis = true;
deviceSampleRate[outputDevice.load()] = sampleRate;
}
}
std::lock_guard<std::recursive_mutex> lock(m_mutex);
if (outputIsThis) {
dac.stopStream();
dac.closeStream();
@ -328,7 +353,8 @@ int AudioThread::getSampleRate() {
void AudioThread::setupDevice(int deviceId) {
std::lock_guard<std::recursive_mutex> lock(m_mutex);
//global lock to setup the device...
std::lock_guard<std::recursive_mutex> lock(m_device_mutex);
parameters.deviceId = deviceId;
parameters.nChannels = 2;
@ -381,6 +407,7 @@ void AudioThread::setupDevice(int deviceId) {
}
int AudioThread::getOutputDevice() {
std::lock_guard<std::recursive_mutex> lock(m_mutex);
if (outputDevice == -1) {
@ -391,7 +418,8 @@ int AudioThread::getOutputDevice() {
void AudioThread::setInitOutputDevice(int deviceId, int sampleRate) {
std::lock_guard<std::recursive_mutex> lock(m_mutex);
//global lock
std::lock_guard<std::recursive_mutex> lock(m_device_mutex);
outputDevice = deviceId;
if (sampleRate == -1) {
@ -441,19 +469,21 @@ void AudioThread::run() {
}
}
//Thread termination, prevent fancy things to happen, lock the whole thing:
//This way audioThreadCallback is rightly protected from thread termination
std::lock_guard<std::recursive_mutex> lock(m_mutex);
// Drain any remaining inputs, with a non-blocking pop
if (inputQueue != nullptr) {
inputQueue->flush();
}
//Thread termination, prevent fancy things to happen, lock the whole thing:
//This way audioThreadCallback is rightly protected from thread termination
std::lock_guard<std::recursive_mutex> lock(m_mutex);
//Nullify currentInput...
currentInput = nullptr;
//Stop
//Stop : this affects the device list , so must be protected globally.
std::lock_guard<std::recursive_mutex> global_lock(m_device_mutex);
if (deviceController[parameters.deviceId] != this) {
deviceController[parameters.deviceId]->removeThread(this);
} else {
@ -484,16 +514,28 @@ bool AudioThread::isActive() {
void AudioThread::setActive(bool state) {
AudioThread* matchingAudioThread = nullptr;
//scope lock here to minimize the common unique static lock contention
{
std::lock_guard<std::recursive_mutex> lock(m_device_mutex);
if (deviceController.find(parameters.deviceId) != deviceController.end()) {
matchingAudioThread = deviceController[parameters.deviceId];
}
}
std::lock_guard<std::recursive_mutex> lock(m_mutex);
if (deviceController[parameters.deviceId] == nullptr) {
if (matchingAudioThread == nullptr) {
return;
}
if (state && !active && inputQueue) {
deviceController[parameters.deviceId]->bindThread(this);
matchingAudioThread->bindThread(this);
} else if (!state && active) {
deviceController[parameters.deviceId]->removeThread(this);
matchingAudioThread->removeThread(this);
}
// Activity state changing, clear any inputs

View File

@ -122,7 +122,9 @@ private:
void removeThread(AudioThread *other);
static std::map<int, AudioThread *> deviceController;
static std::map<int, std::thread *> deviceThread;
//The mutex protecting static deviceController, deviceThread and deviceSampleRate access.
static std::recursive_mutex m_device_mutex;
};

View File

@ -15,7 +15,7 @@
//50 ms
#define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000)
DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance* parent) : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr), iqInputQueue(NULL), iqOutputQueue(NULL)
DemodulatorPreThread::DemodulatorPreThread(DemodulatorInstance* parent) : IOThread(), iqResampler(NULL), iqResampleRatio(1), cModem(nullptr), cModemKit(nullptr)
{
initialized.store(false);
this->parent = parent;

View File

@ -62,10 +62,10 @@ protected:
Modem *cModem = nullptr;
ModemKit *cModemKit = nullptr;
DemodulatorThreadPostInputQueuePtr iqInputQueue = nullptr;
AudioThreadInputQueuePtr audioOutputQueue = nullptr;
DemodulatorThreadOutputQueuePtr audioVisOutputQueue = nullptr;
DemodulatorThreadControlCommandQueuePtr threadQueueControl = nullptr;
DemodulatorThreadPostInputQueuePtr iqInputQueue;
AudioThreadInputQueuePtr audioOutputQueue;
DemodulatorThreadOutputQueuePtr audioVisOutputQueue;
DemodulatorThreadControlCommandQueuePtr threadQueueControl;
DemodulatorThreadOutputQueuePtr audioSinkOutputQueue = nullptr;

View File

@ -10,7 +10,7 @@
#define HEARTBEAT_CHECK_PERIOD_MICROS (50 * 1000)
DemodulatorWorkerThread::DemodulatorWorkerThread() : IOThread(),
commandQueue(nullptr), resultQueue(nullptr), cModem(nullptr), cModemKit(nullptr) {
cModem(nullptr), cModemKit(nullptr) {
}
DemodulatorWorkerThread::~DemodulatorWorkerThread() {

View File

@ -1,8 +1,8 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jun 17 2015)
// C++ code generated with wxFormBuilder (version Oct 27 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "BookmarkPanel.h"

View File

@ -1,8 +1,8 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jun 17 2015)
// C++ code generated with wxFormBuilder (version Oct 27 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __BOOKMARKPANEL_H__

View File

@ -1,8 +1,8 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// C++ code generated with wxFormBuilder (version Oct 27 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "AboutDialogBase.h"
@ -22,7 +22,7 @@ AboutDialogBase::AboutDialogBase( wxWindow* parent, wxWindowID id, const wxStrin
m_appName = new wxStaticText(m_hPanel, wxID_ANY, wxT("CubicSDR"), wxDefaultPosition, wxDefaultSize, 0);
m_appName->Wrap(-1);
m_appName->SetFont( wxFont( 20, 70, 90, 90, false, wxEmptyString ) );
m_appName->SetFont(wxFont(20, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
m_hSizer->Add(m_appName, 0, wxALL, 6);
@ -45,19 +45,19 @@ AboutDialogBase::AboutDialogBase( wxWindow* parent, wxWindowID id, const wxStrin
m_dbHeader = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Developed By"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
m_dbHeader->Wrap(-1);
m_dbHeader->SetFont( wxFont( 15, 70, 90, 90, false, wxEmptyString ) );
m_dbHeader->SetFont(wxFont(15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
m_dbSizer->Add(m_dbHeader, 0, wxALL, 5);
m_dbGHHeader = new wxStaticText(m_dbScroll, wxID_ANY, wxT("GitHub"), wxDefaultPosition, wxDefaultSize, 0);
m_dbGHHeader->Wrap(-1);
m_dbGHHeader->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxEmptyString ) );
m_dbGHHeader->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
m_dbSizer->Add(m_dbGHHeader, 0, wxALL, 5);
m_dbTwitter = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Twitter"), wxDefaultPosition, wxDefaultSize, 0);
m_dbTwitter->Wrap(-1);
m_dbTwitter->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxEmptyString ) );
m_dbTwitter->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
m_dbSizer->Add(m_dbTwitter, 0, wxALL, 5);
@ -98,13 +98,13 @@ AboutDialogBase::AboutDialogBase( wxWindow* parent, wxWindowID id, const wxStrin
m_cContributorsHeader = new wxStaticText(m_dbScroll, wxID_ANY, wxT("Contributors"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
m_cContributorsHeader->Wrap(-1);
m_cContributorsHeader->SetFont( wxFont( 15, 70, 90, 90, false, wxEmptyString ) );
m_cContributorsHeader->SetFont(wxFont(15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
m_cSizer->Add(m_cContributorsHeader, 0, wxALL, 5);
m_cGitHub = new wxStaticText(m_dbScroll, wxID_ANY, wxT("GitHub"), wxDefaultPosition, wxDefaultSize, 0);
m_cGitHub->Wrap(-1);
m_cGitHub->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxEmptyString ) );
m_cGitHub->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
m_cSizer->Add(m_cGitHub, 0, wxALL, 5);
@ -190,7 +190,7 @@ AboutDialogBase::AboutDialogBase( wxWindow* parent, wxWindowID id, const wxStrin
m_dHeader = new wxStaticText(m_dScroll, wxID_ANY, wxT("Thanks to everyone who donated at cubicsdr.com!"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
m_dHeader->Wrap(-1);
m_dHeader->SetFont( wxFont( 15, 70, 90, 90, false, wxEmptyString ) );
m_dHeader->SetFont(wxFont(15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
m_dSizer->Add(m_dHeader, 0, wxALL, 5);
@ -383,7 +383,7 @@ AboutDialogBase::AboutDialogBase( wxWindow* parent, wxWindowID id, const wxStrin
m_stHeader = new wxStaticText(m_stScroll, wxID_ANY, wxT("Special Thanks To"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
m_stHeader->Wrap(-1);
m_stHeader->SetFont( wxFont( 15, 70, 90, 90, false, wxEmptyString ) );
m_stHeader->SetFont(wxFont(15, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
m_stSizer->Add(m_stHeader, 0, wxALL, 5);
@ -392,7 +392,7 @@ AboutDialogBase::AboutDialogBase( wxWindow* parent, wxWindowID id, const wxStrin
m_stSoapyDevAssistHeader = new wxStaticText(m_stScroll, wxID_ANY, wxT("SoapySDR Development and Assistance:"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
m_stSoapyDevAssistHeader->Wrap(-1);
m_stSoapyDevAssistHeader->SetFont( wxFont( 10, 70, 90, 92, false, wxEmptyString ) );
m_stSoapyDevAssistHeader->SetFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString));
m_stSizer->Add(m_stSoapyDevAssistHeader, 0, wxALL, 5);
@ -405,7 +405,7 @@ AboutDialogBase::AboutDialogBase( wxWindow* parent, wxWindowID id, const wxStrin
m_stLiquidDSPHeader = new wxStaticText(m_stScroll, wxID_ANY, wxT("Liquid-DSP Development and Assistance:"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
m_stLiquidDSPHeader->Wrap(-1);
m_stLiquidDSPHeader->SetFont( wxFont( 10, 70, 90, 92, false, wxEmptyString ) );
m_stLiquidDSPHeader->SetFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString));
m_stSizer->Add(m_stLiquidDSPHeader, 0, wxALL, 5);
@ -418,7 +418,7 @@ AboutDialogBase::AboutDialogBase( wxWindow* parent, wxWindowID id, const wxStrin
m_stIdeasDirectionsHeader = new wxStaticText(m_stScroll, wxID_ANY, wxT("Ideas, Direction && Encouragement:"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE);
m_stIdeasDirectionsHeader->Wrap(-1);
m_stIdeasDirectionsHeader->SetFont( wxFont( 10, 70, 90, 92, false, wxEmptyString ) );
m_stIdeasDirectionsHeader->SetFont(wxFont(10, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString));
m_stSizer->Add(m_stIdeasDirectionsHeader, 0, wxALL, 5);

View File

@ -1,8 +1,8 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// C++ code generated with wxFormBuilder (version Oct 27 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __ABOUTDIALOGBASE_H__

View File

@ -1,8 +1,8 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// C++ code generated with wxFormBuilder (version Oct 27 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "ActionDialogBase.h"

View File

@ -1,8 +1,8 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// C++ code generated with wxFormBuilder (version Oct 27 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __ACTIONDIALOGBASE_H__

View File

@ -1,8 +1,8 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// C++ code generated with wxFormBuilder (version Oct 27 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "PortSelectorDialogBase.h"

View File

@ -1,8 +1,8 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// C++ code generated with wxFormBuilder (version Oct 27 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __PORTSELECTORDIALOGBASE_H__

View File

@ -1,8 +1,8 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// C++ code generated with wxFormBuilder (version Oct 27 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "DigitalConsoleFrame.h"
@ -22,7 +22,7 @@ DigitalConsoleFrame::DigitalConsoleFrame( wxWindow* parent, wxWindowID id, const
m_dataView = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_CHARWRAP | wxTE_MULTILINE | wxTE_NOHIDESEL | wxTE_READONLY | wxTE_WORDWRAP | wxALWAYS_SHOW_SB | wxFULL_REPAINT_ON_RESIZE | wxNO_BORDER | wxSIMPLE_BORDER | wxVSCROLL);
m_dataView->SetExtraStyle(wxWS_EX_PROCESS_UI_UPDATES);
m_dataView->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 76, 90, 90, false, wxEmptyString ) );
m_dataView->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString));
dataViewSizer->Add(m_dataView, 1, wxEXPAND, 5);

View File

@ -1,8 +1,8 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// C++ code generated with wxFormBuilder (version Oct 27 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __DIGITALCONSOLEFRAME_H__

View File

@ -1,8 +1,8 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// C++ code generated with wxFormBuilder (version Oct 27 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "SDRDeviceAddForm.h"

View File

@ -1,8 +1,8 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// C++ code generated with wxFormBuilder (version Oct 27 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __SDRDEVICEADDFORM_H__

View File

@ -1,8 +1,8 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// C++ code generated with wxFormBuilder (version Oct 27 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "SDRDevicesForm.h"

View File

@ -1,8 +1,8 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Aug 23 2015)
// C++ code generated with wxFormBuilder (version Oct 27 2017)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#ifndef __SDRDEVICESFORM_H__

View File

@ -24,19 +24,21 @@ public:
typedef std::shared_ptr<VisualInputQueueType> VisualInputQueueTypePtr;
typedef std::shared_ptr<VisualOutputQueueType> VisualOutputQueueTypePtr;
typedef typename std::vector< VisualOutputQueueTypePtr >::iterator outputs_i;
virtual ~VisualProcessor() {
}
bool isInputEmpty() {
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
std::lock_guard < std::mutex > busy_lock(busy_update);
if (input) {
return input->empty();
}
return true;
}
bool isOutputEmpty() {
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
std::lock_guard < std::mutex > busy_lock(busy_update);
for (VisualOutputQueueTypePtr single_output : outputs) {
if (single_output->full()) {
@ -47,7 +49,7 @@ public:
}
bool isAnyOutputEmpty() {
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
std::lock_guard < std::mutex > busy_lock(busy_update);
for (VisualOutputQueueTypePtr single_output : outputs) {
if (!(single_output)->full()) {
@ -59,7 +61,7 @@ public:
//Set a (new) 'input' queue for incoming data.
void setInput(VisualInputQueueTypePtr vis_in) {
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
std::lock_guard < std::mutex > busy_lock(busy_update);
input = vis_in;
}
@ -68,27 +70,39 @@ public:
//dispatched by distribute().
void attachOutput(VisualOutputQueueTypePtr vis_out) {
// attach an output queue
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
std::lock_guard < std::mutex > busy_lock(busy_update);
outputs.push_back(vis_out);
}
//reverse of attachOutput(), removed an existing attached vis_out.
void removeOutput(VisualOutputQueueTypePtr vis_out) {
// remove an output queue
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
std::lock_guard < std::mutex > busy_lock(busy_update);
outputs_i i = std::find(outputs.begin(), outputs.end(), vis_out);
if (i != outputs.end()) {
outputs.erase(i);
auto it = std::find(outputs.begin(), outputs.end(), vis_out);
if (it != outputs.end()) {
outputs.erase(it);
}
}
//Flush all queues, either input or outputs clearing their accumulated messages.
//this is purposefully non-blocking call.
//this is purposefully (almost) non-blocking call.
void flushQueues() {
//DO NOT take the busy_update, we want a never blocking op how imperfect it could be.
input->flush();
for (auto single_output : outputs) {
//capture a local copy atomically, so we don't need to protect input.
VisualInputQueueTypePtr localInput = input;
if (localInput) {
localInput->flush();
}
//scoped-lock: create a local copy of outputs, and work with it.
std::vector<VisualOutputQueueTypePtr> local_outputs;
{
std::lock_guard < std::mutex > busy_lock(busy_update);
local_outputs = outputs;
}
for (auto single_output : local_outputs) {
single_output->flush();
}
@ -97,16 +111,17 @@ public:
//Call process() repeateadly until all available 'input' data is consumed.
void run() {
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
//capture a local copy atomically, so we don't need to protect input.
VisualInputQueueTypePtr localInput = input;
if (input && !input->empty()) {
if (localInput && !localInput->empty()) {
process();
}
}
protected:
// derived class must implement a process() interface
//where typically 'input' data is consummed, procerssed, and then dispatched
//where typically 'input' data is consummed, processed, and then dispatched
//with distribute() to all 'outputs'.
virtual void process() = 0;
@ -117,27 +132,27 @@ protected:
//* \param[in] errorMessage an error message written on std::cout in case pf push timeout.
void distribute(OutputDataTypePtr item, std::uint64_t timeout = BLOCKING_INFINITE_TIMEOUT, const char* errorMessage = nullptr) {
std::lock_guard < std::recursive_mutex > busy_lock(busy_update);
std::lock_guard < std::mutex > busy_lock(busy_update);
//We will try to distribute 'output' among all 'outputs',
//so 'output' will a-priori be shared among all 'outputs'.
for (VisualOutputQueueTypePtr single_output : outputs) {
//'output' can fail to be given to an outputs_i,
//'output' can fail to be given to an single_output,
//using a blocking push, with a timeout
if (!(single_output)->push(item, timeout, errorMessage)) {
//TODO : trace ?
//trace will be std::output if timeout != 0 is set and errorMessage != null.
}
}
}
//the incoming data queue
VisualInputQueueTypePtr input = nullptr;
VisualInputQueueTypePtr input;
//the n-outputs where to process()-ed data is distribute()-ed.
std::vector<VisualOutputQueueTypePtr> outputs;
//protects input and outputs, must be recursive because of re-entrance
std::recursive_mutex busy_update;
//protects input and outputs
std::mutex busy_update;
};
//Specialization much like VisualDataReDistributor, except
@ -153,10 +168,9 @@ protected:
while (VisualProcessor<OutputDataType, OutputDataType>::input->try_pop(inp)) {
//do not try to distribute if all outputs are already full.
if (!VisualProcessor<OutputDataType, OutputDataType>::isAnyOutputEmpty()) {
if (inp) {
//nothing
}
return;
}
@ -187,10 +201,9 @@ protected:
while (VisualProcessor<OutputDataType, OutputDataType>::input->try_pop(inp)) {
//do not try to distribute if all outputs are already full.
if (!VisualProcessor<OutputDataType, OutputDataType>::isAnyOutputEmpty()) {
if (inp) {
//nothing
}
return;
}

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0+
#include "SDRDeviceInfo.h"
#include "CubicSDRDefs.h"
#include <cstdlib>
#include <algorithm>
@ -179,12 +180,38 @@ bool SDRDeviceInfo::hasCORR(int direction, size_t channel) {
}
std::vector<long> SDRDeviceInfo::getSampleRates(int direction, size_t channel) {
SoapySDR::Device *dev = getSoapyDevice();
size_t nbMaxDifferentRates = DEVICE_SAMPLE_RATES_MAX_NB;
std::vector<long> result;
//the original list returned from the driver:
std::vector<double> sampleRates = dev->listSampleRates(direction, channel);
for (double si : sampleRates) {
result.push_back((long)si);
//be paranoid, sort by increasing rates...
std::sort(sampleRates.begin(), sampleRates.end(), [](double a, double b) -> bool { return a < b; });
//if sampleRates.size() > nbMaxDifferentRates, decimate this number to only return nbMaxDifferentRates sample
//rates values.
size_t sampleRateSelectionStep = 1;
if (sampleRates.size() / nbMaxDifferentRates >= 2) {
sampleRateSelectionStep = sampleRates.size() / nbMaxDifferentRates;
}
for (size_t i = 0; sampleRateSelectionStep * i < sampleRates.size(); i++) {
//convert to longs...
result.push_back((long)sampleRates[sampleRateSelectionStep * i]);
}
//always include the biggest value:
if ((long)sampleRates.back() > result.back()) {
result.push_back((long)sampleRates.back());
}
return result;
@ -230,10 +257,13 @@ long SDRDeviceInfo::getSampleRateNear(int direction, size_t channel, long sample
SDRRangeMap SDRDeviceInfo::getGains(int direction, size_t channel) {
SoapySDR::Device *dev = getSoapyDevice();
std::vector<std::string> gainNames = dev->listGains(direction, channel);
std::map<std::string, SoapySDR::Range> gainMap;
for (std::string gname : gainNames) {
gainMap[gname] = dev->getGainRange(direction, channel, gname);
}