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