diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2018-08-16 16:37:38 +0200 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2018-08-16 16:37:38 +0200 |
commit | d57f046c40e716069d37f9e6b7911afd41c7b116 (patch) | |
tree | fd7cec78dd7fd8c3e195aab2a3a01c9525fd37bb | |
parent | 76bd144a8bbedfceceeb9ad2975a3d3f9436e311 (diff) | |
download | dabmux-d57f046c40e716069d37f9e6b7911afd41c7b116.tar.gz dabmux-d57f046c40e716069d37f9e6b7911afd41c7b116.tar.bz2 dabmux-d57f046c40e716069d37f9e6b7911afd41c7b116.zip |
Add support for sending empty linkage sets to clear receiver databases
-rw-r--r-- | doc/servicelinking.mux | 8 | ||||
-rw-r--r-- | src/ConfigParser.cpp | 82 | ||||
-rw-r--r-- | src/MuxElements.cpp | 43 | ||||
-rw-r--r-- | src/fig/FIG0_6.cpp | 18 |
4 files changed, 89 insertions, 62 deletions
diff --git a/doc/servicelinking.mux b/doc/servicelinking.mux index 5706351..d591f5c 100644 --- a/doc/servicelinking.mux +++ b/doc/servicelinking.mux @@ -42,10 +42,14 @@ linking { ; set this to true. international false - ; Every linkage set has to contain a service from the current ensemble (mandatory) + ; If the keyservice and list are absent, a FIG with an empty list will be transmitted for + ; this linkage set. This instructs receivers to delete their corresponding database entry + ; (Change Event Indicator for FIG0/6) + + ; Every linkage set has to contain a service from the current ensemble. keyservice may be omitted. keyservice srv-fu - ; List of services to be included (mandatory) + ; List of services to be included (mandatory if keyservice given) list { ; Every service has a uid that can be used as a human-readable description diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index d484787..f51eb03 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -102,61 +102,65 @@ static void parse_linkage(ptree& pt, bool active = pt_set.get("active", true); bool hard = pt_set.get("hard", true); bool international = pt_set.get("international", false); - string service_uid = pt_set.get("keyservice", ""); - if (service_uid.empty()) { - etiLog.level(error) << "Key Service for linking set " << - setuid << " invalid or missing"; - throw runtime_error("Invalid service linking definition"); - } auto linkageset = make_shared<LinkageSet>(setuid, lsn, active, hard, international); linkageset->keyservice = service_uid; // TODO check if it exists auto pt_list = pt_set.get_child_optional("list"); - if (not pt_list) { - etiLog.level(error) << "list missing in linking set " << - setuid; - throw runtime_error("Invalid service linking definition"); - } - for (const auto& it : *pt_list) { - const string linkuid = it.first; - const ptree pt_link = it.second; - - ServiceLink link; - - string link_type = pt_link.get("type", ""); - if (link_type == "dab") link.type = ServiceLinkType::DAB; - else if (link_type == "fm") link.type = ServiceLinkType::FM; - else if (link_type == "drm") link.type = ServiceLinkType::DRM; - else if (link_type == "amss") link.type = ServiceLinkType::AMSS; - else { - etiLog.level(error) << "Invalid type " << link_type << - " for link " << linkuid; + if (service_uid.empty()) { + if (pt_list) { + etiLog.level(error) << "list defined but no keyservice in linking set " << + setuid; throw runtime_error("Invalid service linking definition"); } - - link.id = hexparse(pt_link.get("id", "0")); - if (link.id == 0) { - etiLog.level(error) << "id for link " << - linkuid << " invalid or missing"; + } + else { + if (not pt_list) { + etiLog.level(error) << "list missing in linking set " << + setuid; throw runtime_error("Invalid service linking definition"); } - if (international) { - link.ecc = hexparse(pt_link.get("ecc", "0")); - if (link.ecc == 0) { - etiLog.level(error) << "ecc for link " << + for (const auto& it : *pt_list) { + const string linkuid = it.first; + const ptree pt_link = it.second; + + ServiceLink link; + + string link_type = pt_link.get("type", ""); + if (link_type == "dab") link.type = ServiceLinkType::DAB; + else if (link_type == "fm") link.type = ServiceLinkType::FM; + else if (link_type == "drm") link.type = ServiceLinkType::DRM; + else if (link_type == "amss") link.type = ServiceLinkType::AMSS; + else { + etiLog.level(error) << "Invalid type " << link_type << + " for link " << linkuid; + throw runtime_error("Invalid service linking definition"); + } + + link.id = hexparse(pt_link.get("id", "0")); + if (link.id == 0) { + etiLog.level(error) << "id for link " << linkuid << " invalid or missing"; throw runtime_error("Invalid service linking definition"); } - } - else { - link.ecc = 0; - } - linkageset->id_list.push_back(link); + if (international) { + link.ecc = hexparse(pt_link.get("ecc", "0")); + if (link.ecc == 0) { + etiLog.level(error) << "ecc for link " << + linkuid << " invalid or missing"; + throw runtime_error("Invalid service linking definition"); + } + } + else { + link.ecc = 0; + } + + linkageset->id_list.push_back(link); + } } ensemble->linkagesets.push_back(linkageset); } diff --git a/src/MuxElements.cpp b/src/MuxElements.cpp index e19c93d..9c1fc7a 100644 --- a/src/MuxElements.cpp +++ b/src/MuxElements.cpp @@ -665,26 +665,35 @@ bool dabEnsemble::validate_linkage_sets() { for (const auto& ls : linkagesets) { const std::string keyserviceuid = ls->keyservice; - const auto& keyservice = std::find_if( - services.cbegin(), - services.cend(), - [&](const std::shared_ptr<DabService>& srv) { + if (keyserviceuid.empty()) { + if (not ls->id_list.empty()) { + etiLog.log(error, "Linkage set 0x%04x with empty key service " + "should have an empty list.", ls->lsn); + return false; + } + } + else { + const auto& keyservice = std::find_if( + services.cbegin(), + services.cend(), + [&](const std::shared_ptr<DabService>& srv) { return srv->uid == keyserviceuid; - }); + }); - if (keyservice == services.end()) { - etiLog.log(error, "Invalid key service %s in linkage set 0x%04x", - keyserviceuid.c_str(), ls->lsn); - return false; - } + if (keyservice == services.end()) { + etiLog.log(error, "Invalid key service %s in linkage set 0x%04x", + keyserviceuid.c_str(), ls->lsn); + return false; + } - // need to add key service to num_ids - const size_t num_ids = 1 + ls->id_list.size(); - if (num_ids > 0x0F) { - etiLog.log(error, - "Too many links for linkage set 0x%04x", - ls->lsn); - return false; + // need to add key service to num_ids + const size_t num_ids = 1 + ls->id_list.size(); + if (num_ids > 0x0F) { + etiLog.log(error, + "Too many links for linkage set 0x%04x", + ls->lsn); + return false; + } } } diff --git a/src/fig/FIG0_6.cpp b/src/fig/FIG0_6.cpp index b7776f4..8af8ded 100644 --- a/src/fig/FIG0_6.cpp +++ b/src/fig/FIG0_6.cpp @@ -80,8 +80,11 @@ FillStatus FIG0_6::fill(uint8_t *buf, size_t max_size) const bool PD = false; const bool ILS = linkageSetFIG0_6->international; - // need to add key service to num_ids - const size_t num_ids = 1 + linkageSetFIG0_6->id_list.size(); + // need to add key service to num_ids, unless it is empty which means we + // send a CEI + const size_t num_ids = linkageSetFIG0_6->keyservice.empty() ? + // do not transmit list if keyservice empty, it should anyway be empty + 0 : (1 + linkageSetFIG0_6->id_list.size()); if (num_ids > 0x0F) { etiLog.log(error, @@ -117,7 +120,7 @@ FillStatus FIG0_6::fill(uint8_t *buf, size_t max_size) FIGtype0_6 *fig0_6 = (FIGtype0_6*)buf; - fig0_6->IdListFlag = (num_ids > 0); + fig0_6->IdListFlag = (num_ids > 0); // C/N=0 and IdListFlag=0 is CEI fig0_6->LA = linkageSetFIG0_6->active; fig0_6->SH = linkageSetFIG0_6->hard; fig0_6->ILS = ILS; @@ -127,6 +130,10 @@ FillStatus FIG0_6::fill(uint8_t *buf, size_t max_size) buf += sizeof(struct FIGtype0_6); remaining -= sizeof(struct FIGtype0_6); + etiLog.log(debug, + "Linkage set 0x%04x wrote %d", + linkageSetFIG0_6->lsn, fig0->Length); + if (num_ids > 0) { FIGtype0_6_header *header = (FIGtype0_6_header*)buf; header->rfu = 0; @@ -243,7 +250,10 @@ void FIG0_6::update() for (const auto& linkageset : m_rti->ensemble->linkagesets) { const auto lsn = linkageset->lsn; - for (const auto& link : linkageset->id_list) { + if (linkageset->keyservice.empty()) { + linkageSubsets.push_back(*linkageset); + } + else for (const auto& link : linkageset->id_list) { const auto type = link.type; const auto subset = |