summaryrefslogtreecommitdiff
path: root/rotord/rotor.cpp
diff options
context:
space:
mode:
authorTim Redfern <tim@herge.(none)>2013-03-06 17:26:24 +0000
committerTim Redfern <tim@herge.(none)>2013-03-06 17:26:24 +0000
commit4e2395d52f9da8efbf7385519f4d7d11a7498f90 (patch)
tree3d46a4f098adb92889381ba5103090ccf241675f /rotord/rotor.cpp
parentcf9568da9b7698e4d2d507030c1e9ea80cf15291 (diff)
mysterious
Diffstat (limited to 'rotord/rotor.cpp')
-rw-r--r--rotord/rotor.cpp186
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