Split up indatahandler with python callback in part and part that calls the Python function. Threading is now handled using a thread pool. Some bugfixes
This commit is contained in:
parent
1e8b18aabe
commit
c75f0dddc5
@ -1,3 +1,4 @@
|
|||||||
|
#define DEBUGTRACE_ENABLED
|
||||||
#include "debugtrace.hpp"
|
#include "debugtrace.hpp"
|
||||||
#include "lasp_daqconfig.h"
|
#include "lasp_daqconfig.h"
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* #define DEBUGTRACE_ENABLED */
|
#define DEBUGTRACE_ENABLED
|
||||||
#include "debugtrace.hpp"
|
#include "debugtrace.hpp"
|
||||||
|
|
||||||
#include "lasp_daqconfig.h"
|
#include "lasp_daqconfig.h"
|
||||||
@ -7,8 +7,6 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#define MAX_DEV_COUNT_PER_API 20
|
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
vector<DaqApi> DaqApi::getAvailableApis() {
|
vector<DaqApi> DaqApi::getAvailableApis() {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
#define DEBUGTRACE_ENABLED
|
||||||
|
#include "debugtrace.hpp"
|
||||||
|
|
||||||
#include "lasp_rtaudiodaq.h"
|
#include "lasp_rtaudiodaq.h"
|
||||||
#if LASP_HAS_RTAUDIO == 1
|
#if LASP_HAS_RTAUDIO == 1
|
||||||
#include "debugtrace.hpp"
|
|
||||||
#include "lasp_daq.h"
|
#include "lasp_daq.h"
|
||||||
#include <RtAudio.h>
|
#include <RtAudio.h>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "lasp_streammgr.h"
|
#define DEBUGTRACE_ENABLED
|
||||||
#include "debugtrace.hpp"
|
#include "debugtrace.hpp"
|
||||||
|
#include "lasp_thread.h"
|
||||||
|
#include "lasp_streammgr.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -37,6 +39,7 @@ InDataHandler::~InDataHandler() {
|
|||||||
StreamMgr &StreamMgr::getInstance() {
|
StreamMgr &StreamMgr::getInstance() {
|
||||||
|
|
||||||
DEBUGTRACE_ENTER;
|
DEBUGTRACE_ENTER;
|
||||||
|
getPool();
|
||||||
static StreamMgr mgr;
|
static StreamMgr mgr;
|
||||||
return mgr;
|
return mgr;
|
||||||
}
|
}
|
||||||
@ -198,6 +201,29 @@ void StreamMgr::startStream(const DeviceInfo &devinfo,
|
|||||||
_outputStream = std::move(daq);
|
_outputStream = std::move(daq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void StreamMgr::stopStream(const StreamType t) {
|
||||||
|
switch (t) {
|
||||||
|
case (StreamType::input): {
|
||||||
|
if (!_inputStream) {
|
||||||
|
throw std::runtime_error("Input stream is not running");
|
||||||
|
}
|
||||||
|
_inputStream = nullptr;
|
||||||
|
} break;
|
||||||
|
case (StreamType::output): {
|
||||||
|
if (_inputStream && _inputStream->duplexMode()) {
|
||||||
|
_inputStream = nullptr;
|
||||||
|
} else {
|
||||||
|
if (!_outputStream) {
|
||||||
|
throw std::runtime_error("Output stream is not running");
|
||||||
|
}
|
||||||
|
_outputStream = nullptr;
|
||||||
|
} // end else
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("BUG");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StreamMgr::addInDataHandler(InDataHandler &handler) {
|
void StreamMgr::addInDataHandler(InDataHandler &handler) {
|
||||||
std::scoped_lock<std::mutex> lck(_inDataHandler_mtx);
|
std::scoped_lock<std::mutex> lck(_inDataHandler_mtx);
|
||||||
|
@ -155,7 +155,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @param stype The stream type to stop.
|
* @param stype The stream type to stop.
|
||||||
*/
|
*/
|
||||||
void stopStream(StreamType stype);
|
void stopStream(const StreamType stype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stop and delete all streams. Also called on destruction of the
|
* @brief Stop and delete all streams. Also called on destruction of the
|
||||||
|
@ -11,12 +11,15 @@ set(lasp_dsp_files
|
|||||||
lasp_thread.cpp
|
lasp_thread.cpp
|
||||||
lasp_timebuffer.cpp
|
lasp_timebuffer.cpp
|
||||||
lasp_slm.cpp
|
lasp_slm.cpp
|
||||||
|
lasp_threadedindatahandler.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
add_library(lasp_dsp_lib STATIC ${lasp_dsp_files})
|
add_library(lasp_dsp_lib STATIC ${lasp_dsp_files})
|
||||||
target_compile_definitions(lasp_dsp_lib PUBLIC "-DARMA_DONT_USE_WRAPPER")
|
target_compile_definitions(lasp_dsp_lib PUBLIC "-DARMA_DONT_USE_WRAPPER")
|
||||||
|
|
||||||
target_link_libraries(lasp_dsp_lib PRIVATE ${BLAS_LIBRARIES})
|
target_link_libraries(lasp_dsp_lib PRIVATE ${BLAS_LIBRARIES})
|
||||||
target_include_directories(lasp_dsp_lib INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
target_include_directories(lasp_dsp_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
target_include_directories(lasp_dsp_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../device)
|
||||||
|
|
||||||
|
@ -1,9 +1,25 @@
|
|||||||
|
#define DEBUGTRACE_ENABLED
|
||||||
#include "lasp_thread.h"
|
#include "lasp_thread.h"
|
||||||
#include "BS_thread_pool.hpp"
|
#include "BS_thread_pool.hpp"
|
||||||
|
#include "debugtrace.hpp"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
BS::thread_pool& getPool() {
|
/**
|
||||||
static BS::thread_pool pool;
|
* @brief It seems to work much better in cooperation with Pybind11 when this
|
||||||
|
* singleton is implemented with a unique_ptr.
|
||||||
return pool;
|
*/
|
||||||
|
std::unique_ptr<BS::thread_pool> _static_storage_threadpool;
|
||||||
|
|
||||||
|
void destroyThreadPool() {
|
||||||
|
DEBUGTRACE_ENTER;
|
||||||
|
_static_storage_threadpool = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
BS::thread_pool &getPool() {
|
||||||
|
/* DEBUGTRACE_ENTER; */
|
||||||
|
if (!_static_storage_threadpool) {
|
||||||
|
DEBUGTRACE_PRINT("Creating new thread pool");
|
||||||
|
_static_storage_threadpool = std::make_unique<BS::thread_pool>();
|
||||||
|
}
|
||||||
|
return *_static_storage_threadpool;
|
||||||
}
|
}
|
||||||
|
@ -9,3 +9,11 @@
|
|||||||
* @return Thread pool ref.
|
* @return Thread pool ref.
|
||||||
*/
|
*/
|
||||||
BS::thread_pool& getPool();
|
BS::thread_pool& getPool();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The global thread pool is stored in a unique_ptr, so in normal C++
|
||||||
|
* code the thread pool is deleted at the end of main(). However this does not
|
||||||
|
* hold when LASP code is run
|
||||||
|
*/
|
||||||
|
void destroyThreadPool();
|
||||||
|
65
src/lasp/dsp/lasp_threadedindatahandler.cpp
Normal file
65
src/lasp/dsp/lasp_threadedindatahandler.cpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#define DEBUGTRACE_ENABLED
|
||||||
|
#include "lasp_threadedindatahandler.h"
|
||||||
|
#include "debugtrace.hpp"
|
||||||
|
#include "lasp_thread.h"
|
||||||
|
#include <future>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
using namespace std::literals::chrono_literals;
|
||||||
|
|
||||||
|
ThreadedInDataHandler::ThreadedInDataHandler(StreamMgr &mgr)
|
||||||
|
: InDataHandler(mgr) {
|
||||||
|
|
||||||
|
DEBUGTRACE_ENTER;
|
||||||
|
|
||||||
|
// Initialize thread pool, if not already done
|
||||||
|
getPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ThreadedInDataHandler::inCallback(const DaqData &daqdata) {
|
||||||
|
/* DEBUGTRACE_ENTER; */
|
||||||
|
|
||||||
|
if (!_lastCallbackResult) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
dataqueue.push(daqdata);
|
||||||
|
|
||||||
|
auto &pool = getPool();
|
||||||
|
|
||||||
|
if (!_thread_running && (!_stopThread) && _lastCallbackResult) {
|
||||||
|
pool.push_task(&ThreadedInDataHandler::threadFcn, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _lastCallbackResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadedInDataHandler::~ThreadedInDataHandler() {
|
||||||
|
|
||||||
|
DEBUGTRACE_ENTER;
|
||||||
|
_stopThread = true;
|
||||||
|
|
||||||
|
// Then wait in steps for the thread to stop running.
|
||||||
|
while (_thread_running) {
|
||||||
|
std::this_thread::sleep_for(10us);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThreadedInDataHandler::threadFcn() {
|
||||||
|
|
||||||
|
/* DEBUGTRACE_ENTER; */
|
||||||
|
_thread_running = true;
|
||||||
|
|
||||||
|
DaqData d{};
|
||||||
|
|
||||||
|
if (dataqueue.pop(d) && !_stopThread) {
|
||||||
|
|
||||||
|
// Call inCallback_threaded
|
||||||
|
if (inCallback_threaded(d) == false) {
|
||||||
|
_lastCallbackResult = false;
|
||||||
|
_thread_running = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_lastCallbackResult = true;
|
||||||
|
_thread_running = false;
|
||||||
|
}
|
36
src/lasp/dsp/lasp_threadedindatahandler.h
Normal file
36
src/lasp/dsp/lasp_threadedindatahandler.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <boost/lockfree/spsc_queue.hpp>
|
||||||
|
#include "lasp_streammgr.h"
|
||||||
|
|
||||||
|
const us RINGBUFFER_SIZE = 1024;
|
||||||
|
|
||||||
|
class ThreadedInDataHandler: public InDataHandler {
|
||||||
|
/**
|
||||||
|
* @brief The queue used to push elements to the handling thread.
|
||||||
|
*/
|
||||||
|
boost::lockfree::spsc_queue<DaqData,
|
||||||
|
boost::lockfree::capacity<RINGBUFFER_SIZE>>
|
||||||
|
dataqueue;
|
||||||
|
|
||||||
|
std::atomic<bool> _thread_running{false};
|
||||||
|
std::atomic<bool> _stopThread{false};
|
||||||
|
std::atomic<bool> _lastCallbackResult{true};
|
||||||
|
|
||||||
|
void threadFcn();
|
||||||
|
|
||||||
|
public:
|
||||||
|
ThreadedInDataHandler(StreamMgr& mgr);
|
||||||
|
~ThreadedInDataHandler();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pushes a copy of the daqdata to the thread queue and returns
|
||||||
|
*
|
||||||
|
* @param daqdata the daq info to push
|
||||||
|
*
|
||||||
|
* @return true, to continue with sampling.
|
||||||
|
*/
|
||||||
|
virtual bool inCallback(const DaqData &daqdata) override;
|
||||||
|
|
||||||
|
virtual bool inCallback_threaded(const DaqData&) = 0;
|
||||||
|
|
||||||
|
};
|
@ -1,8 +1,8 @@
|
|||||||
|
#define DEBUGTRACE_ENABLED
|
||||||
#include "debugtrace.hpp"
|
#include "debugtrace.hpp"
|
||||||
#include "lasp_streammgr.h"
|
#include "lasp_streammgr.h"
|
||||||
|
#include "lasp_threadedindatahandler.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <boost/lockfree/policies.hpp>
|
|
||||||
#include <boost/lockfree/spsc_queue.hpp>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <pybind11/buffer_info.h>
|
#include <pybind11/buffer_info.h>
|
||||||
#include <pybind11/cast.h>
|
#include <pybind11/cast.h>
|
||||||
@ -17,8 +17,6 @@ using namespace std::literals::chrono_literals;
|
|||||||
using std::cerr;
|
using std::cerr;
|
||||||
using std::endl;
|
using std::endl;
|
||||||
|
|
||||||
const us RINGBUFFER_SIZE = 1024;
|
|
||||||
|
|
||||||
namespace py = pybind11;
|
namespace py = pybind11;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,7 +28,7 @@ namespace py = pybind11;
|
|||||||
*
|
*
|
||||||
* @return Numpy array
|
* @return Numpy array
|
||||||
*/
|
*/
|
||||||
template <typename T> py::array_t<T> getPyArray(DaqData &d) {
|
template <typename T> py::array_t<T> getPyArray(const DaqData &d) {
|
||||||
// https://github.com/pybind/pybind11/issues/323
|
// https://github.com/pybind/pybind11/issues/323
|
||||||
//
|
//
|
||||||
// When a valid object is passed as 'base', it tells pybind not to take
|
// When a valid object is passed as 'base', it tells pybind not to take
|
||||||
@ -49,16 +47,17 @@ template <typename T> py::array_t<T> getPyArray(DaqData &d) {
|
|||||||
|
|
||||||
return py::array_t<T>(
|
return py::array_t<T>(
|
||||||
py::array::ShapeContainer({d.nframes, d.nchannels}), // Shape
|
py::array::ShapeContainer({d.nframes, d.nchannels}), // Shape
|
||||||
//
|
|
||||||
py::array::StridesContainer( // Strides
|
|
||||||
{sizeof(T),
|
|
||||||
sizeof(T) * d.nframes}), // Strides (in bytes) for each index
|
|
||||||
|
|
||||||
(T *)d.raw_ptr(), // Pointer to buffer
|
py::array::StridesContainer( // Strides
|
||||||
|
{sizeof(T),
|
||||||
|
sizeof(T) * d.nframes}), // Strides (in bytes) for each index
|
||||||
|
|
||||||
|
reinterpret_cast<T *>(
|
||||||
|
const_cast<DaqData &>(d).raw_ptr()), // Pointer to buffer
|
||||||
|
|
||||||
dummyDataOwner // As stated above, now Numpy does not take ownership of
|
dummyDataOwner // As stated above, now Numpy does not take ownership of
|
||||||
// the data pointer.
|
// the data pointer.
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,130 +65,79 @@ template <typename T> py::array_t<T> getPyArray(DaqData &d) {
|
|||||||
* buffer of sample data. The Python callback is called from a different
|
* buffer of sample data. The Python callback is called from a different
|
||||||
* thread, using a Numpy argument as
|
* thread, using a Numpy argument as
|
||||||
*/
|
*/
|
||||||
class PyIndataHandler : public InDataHandler {
|
class PyIndataHandler : public ThreadedInDataHandler {
|
||||||
/**
|
/**
|
||||||
* @brief The callback function that is called.
|
* @brief The callback function that is called.
|
||||||
*/
|
*/
|
||||||
py::function cb;
|
py::function cb;
|
||||||
/**
|
|
||||||
* @brief The thread that is handling callbacks from the queue
|
|
||||||
*/
|
|
||||||
std::thread pythread;
|
|
||||||
/**
|
|
||||||
* @brief The queue used to push elements to the handling thread.
|
|
||||||
*/
|
|
||||||
boost::lockfree::spsc_queue<DaqData,
|
|
||||||
boost::lockfree::capacity<RINGBUFFER_SIZE>>
|
|
||||||
dataqueue;
|
|
||||||
std::atomic<bool> stopThread{false};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
PyIndataHandler(StreamMgr &mgr, py::function cb)
|
||||||
|
: ThreadedInDataHandler(mgr), cb(cb) {
|
||||||
|
|
||||||
|
DEBUGTRACE_ENTER;
|
||||||
|
/// TODO: Note that if start() throws an exception, which means that the
|
||||||
|
/// destructor of PyIndataHandler is not called and the thread destructor
|
||||||
|
/// calls terminate(). It is a kind of rude way to crash, but it is also
|
||||||
|
/// *very* unlikely to happen, as start() does only add a reference to this
|
||||||
|
/// handler to a list in the stream mgr.
|
||||||
|
start();
|
||||||
|
}
|
||||||
~PyIndataHandler() {
|
~PyIndataHandler() {
|
||||||
DEBUGTRACE_ENTER;
|
DEBUGTRACE_ENTER;
|
||||||
stop();
|
stop();
|
||||||
stopThread = true;
|
|
||||||
if(pythread.joinable()) {
|
|
||||||
pythread.join();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PyIndataHandler(StreamMgr &mgr, py::function cb)
|
|
||||||
: InDataHandler(mgr), cb(cb),
|
|
||||||
pythread(&PyIndataHandler::threadfcn, this) {
|
|
||||||
|
|
||||||
DEBUGTRACE_ENTER;
|
|
||||||
/// TODO: Note that if start() throws an exception, which means that the
|
|
||||||
/// destructor of PyIndataHandler is not called and the thread destructor
|
|
||||||
/// calls terminate(). It is a kind of rude way to crash, but it is also
|
|
||||||
/// *very* unlikely to happen, as start() does only add a reference to this
|
|
||||||
/// handler to a list in the stream mgr.
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reads from the
|
* @brief Reads from the buffer
|
||||||
*/
|
*/
|
||||||
void threadfcn() {
|
bool inCallback_threaded(const DaqData &d) {
|
||||||
|
|
||||||
/* DEBUGTRACE_ENTER; */
|
/* DEBUGTRACE_ENTER; */
|
||||||
|
|
||||||
using DataType = DataTypeDescriptor::DataType;
|
using DataType = DataTypeDescriptor::DataType;
|
||||||
|
|
||||||
DaqData d{};
|
py::gil_scoped_acquire acquire;
|
||||||
|
try {
|
||||||
|
py::array binfo;
|
||||||
|
switch (d.dtype) {
|
||||||
|
case (DataType::dtype_int8):
|
||||||
|
binfo = getPyArray<int8_t>(d);
|
||||||
|
break;
|
||||||
|
case (DataType::dtype_int16):
|
||||||
|
binfo = getPyArray<int16_t>(d);
|
||||||
|
break;
|
||||||
|
case (DataType::dtype_int32):
|
||||||
|
binfo = getPyArray<int32_t>(d);
|
||||||
|
break;
|
||||||
|
case (DataType::dtype_fl32):
|
||||||
|
binfo = getPyArray<float>(d);
|
||||||
|
break;
|
||||||
|
case (DataType::dtype_fl64):
|
||||||
|
binfo = getPyArray<double>(d);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("BUG");
|
||||||
|
} // End of switch
|
||||||
|
|
||||||
while (!stopThread) {
|
py::object bool_val = cb(binfo);
|
||||||
if (dataqueue.pop(d)) {
|
bool res = bool_val.cast<bool>();
|
||||||
/* DEBUGTRACE_PRINT("pop() returned true"); */
|
if (!res)
|
||||||
|
return false;
|
||||||
|
|
||||||
py::gil_scoped_acquire acquire;
|
} catch (py::error_already_set &e) {
|
||||||
try {
|
cerr << "ERROR: Python raised exception from callback function: ";
|
||||||
py::array binfo;
|
cerr << e.what() << endl;
|
||||||
switch (d.dtype) {
|
return false;
|
||||||
case (DataType::dtype_int8):
|
|
||||||
binfo = getPyArray<uint8_t>(d);
|
|
||||||
break;
|
|
||||||
case (DataType::dtype_int16):
|
|
||||||
binfo = getPyArray<uint16_t>(d);
|
|
||||||
break;
|
|
||||||
case (DataType::dtype_int32):
|
|
||||||
binfo = getPyArray<uint32_t>(d);
|
|
||||||
break;
|
|
||||||
case (DataType::dtype_fl32):
|
|
||||||
binfo = getPyArray<float>(d);
|
|
||||||
break;
|
|
||||||
case (DataType::dtype_fl64):
|
|
||||||
binfo = getPyArray<double>(d);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("BUG");
|
|
||||||
} // End of switch
|
|
||||||
|
|
||||||
py::object bool_val = cb(binfo);
|
} catch (py::cast_error &e) {
|
||||||
bool res = bool_val.cast<bool>();
|
cerr << e.what() << endl;
|
||||||
if (!res)
|
cerr << "ERROR: Python callback does not return boolean value." << endl;
|
||||||
stopThread = true;
|
return false;
|
||||||
|
|
||||||
} catch (py::error_already_set &e) {
|
|
||||||
cerr << "ERROR: Python raised exception from callback function: ";
|
|
||||||
cerr << e.what() << endl;
|
|
||||||
stopThread = true;
|
|
||||||
|
|
||||||
} catch (py::cast_error &e) {
|
|
||||||
cerr << e.what() << endl;
|
|
||||||
cerr << "ERROR: Python callback does not return boolean value."
|
|
||||||
<< endl;
|
|
||||||
stopThread = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// When there is nothing to pop from the queue, just sleep for a some
|
|
||||||
// time.
|
|
||||||
else {
|
|
||||||
std::this_thread::sleep_for(2ms);
|
|
||||||
}
|
|
||||||
} // end of while loop
|
|
||||||
|
|
||||||
} // end of threadfcn
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Pushes a copy of the daqdata to the thread queuue and returns
|
|
||||||
*
|
|
||||||
* @param daqdata the daq info to push
|
|
||||||
*
|
|
||||||
* @return true, to continue with sampling.
|
|
||||||
*/
|
|
||||||
virtual bool inCallback(const DaqData &daqdata) override {
|
|
||||||
/* DEBUGTRACE_ENTER; */
|
|
||||||
if (!stopThread) {
|
|
||||||
if (!dataqueue.push(daqdata)) {
|
|
||||||
stopThread = true;
|
|
||||||
cerr << "Pushing DaqData object failed. Probably the ringbuffer is "
|
|
||||||
"full. Try reducing the load"
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void init_datahandler(py::module &m) {
|
void init_datahandler(py::module &m) {
|
||||||
py::class_<PyIndataHandler> h(m, "InDataHandler");
|
py::class_<PyIndataHandler> h(m, "InDataHandler");
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ void init_streammgr(py::module &m) {
|
|||||||
.export_values();
|
.export_values();
|
||||||
|
|
||||||
smgr.def("startStream", &StreamMgr::startStream);
|
smgr.def("startStream", &StreamMgr::startStream);
|
||||||
smgr.def("stopStream", &StreamMgr::startStream);
|
smgr.def("stopStream", &StreamMgr::stopStream);
|
||||||
smgr.def_static("getInstance", []() {
|
smgr.def_static("getInstance", []() {
|
||||||
return std::unique_ptr<StreamMgr, py::nodelete>(&StreamMgr::getInstance());
|
return std::unique_ptr<StreamMgr, py::nodelete>(&StreamMgr::getInstance());
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 1,
|
"execution_count": 1,
|
||||||
|
"id": "b0d15138",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
@ -12,27 +13,15 @@
|
|||||||
"make: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
"make: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
||||||
"make[1]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
"make[1]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
||||||
"make[2]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
"make[2]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
||||||
|
"\u001b[35m\u001b[1mConsolidate compiler generated dependencies of target lasp_dsp_lib\u001b[0m\n",
|
||||||
"make[2]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
"make[2]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
||||||
"[ 26%] Built target lasp_dsp_lib\n",
|
"[ 26%] Built target lasp_dsp_lib\n",
|
||||||
"make[2]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
"make[2]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
||||||
"\u001b[35m\u001b[1mScanning dependencies of target lasp_device_lib\u001b[0m\n",
|
"\u001b[35m\u001b[1mConsolidate compiler generated dependencies of target lasp_device_lib\u001b[0m\n",
|
||||||
"make[2]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
|
||||||
"make[2]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
|
||||||
"[ 31%] \u001b[32mBuilding CXX object src/lasp/device/CMakeFiles/lasp_device_lib.dir/lasp_rtaudiodaq.cpp.o\u001b[0m\n",
|
|
||||||
"\u001b[01m\u001b[K/home/anne/wip/mycode/lasp/src/lasp/device/lasp_rtaudiodaq.cpp:\u001b[m\u001b[K In lambda function:\n",
|
|
||||||
"\u001b[01m\u001b[K/home/anne/wip/mycode/lasp/src/lasp/device/lasp_rtaudiodaq.cpp:258:20:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[Kvariable ‘\u001b[01m\u001b[Kstat\u001b[m\u001b[K’ set but not used [\u001b[01;35m\u001b[K-Wunused-but-set-variable\u001b[m\u001b[K]\n",
|
|
||||||
" 258 | StreamStatus \u001b[01;35m\u001b[Kstat\u001b[m\u001b[K = _streamStatus;\n",
|
|
||||||
" | \u001b[01;35m\u001b[K^~~~\u001b[m\u001b[K\n",
|
|
||||||
"\u001b[01m\u001b[K/home/anne/wip/mycode/lasp/src/lasp/device/lasp_rtaudiodaq.cpp:\u001b[m\u001b[K In member function ‘\u001b[01m\u001b[Kint RtAudioDaq::streamCallback(void*, void*, unsigned int, double, RtAudioStreamStatus)\u001b[m\u001b[K’:\n",
|
|
||||||
"\u001b[01m\u001b[K/home/anne/wip/mycode/lasp/src/lasp/device/lasp_rtaudiodaq.cpp:250:36:\u001b[m\u001b[K \u001b[01;35m\u001b[Kwarning: \u001b[m\u001b[Kunused parameter ‘\u001b[01m\u001b[KstreamTime\u001b[m\u001b[K’ [\u001b[01;35m\u001b[K-Wunused-parameter\u001b[m\u001b[K]\n",
|
|
||||||
" 250 | unsigned int nFrames, \u001b[01;35m\u001b[Kdouble streamTime\u001b[m\u001b[K,\n",
|
|
||||||
" | \u001b[01;35m\u001b[K~~~~~~~^~~~~~~~~~\u001b[m\u001b[K\n",
|
|
||||||
"make[2]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
"make[2]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
||||||
"[ 63%] Built target lasp_device_lib\n",
|
"[ 63%] Built target lasp_device_lib\n",
|
||||||
"make[2]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
"make[2]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
||||||
"make[2]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
"\u001b[35m\u001b[1mConsolidate compiler generated dependencies of target lasp_cpp\u001b[0m\n",
|
||||||
"make[2]: Entering directory '/home/anne/wip/mycode/lasp'\n",
|
|
||||||
"[ 68%] \u001b[32m\u001b[1mLinking CXX shared module lasp_cpp.cpython-38-x86_64-linux-gnu.so\u001b[0m\n",
|
|
||||||
"make[2]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
"make[2]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
||||||
"[100%] Built target lasp_cpp\n",
|
"[100%] Built target lasp_cpp\n",
|
||||||
"make[1]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
"make[1]: Leaving directory '/home/anne/wip/mycode/lasp'\n",
|
||||||
@ -47,8 +36,20 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 2,
|
"execution_count": 2,
|
||||||
|
"id": "1787e24c",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2022-07-20 22:04:50+0200 DebugTrace-cpp 2.0.0a2 (g++ 12.1.0)\n",
|
||||||
|
"2022-07-20 22:04:50+0200 \n",
|
||||||
|
"2022-07-20 22:04:50+0200 Enter fillUlDaqDeviceInfo (lasp_uldaq.cpp: 514)\n",
|
||||||
|
"2022-07-20 22:04:51+0200 Leave fillUlDaqDeviceInfo (lasp_uldaq.cpp)\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"source": [
|
"source": [
|
||||||
"import lasp\n",
|
"import lasp\n",
|
||||||
"ds = lasp.DeviceInfo.getDeviceInfo()"
|
"ds = lasp.DeviceInfo.getDeviceInfo()"
|
||||||
@ -57,6 +58,7 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 3,
|
"execution_count": 3,
|
||||||
|
"id": "cb4ab7d8",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
@ -74,17 +76,26 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 4,
|
"execution_count": 4,
|
||||||
|
"id": "22ae99b1",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"name": "stdout",
|
"name": "stdout",
|
||||||
"output_type": "stream",
|
"output_type": "stream",
|
||||||
"text": [
|
"text": [
|
||||||
"0: Camera Mono\n",
|
"0: Monitor of Starship/Matisse HD Audio Controller Analog Stereo\n",
|
||||||
"1: Starship/Matisse HD Audio Controller Analog Stereo\n",
|
"1: Starship/Matisse HD Audio Controller Analog Stereo\n",
|
||||||
"2: Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X] Digital Stereo (HDMI)\n",
|
"2: GP108 High Definition Audio Controller Digital Stereo (HDMI)\n",
|
||||||
"3: Monitor of Baffin HDMI/DP Audio [Radeon RX 550 640SP / RX 560/560X] Digital Stereo (HDMI)\n",
|
"3: Monitor of GP108 High Definition Audio Controller Digital Stereo (HDMI)\n",
|
||||||
"4: Monitor of Starship/Matisse HD Audio Controller Analog Stereo\n"
|
"4: default\n",
|
||||||
|
"5: hw:HDA NVidia,3\n",
|
||||||
|
"6: hw:HDA NVidia,7\n",
|
||||||
|
"7: hw:HDA NVidia,8\n",
|
||||||
|
"8: hw:HDA NVidia,9\n",
|
||||||
|
"9: hw:HDA NVidia,10\n",
|
||||||
|
"10: hw:HD-Audio Generic,0\n",
|
||||||
|
"11: hw:HD-Audio Generic,1\n",
|
||||||
|
"12: hw:HD-Audio Generic,2\n"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -97,6 +108,7 @@
|
|||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 5,
|
"execution_count": 5,
|
||||||
|
"id": "47385b02",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
@ -107,56 +119,28 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 6,
|
"execution_count": 59,
|
||||||
|
"id": "d12f84b7",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"name": "stdout",
|
||||||
"text/plain": [
|
"output_type": "stream",
|
||||||
"2"
|
"text": [
|
||||||
]
|
"Out channels: 2\n",
|
||||||
},
|
"In channels: 0\n"
|
||||||
"execution_count": 6,
|
]
|
||||||
"metadata": {},
|
|
||||||
"output_type": "execute_result"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"source": [
|
"source": [
|
||||||
"d.noutchannels"
|
"print('Out channels:',d.noutchannels)\n",
|
||||||
|
"print('In channels:',d.ninchannels)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 7,
|
"execution_count": 52,
|
||||||
"metadata": {},
|
"id": "902ce309",
|
||||||
"outputs": [],
|
|
||||||
"source": [
|
|
||||||
"#daq = lasp.Daq.createDaq(d, config)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 8,
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/plain": [
|
|
||||||
"2"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"execution_count": 8,
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "execute_result"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"d.ninchannels"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 9,
|
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
@ -165,16 +149,38 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 15,
|
"execution_count": 55,
|
||||||
|
"id": "b209294b",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2022-07-20 22:07:02+0200 \n",
|
||||||
|
"2022-07-20 22:07:02+0200 Enter createDaq (lasp_daq.cpp: 18)\n",
|
||||||
|
"2022-07-20 22:07:02+0200 | Enter Daq (lasp_daq.cpp: 39)\n",
|
||||||
|
"2022-07-20 22:07:02+0200 | Leave Daq (lasp_daq.cpp)\n",
|
||||||
|
"2022-07-20 22:07:02+0200 | \n",
|
||||||
|
"2022-07-20 22:07:02+0200 | Enter RtAudioDaq (lasp_rtaudiodaq.cpp: 131)\n",
|
||||||
|
"2022-07-20 22:07:02+0200 | Leave RtAudioDaq (lasp_rtaudiodaq.cpp)\n",
|
||||||
|
"2022-07-20 22:07:02+0200 Leave createDaq (lasp_daq.cpp)\n",
|
||||||
|
"2022-07-20 22:07:02+0200 isInput = false\n",
|
||||||
|
"2022-07-20 22:07:02+0200 isOutput = true\n",
|
||||||
|
"2022-07-20 22:07:02+0200 \n",
|
||||||
|
"2022-07-20 22:07:02+0200 Enter start (lasp_rtaudiodaq.cpp: 211)\n",
|
||||||
|
"2022-07-20 22:07:02+0200 Leave start (lasp_rtaudiodaq.cpp)\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"source": [
|
"source": [
|
||||||
"mgr.startStream(d, config)"
|
"mgr.startStream(d, config)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 11,
|
"execution_count": 27,
|
||||||
|
"id": "0830ffb5",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
@ -183,7 +189,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 16,
|
"execution_count": 60,
|
||||||
|
"id": "a7fddc19",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
@ -192,26 +199,36 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 13,
|
"execution_count": 57,
|
||||||
|
"id": "f4610574",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": [
|
||||||
"sine = lasp.Sine(1000)"
|
"sine = lasp.Sine(200)\n",
|
||||||
|
"sine.setLevel(-20, True)\n",
|
||||||
|
"mgr.setSiggen(sine)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 14,
|
"execution_count": 21,
|
||||||
|
"id": "d11c7dae",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": [
|
"source": []
|
||||||
"mgr.setSiggen(sine)"
|
},
|
||||||
]
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "0eeb2311",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"kernelspec": {
|
"kernelspec": {
|
||||||
"display_name": "Python 3 (ipykernel)",
|
"display_name": "Python 3",
|
||||||
"language": "python",
|
"language": "python",
|
||||||
"name": "python3"
|
"name": "python3"
|
||||||
},
|
},
|
||||||
@ -225,7 +242,7 @@
|
|||||||
"name": "python",
|
"name": "python",
|
||||||
"nbconvert_exporter": "python",
|
"nbconvert_exporter": "python",
|
||||||
"pygments_lexer": "ipython3",
|
"pygments_lexer": "ipython3",
|
||||||
"version": "3.8.10"
|
"version": "3.10.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nbformat": 4,
|
"nbformat": 4,
|
||||||
|
Loading…
Reference in New Issue
Block a user