From ebc874413991fbc3d07493ece55f88f23e437af6 Mon Sep 17 00:00:00 2001 From: Tim Redfern Date: Wed, 14 May 2014 20:06:02 +0100 Subject: NT bugs cleaned and variable array type functional --- NT/Makefile | 2 +- NT/src/graph.cpp | 1 + NT/src/nodes.cpp | 1 + NT/src/rendercontext.cpp | 35 ++++++++++-- NT/src/rotor.cpp | 15 ----- NT/src/rotor.h | 138 +++++++++++++++++++++++++++------------------- rotord/src/graph.cpp | 25 +++++---- rotord/src/libavwrapper.h | 9 ++- 8 files changed, 137 insertions(+), 89 deletions(-) diff --git a/NT/Makefile b/NT/Makefile index 40abdf9..36008f1 100644 --- a/NT/Makefile +++ b/NT/Makefile @@ -8,7 +8,7 @@ MY_CFLAGS = -Wswitch -fpermissive -std=c++11 `pkg-config --cflags --libs gtk+-2.0` -I /usr/include/librsvg-2.0/librsvg -I /usr/include/opencv -I /usr/include/cairo -I /usr/include/jsoncpp # -I ../ffmpeg -MY_LIBS = -lgobject-2.0 -lrsvg-2 -lnoise -ljsoncpp -lcairo -lopencv_core -lopencv_video -lopencv_imgproc -lopencv_highgui -lPocoNet -lPocoXML -lPocoUtil -lPocoFoundation -lvamp-hostsdk -lsndfile -L /usr/local/lib -lswscale -lavcodec -lavformat -lavfilter -lavdevice -lavutil -lstdc++ -lm +MY_LIBS = -lffms2 -lgobject-2.0 -lrsvg-2 -lnoise -ljsoncpp -lcairo -lopencv_core -lopencv_video -lopencv_imgproc -lopencv_highgui -lPocoNet -lPocoXML -lPocoUtil -lPocoFoundation -lvamp-hostsdk -lsndfile -L /usr/local/lib -lswscale -lavcodec -lavformat -lavfilter -lavdevice -lavutil -lstdc++ -lm # The linker options.libgstaasinklibgstaasink.so #MY_LIBS = -lgobject-2.0 -lrsvg-2 -lnoise -lffms2 -ljsoncpp -lcairo -lopencv_core -lopencv_video -lopencv_imgproc -lopencv_highgui -lPocoNet -lPocoXML -lPocoUtil -lPocoFoundation -lvamp-hostsdk -lsndfile -L /usr/local/lib -lswscale -lavcodec -lavformat -lavfilter -lavdevice -lavutil -lstdc++ -lm diff --git a/NT/src/graph.cpp b/NT/src/graph.cpp index f108f55..5b0a15a 100644 --- a/NT/src/graph.cpp +++ b/NT/src/graph.cpp @@ -123,6 +123,7 @@ bool Graph::parse_json(string &data,string &media_path){ check_audio(root["audio"].asString(),media_path); init(root["id"].asString()); Json::Value jnodes = root["nodes"]; + //std::cerr<<"json parser found "<* s=(dynamic_cast*>(p)); if (!s) { - logger.error("text_render: node '"+id+"' is not a text node"); + logger.error("text_render: node '"+node_id+"' is not a text node"); return ""; } string st=""; for (double t=0;t<10.0;t+=0.765){ Frame_parameters f=Frame_parameters(t,25.0,10.0,640,360); - st+=(dynamic_cast*>(p))->get_output(f)+"\n"; + st+=toString(t)+":"+(dynamic_cast*>(p))->get_output(f)+","; } return st; } +bool Render_context::video_render(std::string output_filename,std::string node_id=""){ + return true; +} void Render_context::session_command(const Session_command& command,xmlIO& XML,HTTPResponse::HTTPStatus& status){ string s; @@ -259,6 +262,30 @@ void Render_context::session_command(const Session_command& command,xmlIO& XML,H status=HTTPResponse::HTTP_OK; } } + if (command.commands[1]=="text") { + if (command.method=="GET") { + if(state==IDLE){ + string text_node=command.body; + if (text_node!=""){ + XML.addValue("data",text_render(text_node)); + } + else { + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: Text node not specified"); + } + } + else { + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: Session busy"); + XML.addValue("error","Session busy"); + } + } + else { + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: Bad request"); + XML.addValue("error","Bad request"); + } + } /* if (command.commands[1]=="signal") { if (command.method=="GET") { //generate xml from 1st signal output diff --git a/NT/src/rotor.cpp b/NT/src/rotor.cpp index 5f75826..997dc4c 100644 --- a/NT/src/rotor.cpp +++ b/NT/src/rotor.cpp @@ -9,12 +9,6 @@ using namespace std; using namespace Rotor; -std::istream& operator>> (std::istream &in, Rotor::Enum &en) -{ - in >> en.value; - return in; -}; - string Variable::get_connection_id(){ if (connection) return connection->get_id(); return ""; @@ -23,15 +17,6 @@ string Variable::get_name(){ return name; } -template -Json::Value Variable_type::to_json(){ - Json::Value json; - json["type"]=get_type(); - json["name"]=name; - json["connectable"]=connectable?"yes":"no"; - json["input"]=connection?connection->get_id():""; - return json; -} template Json::Value Variable_array_type::to_json(){ diff --git a/NT/src/rotor.h b/NT/src/rotor.h index 6d56299..485ec8c 100644 --- a/NT/src/rotor.h +++ b/NT/src/rotor.h @@ -8,7 +8,11 @@ TJR-Jan-2014 NB when plugging in to framework - convert all cerr messages to logged -What next? +Test suite + +pipe to send commands? + +seperate framework? ie in Python- load server- send http commands */ #define ENABLE_TYPENAME(A) template<> struct TypeName { static const char *Get() { return #A; }}; @@ -93,10 +97,15 @@ namespace Rotor { operator int () const { //overload C style cast to int return value; } - friend std::istream& operator>> (std::istream &in, Rotor::Enum &en); + //only works inside class definition? + friend std::istream &operator>> (std::istream &in, Rotor::Enum &en) { + in >> en.value; + return in; + }; + protected: + int value; private: std::vector labels; - int value; }; class Audio_frame{ @@ -150,6 +159,47 @@ namespace Rotor { bool connectable; std::string input; }; + 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 Variable_type : public Variable { public: Variable_type(std::string _name="",std::string _description="",std::string _title="",bool _connectable=true): Variable(_name,_description,_title){ @@ -172,10 +222,17 @@ namespace Rotor { } return false; } - Json::Value to_json(); - std::string get_type(){ //need this to output node templates - return TypeName::Get(); - } + Json::Value to_json(){ + Json::Value json; + json["type"]=get_type(); + json["name"]=name; + json["connectable"]=connectable?"yes":"no"; + json["input"]=connection?connection->get_id():""; + return 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){ @@ -200,6 +257,7 @@ namespace Rotor { T value; }; class Variable_array: public Variable { + //base type for a variable amount of inlets public: Variable_array(std::string _name="",std::string _description="",std::string _title="",bool _connectable=true): Variable(_name,_description,_title){ connectable=_connectable; @@ -208,32 +266,41 @@ namespace Rotor { std::vector values; }; template class Variable_array_type: public Variable_array { + //is it possible to overload array access operator here? public: Variable_array_type(std::string _name="",std::string _description="",std::string _title="",bool _connectable=true): Variable_array(_name,_description,_title,connectable){}; void init(Json::Value s){ name=s["name"].asString(); if (!s["input"].empty()){ - add(s["input"].size()); + for (int i;i &nodes){ - bool success=true; + bool success=false; //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(); - } + std::string get_type(){ + return TypeName::Get(); + } bool connect(Node* target){ - //array does not connect this way + //array does not connect this way- just connect 1st inlet? return false; } + void add(Json::Value s){ + values.push_back(Variable_type(s.get("name","").asString(),s.get("description","").asString(),s.get("title","").asString(),s.get("connectable",false).asBool())); + } void add(std::string _name="",std::string _description="",std::string _title="",bool _connectable=true){ values.push_back(Variable_type(_name,_description,_title,_connectable)); } @@ -260,48 +327,7 @@ namespace Rotor { std::vector> values; T value; }; - //could specialise a variable type operator double() etc to allow direct cast - 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;}; diff --git a/rotord/src/graph.cpp b/rotord/src/graph.cpp index 6994614..9088a8a 100644 --- a/rotord/src/graph.cpp +++ b/rotord/src/graph.cpp @@ -478,7 +478,8 @@ bool Graph::parseJson(string &data,string &media_path){ //this always falls over on DDs 3404.json file WHY? //is there way to make a json value safe? - //analysis_seed=root.get("seed","0").asInt(); + // + analysis_seed=root.get("seed",0).asInt(); check_audio(root.get("audio","").asString(),media_path); init(root.get("ID","").asString(),root.get("description","").asString()); Json::Value jnodes = root["nodeDefinitions"]; @@ -487,27 +488,27 @@ bool Graph::parseJson(string &data,string &media_path){ //cerr<<"json found node: "< settings; vector attrs; - settings["type"]=jnodes[i]["type"].asString(); + settings["type"]=jnodes[i].get("type","").asString(); settings["Log_name"]=Log_name; //attributes settings["media_path"]=media_path; for (uint32_t m=0;mattributes.find(attribute)!=node->attributes.end()){ Attribute *attr=node->attributes.find(attribute)->second; if (attr->type=="enum"){ - val=jnodes[i]["attributes"][m]["value"].asString(); + val=jnodes[i]["attributes"][m].get("value","").asString(); attr->init(val); } if (attr->type=="string") { - val=jnodes[i]["attributes"][m]["value"].asString(); + val=jnodes[i]["attributes"][m].get("value","").asString(); attr->init(val); } if (attr->type=="array"){ @@ -542,7 +543,7 @@ bool Graph::parseJson(string &data,string &media_path){ //signal inputs for (uint32_t j=0;j< jnodes[i]["signal_inputs"].size();j++){ if ((nodes[nodeID])->inputs.size()>j) { - string fromID=jnodes[i]["signal_inputs"][j]["from"].asString(); + string fromID=jnodes[i]["signal_inputs"][j].get("from","").asString(); if (fromID!=""){ if (nodes.find(fromID)!=nodes.end()) { if (!nodes[nodeID]->inputs[j]->connect((Signal_node*)nodes[fromID])){ @@ -582,7 +583,7 @@ bool Graph::parseJson(string &data,string &media_path){ } } if (((Image_node*)nodes[nodeID])->image_inputs.size()>k) { - string fromID=jnodes[i]["image_inputs"][k]["from"].asString(); + string fromID=jnodes[i]["image_inputs"][k].get("from","").asString(); if (fromID!=""){ if (nodes.find(fromID)!=nodes.end()) { if (dynamic_cast(nodes[fromID])!=nullptr) { @@ -603,15 +604,15 @@ bool Graph::parseJson(string &data,string &media_path){ //parameters for (uint32_t l=0;lparameters.find(parameter)!=nodes[nodeID]->parameters.end()) { - double val=jnodes[i]["parameters"][l]["value"].asFloat(); + double val=jnodes[i]["parameters"][l].get("value",0.0).asFloat(); if (val!=nodes[nodeID]->parameters.find(parameter)->second->value){ nodes[nodeID]->parameters.find(parameter)->second->value=val; cerr << "Rotor: set parameter '"<parameters[parameter]->connect(nodes[fromID])){ cerr << "ERROR: graph loader cannot connect parameter " << parameter << " of node '" << nodeID << "' to node '" << fromID << "'" << endl; diff --git a/rotord/src/libavwrapper.h b/rotord/src/libavwrapper.h index fc628c0..d6f411d 100644 --- a/rotord/src/libavwrapper.h +++ b/rotord/src/libavwrapper.h @@ -31,7 +31,7 @@ extern "C" { namespace libav { - // Some libavcodec calls are not reentrant + // Some libavcodec calls are not reentrant void maybeInitFFMpegLib(); class video_decoder @@ -77,6 +77,13 @@ namespace libav { std::cerr<<"ffmpegsource: "<NumFrames<<" error: "<NumFrames), &err); if (frame == NULL) { std::cerr<<"ffmpegsource: "<