diff --git a/src/buffer_stream.cpp b/src/buffer_stream.cpp
index cd662733..ebbbe6f9 100644
--- a/src/buffer_stream.cpp
+++ b/src/buffer_stream.cpp
@@ -60,7 +60,10 @@ std::string Buffer::Stream::getStats(){
Storage["totals"]["up"] = tot_up;
Storage["totals"]["count"] = tot_count;
Storage["totals"]["now"] = now;
- Storage["totals"]["buffer"] = name;
+ Storage["buffer"] = name;
+ Storage["meta"] = Strm->metadata;
+ if (Storage["meta"].isMember("audio")){Storage["meta"]["audio"].removeMember("init");}
+ if (Storage["meta"].isMember("video")){Storage["meta"]["video"].removeMember("init");}
std::string ret = Storage.toString();
Storage["log"].null();
stats_mutex.unlock();
diff --git a/src/conn_http.cpp b/src/conn_http.cpp
index ea98c26b..8ce0814a 100644
--- a/src/conn_http.cpp
+++ b/src/conn_http.cpp
@@ -101,7 +101,9 @@ namespace Connector_HTTP{
/// Handles internal requests.
void Handle_Internal(HTTP::Parser & H, Socket::Connection * conn){
- if (H.url == "/crossdomain.xml"){
+ std::string url = H.url;
+
+ if (url == "/crossdomain.xml"){
H.Clean();
H.SetHeader("Content-Type", "text/xml");
H.SetHeader("Server", "mistserver/" PACKAGE_VERSION "/" + Util::Config::libver);
@@ -110,22 +112,60 @@ namespace Connector_HTTP{
return;
}//crossdomain.xml
- if (H.url.length() > 10 && H.url.substr(0, 7) == "/embed_" && H.url.substr(H.url.length() - 3, 3) == ".js"){
- std::string streamname = H.url.substr(7, H.url.length() - 10);
+ if ((url.length() > 9 && url.substr(0, 6) == "/info_" && url.substr(url.length() - 3, 3) == ".js") || (url.length() > 10 && url.substr(0, 7) == "/embed_" && url.substr(H.url.length() - 3, 3) == ".js")){
+ std::string streamname;
+ if (url.substr(0, 6) == "/info_"){
+ streamname = url.substr(6, url.length() - 9);
+ }else{
+ streamname = url.substr(7, url.length() - 10);
+ }
JSON::Value ServConf = JSON::fromFile("/tmp/mist/streamlist");
std::string response;
+ std::string host = H.GetHeader("Host");
+ if (host.find(':')){host.resize(host.find(':'));}
H.Clean();
H.SetHeader("Server", "mistserver/" PACKAGE_VERSION "/" + Util::Config::libver);
H.SetHeader("Content-Type", "application/javascript");
- response = "// Generating embed code for stream " + streamname + "\n\n";
- if (ServConf["streams"].isMember(streamname)){
- std::string streamurl = "http://" + H.GetHeader("Host") + "/" + streamname + ".flv";
- response += "// Stream URL: " + streamurl + "\n\n";
- response += "document.write('');\n";
+ response = "// Generating info code for stream " + streamname + "\n\nif (!mistvideo){var mistvideo = {};}\n";
+ JSON::Value json_resp;
+ if (ServConf["streams"].isMember(streamname) && ServConf["config"]["protocols"].size() > 0){
+ json_resp["width"] = ServConf["statistics"][streamname]["meta"]["video"]["width"].asInt();
+ json_resp["height"] = ServConf["statistics"][streamname]["meta"]["video"]["height"].asInt();
+ //first, see if we have RTMP working and output all the RTMP.
+ for (JSON::ArrIter it = ServConf["config"]["protocols"].ArrBegin(); it != ServConf["config"]["protocols"].ArrEnd(); it++){
+ if ((*it)["connector"].asString() == "RTMP"){
+ JSON::Value tmp;
+ tmp["type"] = "rtmp";
+ tmp["url"] = "rtmp://" + host + ":" + (*it)["port"].asString() + "/play/" + streamname;
+ json_resp["source"].append(tmp);
+ }
+ }
+ //then, see if we have HTTP working and output all the dynamic.
+ for (JSON::ArrIter it = ServConf["config"]["protocols"].ArrBegin(); it != ServConf["config"]["protocols"].ArrEnd(); it++){
+ if ((*it)["connector"].asString() == "HTTP"){
+ JSON::Value tmp;
+ tmp["type"] = "f4v";
+ tmp["url"] = "http://" + host + ":" + (*it)["port"].asString() + "/"+streamname+"/manifest.f4m";
+ json_resp["source"].append(tmp);
+ }
+ }
+ //and all the progressive.
+ for (JSON::ArrIter it = ServConf["config"]["protocols"].ArrBegin(); it != ServConf["config"]["protocols"].ArrEnd(); it++){
+ if ((*it)["connector"].asString() == "HTTP"){
+ JSON::Value tmp;
+ tmp["type"] = "flv";
+ tmp["url"] = "http://" + host + ":" + (*it)["port"].asString() + "/"+streamname+".flv";
+ json_resp["source"].append(tmp);
+ }
+ }
}else{
- response += "// Stream not available at this server.\nalert(\"This stream is currently not available at this server.\\\\nPlease try again later!\");";
+ json_resp["error"] = "The specified stream is not available on this server.";
+ json_resp["bbq"] = "sauce";//for legacy purposes ^_^
+ }
+ response += "mistvideo['" + streamname + "'] = "+json_resp.toString()+";\n";
+ if (url.substr(0, 6) != "/info_" && !json_resp.isMember("error")){
+ response += "\n\nif(!mistvideo.hasSupport||!mistvideo.buildPlayer){mistvideo.flashVersion=function(){var version=0;try{version=navigator.mimeTypes['application/x-shockwave-flash'].enabledPlugin.description.replace(/([^0-9\\.])/g,'').split('.')[0];}catch(e){}try{version=new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable(\"$version\").replace(/([^0-9\\,])/g,'').split(',')[0];}catch(e){}return version;};mistvideo.supports={flashversion:parseInt(mistvideo.flashVersion(),10)};mistvideo.hasSupport=function(type){switch(type){case'f4v':return mistvideo.supports.flashversion>=11;break;case'rtmp':return mistvideo.supports.flashversion>=10;break;case'flv':return mistvideo.supports.flashversion>=7;break;default:return false;}};mistvideo.buildPlayer=function(src,container,width,height){switch(src.type){case'f4v':case'rtmp':case'flv':container.innerHTML='';break;}};}var video=mistvideo['"+streamname+"'],container=document.createElement('div'),scripts=document.getElementsByTagName('script'),me=scripts[scripts.length-1];me.parentNode.insertBefore(container,me);container.setAttribute('class','mistvideo');me.parentNode.removeChild(me);if(video.error){container.innerHTML=['Error: ',video.error,''].join('');}else if(video.source.length<1){container.innerHTML='Error: no streams found';}else{var i,videofoundPlayer=false,len=video.source.length;for(i=0;iSend(H.BuildResponse("200", "OK"));
return;
@@ -261,6 +301,7 @@ namespace Connector_HTTP{
}
if (H.url == "/crossdomain.xml"){return "internal";}
if (H.url.length() > 10 && H.url.substr(0, 7) == "/embed_" && H.url.substr(H.url.length() - 3, 3) == ".js"){return "internal";}
+ if (H.url.length() > 9 && H.url.substr(0, 6) == "/info_" && H.url.substr(H.url.length() - 3, 3) == ".js"){return "internal";}
return "none";
}
diff --git a/src/controller.cpp b/src/controller.cpp
index df61f517..7fb7f61e 100644
--- a/src/controller.cpp
+++ b/src/controller.cpp
@@ -171,7 +171,11 @@ void CheckProtocols(JSON::Value & p){
}
counter = counter.asInt() + 1;
new_connectors[std::string("Conn")+counter.asString()] = tmp;
- (*ait)["online"] = Util::Procs::isActive(std::string("Conn")+counter.asString());
+ if (Util::Procs::isActive(std::string("Conn")+counter.asString())){
+ (*ait)["online"] = 1;
+ }else{
+ (*ait)["online"] = 0;
+ }
}
//shut down deleted/changed connectors
@@ -423,18 +427,22 @@ int main(int argc, char ** argv){
size_t newlines = it->Received().find("\n\n");
while (newlines != std::string::npos){
Request = JSON::fromString(it->Received().substr(0, newlines));
- if (Request.isMember("totals") && Request["totals"].isMember("buffer")){
- std::string thisbuffer = Request["totals"]["buffer"];
+ if (Request.isMember("buffer")){
+ std::string thisbuffer = Request["buffer"];
Connector::lastBuffer[thisbuffer] = time(0);
- Connector::Storage["statistics"][thisbuffer]["curr"] = Request["curr"];
- std::stringstream st;
- st << Request["totals"]["now"].asInt();
- std::string nowstr = st.str();
- Connector::Storage["statistics"][thisbuffer]["totals"][nowstr] = Request["totals"];
- Connector::Storage["statistics"][thisbuffer]["totals"].shrink(600);//limit to 10 minutes of data
- for (JSON::ObjIter jit = Request["log"].ObjBegin(); jit != Request["log"].ObjEnd(); jit++){
- Connector::Storage["statistics"][thisbuffer]["log"].append(jit->second);
- Connector::Storage["statistics"][thisbuffer]["log"].shrink(1000);//limit to 1000 users per buffer
+ if (Request.isMember("meta")){
+ Connector::Storage["statistics"][thisbuffer]["meta"] = Request["meta"];
+ }
+ if (Request.isMember("totals")){
+ Connector::Storage["statistics"][thisbuffer]["curr"] = Request["curr"];
+ std::string nowstr = Request["totals"]["now"].asString();
+ Connector::Storage["statistics"][thisbuffer]["totals"][nowstr] = Request["totals"];
+ Connector::Storage["statistics"][thisbuffer]["totals"].shrink(600);//limit to 10 minutes of data
+ //if metadata is available, store it
+ for (JSON::ObjIter jit = Request["log"].ObjBegin(); jit != Request["log"].ObjEnd(); jit++){
+ Connector::Storage["statistics"][thisbuffer]["log"].append(jit->second);
+ Connector::Storage["statistics"][thisbuffer]["log"].shrink(1000);//limit to 1000 users per buffer
+ }
}
}
it->Received().erase(0, newlines+2);