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);