#include "rotord.h"
/*
ultimately- audio analysis request will spawn a task - there will be another call that will check progress
audio analysis will be saved - to a file? into a db?
for now - dump analysis into the http request
architecture - running rendering process
main vamp library segmenter, beat detector
http://127.0.0.1:9000/vamp/qm-vamp-plugins/qm-segmenter/01.wav
Running plugin: "qm-segmenter"...
Using block size = 26460, step size = 8820
Plugin accepts 1 -> 1 channel(s)
Sound file has 2 (will mix/augment if necessary)
Output is: "segmentation"
Done
./rotord: symbol lookup error: /usr/local/lib/vamp/qm-vamp-plugins.so: undefined symbol: clapack_dgetrf
http://www.codeproject.com/Articles/252827/Learning-Poco-A-simple-HTTP-server
next:
load a movie and retreive frames
save a movie
how do we deal with frames in libavcodec - can we request a frame by number
how do we deal with resolution
avcodec class
what does it have to do?
-open files (could be video, audio, or both)
-process files i.e. thumbnail the audio or do audio analysis, make a no-keyframe proxy of a movie
-retrieve video frames (with caching- what's the best way to approach this)
just for a quick think through: signal data is trivial: 1 floating point number per frame.
to store a whole uncompressed video track for a 3 minute @ 720.25p in RGB \= 12GB
caching the whole thing isn't a goer
*/
RotorRequestHandler::RotorRequestHandler(const std::string& format): _format(format){
}
void RotorRequestHandler::handleRequest(HTTPServerRequest& request,HTTPServerResponse& response) {
Timestamp now;
std::string dt(DateTimeFormatter::format(now, _format));
response.setChunkedTransferEncoding(true);
response.setContentType("text/html");
std::ostream& ostr = response.send();
ostr << "
RotorServer powered by "
"POCO C++ Libraries";
ostr << "";
ostr << "";
ostr << dt;
ostr << "
";
}
RenderContextHandler::RenderContextHandler(const std::string _content,const HTTPServerResponse::HTTPStatus _status){
content=_content;
status=_status;
}
void RenderContextHandler::handleRequest(HTTPServerRequest& request,HTTPServerResponse& response) {
response.setChunkedTransferEncoding(true);
response.setContentType("text/html");
response.setStatus(status);
std::ostream& ostr = response.send();
ostr << "\n";
ostr << content;
}
HTTPRequestHandler* RotorRequestHandlerFactory::createRequestHandler(const HTTPServerRequest& request){
Logger& logger = Logger::get("Rotor");
Poco::URI theuri=Poco::URI(request.getURI());
std::vector command;
theuri.getPathSegments(command);
logger.information(request.clientAddress().toString()+" "+request.getMethod());
HTTPResponse::HTTPStatus status=HTTPResponse::HTTP_BAD_REQUEST; //by default
std::string body;
std::ostringstream os;
os< >::iterator it;
//it=manager.taskList().begin();
//for (it=manager.taskList().begin();it !=manager.taskList().end();++it) {
//content+=""+(*it)->name()+"\n";
//}
//massive problems making an iterator for the tasklist, the above crashes
//solution: auto type range-based for-loop
//this is c++11 specific but works
for (auto& task: manager.taskList()) { //c++11
XML.addValue("sID",task->name());
}
status=HTTPResponse::HTTP_OK;
}
}
else if (command[0]=="exit") {
exit(0);
}
else {
bool found=false;
for (auto& task: manager.taskList()) { //c++11
if(task->name()==command[0]) {
//valid session command
found=true;
XML.addAttribute("rotor","context",task->name(),0);
XML.pushTag("rotor");
if (command.size()==1) {
//just invoking sID
if (request.getMethod()=="DELETE") {
task->cancel();
status=HTTPResponse::HTTP_OK;
XML.addValue("status","context deleted successfully");
}
else {
XML.addValue("error","Render context invoked with no command");
}
}
else { //session modifier command- to be passed to render context
//some commands need to return error codes
//ie where the audio file isn't found
//on the other hand, some commands need to know state of the renderer?
vector sc; //method,id,command1,{command2,}{body}
sc.push_back(request.getMethod());
for (auto& i: command){
sc.push_back(i);
}
sc.push_back(body);
//Rotor::Command_response response=((Poco::AutoPtr)task)->session_command(sc);
((Poco::AutoPtr)task)->session_command(sc,XML,status);
//content=response.description;
//status=response.status;
}
}
}
if (!found) {
status=HTTPResponse::HTTP_NOT_FOUND;
XML.pushTag("rotor");
XML.addValue("error","Render context not found");
}
}
}
else {
XML.addValue("error","Emoty request");
}
string content;
XML.copyXmlToString(content);
return new RenderContextHandler(content, status);
}
RotorServer::RotorServer(): _helpRequested(false)
{
}
RotorServer::~RotorServer()
{
}
void RotorServer::initialize(Application& self){
loadConfiguration();
ServerApplication::initialize(self);
}
void RotorServer::uninitialize(){
ServerApplication::uninitialize();
}
void RotorServer::defineOptions(OptionSet& options) {
ServerApplication::defineOptions(options);
options.addOption(
Option("help", "h", "display argument help information")
.required(false)
.repeatable(false)
.callback(OptionCallback(this, &RotorServer::handleHelp)
)
);
}
void RotorServer::handleHelp(const std::string& name, const std::string& value){
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader(
"Rotor");
helpFormatter.format(std::cout);
stopOptionsProcessing();
_helpRequested = true;
}
int RotorServer::main(const std::vector& args){
if (!_helpRequested) {
unsigned short port;
xmlIO xml;
if(xml.loadFile("settings.xml") ){
port=xml.getAttribute("Rotor","port",9000,0);
}
else cerr<<"Rotord: settings.xml not found, using defaults"<