#ifndef ROTOR_H #define ROTOR_H /* ROTORD rewrite TJR-Jan-2014 NB when plugging in to framework - convert all cerr messages to logged What next? */ #define ENABLE_TYPENAME(A) template<> struct TypeName { static const char *Get() { return #A; }}; #include #include #include #include #include #include #include #include #include "xmlIO.h" #include "libavwrapper.h" #include "Poco/Logger.h" #include "Poco/Channel.h" #include "Poco/SplitterChannel.h" #include "Poco/ConsoleChannel.h" #include "Poco/FormattingChannel.h" #include "Poco/FileChannel.h" #include "Poco/Message.h" #include "Poco/Formatter.h" #include "Poco/PatternFormatter.h" #include "Poco/AutoPtr.h" #include "Poco/Net/HTTPResponse.h" using Poco::Logger; using Poco::Channel; using Poco::SplitterChannel; using Poco::ConsoleChannel; using Poco::FormattingChannel; using Poco::Formatter; using Poco::PatternFormatter; using Poco::FileChannel; using Poco::Message; using Poco::AutoPtr; template struct TypeName { static const char* Get() { return typeid(T).name(); } }; template <> struct TypeName { static const char* Get() { return "int"; } }; template <> struct TypeName { static const char* Get() { return "number"; } }; template <> struct TypeName { static const char* Get() { return "string"; } }; namespace Rotor { class Node; template class Node_type; class Enum{ //enumerated string type for menus public: Enum(std::initializer_list init) : labels(init){}; private: std::vector labels; int value; }; class Audio_frame{ public: Audio_frame(uint16_t *_samples,int _channels,int _numsamples){ samples=_samples; channels=_channels; numsamples=_numsamples; } uint16_t *samples; int channels,numsamples; }; class Frame_parameters{ public: Frame_parameters(double _time,double _framerate,double _duration,int _w,int _h,Audio_frame *_audio=nullptr) { time=_time; framerate=_framerate; duration=_duration; w=_w; h=_h;audio=_audio;}; Frame_parameters(int _frame,double _framerate,double _duration,int _w,int _h,Audio_frame *_audio=nullptr) { time=((double)_frame)/_framerate; framerate=_framerate; duration=_duration; w=_w; h=_h;audio=_audio;}; int h,w; Frame_parameters lastframe() const{ return Frame_parameters(time-(1.0/framerate),framerate,duration,w,h); } Frame_parameters nextframe() const{ return Frame_parameters(time+(1.0/framerate),framerate,duration,w,h); } double get_time() const{ return time; } private: double time; //num/denom ? double framerate; double duration; Audio_frame *audio; }; class Variable { //pure virtual base type for variable pointers public: Variable():name(""),description(""),title(""),connection(nullptr){}; virtual ~Variable(){}; virtual Json::Value to_json()=0; virtual void init(Json::Value s)=0; virtual bool connect(Node* target)=0; virtual std::string get_type()=0; virtual bool create_connection(std::unordered_map &nodes)=0; bool is_connected(){ if (connection) return true; return false; } std::string get_connection_id(); std::string get_name(); protected: std::string name,description,title; Node* connection; bool connectable; std::string input; }; template class Variable_type : public Variable { public: Variable_type(std::string _name="",std::string _input="",bool _connectable=true){ name=_name; input=_input; connectable=_connectable; }; void init(Json::Value s){ std::istringstream cur(s["value"].asString()); cur >> value; name=s["name"].asString(); input=s["input"].asString(); } bool create_connection(std::unordered_map &nodes){ for (auto node:nodes){ if (node.first==input){ if (connect(node.second)) return true; } } return false; } Json::Value to_json(); std::string get_type(){ //need this to output node templates return TypeName::Get(); } //have to cast connect and get_output to use templated return types bool connect(Node* target){ if (connectable){ if (dynamic_cast*>(target)){ connection=target; return true; } } return false; } const T& get(const Frame_parameters &frame){ //if (connection) std::cerr<<"still connected to '"<<(dynamic_cast*>(connection))->get_type()<<"'"<*>(connection))->get_type()<<"' node ("<*>(connection))->get_output(frame)<*>(connection))->get_output(frame); } //else std::cerr<<"variable: returning default"< values; }; template class Variable_array_type: public Variable_array { public: Variable_array_type(std::string n){name=n;connectable=true;}; void init(Json::Value s){ name=s["name"].asString(); if (!s["input"].empty()){ for (uint32_t i=0;i &nodes){ bool success=true; //for (auto v:values){ //weirdly does not work even though it seems to! maybe it returns a copy of of the object? // v.create_connection(nodes); //} for (uint32_t i=0;i::Get(); } bool connect(Node* target){ //array does not connect this way return false; } void add(std::string _name,std::string _input,bool _connectable=true){ values.push_back(Variable_type(_name,_input,_connectable)); } void add(std::string _name="",bool _connectable=true,int num=1){ for (int i=0;i(_name,"",_connectable)); } bool connect(uint32_t which,Node* target){ if (values.size()>which){ return values[which].connect(target); } return false; } const T& get(uint32_t which,const Frame_parameters &frame){ if (values.size()>which){ //std::cerr<<"array: requested value "<>& get_values(){return values;}; uint32_t get_number(){return values.size();}; protected: std::vector> values; T value; }; //don't forget the dupliicate inlets //it needs to be a property of a var //vars need to be: //std::unordered_map>> //?? //or could it be that a var has properties //var needs to be a class? //or multi var could be a subclass of var? //with an extra accessor const T& get(int which,const Frame_parameters &frame) //in Node we could have create_multi_inlet() and add_multi_inlet() class Node { //base type for node pointers public: Node(){type="";type_id="";id="";description="";}; virtual ~Node(){ for (auto v:vars){ delete v.second; } } bool connect(std::string v,Node *t){ auto var=vars.find(v); if (var!=vars.end()){ if ((*var).second->connect(t)){ return true; } } return false; } std::string get_type(){return type;}; std::string& get_id(){return id;}; std::string& get_description(){return description;}; Json::Value to_json(); virtual Node* clone(Json::Value &_settings)=0; virtual std::string get_output_type()=0; void create_connections(std::unordered_map &nodes){ Logger& logger = Logger::get(log_id); for (auto var:vars) { if (var.second->create_connection(nodes)) { logger.information("Connected input '"+var.second->get_name()+"' of node '"+id+"' to node "+var.second->get_connection_id()); } } } protected: std::unordered_map vars; std::string type; std::string id; std::string type_id; std::string description; std::string title; std::string ui_type; std::string log_id; }; template class Node_type : public Node { public: virtual const NT& get_output(const Frame_parameters &frame){return value;}; void init(Json::Value settings){ if (!settings["vars"].empty()){ for ( uint32_t i = 0; i < settings["vars"].size(); ++i ) { if (!settings["id"].empty()) settings["vars"][i]["log_id"]=settings["log_id"].asString(); vars[settings["vars"][i]["name"].asString()]->init(settings["vars"][i]); } } if (!settings["id"].empty()) id=settings["id"].asString(); if (!settings["log_id"].empty()) log_id=settings["log_id"].asString(); } std::string get_output_type(){return TypeName::Get();}; template Variable_type* create_inlet(std::string name){ vars[name]=new Variable_type(name,"",true); return (dynamic_cast*>(vars[name])); } template Variable_type* create_attribute(std::string name="",std::string description="",std::string title="",IT _default=IT()){ vars[name]=new Variable_type(name,"",false); return (dynamic_cast*>(vars[name])); } template Variable_array_type* create_array(std::string name){ vars[name]=new Variable_array_type(name); return (dynamic_cast*>(vars[name])); } //enum will require specialisation //1st, define the enum data type protected: NT value; //every node has a value so it can return a reference }; } #endif //ROTOR_H