#ifndef _RAPID_PIPO_HOST_H_ #define _RAPID_PIPO_HOST_H_ #include "PiPo.h" #include "PiPoHost.h" #include "PiPoCollection.h" #define MIN_PIPO_SAMPLERATE (1.0 / 31536000000.0) /* once a year */ #define MAX_PIPO_SAMPLERATE (96000000000.0) #define PIPO_OUT_RING_SIZE 2 struct pipoStreamAttributes { pipoStreamAttributes() : hasTimeTags(false), rate(MIN_PIPO_SAMPLERATE), offset(0), labels({ "" }), hasVarSize(false), domain(0), maxFrames(256) { dims[0] = 1; dims[1] = 1; } bool hasTimeTags; double rate; double offset; unsigned int dims[2]; // width, height (by pipo convention) std::vector<std::string> labels; bool hasVarSize; double domain; unsigned int maxFrames; }; //class PiPoObserver; class PiPoOut; //================================ H O S T ===================================// class PiPoHost : public PiPo::Parent { friend class PiPoOut; private: PiPo *graph; std::string graphName; PiPoOut *out; // PiPoObserver *obs; PiPoStreamAttributes inputStreamAttrs; PiPoStreamAttributes outputStreamAttrs; public: // PiPoHost(PiPoObserver *obs); PiPoHost(); ~PiPoHost(); // PiPoObserver *getObserver(); virtual bool setPiPoGraph(std::string name); virtual void clearPiPoGraph(); // override this method when inheriting !!! virtual void onNewFrameOut(double time, std::vector<PiPoValue> &frame); virtual std::vector<PiPoValue> getLastFrameOut(); virtual int setInputStreamAttributes(pipoStreamAttributes sa, bool propagate = true); virtual pipoStreamAttributes &getOutputStreamAttributes(); virtual int frames(double time, double weight, PiPoValue *values, unsigned int size, unsigned int num); // virtual bool setAttr(const std::string &attrName, bool value); // virtual bool setAttr(const std::string &attrName, int value); virtual bool setAttr(const std::string &attrName, double value); virtual bool setAttr(const std::string &attrName, const std::vector<double> &values); virtual bool setAttr(const std::string &attrName, const std::string &value); // for enums // virtual const std::vector<std::string>& getAttrNames(); // virtual bool isBoolAttr(const std::string &attrName); // virtual bool isEnumAttr(const std::string &attrName); // virtual bool isIntAttr(const std::string &attrName); // virtual bool isIntArrayAttr(const std::string &attrName); // virtual bool isFloatAttr(const std::string &attrName); // virtual bool isFloatArrayAttr(const std::string &attrName); // virtual bool isStringAttr(const std::string &attrName); // virtual bool getBoolAttr(const std::string &attrName); // virtual int getIntAttr(const std::string &attrName); // virtual float getFloatAttr(const std::string &attrName); // int streamAttributes(bool hasTimeTags, double rate, double offset, // unsigned int width, unsigned int height, // const std::vector<std::string> &labels, // bool hasVarSize, double domain, unsigned int maxFrames, // bool propagate = true); // void propagateInputAttributes(); // void streamAttributesChanged(PiPo *pipo, PiPo::Attr *attr); // void signalError(PiPo *pipo, std::string errorMsg); // void signalWarning(PiPo *pipo, std::string warningMsg); /* void setInputHasTimeTags(bool hasTimeTags, bool propagate = true); void setInputFrameRate(double rate, bool propagate = true); void setInputFrameOffset(double offset, bool propagate = true); void setInputDims(int width, int height, bool propagate = true); void setInputLabels(const std::vector<std::string> &labels, bool propagate = true); void setInputHasVarSize(bool hasVarSize, bool propagate = true); void setInputDomain(double domain, bool propagate = true); void setInputMaxFrames(int maxFrames, bool propagate = true); bool getInputHasTimeTags(); double getInputFrameRate(); double getInputFrameOffset(); void getInputDims(int &width, int &height); void getInputLabels(std::vector<std::string> &labels); bool getInputHasVarSize(); double getInputDomain(); int getInputMaxFrames(); bool getOutputHasTimeTags(); double getOutputFrameRate(); double getOutputFrameOffset(); void getOutputDims(int &width, int &height); void getOutputLabels(std::vector<std::string> &labels); bool getOutputHasVarSize(); double getOutputDomain(); int getOutputMaxFrames(); // void setPiPoParam(PiPoParam *param); //*/ private: void propagateInputStreamAttributes(); void setOutputAttributes(bool hasTimeTags, double rate, double offset, unsigned int width, unsigned int height, const char **labels, bool hasVarSize, double domain, unsigned int maxFrames); }; //================================= PiPoOut ==================================// class PiPoOut : public PiPo { private: PiPoHost *host; std::atomic<int> writeIndex, readIndex; std::vector<std::vector<PiPoValue>> ringBuffer; //std::function<void(std::vector<PiPoValue>, PiPoObserver *rpo)> frameCallback; std::function<void(std::vector<PiPoValue>)> simpleFrameCallback; public: PiPoOut(PiPoHost *host) : PiPo((PiPo::Parent *)host) { this->host = host; writeIndex = 0; readIndex = 0; ringBuffer.resize(PIPO_OUT_RING_SIZE); } ~PiPoOut() {} int streamAttributes(bool hasTimeTags, double rate, double offset, unsigned int width, unsigned int height, const char **labels, bool hasVarSize, double domain, unsigned int maxFrames) { this->host->setOutputAttributes(hasTimeTags, rate, offset, width, height, labels, hasVarSize, domain, maxFrames); for (int i = 0; i < PIPO_OUT_RING_SIZE; ++i) { ringBuffer[i].resize(width * height); } return 0; } int frames(double time, double weight, float *values, unsigned int size, unsigned int num) { if (num > 0) { for (int i = 0; i < num; ++i) { for (int j = 0; j < size; ++j) { ringBuffer[writeIndex][j] = values[i * size + j]; } // atomic swap ? writeIndex = 1 - writeIndex; readIndex = 1 - writeIndex; this->host->onNewFrameOut(time, ringBuffer[readIndex]); if (writeIndex + 1 == PIPO_OUT_RING_SIZE) { writeIndex = 0; } else { writeIndex++; } } } return 0; } //void setFrameCallback(std::function<void(std::vector<PiPoValue>, // PiPoObserver *obs)> f) { // frameCallback = f; //} void setSimpleFrameCallback(std::function<void(std::vector<PiPoValue>)> f) { simpleFrameCallback = f; } std::vector<PiPoValue> getLastFrame() { std::vector<PiPoValue> f; if (readIndex > -1) { f = ringBuffer[readIndex]; } return f; } }; //================================ PARAMETER =================================// // can we avoid using such a class ? /* class rapidPiPoParam { std::string name; std::string pipoName; std::string paramName; std::vector<std::string> values; public: rapidPiPoParam() : name(""), pipoName(""), paramName("") {} rapidPiPoParam(std::string name, std::string pipoName, std::string paramName, std::vector<std::string> const &values) { this->name = name; this->pipoName = pipoName; this->paramName = paramName; this->values = std::vector<std::string>(values.size()); for (int i = 0; i < values.size(); ++i) { this->values[i] = values[i]; } } const char *getName() { return name.c_str(); } const char *getParamName() { return paramName.c_str(); } const char *getPiPoName() { return pipoName.c_str(); } int getNumValues() { return values.size(); } bool isValueInt(int i) { // todo return false; } bool isValueFloat(int i) { // todo return false; } bool isValueNum(int i) { // todo; return false; } float getValueFloat(int i) { // todo return 0.; } int getValueInt(int i) { // todo return 0; } const char *getValueString() { return values[0].c_str(); //return values[i].c_str(); } std::string getValuesAsString() { std::string res = values[0]; for (int i = 1; i < values.size(); ++i) { res += " " + values[i]; } return res; } }; //*/ #endif /* _RAPID_PIPO_HOST_H_ */