lots o shit

This commit is contained in:
AlexandreRouma
2022-06-15 16:08:28 +02:00
parent 79a15ed186
commit 343ec6ca1c
109 changed files with 496 additions and 18305 deletions

View File

@ -1,209 +1,193 @@
#pragma once
#include <dsp/stream.h>
#include <type_traits>
#include <vector>
#include <utils/event.h>
#include <map>
#include "processor.h"
namespace dsp {
template <class T>
class ChainLinkAny {
template<class T>
class chain {
public:
virtual ~ChainLinkAny() {}
virtual void setInput(stream<T>* stream) = 0;
virtual stream<T>* getOutput() = 0;
virtual void start() = 0;
virtual void stop() = 0;
bool enabled = false;
};
chain() {}
template <class BLOCK, class T>
class ChainLink : public ChainLinkAny<T> {
public:
~ChainLink() {}
chain(stream<T>* in) { init(in); }
void setInput(stream<T>* stream) {
block.setInput(stream);
void init(stream<T>* in) {
_in = in;
out = _in;
}
stream<T>* getOutput() {
return &block.out;
template<typename Func>
void setInput(stream<T>* in, Func onOutputChange) {
_in = in;
for (auto& ln : links) {
if (states[ln]) {
ln->setInput(_in);
return;
}
}
out = _in;
onOutputChange(out);
}
void addBlock(Processor<T, T>* block, bool enabled) {
// Check if block is already part of the chain
if (blockExists(block)) {
throw std::runtime_error("[chain] Tried to add a block that is already part of the chain");
}
// Add to the list
links.push_back(block);
states[block] = false;
// Enable if needed
if (enabled) { enableBlock(block, [](stream<T>* out){}); }
}
template<typename Func>
void removeBlock(Processor<T, T>* block, Func onOutputChange) {
// Check if block is part of the chain
if (!blockExists(block)) {
throw std::runtime_error("[chain] Tried to remove a block that is not part of the chain");
}
// Disable the block
disableBlock(block, onOutputChange);
// Remove block from the list
states.erase(block);
links.erase(std::find(links.begin(), links.end(), block));
}
template<typename Func>
void enableBlock(Processor<T, T>* block, Func onOutputChange) {
// Check that the block is part of the chain
if (!blockExists(block)) {
throw std::runtime_error("[chain] Tried to enable a block that isn't part of the chain");
}
// If already enable, don't do anything
if (states[block]) { return; }
// Gather blocks before and after the block to enable
Processor<T, T>* before = blockBefore(block);
Processor<T, T>* after = blockAfter(block);
// Update input of next block or output
if (after) {
after->setInput(&block->out);
}
else {
out = &block->out;
onOutputChange(out);
}
// Set input of the new block
block->setInput(before ? &before->out : _in);
// Start new block
if (running) { block->start(); }
states[block] = true;
}
template<typename Func>
void disableBlock(Processor<T, T>* block, Func onOutputChange) {
// Check that the block is part of the chain
if (!blockExists(block)) {
throw std::runtime_error("[chain] Tried to enable a block that isn't part of the chain");
}
// If already disabled, don't do anything
if (!states[block]) { return; }
// Stop disabled block
block->stop();
states[block] = false;
// Gather blocks before and after the block to disable
Processor<T, T>* before = blockBefore(block);
Processor<T, T>* after = blockAfter(block);
// Update input of next block or output
if (after) {
after->setInput(before ? &before->out : _in);
}
else {
out = before ? &before->out : _in;
onOutputChange(out);
}
}
template<typename Func>
void setBlockEnabled(Processor<T, T>* block, bool enabled, Func onOutputChange) {
if (enabled) {
enableBlock(block, onOutputChange);
}
else {
disableBlock(block, onOutputChange);
}
}
template<typename Func>
void enableAllBlocks(Func onOutputChange) {
for (auto& ln : links) {
enableBlock(ln, onOutputChange);
}
}
template<typename Func>
void disableAllBlocks(Func onOutputChange) {
for (auto& ln : links) {
disableBlock(ln, onOutputChange);
}
}
void start() {
block.start();
}
void stop() {
block.stop();
}
BLOCK block;
};
template <class T>
class Chain {
public:
Chain() {}
Chain(stream<T>* input, EventHandler<stream<T>*>* outputChangedHandler) {
init(input, outputChangedHandler);
}
void init(stream<T>* input, EventHandler<stream<T>*>* outputChangedHandler) {
_input = input;
onOutputChanged.bindHandler(outputChangedHandler);
}
void add(ChainLinkAny<T>* link) {
// Check that link exists
if (std::find(links.begin(), links.end(), link) != links.end()) {
spdlog::error("Could not add new link to the chain, link already in the chain");
return;
}
// Assert that the link is stopped and disabled
link->stop();
link->enabled = false;
// Add new link to the list
links.push_back(link);
}
void enable(ChainLinkAny<T>* link) {
// Check that link exists and locate it
auto lnit = std::find(links.begin(), links.end(), link);
if (lnit == links.end()) {
spdlog::error("Could not enable link");
return;
}
// Enable the link
link->enabled = true;
// Find input
stream<T>* input = _input;
for (auto i = links.begin(); i < lnit; i++) {
if (!(*i)->enabled) { continue; }
input = (*i)->getOutput();
}
// Find next block
ChainLinkAny<T>* nextLink = NULL;
for (auto i = ++lnit; i < links.end(); i++) {
if (!(*i)->enabled) { continue; }
nextLink = *i;
break;
}
if (nextLink) {
// If a next block exists, change its input
nextLink->setInput(link->getOutput());
}
else {
// If there are no next blocks, change output of outside reader
onOutputChanged.emit(link->getOutput());
}
// Set input of newly enabled link
link->setInput(input);
// If running, start everything
if (running) { start(); }
}
void disable(ChainLinkAny<T>* link) {
// Check that link exists and locate it
auto lnit = std::find(links.begin(), links.end(), link);
if (lnit == links.end()) {
spdlog::error("Could not disable link");
return;
}
// Stop and disable link
link->stop();
link->enabled = false;
// Find its input
stream<T>* input = _input;
for (auto i = links.begin(); i < lnit; i++) {
if (!(*i)->enabled) { continue; }
input = (*i)->getOutput();
}
// Find next block
ChainLinkAny<T>* nextLink = NULL;
for (auto i = ++lnit; i < links.end(); i++) {
if (!(*i)->enabled) { continue; }
nextLink = *i;
break;
}
if (nextLink) {
// If a next block exists, change its input
nextLink->setInput(input);
}
else {
// If there are no next blocks, change output of outside reader
onOutputChanged.emit(input);
}
}
void disableAll() {
if (running) { return; }
for (auto& ln : links) {
disable(ln);
if (!states[ln]) { continue; }
ln->start();
}
}
void setState(ChainLinkAny<T>* link, bool enabled) {
enabled ? enable(link) : disable(link);
}
void setInput(stream<T>* input) {
_input = input;
// Set input of first enabled link
for (auto& ln : links) {
if (!ln->enabled) { continue; }
ln->setInput(_input);
return;
}
// No block found, this means nothing is enabled
onOutputChanged.emit(_input);
}
stream<T>* getOutput() {
stream<T>* lastOutput = _input;
for (auto& ln : links) {
if (!ln->enabled) { continue; }
lastOutput = ln->getOutput();
}
return lastOutput;
}
void start() {
running = true;
for (auto& ln : links) {
if (ln->enabled) {
ln->start();
}
else {
ln->stop();
}
}
}
void stop() {
running = false;
if (!running) { return; }
for (auto& ln : links) {
if (!states[ln]) { continue; }
ln->stop();
}
running = false;
}
Event<stream<T>*> onOutputChanged;
stream<T>* out;
private:
stream<T>* _input;
std::vector<ChainLinkAny<T>*> links;
Processor<T, T>* blockBefore(Processor<T, T>* block) {
for (auto& ln : links) {
if (ln == block) { return NULL; }
if (states[ln]) { return ln; }
}
}
Processor<T, T>* blockAfter(Processor<T, T>* block) {
bool blockFound = false;
for (auto& ln : links) {
if (ln == block) {
blockFound = true;
continue;
}
if (states[ln] && blockFound) { return ln; }
}
return NULL;
}
bool blockExists(Processor<T, T>* block) {
return states.find(block) != states.end();
}
stream<T>* _in;
std::vector<Processor<T, T>*> links;
std::map<Processor<T, T>*, bool> states;
bool running = false;
};
}