diff --git a/README b/README index 6405461..99b3bdc 100644 --- a/README +++ b/README @@ -52,9 +52,10 @@ separated list of "||" entries. The model consists of a DVB system (DVBS2,DVBT2,DVBT,DVBC) and number of available frontends separated by a hyphen: -vdr -P 'satip -s ||;...' +vdr -P 'satip -s [:]|[:]|;...' vdr -P 'satip -s 192.168.0.1|DVBS2-2,DVBT2-2|OctopusNet' vdr -P 'satip -s 192.168.0.1|DVBS2-4|OctopusNet;192.168.0.2|DVBT2-4|minisatip' +vdr -P 'satip -s 192.168.0.1:554|DVBS2-2:S19.2E|OctopusNet;192.168.0.2:8554|DVBS2-4:S19.2E,S1W|minisatip' The plugin accepts a "--portrange" (-p) command-line parameter, that can be used to manually specify the RTP & RTCP port range and therefore diff --git a/discover.c b/discover.c index 511f5c4..6ba16b2 100644 --- a/discover.c +++ b/discover.c @@ -32,7 +32,7 @@ bool cSatipDiscover::Initialize(cSatipDiscoverServers *serversP) if (instanceS) { if (serversP) { for (cSatipDiscoverServer *s = serversP->First(); s; s = serversP->Next(s)) - instanceS->AddServer(s->IpAddress(), s->IpPort(), s->Model(), s->Description()); + instanceS->AddServer(s->IpAddress(), s->IpPort(), s->Model(), s->Filters(), s->Description()); } else instanceS->Activate(); @@ -271,12 +271,12 @@ void cSatipDiscover::ParseDeviceInfo(const char *addrP, const int portP) model = modelNode.text().as_string("DVBS2-1"); } #endif - AddServer(addrP, portP, model, desc); + AddServer(addrP, portP, model, NULL, desc); } -void cSatipDiscover::AddServer(const char *addrP, const int portP, const char *modelP, const char * descP) +void cSatipDiscover::AddServer(const char *addrP, const int portP, const char *modelP, const char *filtersP, const char *descP) { - debug1("%s (%s, %d, %s, %s)", __PRETTY_FUNCTION__, addrP, portP, modelP, descP); + debug1("%s (%s, %d, %s, %s, %s)", __PRETTY_FUNCTION__, addrP, portP, modelP, filtersP, descP); cMutexLock MutexLock(&mutexM); if (SatipConfig.GetUseSingleModelServers() && modelP && !isempty(modelP)) { int n = 0; @@ -285,9 +285,9 @@ void cSatipDiscover::AddServer(const char *addrP, const int portP, const char *m while (r) { r = skipspace(r); cString desc = cString::sprintf("%s #%d", !isempty(descP) ? descP : "MyBrokenHardware", n++); - cSatipServer *tmp = new cSatipServer(addrP, portP, r, desc); + cSatipServer *tmp = new cSatipServer(addrP, portP, r, filtersP, desc); if (!serversM.Update(tmp)) { - info("Adding server '%s|%s|%s' CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none"); + info("Adding server '%s|%s|%s' Filters: %s CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), !isempty(tmp->Filters()) ? tmp->Filters() : "none", tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none"); serversM.Add(tmp); } else @@ -297,9 +297,9 @@ void cSatipDiscover::AddServer(const char *addrP, const int portP, const char *m FREE_POINTER(p); } else { - cSatipServer *tmp = new cSatipServer(addrP, portP, modelP, descP); + cSatipServer *tmp = new cSatipServer(addrP, portP, modelP, filtersP, descP); if (!serversM.Update(tmp)) { - info("Adding server '%s|%s|%s' CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none"); + info("Adding server '%s|%s|%s' Filters: %s CI: %s Quirks: %s", tmp->Address(), tmp->Model(), tmp->Description(), !isempty(tmp->Filters()) ? tmp->Filters() : "none", tmp->HasCI() ? "yes" : "no", tmp->HasQuirk() ? tmp->Quirks() : "none"); serversM.Add(tmp); } else diff --git a/discover.h b/discover.h index dd284ed..7c1148c 100644 --- a/discover.h +++ b/discover.h @@ -25,14 +25,16 @@ private: cString ipAddressM; cString descriptionM; cString modelM; + cString filtersM; public: - cSatipDiscoverServer(const char *ipAddressP, const int ipPortP, const char *modelP, const char *descriptionP) + cSatipDiscoverServer(const char *ipAddressP, const int ipPortP, const char *modelP, const char *filtersP, const char *descriptionP) { - ipAddressM = ipAddressP; ipPortM = ipPortP; modelM = modelP; descriptionM = descriptionP; + ipAddressM = ipAddressP; ipPortM = ipPortP; modelM = modelP; filtersM = filtersP; descriptionM = descriptionP; } int IpPort(void) { return ipPortM; } const char *IpAddress(void) { return *ipAddressM; } const char *Model(void) { return *modelM; } + const char *Filters(void) { return *filtersM; } const char *Description(void) { return *descriptionM; } }; @@ -65,7 +67,7 @@ private: void Deactivate(void); int ParseRtspPort(void); void ParseDeviceInfo(const char *addrP, const int portP); - void AddServer(const char *addrP, const int portP, const char *modelP, const char *descP); + void AddServer(const char *addrP, const int portP, const char *modelP, const char *filtersP, const char *descP); void Fetch(const char *urlP); // constructor cSatipDiscover(); diff --git a/satip.c b/satip.c index 4cb0cd0..d80cacf 100644 --- a/satip.c +++ b/satip.c @@ -84,7 +84,7 @@ const char *cPluginSatip::CommandLineHelp(void) // Return a string that describes all known command line options. return " -d , --devices= set number of devices to be created\n" " -t , --trace= set the tracing mode\n" - " -s ||, --server=||;||\n" + " -s ||, --server=||;:|:|\n" " define hard-coded SAT>IP server(s)\n" " -D, --detach set the detached mode on\n" " -S, --single set the single model server mode on\n" @@ -232,7 +232,7 @@ void cPluginSatip::ParseServer(const char *paramP) while (r) { r = skipspace(r); debug3("%s server[%d]=%s", __PRETTY_FUNCTION__, n, r); - cString serverAddr, serverModel, serverDescription; + cString serverAddr, serverModel, serverFilters, serverDescription; int serverPort = SATIP_DEFAULT_RTSP_PORT; int n2 = 0; char *s2, *p2 = r; @@ -251,7 +251,14 @@ void cPluginSatip::ParseServer(const char *paramP) } break; case 1: + { serverModel = r2; + char *r3 = strchr(r2, ':'); + if (r3) { + serverFilters = r3 + 1; + serverModel = serverModel.Truncate(r3 - r2); + } + } break; case 2: serverDescription = r2; @@ -262,10 +269,10 @@ void cPluginSatip::ParseServer(const char *paramP) r2 = strtok_r(NULL, "|", &s2); } if (*serverAddr && *serverModel && *serverDescription) { - debug1("%s ipaddr=%s port=%d model=%s desc=%s", __PRETTY_FUNCTION__, *serverAddr, serverPort, *serverModel, *serverDescription); + debug1("%s ipaddr=%s port=%d model=%s (%s) desc=%s", __PRETTY_FUNCTION__, *serverAddr, serverPort, *serverModel, *serverFilters, *serverDescription); if (!serversM) serversM = new cSatipDiscoverServers(); - serversM->Add(new cSatipDiscoverServer(*serverAddr, serverPort, *serverModel, *serverDescription)); + serversM->Add(new cSatipDiscoverServer(*serverAddr, serverPort, *serverModel, *serverFilters, *serverDescription)); } ++n; r = strtok_r(NULL, ";", &s); diff --git a/server.c b/server.c index 62cb7d5..1e89fd9 100644 --- a/server.c +++ b/server.c @@ -80,9 +80,10 @@ bool cSatipFrontends::Detach(int deviceIdP, int transponderP) // --- cSatipServer ----------------------------------------------------------- -cSatipServer::cSatipServer(const char *addressP, const int portP, const char *modelP, const char *descriptionP) +cSatipServer::cSatipServer(const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP) : addressM((addressP && *addressP) ? addressP : "0.0.0.0"), modelM((modelP && *modelP) ? modelP : "DVBS-1"), + filtersM((filtersP && *filtersP) ? filtersP : ""), descriptionM(!isempty(descriptionP) ? descriptionP : "MyBrokenHardware"), quirksM(""), portM(portP), @@ -92,6 +93,25 @@ cSatipServer::cSatipServer(const char *addressP, const int portP, const char *mo createdM(time(NULL)), lastSeenM(0) { + memset(sourceFiltersM, 0, sizeof(sourceFiltersM)); + if (!isempty(*filtersM)) { + char *s, *p = strdup(*filtersM); + char *r = strtok_r(p, ",", &s); + unsigned int i = 0; + while (r) { + int t = cSource::FromString(skipspace(r)); + if (t && i < ELEMENTS(sourceFiltersM)) + sourceFiltersM[i++] = t; + r = strtok_r(NULL, ",", &s); + } + if (i) { + filtersM = ""; + for (unsigned int j = 0; j < i; ++j) + filtersM = cString::sprintf("%s%s%s", *filtersM, isempty(*filtersM) ? "" : ",", *cSource::ToString(sourceFiltersM[j])); + debug3("%s filters=%s", __PRETTY_FUNCTION__, *filtersM); + } + FREE_POINTER(p); + } if (!SatipConfig.GetDisableServerQuirks()) { // These devices contain a session id bug: // Inverto Airscreen Server IDL 400 ? @@ -165,7 +185,7 @@ cSatipServer::cSatipServer(const char *addressP, const int portP, const char *mo } r = strtok_r(NULL, ",", &s); } - free(p); + FREE_POINTER(p); } cSatipServer::~cSatipServer() @@ -204,33 +224,50 @@ bool cSatipServer::Assign(int deviceIdP, int sourceP, int systemP, int transpond return result; } +bool cSatipServer::IsValidSource(int sourceP) +{ + if (sourceFiltersM[0]) { + for (unsigned int i = 0; i < ELEMENTS(sourceFiltersM); ++i) { + if (sourceP == sourceFiltersM[i]) { + return true; + } + } + return false; + } + return true; +} + bool cSatipServer::Matches(int sourceP) { - if (cSource::IsType(sourceP, 'S')) - return GetModulesDVBS2(); - else if (cSource::IsType(sourceP, 'T')) - return GetModulesDVBT() || GetModulesDVBT2(); - else if (cSource::IsType(sourceP, 'C')) - return GetModulesDVBC() || GetModulesDVBC2(); + if (IsValidSource(sourceP)) { + if (cSource::IsType(sourceP, 'S')) + return GetModulesDVBS2(); + else if (cSource::IsType(sourceP, 'T')) + return GetModulesDVBT() || GetModulesDVBT2(); + else if (cSource::IsType(sourceP, 'C')) + return GetModulesDVBC() || GetModulesDVBC2(); + } return false; } bool cSatipServer::Matches(int deviceIdP, int sourceP, int systemP, int transponderP) { bool result = false; - if (cSource::IsType(sourceP, 'S')) - result = frontendsM[eSatipFrontendDVBS2].Matches(deviceIdP, transponderP); - else if (cSource::IsType(sourceP, 'T')) { - if (systemP) - result = frontendsM[eSatipFrontendDVBT2].Matches(deviceIdP, transponderP); - else - result = frontendsM[eSatipFrontendDVBT].Matches(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBT2].Matches(deviceIdP, transponderP); - } - else if (cSource::IsType(sourceP, 'C')) { - if (systemP) - result = frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, transponderP); - else - result = frontendsM[eSatipFrontendDVBC].Matches(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, transponderP); + if (IsValidSource(sourceP)) { + if (cSource::IsType(sourceP, 'S')) + result = frontendsM[eSatipFrontendDVBS2].Matches(deviceIdP, transponderP); + else if (cSource::IsType(sourceP, 'T')) { + if (systemP) + result = frontendsM[eSatipFrontendDVBT2].Matches(deviceIdP, transponderP); + else + result = frontendsM[eSatipFrontendDVBT].Matches(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBT2].Matches(deviceIdP, transponderP); + } + else if (cSource::IsType(sourceP, 'C')) { + if (systemP) + result = frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, transponderP); + else + result = frontendsM[eSatipFrontendDVBC].Matches(deviceIdP, transponderP) || frontendsM[eSatipFrontendDVBC2].Matches(deviceIdP, transponderP); + } } return result; } diff --git a/server.h b/server.h index 657a55b..5afbc4e 100644 --- a/server.h +++ b/server.h @@ -54,17 +54,23 @@ private: eSatipFrontendDVBC2, eSatipFrontendCount }; + enum { + eSatipMaxSourceFilters = 16 + }; cString addressM; cString modelM; + cString filtersM; cString descriptionM; cString quirksM; cSatipFrontends frontendsM[eSatipFrontendCount]; + int sourceFiltersM[eSatipMaxSourceFilters]; int portM; int quirkM; bool hasCiM; bool activeM; time_t createdM; cTimeMs lastSeenM; + bool IsValidSource(int sourceP); public: enum eSatipQuirk { @@ -75,7 +81,7 @@ public: eSatipQuirkRtpOverTcp = 0x08, eSatipQuirkMask = 0x0F }; - cSatipServer(const char *addressP, const int portP, const char *modelP, const char *descriptionP); + cSatipServer(const char *addressP, const int portP, const char *modelP, const char *filtersP, const char *descriptionP); virtual ~cSatipServer(); virtual int Compare(const cListObject &listObjectP) const; bool Assign(int deviceIdP, int sourceP, int systemP, int transponderP); @@ -91,6 +97,7 @@ public: void Activate(bool onOffP) { activeM = onOffP; } const char *Address(void) { return *addressM; } const char *Model(void) { return *modelM; } + const char *Filters(void) { return *filtersM; } const char *Description(void) { return *descriptionM; } const char *Quirks(void) { return *quirksM; } int Port(void) { return portM; }