aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/servicelinking.mux8
-rw-r--r--src/ConfigParser.cpp82
-rw-r--r--src/MuxElements.cpp43
-rw-r--r--src/fig/FIG0_6.cpp18
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 =