From 288e7c8dc51a5774a9130e29e5716e237399e962 Mon Sep 17 00:00:00 2001 From: "J.A. de Jong - Redu-Sone B.V., ASCEE V.O.F" Date: Tue, 27 Sep 2022 17:20:45 +0200 Subject: [PATCH] Input stream and output stream both running. Added lockfree boost dependency to git modules, removed carma build as it is not required and every time again downloads Armadillo. Added functions to enable / disable all channels at once. Fixed a bug with RtAudio input streams. Fixed a bug in StreamMgr leading to segfaults (how to: use std::move ;)). --- .gitmodules | 8 +- CMakeLists.txt | 1 - src/lasp/CMakeLists.txt | 9 +- src/lasp/device/lasp_daq.cpp | 3 +- src/lasp/device/lasp_daqconfig.cpp | 2 +- src/lasp/device/lasp_daqconfig.h | 22 +++ src/lasp/device/lasp_daqdata.cpp | 3 +- src/lasp/device/lasp_rtaudiodaq.cpp | 262 +++++++++++++------------- src/lasp/device/lasp_streammgr.cpp | 13 +- src/lasp/device/lasp_streammgr.h | 92 +++++---- src/lasp/pybind11/lasp_daq.cpp | 4 +- src/lasp/pybind11/lasp_daqconfig.cpp | 2 + src/lasp/pybind11/lasp_dsp_pybind.cpp | 2 +- src/lasp/pybind11/lasp_streammgr.cpp | 1 + third_party/boost/core | 1 + third_party/{ => boost}/lockfree | 0 third_party/rtaudio | 1 + 17 files changed, 244 insertions(+), 182 deletions(-) create mode 160000 third_party/boost/core rename third_party/{ => boost}/lockfree (100%) create mode 160000 third_party/rtaudio diff --git a/.gitmodules b/.gitmodules index 36191d5..8df0461 100644 --- a/.gitmodules +++ b/.gitmodules @@ -14,7 +14,7 @@ path = third_party/tomlplusplus url = https://github.com/marzer/tomlplusplus [submodule "third_party/lockfree"] - path = third_party/lockfree + path = third_party/boost/lockfree url = https://github.com/boostorg/lockfree [submodule "third_party/carma"] path = third_party/carma @@ -22,3 +22,9 @@ [submodule "third_party/thread-pool"] path = third_party/thread-pool url = https://github.com/bshoshany/thread-pool +[submodule "third_party/rtaudio"] + path = third_party/rtaudio + url = https://github.com/thestk/rtaudio +[submodule "third_party/boost/core"] + path = third_party/boost/core + url = https://github.com/boostorg/core diff --git a/CMakeLists.txt b/CMakeLists.txt index bb5b296..f1ff9fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,7 +80,6 @@ set(CMAKE_C_FLAGS_RELEASE "-O3 -flto -mfpmath=sse -march=x86-64 -mtune=native \ # ############################# End compilation flags include_directories(/usr/lib/python3.10/site-packages/numpy/core/include) -add_subdirectory(third_party/carma) if(LASP_FFT_BACKEND STREQUAL "FFTW") find_library(fftw3 REQUIRED NAMES fftw fftw3) diff --git a/src/lasp/CMakeLists.txt b/src/lasp/CMakeLists.txt index 5bfb393..a66c7c0 100644 --- a/src/lasp/CMakeLists.txt +++ b/src/lasp/CMakeLists.txt @@ -5,14 +5,15 @@ add_definitions(-DARMA_DONT_USE_WRAPPER) configure_file(lasp_config.h.in lasp_config.h) include_directories(${CMAKE_CURRENT_BINARY_DIR}) -include_directories(SYSTEM ../../third_party/carma/include) -include_directories(SYSTEM - ../../third_party/carma/extern/armadillo-code/include) include_directories(SYSTEM ../../third_party/carma/extern/pybind11/include) +include_directories(SYSTEM + ../../third_party/carma/extern/armadillo-code/include) +include_directories(SYSTEM ../../third_party/carma/include) include_directories(../../third_party/DebugTrace-cpp/include) -include_directories(../../third_party/lockfreeThreadsafe/include) +include_directories(../../third_party/boost/core/include) +include_directories(../../third_party/boost/lockfree/include) include_directories(../../third_party/gsl-lite/include) include_directories(../../third_party/tomlplusplus/include) include_directories(../../third_party/thread-pool) diff --git a/src/lasp/device/lasp_daq.cpp b/src/lasp/device/lasp_daq.cpp index a6d5db2..4c1f8fd 100644 --- a/src/lasp/device/lasp_daq.cpp +++ b/src/lasp/device/lasp_daq.cpp @@ -2,8 +2,6 @@ #include "debugtrace.hpp" #include "lasp_daqconfig.h" -DEBUGTRACE_VARIABLES; - #include "lasp_daq.h" #if LASP_HAS_ULDAQ == 1 #include "lasp_uldaq.h" @@ -57,6 +55,7 @@ Daq::Daq(const DeviceInfo &devinfo, const DaqConfiguration &config) } double Daq::samplerate() const { + DEBUGTRACE_ENTER; return availableSampleRates.at(sampleRateIndex); } diff --git a/src/lasp/device/lasp_daqconfig.cpp b/src/lasp/device/lasp_daqconfig.cpp index 0df5f02..bdae42f 100644 --- a/src/lasp/device/lasp_daqconfig.cpp +++ b/src/lasp/device/lasp_daqconfig.cpp @@ -1,4 +1,4 @@ -#define DEBUGTRACE_ENABLED +/* #define DEBUGTRACE_ENABLED */ #include "debugtrace.hpp" #include "lasp_daqconfig.h" diff --git a/src/lasp/device/lasp_daqconfig.h b/src/lasp/device/lasp_daqconfig.h index fa377a9..3ceb42a 100644 --- a/src/lasp/device/lasp_daqconfig.h +++ b/src/lasp/device/lasp_daqconfig.h @@ -315,6 +315,28 @@ public: * enabled. */ int getLowestOutChannel() const; + + /** + * @brief Set all input channels to enabled / disabled state. + * + * @param val true if enabled, false if disabled. + */ + void setAllInputEnabled(bool val) { + for(auto& ch: inchannel_config) { + ch.enabled = val; + } + } + + /** + * @brief Set all output channels to enabled / disabled state. + * + * @param val true if enabled, false if disabled. + */ + void setAllOutputEnabled(bool val) { + for(auto& ch: outchannel_config) { + ch.enabled = val; + } + } }; /** * @} diff --git a/src/lasp/device/lasp_daqdata.cpp b/src/lasp/device/lasp_daqdata.cpp index 04170c3..94174b3 100644 --- a/src/lasp/device/lasp_daqdata.cpp +++ b/src/lasp/device/lasp_daqdata.cpp @@ -1,6 +1,7 @@ -#include "lasp_daqdata.h" +/* #define DEBUGTRACE_ENABLED */ #include "debugtrace.hpp" #include +#include "lasp_daqdata.h" DEBUGTRACE_VARIABLES; diff --git a/src/lasp/device/lasp_rtaudiodaq.cpp b/src/lasp/device/lasp_rtaudiodaq.cpp index d6714ab..55acf8e 100644 --- a/src/lasp/device/lasp_rtaudiodaq.cpp +++ b/src/lasp/device/lasp_rtaudiodaq.cpp @@ -17,6 +17,7 @@ using std::vector; DEBUGTRACE_VARIABLES; void fillRtAudioDeviceInfo(vector &devinfolist) { + DEBUGTRACE_ENTER; vector apis; RtAudio::getCompiledApi(apis); @@ -34,25 +35,25 @@ void fillRtAudioDeviceInfo(vector &devinfolist) { // "Our device info struct" DeviceInfo d; switch (api) { - case RtAudio::LINUX_ALSA: - d.api = rtaudioAlsaApi; - break; - case RtAudio::LINUX_PULSE: - d.api = rtaudioPulseaudioApi; - break; - case RtAudio::WINDOWS_WASAPI: - d.api = rtaudioWasapiApi; - break; - case RtAudio::WINDOWS_DS: - d.api = rtaudioDsApi; - break; - case RtAudio::WINDOWS_ASIO: - d.api = rtaudioAsioApi; - break; - default: - cerr << "Not implemented RtAudio API, skipping." << endl; - continue; - break; + case RtAudio::LINUX_ALSA: + d.api = rtaudioAlsaApi; + break; + case RtAudio::LINUX_PULSE: + d.api = rtaudioPulseaudioApi; + break; + case RtAudio::WINDOWS_WASAPI: + d.api = rtaudioWasapiApi; + break; + case RtAudio::WINDOWS_DS: + d.api = rtaudioDsApi; + break; + case RtAudio::WINDOWS_ASIO: + d.api = rtaudioAsioApi; + break; + default: + cerr << "Not implemented RtAudio API, skipping." << endl; + continue; + break; } d.device_name = devinfo.name; @@ -82,7 +83,7 @@ void fillRtAudioDeviceInfo(vector &devinfolist) { } /* if (formats & RTAUDIO_SINT32) { */ /* d.availableDataTypes.push_back(DataTypeDescriptor::DataType::dtype_int24); - */ + */ /* } */ if (formats & RTAUDIO_SINT32) { d.availableDataTypes.push_back( @@ -106,8 +107,9 @@ void fillRtAudioDeviceInfo(vector &devinfolist) { } } -static int mycallback(void *outputBuffer, void *inputBuffer, unsigned int nFrames, - double streamTime, RtAudioStreamStatus status, void *userData); +static int mycallback(void *outputBuffer, void *inputBuffer, + unsigned int nFrames, double streamTime, + RtAudioStreamStatus status, void *userData); static void myerrorcallback(RtAudioError::Type, const string &errorText); @@ -124,91 +126,91 @@ class RtAudioDaq : public Daq { std::atomic _streamStatus{}; - public: +public: RtAudioDaq(const DeviceInfo &devinfo, const DaqConfiguration &config) - : Daq(devinfo, config), - rtaudio(static_cast(devinfo.api.api_specific_subcode)), - nFramesPerBlock(Daq::framesPerBlock()) { + : Daq(devinfo, config), + rtaudio(static_cast(devinfo.api.api_specific_subcode)), + nFramesPerBlock(Daq::framesPerBlock()) { - DEBUGTRACE_ENTER; + DEBUGTRACE_ENTER; - // We make sure not to run RtAudio in duplex mode. This seems to be buggy - // and untested. Better to use a hardware-type loopback into the system. - if (duplexMode()) { - throw runtime_error("RtAudio backend cannot run in duplex mode."); + // We make sure not to run RtAudio in duplex mode. This seems to be buggy + // and untested. Better to use a hardware-type loopback into the system. + if (duplexMode()) { + throw runtime_error("RtAudio backend cannot run in duplex mode."); + } + assert(!monitorOutput); + + std::unique_ptr inParams, outParams; + + if (neninchannels() > 0) { + + inParams = std::make_unique(); + + // +1 to get the count. + inParams->nChannels = getHighestInChannel() + 1; + if (inParams->nChannels < 1) { + throw runtime_error("Invalid input number of channels"); } - assert(!monitorOutput); + inParams->firstChannel = 0; + inParams->deviceId = devinfo.api_specific_devindex; - std::unique_ptr inParams, outParams; + } else { - if (neninchannels() > 0) { + outParams = std::make_unique(); - inParams = std::make_unique(); - - // +1 to get the count. - inParams->nChannels = getHighestInChannel() + 1; - if (inParams->nChannels < 1) { - throw runtime_error("Invalid input number of channels"); - } - inParams->firstChannel = 0; - inParams->deviceId = devinfo.api_specific_devindex; - - } else { - - outParams = std::make_unique(); - - outParams->nChannels = getHighestOutChannel() + 1; - if (outParams->nChannels < 1) { - throw runtime_error("Invalid output number of channels"); - } - outParams->firstChannel = 0; - outParams->deviceId = devinfo.api_specific_devindex; + outParams->nChannels = getHighestOutChannel() + 1; + if (outParams->nChannels < 1) { + throw runtime_error("Invalid output number of channels"); } - - RtAudio::StreamOptions streamoptions; - streamoptions.flags = RTAUDIO_HOG_DEVICE | RTAUDIO_NONINTERLEAVED; - - streamoptions.numberOfBuffers = 2; - streamoptions.streamName = "RtAudio stream"; - streamoptions.priority = 0; - - RtAudioFormat format; - using Dtype = DataTypeDescriptor::DataType; - const Dtype dtype = dataType(); - switch (dtype) { - case Dtype::dtype_fl32: - format = RTAUDIO_FLOAT32; - break; - case Dtype::dtype_fl64: - format = RTAUDIO_FLOAT64; - break; - case Dtype::dtype_int8: - format = RTAUDIO_SINT8; - break; - case Dtype::dtype_int16: - format = RTAUDIO_SINT16; - break; - case Dtype::dtype_int32: - format = RTAUDIO_SINT32; - break; - default: - throw runtime_error("Invalid data type specified for DAQ stream."); - break; - } - - // Copy here, as it is used to return the *actual* number of frames per - // block. - unsigned int nFramesPerBlock_copy = nFramesPerBlock; - - // Final step: open the stream. - rtaudio.openStream(outParams.get(), inParams.get(), format, - static_cast(samplerate()), &nFramesPerBlock_copy, - mycallback, (void *)this, &streamoptions, - &myerrorcallback); + outParams->firstChannel = 0; + outParams->deviceId = devinfo.api_specific_devindex; } + RtAudio::StreamOptions streamoptions; + streamoptions.flags = RTAUDIO_HOG_DEVICE | RTAUDIO_NONINTERLEAVED; + + streamoptions.numberOfBuffers = 2; + streamoptions.streamName = "RtAudio stream"; + streamoptions.priority = 0; + + RtAudioFormat format; + using Dtype = DataTypeDescriptor::DataType; + const Dtype dtype = dataType(); + switch (dtype) { + case Dtype::dtype_fl32: + format = RTAUDIO_FLOAT32; + break; + case Dtype::dtype_fl64: + format = RTAUDIO_FLOAT64; + break; + case Dtype::dtype_int8: + format = RTAUDIO_SINT8; + break; + case Dtype::dtype_int16: + format = RTAUDIO_SINT16; + break; + case Dtype::dtype_int32: + format = RTAUDIO_SINT32; + break; + default: + throw runtime_error("Invalid data type specified for DAQ stream."); + break; + } + + // Copy here, as it is used to return the *actual* number of frames per + // block. + unsigned int nFramesPerBlock_copy = nFramesPerBlock; + + // Final step: open the stream. + rtaudio.openStream(outParams.get(), inParams.get(), format, + static_cast(samplerate()), &nFramesPerBlock_copy, + mycallback, (void *)this, &streamoptions, + &myerrorcallback); + } + virtual void start(InDaqCallback inCallback, - OutDaqCallback outCallback) override { + OutDaqCallback outCallback) override final { DEBUGTRACE_ENTER; @@ -221,24 +223,25 @@ class RtAudioDaq : public Daq { // Logical XOR if (inCallback && outCallback) { throw runtime_error("Either input or output stream possible for RtAudio. " - "Stream duplex mode not provided."); + "Stream duplex mode not provided."); } if (inCallback) { _incallback = inCallback; - if (neninchannels()==0) { + if (neninchannels() == 0) { throw runtime_error( "Input callback given, but stream does not provide input data"); } } if (outCallback) { _outcallback = outCallback; - if (nenoutchannels()==0) { + if (nenoutchannels() == 0) { throw runtime_error( "Output callback given, but stream does not provide output data"); } } + // Start the stream. Throws on error. rtaudio.startStream(); // If we are here, we are running without errors. @@ -247,9 +250,9 @@ class RtAudioDaq : public Daq { _streamStatus = status; } - StreamStatus getStreamStatus() const override { return _streamStatus; } + StreamStatus getStreamStatus() const override final { return _streamStatus; } - void stop() override { + void stop() override final { DEBUGTRACE_ENTER; if (getStreamStatus().runningOK()) { rtaudio.stopStream(); @@ -261,11 +264,10 @@ class RtAudioDaq : public Daq { } int streamCallback(void *outputBuffer, void *inputBuffer, - unsigned int nFrames, double streamTime, + unsigned int nFrames, double streamTime, + RtAudioStreamStatus status) { - RtAudioStreamStatus status) { - - /* DEBUGTRACE_ENTER; */ + DEBUGTRACE_ENTER; using se = StreamStatus::StreamError; @@ -280,16 +282,16 @@ class RtAudioDaq : public Daq { }; switch (status) { - case RTAUDIO_INPUT_OVERFLOW: - stopWithError(se::inputXRun); - return 1; - break; - case RTAUDIO_OUTPUT_UNDERFLOW: - stopWithError(se::outputXRun); - return 1; - break; - default: - break; + case RTAUDIO_INPUT_OVERFLOW: + stopWithError(se::inputXRun); + return 1; + break; + case RTAUDIO_OUTPUT_UNDERFLOW: + stopWithError(se::outputXRun); + return 1; + break; + default: + break; } const auto &dtype_descr = DataTypeDescriptor(); @@ -299,25 +301,27 @@ class RtAudioDaq : public Daq { us sw = dtype_descr.sw; if (nFrames != nFramesPerBlock) { cerr << "RtAudio backend error: nFrames does not match block size!" - << endl; + << endl; stopWithError(se::logicError); return 1; } if (inputBuffer) { + assert(_incallback); std::vector ptrs; ptrs.reserve(neninchannels); - /* DaqData(neninchannels_inc_mon, nFramesPerBlock, dtype); */ + + us i = 0; for (int ch = getLowestInChannel(); ch <= getHighestInChannel(); ch++) { if (inchannel_config.at(ch).enabled) { - ptrs.push_back(&static_cast( - inputBuffer)[sw * ninchannels * ch * nFramesPerBlock]); + ptrs.push_back(static_cast(inputBuffer) + + sw * i * nFramesPerBlock); + i++; } } DaqData d{neninchannels, nFramesPerBlock, dtype}; d.copyInFromRaw(ptrs); - assert(_incallback); bool ret = _incallback(d); if (!ret) { stopWithError(se::noError); @@ -326,20 +330,24 @@ class RtAudioDaq : public Daq { } if (outputBuffer) { + assert(_outcallback); std::vector ptrs; ptrs.reserve(nenoutchannels); /* outCallback */ - for (int ch = 0; ch <= getHighestOutChannel(); ch++) { - /* DEBUGTRACE_PRINT(outchannel_config.at(ch).enabled); */ + us i = 0; + for (int ch = getLowestOutChannel(); ch <= getHighestOutChannel(); ch++) { + if (outchannel_config.at(ch).enabled) { - ptrs.push_back(&(static_cast( - outputBuffer)[sw * nenoutchannels * ch * nFramesPerBlock])); + + ptrs.push_back(static_cast(outputBuffer) + + sw * i * nFramesPerBlock); + + i++; } } DaqData d{nenoutchannels, nFramesPerBlock, dtype}; - assert(_outcallback); bool ret = _outcallback(d); if (!ret) { stopWithError(se::noError); @@ -362,7 +370,7 @@ class RtAudioDaq : public Daq { }; std::unique_ptr createRtAudioDevice(const DeviceInfo &devinfo, - const DaqConfiguration &config) { + const DaqConfiguration &config) { return std::make_unique(devinfo, config); } @@ -370,7 +378,7 @@ void myerrorcallback(RtAudioError::Type, const string &errorText) { cerr << "RtAudio backend stream error: " << errorText << endl; } int mycallback(void *outputBuffer, void *inputBuffer, unsigned int nFrames, - double streamTime, RtAudioStreamStatus status, void *userData) { + double streamTime, RtAudioStreamStatus status, void *userData) { return static_cast(userData)->streamCallback( outputBuffer, inputBuffer, nFrames, streamTime, status); diff --git a/src/lasp/device/lasp_streammgr.cpp b/src/lasp/device/lasp_streammgr.cpp index 5752156..42c2eec 100644 --- a/src/lasp/device/lasp_streammgr.cpp +++ b/src/lasp/device/lasp_streammgr.cpp @@ -57,7 +57,14 @@ void StreamMgr::checkRightThread() const { void StreamMgr::rescanDAQDevices(bool background, std::function callback) { + DEBUGTRACE_ENTER; + checkRightThread(); + if(!_devices_mtx.try_lock()) { + throw rte("A background DAQ device scan is probably already running"); + } + _devices_mtx.unlock(); + if (_inputStream || _outputStream) { throw rte("Rescanning DAQ devices only possible when no stream is running"); } @@ -70,6 +77,7 @@ void StreamMgr::rescanDAQDevices(bool background, } } void StreamMgr::rescanDAQDevices_impl(std::function callback) { + DEBUGTRACE_ENTER; std::scoped_lock lck(_devices_mtx); _devices = DeviceInfo::getDeviceInfo(); if (callback) { @@ -79,6 +87,7 @@ void StreamMgr::rescanDAQDevices_impl(std::function callback) { bool StreamMgr::inCallback(const DaqData &data) { /* DEBUGTRACE_ENTER; */ + std::scoped_lock lck(_inDataHandler_mtx); for (auto &handler : _inDataHandlers) { @@ -122,8 +131,6 @@ template bool fillData(DaqData &data, const vd &signal) { /* DEBUGTRACE_ENTER; */ assert(data.nframes == signal.size()); - /* cerr << "SFSG: data.nframes:" << data.nframes << endl; */ - /* cerr << "SFSG: data.nchannels:" << data.nchannels << endl; */ T *res = reinterpret_cast(data.raw_ptr()); if (std::is_floating_point()) { for (us ch = 0; ch < data.nchannels; ch++) { @@ -266,7 +273,7 @@ void StreamMgr::startStream(const DaqConfiguration &config) { if (isInput) { _inputStream = std::move(daq); - if (daq->duplexMode()) { + if (_inputStream->duplexMode()) { assert(!_outputStream); } } else { diff --git a/src/lasp/device/lasp_streammgr.h b/src/lasp/device/lasp_streammgr.h index c003a0b..8498dbb 100644 --- a/src/lasp/device/lasp_streammgr.h +++ b/src/lasp/device/lasp_streammgr.h @@ -13,48 +13,48 @@ class StreamMgr; class InDataHandler { -protected: - StreamMgr &_mgr; + protected: + StreamMgr &_mgr; #if LASP_DEBUG == 1 - std::atomic stopCalled{false}; + std::atomic stopCalled{false}; #endif -public: - virtual ~InDataHandler(); + public: + virtual ~InDataHandler(); - /** - * @brief When constructed, the handler is added to the stream manager, which - * will call the handlers's inCallback() until stop() is called. - * - * @param mgr Stream manager. - */ - InDataHandler(StreamMgr &mgr); + /** + * @brief When constructed, the handler is added to the stream manager, which + * will call the handlers's inCallback() until stop() is called. + * + * @param mgr Stream manager. + */ + InDataHandler(StreamMgr &mgr); - /** - * @brief This function is called when input data from a DAQ is available. - * - * @param daqdata Input data from DAQ - * - * @return true if no error. False to stop the stream from running. - */ - virtual bool inCallback(const DaqData &daqdata) = 0; + /** + * @brief This function is called when input data from a DAQ is available. + * + * @param daqdata Input data from DAQ + * + * @return true if no error. False to stop the stream from running. + */ + virtual bool inCallback(const DaqData &daqdata) = 0; - /** - * @brief This function should be called from the constructor of the - * implementation of InDataHandler. It will start the stream's calling of - * inCallback(). - */ - void start(); + /** + * @brief This function should be called from the constructor of the + * implementation of InDataHandler. It will start the stream's calling of + * inCallback(). + */ + void start(); - /** - * @brief This function should be called from the destructor of derived - * classes, to disable the calls to inCallback(), such that proper - * destruction of the object is allowed and no other threads call methods - * from the object. It removes the inCallback() from the callback list of the - * StreamMgr(). **Failing to call this function results in deadlocks, errors - * like "pure virtual function called", or other**. - */ - void stop(); + /** + * @brief This function should be called from the destructor of derived + * classes, to disable the calls to inCallback(), such that proper + * destruction of the object is allowed and no other threads call methods + * from the object. It removes the inCallback() from the callback list of the + * StreamMgr(). **Failing to call this function results in deadlocks, errors + * like "pure virtual function called", or other**. + */ + void stop(); }; /** @@ -101,7 +101,7 @@ class StreamMgr { // Singleton, no public destructor ~StreamMgr(); -public: + public: enum class StreamType : us { /** * @brief Input stream @@ -136,15 +136,16 @@ public: /** * @brief Triggers a background scan of the DAQ devices, which updates the - * internally stored list of devices. + * internally stored list of devices. Throws a runtime error when a + * background thread is already scanning for devices. * * @param background Perform searching for DAQ devices in the background. If * set to true, the function returns immediately. * @param callback Function to call when complete. */ void - rescanDAQDevices(bool background = false, - std::function callback = std::function()); + rescanDAQDevices(bool background = false, + std::function callback = std::function()); /** * @brief Start a stream based on given configuration. @@ -163,6 +164,17 @@ public: bool isStreamRunningOK(const StreamType type) const { return getStreamStatus(type).runningOK(); } + bool isStreamRunning(const StreamType type) const { + switch(type) { + case(StreamType::input): + return bool(_inputStream); + break; + case(StreamType::output): + return bool(_outputStream); + break; + } + return false; + } /** * @brief Get the streamstatus object corresponding to a given stream. @@ -205,7 +217,7 @@ public: */ void setSiggen(std::shared_ptr s); -private: + private: bool inCallback(const DaqData &data); bool outCallback(DaqData &data); diff --git a/src/lasp/pybind11/lasp_daq.cpp b/src/lasp/pybind11/lasp_daq.cpp index 38aeb89..7ddffb2 100644 --- a/src/lasp/pybind11/lasp_daq.cpp +++ b/src/lasp/pybind11/lasp_daq.cpp @@ -12,7 +12,7 @@ void init_daq(py::module &m) { py::class_ daq(m, "Daq"); /// Daq::StreamStatus - py::class_ ss(m, "StreamStatus"); + py::class_ ss(daq, "StreamStatus"); ss.def("error", &Daq::StreamStatus::error); ss.def("runningOK", &Daq::StreamStatus::runningOK); ss.def_readonly("isRunning", &Daq::StreamStatus::isRunning); @@ -29,6 +29,8 @@ void init_daq(py::module &m) { .value("apiSpecificError", Daq::StreamStatus::StreamError::apiSpecificError); + ss.def("errorMsg", &Daq::StreamStatus::errorMsg); + /// Daq daq.def("neninchannels", &Daq::neninchannels); daq.def("nenoutchannels", &Daq::nenoutchannels); diff --git a/src/lasp/pybind11/lasp_daqconfig.cpp b/src/lasp/pybind11/lasp_daqconfig.cpp index be97adf..41fc8a0 100644 --- a/src/lasp/pybind11/lasp_daqconfig.cpp +++ b/src/lasp/pybind11/lasp_daqconfig.cpp @@ -91,4 +91,6 @@ void init_daqconfiguration(py::module &m) { &DaqConfiguration::inchannel_config); daqconfig.def_readwrite("outchannel_config", &DaqConfiguration::outchannel_config); + daqconfig.def("setAllInputEnabled", &DaqConfiguration::setAllInputEnabled); + daqconfig.def("setAllOutputEnabled", &DaqConfiguration::setAllOutputEnabled); } diff --git a/src/lasp/pybind11/lasp_dsp_pybind.cpp b/src/lasp/pybind11/lasp_dsp_pybind.cpp index ca6c0e5..c6562c6 100644 --- a/src/lasp/pybind11/lasp_dsp_pybind.cpp +++ b/src/lasp/pybind11/lasp_dsp_pybind.cpp @@ -56,7 +56,7 @@ void init_dsp(py::module &m) { }); /// BiquadBank - py::class_ bqb(m, "BiquadBank"); + py::class_> bqb(m, "BiquadBank"); bqb.def(py::init()); bqb.def("setGains",&BiquadBank::setGains); bqb.def("filter",&BiquadBank::filter); diff --git a/src/lasp/pybind11/lasp_streammgr.cpp b/src/lasp/pybind11/lasp_streammgr.cpp index 15bc6d0..6e244f2 100644 --- a/src/lasp/pybind11/lasp_streammgr.cpp +++ b/src/lasp/pybind11/lasp_streammgr.cpp @@ -29,4 +29,5 @@ void init_streammgr(py::module &m) { smgr.def("getDeviceInfo", &StreamMgr::getDeviceInfo); smgr.def("getStreamStatus", &StreamMgr::getStreamStatus); smgr.def("isStreamRunningOK", &StreamMgr::isStreamRunningOK); + smgr.def("isStreamRunning", &StreamMgr::isStreamRunning); } diff --git a/third_party/boost/core b/third_party/boost/core new file mode 160000 index 0000000..b407b5d --- /dev/null +++ b/third_party/boost/core @@ -0,0 +1 @@ +Subproject commit b407b5d87df30f75ca501c1b6f2930c0913d4ca7 diff --git a/third_party/lockfree b/third_party/boost/lockfree similarity index 100% rename from third_party/lockfree rename to third_party/boost/lockfree diff --git a/third_party/rtaudio b/third_party/rtaudio new file mode 160000 index 0000000..a3e9aa6 --- /dev/null +++ b/third_party/rtaudio @@ -0,0 +1 @@ +Subproject commit a3e9aa621e65a0744f125e9740d057a4d088e0e9