Added "deletestreamsource" call that deletes a stream AND the corresponding source file.
This commit is contained in:
parent
31403f2685
commit
7af419fdad
12 changed files with 146 additions and 10 deletions
|
@ -511,6 +511,81 @@ void Controller::handleAPICommands(JSON::Value & Request, JSON::Value & Response
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (Request.isMember("deletestreamsource")){
|
||||||
|
//if array, delete all elements
|
||||||
|
//if object, delete all entries
|
||||||
|
//if string, delete just the one
|
||||||
|
if (Request["deletestreamsource"].isString()){
|
||||||
|
switch (Controller::deleteStream(Request["deletestreamsource"].asStringRef(), Controller::Storage["streams"], true)){
|
||||||
|
case 0:
|
||||||
|
Response["deletestreamsource"] = "0: No action taken";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Response["deletestreamsource"] = "1: Source file deleted";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Response["deletestreamsource"] = "2: Source file and dtsh deleted";
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
Response["deletestreamsource"] = "-1: Stream deleted, source remains";
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
Response["deletestreamsource"] = "-2: Stream and source file deleted";
|
||||||
|
break;
|
||||||
|
case -3:
|
||||||
|
Response["deletestreamsource"] = "-3: Stream, source file and dtsh deleted";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Request["deletestreamsource"].isArray()){
|
||||||
|
jsonForEach(Request["deletestreamsource"], it){
|
||||||
|
switch (Controller::deleteStream(it->asStringRef(), Controller::Storage["streams"], true)){
|
||||||
|
case 0:
|
||||||
|
Response["deletestreamsource"][it.num()] = "0: No action taken";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Response["deletestreamsource"][it.num()] = "1: Source file deleted";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Response["deletestreamsource"][it.num()] = "2: Source file and dtsh deleted";
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
Response["deletestreamsource"][it.num()] = "-1: Stream deleted, source remains";
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
Response["deletestreamsource"][it.num()] = "-2: Stream and source file deleted";
|
||||||
|
break;
|
||||||
|
case -3:
|
||||||
|
Response["deletestreamsource"][it.num()] = "-3: Stream, source file and dtsh deleted";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Request["deletestreamsource"].isObject()){
|
||||||
|
jsonForEach(Request["deletestreamsource"], it){
|
||||||
|
switch (Controller::deleteStream(it.key(), Controller::Storage["streams"], true)){
|
||||||
|
case 0:
|
||||||
|
Response["deletestreamsource"][it.key()] = "0: No action taken";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Response["deletestreamsource"][it.key()] = "1: Source file deleted";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Response["deletestreamsource"][it.key()] = "2: Source file and dtsh deleted";
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
Response["deletestreamsource"][it.key()] = "-1: Stream deleted, source remains";
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
Response["deletestreamsource"][it.key()] = "-2: Stream and source file deleted";
|
||||||
|
break;
|
||||||
|
case -3:
|
||||||
|
Response["deletestreamsource"][it.key()] = "-3: Stream, source file and dtsh deleted";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (Request.isMember("addprotocol")){
|
if (Request.isMember("addprotocol")){
|
||||||
if (Request["addprotocol"].isArray()){
|
if (Request["addprotocol"].isArray()){
|
||||||
jsonForEach(Request["addprotocol"], it){
|
jsonForEach(Request["addprotocol"], it){
|
||||||
|
|
|
@ -293,24 +293,75 @@ namespace Controller {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \triggers
|
/// Deletes the stream (name) from the config (out), optionally also deleting the VoD source file if sourceFileToo is true.
|
||||||
/// The `"STREAM_REMOVE"` trigger is stream-specific, and is ran whenever a stream is removed from the server configuration. If cancelled, the stream is not removed. Its payload is:
|
int deleteStream(const std::string & name, JSON::Value & out, bool sourceFileToo) {
|
||||||
/// ~~~~~~~~~~~~~~~
|
int ret = 0;
|
||||||
/// streamname
|
if (sourceFileToo){
|
||||||
/// ~~~~~~~~~~~~~~~
|
std::string cleaned = name;
|
||||||
void deleteStream(const std::string & name, JSON::Value & out) {
|
Util::sanitizeName(cleaned);
|
||||||
|
std::string strmSource;
|
||||||
|
if (Util::getStreamStatus(cleaned) != STRMSTAT_OFF){
|
||||||
|
DTSC::Meta mData = Util::getStreamMeta(cleaned);
|
||||||
|
if (mData.sourceURI.size()){
|
||||||
|
strmSource = mData.sourceURI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!strmSource.size()){
|
||||||
|
std::string smp = cleaned.substr(0, cleaned.find_first_of("+ "));
|
||||||
|
if (out.isMember(smp) && out[smp].isMember("source")){
|
||||||
|
strmSource = out[smp]["source"].asStringRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool noFile = false;
|
||||||
|
if (strmSource.size()){
|
||||||
|
std::string prevInput;
|
||||||
|
while (true){
|
||||||
|
std::string oldSrc = strmSource;
|
||||||
|
JSON::Value inputCapa = Util::getInputBySource(oldSrc, true);
|
||||||
|
if (inputCapa["name"].asStringRef() == prevInput){break;}
|
||||||
|
prevInput = inputCapa["name"].asStringRef();
|
||||||
|
strmSource = inputCapa["source_file"].asStringRef();
|
||||||
|
if (!strmSource.size()){
|
||||||
|
noFile = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Util::streamVariables(strmSource, cleaned, oldSrc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (noFile){
|
||||||
|
WARN_MSG("Not deleting source for stream %s, since the stream does not have an unambiguous source file.", cleaned.c_str());
|
||||||
|
}else{
|
||||||
|
Util::streamVariables(strmSource, cleaned);
|
||||||
|
if (!strmSource.size()){
|
||||||
|
FAIL_MSG("Could not delete source for stream %s: unable to detect stream source URI using any method", cleaned.c_str());
|
||||||
|
}else{
|
||||||
|
if (unlink(strmSource.c_str())){
|
||||||
|
FAIL_MSG("Could not delete source %s for %s: %s (%d)", strmSource.c_str(), cleaned.c_str(), strerror(errno), errno);
|
||||||
|
}else{
|
||||||
|
++ret;
|
||||||
|
Log("STRM", "Deleting source file for stream "+cleaned+": "+strmSource);
|
||||||
|
//Delete dtsh, ignore failures
|
||||||
|
if (!unlink((strmSource+".dtsh").c_str())){
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!out.isMember(name)){
|
if (!out.isMember(name)){
|
||||||
return;
|
return ret;
|
||||||
}
|
}
|
||||||
/*LTS-START*/
|
/*LTS-START*/
|
||||||
if(Triggers::shouldTrigger("STREAM_REMOVE")){
|
if(Triggers::shouldTrigger("STREAM_REMOVE")){
|
||||||
if (!Triggers::doTrigger("STREAM_REMOVE", name, name)){
|
if (!Triggers::doTrigger("STREAM_REMOVE", name, name)){
|
||||||
return;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*LTS-END*/
|
/*LTS-END*/
|
||||||
Log("STRM", std::string("Deleted stream ") + name);
|
Log("STRM", "Deleted stream " + name);
|
||||||
out.removeMember(name);
|
out.removeMember(name);
|
||||||
|
++ret;
|
||||||
|
ret *= -1;
|
||||||
if (inputProcesses.count(name)){
|
if (inputProcesses.count(name)){
|
||||||
pid_t procId = inputProcesses[name];
|
pid_t procId = inputProcesses[name];
|
||||||
if (Util::Procs::isRunning(procId)){
|
if (Util::Procs::isRunning(procId)){
|
||||||
|
@ -318,6 +369,7 @@ namespace Controller {
|
||||||
}
|
}
|
||||||
inputProcesses.erase(name);
|
inputProcesses.erase(name);
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
} //Controller namespace
|
} //Controller namespace
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace Controller {
|
||||||
bool CheckAllStreams(JSON::Value & data);
|
bool CheckAllStreams(JSON::Value & data);
|
||||||
void CheckStreams(JSON::Value & in, JSON::Value & out);
|
void CheckStreams(JSON::Value & in, JSON::Value & out);
|
||||||
void AddStreams(JSON::Value & in, JSON::Value & out);
|
void AddStreams(JSON::Value & in, JSON::Value & out);
|
||||||
void deleteStream(const std::string & name, JSON::Value & out);
|
int deleteStream(const std::string & name, JSON::Value & out, bool sourceFileToo = false);
|
||||||
|
|
||||||
struct liveCheck {
|
struct liveCheck {
|
||||||
long long int lastms;
|
long long int lastms;
|
||||||
|
|
|
@ -16,6 +16,7 @@ namespace Mist {
|
||||||
capa["name"] = "AV";
|
capa["name"] = "AV";
|
||||||
capa["desc"] = "This input uses libavformat to read any type of file. Unfortunately this input cannot be redistributed, but it is a great tool for testing the other file-based inputs against.";
|
capa["desc"] = "This input uses libavformat to read any type of file. Unfortunately this input cannot be redistributed, but it is a great tool for testing the other file-based inputs against.";
|
||||||
capa["source_match"] = "/*";
|
capa["source_match"] = "/*";
|
||||||
|
capa["source_file"] = "$source";
|
||||||
capa["priority"] = 1ll;
|
capa["priority"] = 1ll;
|
||||||
capa["codecs"][0u][0u].null();
|
capa["codecs"][0u][0u].null();
|
||||||
capa["codecs"][0u][1u].null();
|
capa["codecs"][0u][1u].null();
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace Mist {
|
||||||
capa["priority"] = 9ll;
|
capa["priority"] = 9ll;
|
||||||
capa["source_match"].append("/*.dtsc");
|
capa["source_match"].append("/*.dtsc");
|
||||||
capa["source_match"].append("dtsc://*");
|
capa["source_match"].append("dtsc://*");
|
||||||
|
capa["source_file"] = "$source";
|
||||||
capa["codecs"][0u][0u].append("H264");
|
capa["codecs"][0u][0u].append("H264");
|
||||||
capa["codecs"][0u][0u].append("H263");
|
capa["codecs"][0u][0u].append("H263");
|
||||||
capa["codecs"][0u][0u].append("VP6");
|
capa["codecs"][0u][0u].append("VP6");
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace Mist{
|
||||||
capa["source_match"].append("/*.mk3d");
|
capa["source_match"].append("/*.mk3d");
|
||||||
capa["source_match"].append("/*.mks");
|
capa["source_match"].append("/*.mks");
|
||||||
capa["source_match"].append("/*.webm");
|
capa["source_match"].append("/*.webm");
|
||||||
|
capa["source_file"] = "$source";
|
||||||
capa["priority"] = 9ll;
|
capa["priority"] = 9ll;
|
||||||
capa["codecs"].append("H264");
|
capa["codecs"].append("H264");
|
||||||
capa["codecs"].append("HEVC");
|
capa["codecs"].append("HEVC");
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace Mist {
|
||||||
capa["name"] = "FLV";
|
capa["name"] = "FLV";
|
||||||
capa["desc"] = "Allows loading FLV files for Video on Demand.";
|
capa["desc"] = "Allows loading FLV files for Video on Demand.";
|
||||||
capa["source_match"] = "/*.flv";
|
capa["source_match"] = "/*.flv";
|
||||||
|
capa["source_file"] = "$source";
|
||||||
capa["priority"] = 9ll;
|
capa["priority"] = 9ll;
|
||||||
capa["codecs"][0u][0u].append("H264");
|
capa["codecs"][0u][0u].append("H264");
|
||||||
capa["codecs"][0u][0u].append("H263");
|
capa["codecs"][0u][0u].append("H263");
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace Mist {
|
||||||
capa["name"] = "Folder";
|
capa["name"] = "Folder";
|
||||||
capa["desc"] = "The folder input will make available all supported files in the given folder as streams under this stream name, in the format STREAMNAME+FILENAME. For example, if your stream is called 'files' and you have a file called 'movie.flv', you could access this file streamed as 'files+movie.flv'. This input does not support subdirectories. To support more complex libraries, look into the documentation for the STREAM_SOURCE trigger.";
|
capa["desc"] = "The folder input will make available all supported files in the given folder as streams under this stream name, in the format STREAMNAME+FILENAME. For example, if your stream is called 'files' and you have a file called 'movie.flv', you could access this file streamed as 'files+movie.flv'. This input does not support subdirectories. To support more complex libraries, look into the documentation for the STREAM_SOURCE trigger.";
|
||||||
capa["source_match"] = "/*/";
|
capa["source_match"] = "/*/";
|
||||||
|
capa["source_file"] = "$source/$wildcard";
|
||||||
capa["priority"] = 9ll;
|
capa["priority"] = 9ll;
|
||||||
capa["morphic"] = 1ll;
|
capa["morphic"] = 1ll;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ namespace Mist {
|
||||||
capa["name"] = "MP3";
|
capa["name"] = "MP3";
|
||||||
capa["desc"] = "This input allows you to stream MP3 Video on Demand files.";
|
capa["desc"] = "This input allows you to stream MP3 Video on Demand files.";
|
||||||
capa["source_match"] = "/*.mp3";
|
capa["source_match"] = "/*.mp3";
|
||||||
|
capa["source_file"] = "$source";
|
||||||
capa["priority"] = 9ll;
|
capa["priority"] = 9ll;
|
||||||
capa["codecs"][0u][0u].append("MP3");
|
capa["codecs"][0u][0u].append("MP3");
|
||||||
timestamp = 0;
|
timestamp = 0;
|
||||||
|
|
|
@ -160,6 +160,7 @@ namespace Mist{
|
||||||
capa["name"] = "MP4";
|
capa["name"] = "MP4";
|
||||||
capa["desc"] = "This input allows streaming of MP4 files as Video on Demand.";
|
capa["desc"] = "This input allows streaming of MP4 files as Video on Demand.";
|
||||||
capa["source_match"] = "/*.mp4";
|
capa["source_match"] = "/*.mp4";
|
||||||
|
capa["source_file"] = "$source";
|
||||||
capa["priority"] = 9ll;
|
capa["priority"] = 9ll;
|
||||||
capa["codecs"][0u][0u].append("HEVC");
|
capa["codecs"][0u][0u].append("HEVC");
|
||||||
capa["codecs"][0u][0u].append("H264");
|
capa["codecs"][0u][0u].append("H264");
|
||||||
|
|
|
@ -48,6 +48,7 @@ namespace Mist {
|
||||||
capa["name"] = "OGG";
|
capa["name"] = "OGG";
|
||||||
capa["desc"] = "This input allows streaming of OGG files as Video on Demand.";
|
capa["desc"] = "This input allows streaming of OGG files as Video on Demand.";
|
||||||
capa["source_match"] = "/*.ogg";
|
capa["source_match"] = "/*.ogg";
|
||||||
|
capa["source_file"] = "$source";
|
||||||
capa["codecs"][0u][0u].append("theora");
|
capa["codecs"][0u][0u].append("theora");
|
||||||
capa["codecs"][0u][1u].append("vorbis");
|
capa["codecs"][0u][1u].append("vorbis");
|
||||||
capa["codecs"][0u][1u].append("opus");
|
capa["codecs"][0u][1u].append("opus");
|
||||||
|
|
|
@ -113,6 +113,7 @@ namespace Mist {
|
||||||
capa["name"] = "TS";
|
capa["name"] = "TS";
|
||||||
capa["desc"] = "This input allows you to stream MPEG2-TS data from static files (/*.ts), streamed files or named pipes (stream://*.ts), streamed over HTTP (http://*.ts, http-ts://*), standard input (ts-exec:*), or multicast/unicast UDP sockets (tsudp://*).";
|
capa["desc"] = "This input allows you to stream MPEG2-TS data from static files (/*.ts), streamed files or named pipes (stream://*.ts), streamed over HTTP (http://*.ts, http-ts://*), standard input (ts-exec:*), or multicast/unicast UDP sockets (tsudp://*).";
|
||||||
capa["source_match"].append("/*.ts");
|
capa["source_match"].append("/*.ts");
|
||||||
|
capa["source_file"] = "$source";
|
||||||
capa["source_match"].append("stream://*.ts");
|
capa["source_match"].append("stream://*.ts");
|
||||||
capa["source_match"].append("tsudp://*");
|
capa["source_match"].append("tsudp://*");
|
||||||
capa["source_match"].append("ts-exec:*");
|
capa["source_match"].append("ts-exec:*");
|
||||||
|
|
Loading…
Add table
Reference in a new issue