diff options
| author | Tim Redfern <tim@herge.(none)> | 2013-03-06 17:26:24 +0000 |
|---|---|---|
| committer | Tim Redfern <tim@herge.(none)> | 2013-03-06 17:26:24 +0000 |
| commit | 4e2395d52f9da8efbf7385519f4d7d11a7498f90 (patch) | |
| tree | 3d46a4f098adb92889381ba5103090ccf241675f /rotord/rotor.cpp | |
| parent | cf9568da9b7698e4d2d507030c1e9ea80cf15291 (diff) | |
mysterious
Diffstat (limited to 'rotord/rotor.cpp')
| -rw-r--r-- | rotord/rotor.cpp | 186 |
1 files changed, 183 insertions, 3 deletions
diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp index 8360824..4164baa 100644 --- a/rotord/rotor.cpp +++ b/rotord/rotor.cpp @@ -1,13 +1,21 @@ #include "rotor.h" -using namespace Rotor; +//float equality +bool fequal(const float u,const float v){ + if (abs(u-v)<.001) return true; + else return false; +}; + +using namespace Rotor; +/* string soname="qm-vamp-plugins"; string id="qm-tempotracker"; string myname=""; string output=""; int outputNo=0; + */ void Render_context::runTask() { while (!isCancelled()) { @@ -34,6 +42,29 @@ void Render_context::add_queue(int item) { mutex.unlock(); } +bool Signal_input::connect(Node* source) { + if (source->output_type=="signal") { + connection=source; + return true; + } + else return false; +}; + +bool Signal_output::render(const float duration, const float framerate,string &xml_out){ + cerr << "Rotor: Signal_output rendering " << duration << " seconds at " << framerate << " frames per second" << endl; + float step=1.0f/framerate; + float v=0.0f; + for (float f=0.0f;f<duration;f+=step) { + float u=get_output(f); + cerr << "Rotor: Signal_output got " << u << "as output" << endl; + if (!fequal(u,v)) { + xml_out+=("<signal time='"+ofToString(f)+"'>"+ofToString(u)+"</signal>\n"); + v=u; + } + } + return true; +} + Command_response Render_context::session_command(const std::vector<std::string>& command){ //method,id,command1,{command2,}{body} //here we allow the controlling server to communicate with running tasks @@ -95,6 +126,11 @@ Command_response Render_context::session_command(const std::vector<std::string>& string graph_filename=command[3]; if (load_graph(graph_filename)) { response.description="<status context='"+command[1]+"'>Rotor: loaded graph "+command[3]+"</status>\n"; + string xmlstring; + xml.copyXmlToString(xmlstring); + response.description+=xmlstring; + //the graph could actually contain an xml object and we could just print it here? + //or could our nodes even be subclassed from xml nodes? } else { response.status=HTTPResponse::HTTP_INTERNAL_SERVER_ERROR; //~/sources/poco-1.4.6-all/Net/include/Poco/Net/HTTPResponse.h @@ -109,9 +145,153 @@ Command_response Render_context::session_command(const std::vector<std::string>& } } } + if (command[2]=="signal") { + if (command[0]=="GET") { //generate xml from 1st signal output + if (state==IDLE) { + //direct call for testing + float framerate=0.0f; + if (command.size()>2) { + framerate=ofToFloat(command[3]); + } + string signal_xml; + if (graph.signal_render(framerate,signal_xml)){ + response.description=signal_xml; + } + else { + response.status=HTTPResponse::HTTP_INTERNAL_SERVER_ERROR; + response.description="<status context='"+command[1]+"'>Rotor: could not render output signal</status>\n"; + } + } + else { + response.status=HTTPResponse::HTTP_NOT_FOUND; + response.description="<status context='"+command[1]+"'>Signal output not found</status>\n"; + } + } + else { + response.status=HTTPResponse::HTTP_SERVICE_UNAVAILABLE; + response.description="<status context='"+command[1]+"'>Rotor: context busy</status>\n"; + } + } return response; } -bool Render_context::load_graph(string graph_filename){ - return true; +//how to do this? +//aim - load nodes from xml +//easily maintain the xml tree +//be able to save it or print it +//--if the list of nodes is a flat vector - don't need to store ID with the node - just refer to the index # of the node while loading? +//--if instead it refers to the index# in the unordered map - can handle deletion etc - have to check if a node exists when linking +//--also can a node link to one 'later' ? it may have to? in which case there's a 2 step process - 1 load the nodes - 2 link them +//maybe + + +// a generic way to create a named node- each node is an object- will be loadable from .so +// eventually need to figure out to load .sos and enumerate classes +// in the short term either +// - hand logic that recognises nodes and creates inputs etc +// - not sure how else? + +//its a factory? +//http://stackoverflow.com/questions/4007382/how-to-create-class-objects-dynamically +//http://www.codeproject.com/Articles/3734/Different-ways-of-implementing-factories +//http://stackoverflow.com/questions/13292856/create-derived-class-in-base-class-based-on-parameter +//http://en.wikipedia.org/wiki/Factory_method_pattern + +//what is a good way to pass parameters to objects? +//get all attributes of node and pass them as creation parameters? +//could just pass them all as strings, let the object choose what to do itself? +//YES + +bool Render_context::load_graph(string filename){ + printf("loading %s\n",filename.c_str()); + if(xml.loadFile(filename) ){ + graph=Graph(xml.getAttribute("patchbay","ID","",0),xml.getValue("patchbay","",0)); + if(xml.pushTag("patchbay")) { + int n1=xml.getNumTags("node"); + for (int i1=0;i1<n1;i1++){ + map<string,string> settings; + vector<string> attrs; + xml.getAttributeNames("node",attrs,i1); + for (auto& attr: attrs) { + settings[attr]=xml.getAttribute("node",attr,"",i1); + //cerr << "Got attribute: " << attr << ":" << xml.getAttribute("node",attr,"",i1) << endl; + } + settings["description"]=xml.getValue("node","",i1); + Node* node=factory.create(settings); + if (node) { + cerr << "Rotor: created '" << xml.getAttribute("node","type","",i1) << "'" << endl; + string nodeID=xml.getAttribute("node","ID","",i1); + graph.nodes[nodeID]=node; + if(xml.pushTag("node",i1)) { + int n2=xml.getNumTags("signal_input"); + for (int i2=0;i2<n2;i2++){ + graph.nodes[nodeID]->create_signal_input(xml.getValue("signal_input","",i2)); + string fromID=xml.getAttribute("signal_input","from","",i2); + if (graph.nodes.find(fromID)!=graph.nodes.end()) { + if (!graph.nodes[nodeID]->inputs[i2]->connect(graph.nodes[fromID])){ + cerr << "Rotor: graph loader cannot connect input " << i2 << " of node '" << nodeID << "' to node '" << fromID << "'" << endl; + return false; + } + else cerr << "Rotor: linked input " << i2 << " of node '" << nodeID << "' to node '" << fromID << "'" << endl; + } + else cerr << "Rotor: linking input " << i2 << " of node: '" << nodeID << "', cannot find target '" << fromID << "'" << endl; + } + xml.popTag(); + } + } + else { + cerr << "Rotor: graph loader cannot find node '" << xml.getAttribute("node","type","",i1) << "'" << endl; + return false; + } + } + xml.popTag(); + } + /* + model_name=XML.getAttribute("map4","model","none",0); + model_x=ofToFloat(XML.getAttribute("map4","x","none",0)); + model_y=ofToFloat(XML.getAttribute("map4","y","none",0)); + model_z=ofToFloat(XML.getAttribute("map4","z","none",0)); + if(XML.pushTag("map4")) { + numViews=XML.getNumTags("view"); + if(numViews) { + views=new viewpoint[numViews]; + for (int i=0;i<numViews;i++){ + XML.pushTag("view",i); + vector<string>keys; + XML.getAttributeNames("settings", keys, 0); + map<string,string>settings; + for (int k=0;k<keys.size();k++) { + settings[keys[k]]=XML.getAttribute("settings",keys[k],"none",0); + } + views[i].setup(settings); + XML.popTag(); + } + } + + numClips=XML.getNumTags("clip"); + if (numClips) { + clips=new string[numClips]; + for (int i=0;i< numClips;i++) { + XML.pushTag("clip",i); + clips[i]=XML.getAttribute("settings","file","none",0); + XML.popTag(); + } + } + + XML.popTag(); + for (int i=0;i< numClips;i++) { + printf("clip: %s\n",clips[i].c_str()); + } + } + */ + return true; + } + else return false; +} + +Node_factory::Node_factory(){ + //for now, statically load prototype map in constructor + add_type("audio_analysis",Audio_analysis()); + add_type("==",Is_new_integer()); + add_type("signal_output",Signal_output()); }
\ No newline at end of file |
