From e80b647faa5a61c81964252a395fe4cb48443315 Mon Sep 17 00:00:00 2001 From: Tim Redfern Date: Tue, 28 Jan 2014 17:10:22 +0000 Subject: reinstating session command array --- NT/src/rendercontext.cpp | 477 +++++++++++++++++++++++++++++++++++++++++++++++ NT/src/rendercontext.h | 21 ++- NT/src/rotor.cpp | 4 +- NT/src/rotor.h | 3 + NT/src/rotord.cpp | 8 +- NT/src/rotord.h | 1 - NT/src/rotord.o | Bin 122328 -> 136232 bytes 7 files changed, 503 insertions(+), 11 deletions(-) (limited to 'NT') diff --git a/NT/src/rendercontext.cpp b/NT/src/rendercontext.cpp index ffc55ed..3309b16 100644 --- a/NT/src/rendercontext.cpp +++ b/NT/src/rendercontext.cpp @@ -2,6 +2,8 @@ using namespace Rotor; using namespace std; +using Poco::Net::HTTPResponse; +using Poco::Logger; string Render_context::text_render(string node_id){ Logger& logger = Logger::get(id); @@ -31,4 +33,479 @@ string Render_context::text_render(string node_id){ st+=(dynamic_cast*>(p))->get_output(f)+"\n"; } return st; +} +void Render_context::session_command(const Session_command& command,xmlIO& XML,HTTPResponse::HTTPStatus& status){ + + string s; + for (auto c:command.commands){ + s+=c; + s+=" "; + } + + Logger& logger = Logger::get(id); + status=HTTPResponse::HTTP_BAD_REQUEST; //error by default + if (command.commands[1]=="resolution") { + if (command.method=="PUT") { + if (command.body!="") { + if (state!=RENDERING) { + Poco::StringTokenizer t1(command.body,","); + if (t1.count()>1){ + int w=toInt(t1[0]); + int h=toInt(t1[1]); + if (set_resolution(w,h)){ + logger.information("resolution set to "+t1[0]+"x"+t1[1]); + XML.addValue("status","resolution set to "+t1[0]+"x"+t1[1]); + status=HTTPResponse::HTTP_OK; + } + else { + logger.error("ERROR: invalid resolution request: "+t1[0]+"x"+t1[1]); + XML.addValue("error","invalid resolution request: "+t1[0]+"x"+t1[1]); + } + } + } + else { + XML.addValue("error","session busy"); + } + } + } + } + if (command.commands[1]=="bitrate") { + if (command.method=="PUT") { + int b=toInt(command.body); + if (graph.set_bitrate(b)){ + logger.information("bitrate set to "+command.body); + XML.addValue("status","bitrate set to "+command.body); + status=HTTPResponse::HTTP_OK; + } + else { + logger.error("ERROR: Could not set bitrate set to "+command.body); + XML.addValue("error","Could not set bitrate set to "+command.body); + } + } + else { + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: Bad request"); + XML.addValue("error","Bad request"); + } + } + if (command.commands[1]=="fragmentation") { + if (command.method=="PUT") { + bool f=(toInt(command.body)!=0); + if (graph.set_fragmentation(f)){ + string fs=f?"on":"off"; + logger.information("MP4 fragmentation "+fs); + XML.addValue("status","MP4 fragmentation "+fs); + status=HTTPResponse::HTTP_OK; + } + else { + logger.error("ERROR: Could not set MP4 fragmentation"); + XML.addValue("error","Could not set MP4 fragmentation"); + } + } + else { + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: Bad request"); + XML.addValue("error","Bad request"); + } + } + if (command.commands[1]=="dash") { + if (command.method=="PUT") { + bool f=(toInt(command.body)!=0); + if (graph.set_dash(f)){ + string fs=f?"on":"off"; + logger.information("MPEG-DASH output "+fs); + XML.addValue("status","MPEG-DASH output "+fs); + status=HTTPResponse::HTTP_OK; + } + else { + logger.error("ERROR: Could not set MPEG-DASH output"); + XML.addValue("error","Could not set MPEG-DASH output"); + } + } + else { + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: Bad request"); + XML.addValue("error","Bad request"); + } + } + if (command.commands[1]=="audio") { + if (command.method=="PUT") { //get audio file location and initiate analysis + if (command.body!="") { + if (state==IDLE) { + graph.audio_filename=media_dir+command.body; //for now, store session variables in memory //check file exists + Poco::File f=Poco::File(graph.audio_filename); + if (f.exists()) { + //pass to worker thread ??if engine is ready?? ??what if engine has finished but results aren't read?? + add_queue(Session_task(command.uid,ANALYSE_AUDIO)); + status=HTTPResponse::HTTP_OK; + logger.information("Audio analysis: "+command.body); + XML.addValue("status","Starting audio analysis: "+command.body); + } + else { + status=HTTPResponse::HTTP_NOT_FOUND; + logger.error("ERROR: audio file "+command.body+" not found"); + XML.addValue("error",command.body+" not found"); + } + + } + else { + logger.error("ERROR: Session busy"); + XML.addValue("error","Session busy"); + } + } + } + if (command.method=="GET") { + if (state==ANALYSING_AUDIO) { + status=HTTPResponse::HTTP_OK; + XML.addValue("status","Analysing audio"); + char c[20]; + sprintf(c,"%02f",graph.progress); + XML.addValue("progress",string(c)); + } + else if (graph.audio_loaded) { + //not sure about this-- should this state be retained? + //can the data only be read once? + //for now + status=HTTPResponse::HTTP_OK; + XML.addValue("status","Audio ready"); + graph.audio_thumb->print_vector(XML); + //XML.addValue("audio",audio_thumb->print()); + } + else { + logger.error("ERROR: audio thumbnail requested but no audio loaded"); + XML.addValue("error","No audio loaded"); + } + } + if (command.method=="DELETE") { + if (state==IDLE) { + graph.audio_filename=""; + graph.audio_loaded=false; + logger.information("Audio deleted"); + XML.addValue("status","Audio deleted"); + status=HTTPResponse::HTTP_OK; + } + else { + logger.error("ERROR: Session busy"); + XML.addValue("error","Session busy"); + } + } + } + if (command.commands[1]=="graph") { + if (command.method=="GET") { + if (state!=LOADING_GRAPH) { + if (graph.loaded) { + status=HTTPResponse::HTTP_OK; + //XML.addValue("patchbay",graph.toString()); + logger.information("Graph loaded"); + //XML.loadFromBuffer(graph.graphToString()); + XML.addValue("status","Graph loaded"); + } + else { + logger.error("ERROR: graph not loaded"); + XML.addValue("error","graph not loaded"); + } + } + else { + logger.error("ERROR: Graph loading"); + XML.addValue("error","Graph loading"); + } + } + if (command.method=="PUT") { //get new graph from file + if (command.body!="") { + //should interrupt whatever is happening? + //before begining to load from xml + if (state==IDLE) { //eventually not like this + if (command.body!="") { + graph_filename=""; + graph_body=""; + if (Poco::File(graph_dir+command.body).exists()) { + graph_filename=graph_dir+command.body; + add_queue(Session_task(command.uid,LOAD_GRAPH)); + status=HTTPResponse::HTTP_OK; + logger.information("Loading graph from file: "+command.body); + XML.addValue("status","Loading graph from file: "+command.body); + //XML.addValue("render_id",command.uid); process ID? + } + else { + xmlIO xml; + bool readable=true; + if (!xml.loadFromBuffer(command.body)){ + Json::Value root; // will contains the root value after parsing. + Json::Reader reader; + if ( !reader.parse( command.body, root ) ) + { + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: Could not load graph"); + XML.addValue("error","Could not load graph"); + readable=false; + } + } + if (readable) { + graph_body=command.body; + add_queue(Session_task(command.uid,LOAD_GRAPH)); + status=HTTPResponse::HTTP_OK; + logger.information("Loading graph from body request"); + XML.addValue("status","Loading graph from body request"); + } + } + } + else { + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: Empty request"); + XML.addValue("error","Empty request"); + } + } + else { + logger.error("ERROR: Session busy"); + XML.addValue("error","Session busy"); + } + } + } + if (command.method=="DELETE") { + //for now + graph.clear(); + logger.information("graph deleted"); + XML.addValue("status","graph deleted"); + status=HTTPResponse::HTTP_OK; + } + } + if (command.commands[1]=="signal") { + if (command.method=="GET") { //generate xml from 1st signal output + if (state==IDLE) { + if (command.commands.size()>2) { + double framerate; + framerate=toFloat(command.body); + if (framerate==0.0) framerate=graph.framerate; + if (graph.signal_render(XML,command.commands[2],framerate)){ + status=HTTPResponse::HTTP_OK; + logger.information("rendering signal to xml"); + //XML.addValue("signal",signal_xml); //this doesn't work >> pseudo xml + } + else { + status=HTTPResponse::HTTP_INTERNAL_SERVER_ERROR; + logger.error("ERROR: could not render output signal"); + XML.addValue("error","could not render output signal"); + } + //else { + // status=HTTPResponse::HTTP_NOT_FOUND; + // XML.addValue("error","Signal output not found in graph"); + //} + } + } + else { + status=HTTPResponse::HTTP_SERVICE_UNAVAILABLE; + logger.error("ERROR: context busy"); + XML.addValue("error","Context busy"); + } + } + } + if (command.commands[1]=="video") { + if (command.method=="PUT") { //get vide file location and initiate analysis + if (command.body!="") { //there should be a filename + a destination node + if (state!=RENDERING) { + if (command.commands.size()>2) { + string video_filename=media_dir+command.body; + //check file exists + Poco::File f=Poco::File(video_filename); + if (f.exists()) { + if (graph.load_video(command.commands[2],video_filename)) { + //pass to worker thread ??if engine is ready?? ??what if engine has finished but results aren't read?? + //DUMMY RESPONSE + status=HTTPResponse::HTTP_OK; + logger.information("Succesfully loaded "+command.body+" into video node "+command.commands[2]); + XML.addValue("status","Succesfully loaded "+command.body+" into video node "+command.commands[2]); + } + else { + status=HTTPResponse::HTTP_INTERNAL_SERVER_ERROR; + logger.error("ERROR: could not load "+command.body+" into video node "+command.commands[2]); + XML.addValue("error","could not load "+command.body+" into video node "+command.commands[2]); + } + } + else { + status=HTTPResponse::HTTP_NOT_FOUND; + logger.error("ERROR: "+command.body+" not found"); + XML.addValue("error",command.body+" not found"); + } + } + else { + status=HTTPResponse::HTTP_NOT_FOUND; + logger.error("ERROR: video loader node not specified"); + XML.addValue("error","video loader 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"); + } + } + else { + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: Bad request"); + XML.addValue("error","Bad request"); + } + } + if (command.commands[1]=="preview") { + if (command.method=="GET") { + if(state==IDLE){ + //parse json to get preview spec, return XML? this is a mess + string preview_node=command.commands[2]; + Json::Value root; // will contains the root value after parsing. + Json::Reader reader; + if (reader.parse( command.body, root )) { + int frame=root["frame"].asInt(); + int width=root["width"].asInt(); + int height=root["height"].asInt(); + string format=root["format"].asString(); + if (graph.preview(XML,preview_node,format,frame,width,height)) { + status=HTTPResponse::HTTP_OK; + } + else { + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: Could not create preview"); + XML.addValue("error","Could not preview node '"+preview_node+"', frame "+toString(frame)+" at "+toString(width)+"x"+toString(height)); + } + } + else { + std::cout << "Failed to parse preview request\n" + << reader.getFormattedErrorMessages(); + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: Bad preview request"); + XML.addValue("error","Bad preview request"); + } + } + 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]=="features") { + if (command.method=="GET") { + if(state==IDLE){ + if (command.commands.size()>2){ + //parse json to get preview spec, return XML? this is a mess + string features_node=command.commands[2]; + if (graph.print_features(XML,features_node)) { + status=HTTPResponse::HTTP_OK; + } + else { + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: Could not print features for node /"+features_node+"/"); + } + } + else { + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: Features 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]=="render") { + if (command.method=="GET") { + if(state==RENDERING){ + //graph.mutex.lock(); + status=HTTPResponse::HTTP_OK; + XML.addValue("status","Rendering video"); + XML.addValue("progress",toString(graph.progress)); + //graph.mutex.unlock(); + } + else { + logger.error("ERROR: Render progress requested but not rendering"); + XML.addValue("error","Not rendering"); + } + } + if (command.method=="PUT") { + if (command.body!="") { + if (state==IDLE) { + Poco::StringTokenizer t1(command.body,","); + if (t1.count()>1){ + output_filename=output_dir+t1[0]; + start=toInt(t1[1]); + if (t1.count()>2){ + stop=toInt(t1[2]); + if (t1.count()>3){ + double framerate=toFloat(t1[3]); + if (framerate>0.0) { + output_framerate=framerate; + } + } + } + } + else { + start=0; + stop=999999; + output_filename=output_dir+command.body; + } + add_queue(Session_task(command.uid,RENDER)); + status=HTTPResponse::HTTP_OK; + logger.information("Starting render: "+command.body); + XML.addValue("status","Starting render: "+command.body); + XML.addValue("render_id",command.uid); + XML.addValue("path",output_filename); + } + 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: No output file specified"); + XML.addValue("error","No output file specified"); + } + } + if (command.method=="DELETE") { + status=HTTPResponse::HTTP_OK; + logger.error("ERROR: Not implemented"); + XML.addValue("status","DUMMY RESPONSE: cancelling render"); + } + } + if (command.commands[1]=="cancel") { + if (command.method=="PUT") { + if (state==RENDERING){ + graph.cancelled=true; + logger.information("Render cancelled."); + XML.addValue("status","render cancelled"); + } + else if (state==ANALYSING_AUDIO){ + graph.cancelled=true; + logger.information("Audio analysis cancelled."); + XML.addValue("status","audio analysis cancelled"); + } + else { + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: no process to cancel"); + XML.addValue("error","No process to cancel"); + } + } + else { + status=HTTPResponse::HTTP_BAD_REQUEST; + logger.error("ERROR: Bad request"); + XML.addValue("error","Bad request"); + } + } } \ No newline at end of file diff --git a/NT/src/rendercontext.h b/NT/src/rendercontext.h index 097af3f..a84cad8 100644 --- a/NT/src/rendercontext.h +++ b/NT/src/rendercontext.h @@ -43,6 +43,12 @@ namespace Rotor { #define RENDER 3 #define LOAD_GRAPH 4 + class Session_command { + public: + Session_command(){body="";}; + string uid,method,id,body; + vector commands; + }; class Render_status { public: Render_status():status(0),progress(0.0){}; @@ -50,6 +56,11 @@ namespace Rotor { int status; double progress; }; + class Render_settings { + public: + Render_settings(int w=640,int h=360):width(w),height(h){}; + int width,height; + }; class Render_context: public Poco::Task { public: Render_context(const std::string& _id): Task(_id) { @@ -76,6 +87,12 @@ namespace Rotor { sleep(100); } } + bool set_preset(std::string& _preset){ + if (presets.find(_preset)==presets.end()) return false; + preset=_preset; + return true; + } + void session_command(const Session_command& command,xmlIO& XML,Poco::Net::HTTPResponse::HTTPStatus& status); Render_status get_render_status(const string &uid){ if (renders.find(uid)!=renders.end()){ if (renders[uid].status==RENDERING){ @@ -89,7 +106,9 @@ namespace Rotor { Graph graph; private: std::string id; - std::unordered_map renders; + std::unordered_map renders; + std::unordered_map presets; + std::string preset; }; }; diff --git a/NT/src/rotor.cpp b/NT/src/rotor.cpp index 2909255..12218e5 100644 --- a/NT/src/rotor.cpp +++ b/NT/src/rotor.cpp @@ -40,10 +40,9 @@ Json::Value Variable_array_type::to_json(){ return json; } -//explicit template instantiation +//explicit template instantiation to avoid linker errors template class Variable_type; template class Variable_type; - template class Variable_array_type; @@ -65,7 +64,6 @@ Json::Value Node::to_json(){ return node; } -//factory generates linker errors if rotor.h implementation is seperated: why? //int main(){ diff --git a/NT/src/rotor.h b/NT/src/rotor.h index 17c8545..f687694 100644 --- a/NT/src/rotor.h +++ b/NT/src/rotor.h @@ -22,6 +22,8 @@ What next? #include #include +#include "xmlIO.h" + #include "Poco/Logger.h" #include "Poco/Channel.h" #include "Poco/SplitterChannel.h" @@ -32,6 +34,7 @@ What next? #include "Poco/Formatter.h" #include "Poco/PatternFormatter.h" #include "Poco/AutoPtr.h" +#include "Poco/Net/HTTPResponse.h" using Poco::Logger; using Poco::Channel; diff --git a/NT/src/rotord.cpp b/NT/src/rotord.cpp index d1c1e66..983bbe7 100644 --- a/NT/src/rotord.cpp +++ b/NT/src/rotord.cpp @@ -41,10 +41,6 @@ HTTPRequestHandler* RotorRequestHandlerFactory::createRequestHandler(const HTTPS xmlIO XML; //xml object handles the servers responses XML.addTag("rotor"); - //can we create a tinyxml object here and pass a pointer to it to the render context? - //can tinyxml output to a string? is there any reason to use poco instead? - - if (command.size()) { /* if (command[0]=="thumbnail") { @@ -250,7 +246,7 @@ HTTPRequestHandler* RotorRequestHandlerFactory::createRequestHandler(const HTTPS if(task->name()==command[0]) { //valid session command - /* + found=true; XML.addAttribute("rotor","context",task->name(),0); XML.pushTag("rotor"); @@ -291,7 +287,7 @@ HTTPRequestHandler* RotorRequestHandlerFactory::createRequestHandler(const HTTPS renders[SC.uid]=command[0]; } } - */ + } } if (!found) { diff --git a/NT/src/rotord.h b/NT/src/rotord.h index 659bb74..c57c6c4 100644 --- a/NT/src/rotord.h +++ b/NT/src/rotord.h @@ -73,7 +73,6 @@ using Poco::AutoPtr; #include "rendercontext.h" -#include "xmlIO.h" class RenderContextHandler: public HTTPRequestHandler { diff --git a/NT/src/rotord.o b/NT/src/rotord.o index 3c1187f..e73e551 100644 Binary files a/NT/src/rotord.o and b/NT/src/rotord.o differ -- cgit v1.2.3