aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2017-04-27 01:39:20 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2017-04-27 01:39:20 +0200
commit0616c12772c4995d0a22b803127af156a37a3a7d (patch)
tree0561c72fa58cc71209edc196e4706b850b000868
parent36d70772c7ba15bf1d769f7ec54ba129377f4617 (diff)
downloadetisnoop-0616c12772c4995d0a22b803127af156a37a3a7d.tar.gz
etisnoop-0616c12772c4995d0a22b803127af156a37a3a7d.tar.bz2
etisnoop-0616c12772c4995d0a22b803127af156a37a3a7d.zip
Refactor FIG0/X message generation
-rw-r--r--src/etisnoop.cpp21
-rw-r--r--src/fig0_0.cpp51
-rw-r--r--src/fig0_1.cpp46
-rw-r--r--src/fig0_10.cpp26
-rw-r--r--src/fig0_11.cpp99
-rw-r--r--src/fig0_13.cpp21
-rw-r--r--src/fig0_14.cpp17
-rw-r--r--src/fig0_16.cpp48
-rw-r--r--src/fig0_17.cpp67
-rw-r--r--src/fig0_18.cpp42
-rw-r--r--src/fig0_19.cpp34
-rw-r--r--src/fig0_2.cpp80
-rw-r--r--src/fig0_21.cpp141
-rw-r--r--src/fig0_22.cpp63
-rw-r--r--src/fig0_24.cpp38
-rw-r--r--src/fig0_25.cpp49
-rw-r--r--src/fig0_26.cpp42
-rw-r--r--src/fig0_27.cpp39
-rw-r--r--src/fig0_28.cpp36
-rw-r--r--src/fig0_3.cpp49
-rw-r--r--src/fig0_31.cpp43
-rw-r--r--src/fig0_5.cpp45
-rw-r--r--src/fig0_6.cpp94
-rw-r--r--src/fig0_8.cpp42
-rw-r--r--src/fig0_9.cpp67
-rw-r--r--src/figs.cpp15
-rw-r--r--src/figs.hpp70
-rw-r--r--src/utils.cpp43
-rw-r--r--src/utils.hpp7
29 files changed, 701 insertions, 734 deletions
diff --git a/src/etisnoop.cpp b/src/etisnoop.cpp
index 7137d2e..1ebdf70 100644
--- a/src/etisnoop.cpp
+++ b/src/etisnoop.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -701,8 +701,23 @@ void decodeFIG(
figs.push_back(figtype, fig0.ext(), figlen);
- bool complete = fig0_select(fig0, disp);
- rate_announce_fig(figtype, fig0.ext(), complete);
+ auto fig_result = fig0_select(fig0, disp);
+ for (const auto& msg : fig_result.msgs) {
+ std::string s;
+ for (int i = 0; i < msg.level; i++) {
+ s += " ";
+ }
+ s += msg.msg;
+ printbuf(s.c_str(), disp.indent+1, nullptr, 0);
+ }
+ if (not fig_result.errors.empty()) {
+ printf("ERRORS:\n");
+ for (const auto& err : fig_result.errors) {
+ printbuf(err.c_str(), disp.indent+1, nullptr, 0);
+ }
+ }
+
+ rate_announce_fig(figtype, fig0.ext(), fig_result.complete);
}
break;
diff --git a/src/fig0_0.cpp b/src/fig0_0.cpp
index 83f7efa..162110b 100644
--- a/src/fig0_0.cpp
+++ b/src/fig0_0.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -29,34 +29,39 @@
// FIG 0/0 Ensemble information
// ETSI EN 300 401 6.4
-bool fig0_0(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_0(fig0_common_t& fig0, const display_settings_t &disp)
{
- uint8_t cid, al, ch, hic, lowc, occ;
- uint16_t eid, eref;
- char desc[128];
+ uint8_t occ;
+ fig_result_t r;
uint8_t* f = fig0.f;
- eid = f[1]*256+f[2];
- cid = (f[1] & 0xF0) >> 4;
- eref = (f[1] & 0x0F)*256 + \
- f[2];
- ch = (f[3] & 0xC0) >> 6;
- al = (f[3] & 0x20) >> 5;
- hic = f[3] & 0x1F;
- lowc = f[4];
+ const uint16_t eid = f[1]*256+f[2];
+ r.msgs.push_back(strprintf("Ensemble ID=0x%02x", eid));
+
+ const uint8_t cid = (f[1] & 0xF0) >> 4;
+ r.msgs.emplace_back(1, strprintf("Country ID=%d", cid));
+
+ const uint16_t eref = (f[1] & 0x0F)*256 + \
+ f[2];
+ r.msgs.emplace_back(1, strprintf("Ensemble reference=%d", eref));
+
+ const uint8_t ch = (f[3] & 0xC0) >> 6;
+ r.msgs.push_back(strprintf("Change flag=%d", ch));
+
+ const uint8_t al = (f[3] & 0x20) >> 5;
+ r.msgs.push_back(strprintf("Alarm flag=%d", al));
+
+ const uint8_t hic = f[3] & 0x1F;
+ const uint8_t lowc = f[4];
+ r.msgs.push_back(strprintf("CIF Count=%d/%d", hic, lowc));
+
if (ch != 0) {
occ = f[5];
- sprintf(desc,
- "Ensemble ID=0x%02x (Country id=%d, Ensemble reference=%d), Change flag=%d, Alarm flag=%d, CIF Count=%d/%d, Occurance change=%d",
- eid, cid, eref, ch, al, hic, lowc, occ);
+ r.msgs.push_back(strprintf("Occurrence change=%d", occ));
}
- else {
- sprintf(desc,
- "Ensemble ID=0x%02x (Country id=%d, Ensemble reference=%d), Change flag=%d, Alarm flag=%d, CIF Count=%d/%d",
- eid, cid, eref, ch, al, hic, lowc);
- }
- printbuf(desc, disp+1, NULL, 0);
- return true;
+ r.complete = true;
+
+ return r;
}
diff --git a/src/fig0_1.cpp b/src/fig0_1.cpp
index 80ed906..76cda36 100644
--- a/src/fig0_1.cpp
+++ b/src/fig0_1.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -46,17 +46,16 @@ bool fig0_1_is_complete(int subch_id)
// FIG 0/1 Basic sub-channel organization
// ETSI EN 300 401 6.2.1
-bool fig0_1(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_1(fig0_common_t& fig0, const display_settings_t &disp)
{
int i = 1;
uint8_t* f = fig0.f;
- char desc[128];
- bool complete = false;
+ fig_result_t r;
while (i <= fig0.figlen-3) {
// iterate over subchannels
int subch_id = f[i] >> 2;
- complete |= fig0_1_is_complete(subch_id);
+ r.complete |= fig0_1_is_complete(subch_id);
int start_addr = ((f[i] & 0x03) << 8) |
(f[i+1]);
@@ -70,43 +69,38 @@ bool fig0_1(fig0_common_t& fig0, const display_settings_t &disp)
i += 4;
+ r.msgs.push_back(strprintf("Subch 0x%x", subch_id));
+ r.msgs.push_back(strprintf("start_addr %d", start_addr));
+ r.msgs.emplace_back("long");
+
if (option == 0x00) {
- sprintf(desc,
- "Subch 0x%x, start_addr %d, long, EEP %d-A, subch size %d",
- subch_id, start_addr, protection_level, subchannel_size);
+ r.msgs.push_back(strprintf("EEP %d-A", protection_level));
}
else if (option == 0x01) {
- sprintf(desc,
- "Subch 0x%x, start_addr %d, long, EEP %d-B, subch size %d",
- subch_id, start_addr, protection_level, subchannel_size);
+ r.msgs.push_back(strprintf("EEP %d-B", protection_level));
}
else {
- sprintf(desc,
- "Subch 0x%x, start_addr %d, long, invalid option %d, protection %d, subch size %d",
- subch_id, start_addr, option, protection_level, subchannel_size);
+ r.errors.push_back(strprintf("Invalid option %d protection %d", option, protection_level));
}
+
+ r.msgs.push_back(strprintf("subch size %d", subchannel_size));
}
else {
int table_switch = (f[i+2] >> 6) & 0x01;
uint32_t table_index = (f[i+2] & 0x3F);
-
- if (table_switch == 0) {
- sprintf(desc,
- "Subch 0x%x, start_addr %d, short, table index %d",
- subch_id, start_addr, table_index);
- }
- else {
- sprintf(desc,
- "Subch 0x%x, start_addr %d, short, invalid table_switch(=1), table index %d",
- subch_id, start_addr, table_index);
+ r.msgs.push_back(strprintf("Subch 0x%x", subch_id));
+ r.msgs.push_back(strprintf("start_addr %d", start_addr));
+ r.msgs.emplace_back("short");
+ if (table_switch != 0) {
+ r.errors.push_back(strprintf("Invalid table_switch %d", table_switch));
}
+ r.msgs.push_back(strprintf("table index %d", table_index));
i += 3;
}
- printbuf(desc, disp+1, NULL, 0);
}
- return complete;
+ return r;
}
diff --git a/src/fig0_10.cpp b/src/fig0_10.cpp
index 3c01547..b4af859 100644
--- a/src/fig0_10.cpp
+++ b/src/fig0_10.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -31,11 +31,11 @@
// FIG 0/10 Date and time
// ETSI EN 300 401 8.1.3.1
-bool fig0_10(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_10(fig0_common_t& fig0, const display_settings_t &disp)
{
- char desc[256];
char dateStr[256];
dateStr[0] = 0;
+ fig_result_t r;
uint8_t* f = fig0.f;
//bool RFU = f[1] >> 7;
@@ -59,16 +59,22 @@ bool fig0_10(fig0_common_t& fig0, const display_settings_t &disp)
uint8_t seconds = f[5] >> 2;
uint16_t milliseconds = ((uint16_t)(f[5] & 0x3) << 8) | f[6];
- sprintf(desc, "FIG 0/%d(long): MJD=0x%X %s, LSI %u, ConfInd %u, UTC Time: %02d:%02d:%02d.%d",
- fig0.ext(), MJD, dateStr, LSI, ConfInd, hours, minutes, seconds, milliseconds);
- printbuf(desc, disp+1, NULL, 0);
+ r.msgs.emplace_back("long form");
+ r.msgs.push_back(strprintf("MJD=0x%X %s", MJD, dateStr));
+ r.msgs.push_back(strprintf("LSI %u", LSI));
+ r.msgs.push_back(strprintf("ConfInd %u", ConfInd));
+ r.msgs.push_back(strprintf("UTC Time: %02d:%02d:%02d.%d",
+ hours, minutes, seconds, milliseconds));
}
else {
- sprintf(desc, "FIG 0/%d(short): MJD=0x%X %s, LSI %u, ConfInd %u, UTC Time: %02d:%02d",
- fig0.ext(), MJD, dateStr, LSI, ConfInd, hours, minutes);
- printbuf(desc, disp+1, NULL, 0);
+ r.msgs.emplace_back("short form");
+ r.msgs.push_back(strprintf("MJD=0x%X %s", MJD, dateStr));
+ r.msgs.push_back(strprintf("LSI %u", LSI));
+ r.msgs.push_back(strprintf("ConfInd %u", ConfInd));
+ r.msgs.push_back(strprintf("UTC Time: %02d:%02d", hours, minutes));
}
- return true;
+ r.complete = true;
+ return r;
}
diff --git a/src/fig0_11.cpp b/src/fig0_11.cpp
index d26795f..f019fa3 100644
--- a/src/fig0_11.cpp
+++ b/src/fig0_11.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -49,15 +49,14 @@ bool fig0_11_is_complete(int region_id)
// FIG 0/11 Region definition
// ETSI EN 300 401 8.1.16.1
-bool fig0_11(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_11(fig0_common_t& fig0, const display_settings_t &disp)
{
Lat_Lng gps_pos = {0, 0};
int16_t Latitude_coarse, Longitude_coarse;
uint16_t Region_Id, Extent_Latitude, Extent_Longitude, key;
uint8_t i = 1, j, k, GATy, Rfu, Length_TII_list, Rfa, MainId, Length_SubId_list, SubId;
int8_t bit_pos;
- char desc[256];
- char tmpbuf[256];
+ fig_result_t r;
bool GE_flag;
uint8_t* f = fig0.f;
uint8_t Mode_Identity = get_mode_identity();
@@ -74,58 +73,54 @@ bool fig0_11(fig0_common_t& fig0, const display_settings_t &disp)
i += 2;
if (GATy == 0) {
// TII list
- sprintf(desc, "GATy=%d Geographical area defined by a TII list, G/E flag=%d %s coverage area, RegionId=0x%X, database key=0x%X",
- GATy, GE_flag, GE_flag?"Global":"Ensemble", Region_Id, key);
+ r.msgs.push_back(strprintf("GATy=%d", GATy));
+ r.msgs.emplace_back("Geographical area defined by a TII list");
+ r.msgs.push_back(strprintf("G/E flag=%d %s coverage area",
+ GE_flag, GE_flag ? "Global" : "Ensemble"));
+ r.msgs.push_back(strprintf("RegionId=0x%X", Region_Id));
+ r.msgs.push_back(strprintf("database key=0x%X", key));
+
if (i < fig0.figlen) {
Rfu = f[i] >> 5;
if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=%d invalid value", Rfu);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfu=%d invalid value", Rfu));
}
Length_TII_list = f[i] & 0x1F;
- sprintf(tmpbuf, ", Length of TII list=%d", Length_TII_list);
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf(", Length of TII list=%d", Length_TII_list));
if (Length_TII_list == 0) {
- strcat(desc, ", CEI");
+ r.msgs.emplace_back("CEI");
}
- printbuf(desc, disp+1, NULL, 0);
i++;
- for(j = 0;(i < (fig0.figlen - 1)) && (j < Length_TII_list); j++) {
+ for (j = 0; (i < (fig0.figlen - 1)) && (j < Length_TII_list); j++) {
// iterate over Transmitter group
Rfa = f[i] >> 7;
MainId = f[i] & 0x7F;
if (Rfa != 0) {
- sprintf(desc, "Rfa=%d invalid value, MainId=0x%X",
- Rfa, MainId);
+ r.errors.push_back(strprintf("Rfa=%d invalid value, MainId=0x%X", Rfa, MainId));
}
else {
- sprintf(desc, "MainId=0x%X", MainId);
+ r.msgs.emplace_back(1, strprintf("MainId=0x%X", MainId));
}
// check MainId value
if ((Mode_Identity == 1) || (Mode_Identity == 2) || (Mode_Identity == 4)) {
if (MainId > 69) {
// The coding range shall be 0 to 69 for transmission modes I, II and IV
- sprintf(tmpbuf, " invalid value for transmission mode %d", Mode_Identity);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("invalid value for transmission mode %d", Mode_Identity));
}
}
else if (Mode_Identity == 3) {
if (MainId > 5) {
// The coding range shall be 0 to 5 for transmission modes I, II and IV
- sprintf(tmpbuf, " invalid value for transmission mode %d", Mode_Identity);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("invalid value for transmission mode %d", Mode_Identity));
}
}
Rfa = f[i+1] >> 5;
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=%d invalid value", Rfa));
}
Length_SubId_list = f[i+1] & 0x1F;
- sprintf(tmpbuf, ", Length of SubId=%d", Length_SubId_list);
- strcat(desc, tmpbuf);
- printbuf(desc, disp+2, NULL, 0);
+ r.msgs.emplace_back(1, strprintf("Length of SubId=%d", Length_SubId_list));
i += 2;
bit_pos = 3;
@@ -134,12 +129,11 @@ bool fig0_11(fig0_common_t& fig0, const display_settings_t &disp)
// iterate SubId
if (bit_pos >= 0) {
SubId |= (f[i] >> bit_pos) & 0x1F;
- sprintf(desc, "SubId=0x%X", SubId);
+ r.msgs.emplace_back(2, strprintf("SubId=0x%X", SubId));
// check SubId value
if ((SubId == 0) || (SubId > 23)) {
- strcat(desc, " invalid value");
+ r.errors.push_back(strprintf("Invalid SubId=0x%X", SubId));
}
- printbuf(desc, disp+3, NULL, 0);
bit_pos -= 5;
SubId = 0;
}
@@ -154,56 +148,61 @@ bool fig0_11(fig0_common_t& fig0, const display_settings_t &disp)
i++;
}
if (k < Length_SubId_list) {
- sprintf(desc, "%d SubId missing, fig length too short !", (Length_SubId_list - k));
- printbuf(desc, disp+3, NULL, 0);
- fprintf(stderr, "WARNING: FIG 0/%d length %d too short !\n", fig0.ext(), fig0.figlen);
+ r.errors.push_back(strprintf("%d SubId missing, fig length too short !", Length_SubId_list - k));
}
}
if (j < Length_TII_list) {
- sprintf(desc, "%d Transmitter group missing, fig length too short !", (Length_TII_list - j));
- printbuf(desc, disp+2, NULL, 0);
- fprintf(stderr, "WARNING: FIG 0/%d length %d too short !\n", fig0.ext(), fig0.figlen);
+ r.errors.push_back(strprintf("%d Transmitter group missing, fig length too short !", Length_TII_list - j));
}
}
}
else if (GATy == 1) {
// Coordinates
- sprintf(desc, "GATy=%d Geographical area defined as a spherical rectangle by the geographical co-ordinates of one corner and its latitude and longitude extents, G/E flag=%d %s coverage area, RegionId=0x%X, database key=0x%X",
- GATy, GE_flag, GE_flag?"Global":"Ensemble", Region_Id, key);
+ r.msgs.push_back(strprintf("GATy=%d", GATy));
+ r.msgs.emplace_back("Geographical area defined as a spherical rectangle "
+ "by the geographical co-ordinates of one corner and its latitude and "
+ "longitude extents");
+ r.msgs.push_back(strprintf("G/E flag=%d %s coverage area",
+ GE_flag, GE_flag ? "Global" : "Ensemble"));
+ r.msgs.push_back(strprintf("RegionId=0x%X", Region_Id));
+ r.msgs.push_back(strprintf("database key=0x%X", key));
+
if (i < (fig0.figlen - 6)) {
Latitude_coarse = ((int16_t)f[i] << 8) | ((uint16_t)f[i+1]);
Longitude_coarse = ((int16_t)f[i+2] << 8) | ((uint16_t)f[i+3]);
gps_pos.latitude = ((double)Latitude_coarse) * 90 / 32768;
gps_pos.longitude = ((double)Latitude_coarse) * 180 / 32768;
- sprintf(tmpbuf, ", Lat Lng coarse=0x%X 0x%X => %f, %f",
- Latitude_coarse, Longitude_coarse, gps_pos.latitude, gps_pos.longitude);
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("Lat Lng coarse=0x%X 0x%X => %f, %f",
+ Latitude_coarse, Longitude_coarse, gps_pos.latitude, gps_pos.longitude));
Extent_Latitude = ((uint16_t)f[i+4] << 4) | ((uint16_t)(f[i+5] >> 4));
Extent_Longitude = ((uint16_t)(f[i+5] & 0x0F) << 8) | ((uint16_t)f[i+6]);
gps_pos.latitude += ((double)Extent_Latitude) * 90 / 32768;
gps_pos.longitude += ((double)Extent_Longitude) * 180 / 32768;
- sprintf(tmpbuf, ", Extent Lat Lng=0x%X 0x%X => %f, %f",
- Extent_Latitude, Extent_Longitude, gps_pos.latitude, gps_pos.longitude);
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("Extent Lat Lng=0x%X 0x%X => %f, %f",
+ Extent_Latitude, Extent_Longitude, gps_pos.latitude, gps_pos.longitude));
}
else {
- sprintf(tmpbuf, ", Coordinates missing, fig length too short !");
- strcat(desc, tmpbuf);
- fprintf(stderr, "WARNING: FIG 0/%d length %d too short !\n", fig0.ext(), fig0.figlen);
+ r.errors.push_back("Coordinates missing, fig length too short !");
}
- printbuf(desc, disp+1, NULL, 0);
i += 7;
}
else {
// Rfu
- sprintf(desc, "GATy=%d reserved for future use of the geographical, G/E flag=%d %s coverage area, RegionId=0x%X, database key=0x%X, stop Region definition iteration %d/%d",
- GATy, GE_flag, GE_flag?"Global":"Ensemble", Region_Id, key, i, fig0.figlen);
- printbuf(desc, disp+1, NULL, 0);
+ r.msgs.push_back(strprintf("GATy=%d", GATy));
+ r.msgs.emplace_back("reserved for future use of the geographical");
+ r.msgs.push_back(strprintf("G/E flag=%d %s coverage area",
+ GE_flag, GE_flag ? "Global" : "Ensemble"));
+ r.msgs.push_back(strprintf("RegionId=0x%X", Region_Id));
+ r.msgs.push_back(strprintf("database key=0x%X", key));
+ r.msgs.push_back(strprintf("stop Region definition iteration %d/%d",
+ i, fig0.figlen));
// stop Region definition iteration
i = fig0.figlen;
+ r.errors.push_back("Stopping iteration because Rfu encountered");
}
}
- return complete;
+ r.complete = complete;
+ return r;
}
diff --git a/src/fig0_13.cpp b/src/fig0_13.cpp
index 36c36df..ca8880f 100644
--- a/src/fig0_13.cpp
+++ b/src/fig0_13.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -73,14 +73,13 @@ std::string get_fig_0_13_userapp(int user_app_type)
// FIG 0/13 User application information
// ETSI EN 300 401 8.1.20
-bool fig0_13(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_13(fig0_common_t& fig0, const display_settings_t &disp)
{
uint32_t SId;
uint8_t SCIdS;
uint8_t No;
uint8_t* f = fig0.f;
- const int figtype = 0;
- char desc[256];
+ fig_result_t r;
bool complete = false;
int k = 1;
@@ -109,9 +108,9 @@ bool fig0_13(fig0_common_t& fig0, const display_settings_t &disp)
complete |= fig0_13_is_complete(SId, SCIdS);
- sprintf(desc, "FIG %d/%d: SId=0x%X SCIdS=%u No=%u",
- figtype, fig0.ext(), SId, SCIdS, No);
- printbuf(desc, disp+1, NULL, 0);
+ r.msgs.push_back(strprintf("SId=0x%X", SId));
+ r.msgs.push_back(strprintf("SCIdS=%u", SCIdS));
+ r.msgs.push_back(strprintf("No=%u", No));
for (int numapp = 0; numapp < No; numapp++) {
uint16_t user_app_type = ((f[k] << 8) |
@@ -119,13 +118,13 @@ bool fig0_13(fig0_common_t& fig0, const display_settings_t &disp)
uint8_t user_app_len = f[k+1] & 0x1F;
k+=2;
- sprintf(desc, "User Application %d '%s'; length %u",
+ r.msgs.emplace_back(1, strprintf("User Application %d '%s'; length %u",
user_app_type,
get_fig_0_13_userapp(user_app_type).c_str(),
- user_app_len);
- printbuf(desc, disp+2, NULL, 0);
+ user_app_len));
}
- return complete;
+ r.complete = complete;
+ return r;
}
diff --git a/src/fig0_14.cpp b/src/fig0_14.cpp
index 029a21c..65b5797 100644
--- a/src/fig0_14.cpp
+++ b/src/fig0_14.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -58,24 +58,23 @@ const char *FEC_schemes_str[4] = {
// FIG 0/14 FEC sub-channel organization
// ETSI EN 300 401 6.2.2
-bool fig0_14(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_14(fig0_common_t& fig0, const display_settings_t &disp)
{
uint8_t i = 1, SubChId, FEC_scheme;
uint8_t* f = fig0.f;
- char desc[256];
- bool complete = false;
+ fig_result_t r;
while (i < fig0.figlen) {
// iterate over Sub-channel
SubChId = f[i] >> 2;
- complete |= fig0_14_is_complete(SubChId);
+ r.complete |= fig0_14_is_complete(SubChId);
FEC_scheme = f[i] & 0x3;
- sprintf(desc, "SubChId=0x%X, FEC scheme=%d %s",
- SubChId, FEC_scheme, FEC_schemes_str[FEC_scheme]);
- printbuf(desc, disp+1, NULL, 0);
+ r.msgs.push_back(strprintf("SubChId=0x%X", SubChId));
+ r.msgs.emplace_back(1, strprintf("FEC scheme=%d %s",
+ FEC_scheme, FEC_schemes_str[FEC_scheme]));
i++;
}
- return complete;
+ return r;
}
diff --git a/src/fig0_16.cpp b/src/fig0_16.cpp
index 4583fc7..bff2a01 100644
--- a/src/fig0_16.cpp
+++ b/src/fig0_16.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -54,74 +54,62 @@ bool fig0_16_is_complete(SId_t SId, PNum_t PNum)
// FIG 0/16 Programme Number & fig0.oe() Programme Number
// ETSI EN 300 401 8.1.4 & 8.1.10.3
-bool fig0_16(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_16(fig0_common_t& fig0, const display_settings_t &disp)
{
uint16_t SId, PNum, New_SId, New_PNum;
uint8_t i = 1, Rfa, Rfu;
- char tmpbuf[256];
- char desc[256];
+ fig_result_t r;
bool Continuation_flag, Update_flag;
uint8_t* f = fig0.f;
- bool complete = false;
while (i < (fig0.figlen - 4)) {
// iterate over Programme Number
SId = ((uint16_t)f[i] << 8) | ((uint16_t)f[i+1]);
PNum = ((uint16_t)f[i+2] << 8) | ((uint16_t)f[i+3]);
- complete |= fig0_16_is_complete(SId, PNum);
+ r.complete |= fig0_16_is_complete(SId, PNum);
Rfa = f[i+4] >> 6;
Rfu = (f[i+4] >> 2) & 0x0F;
Continuation_flag = (f[i+4] >> 1) & 0x01;
Update_flag = f[i+4] & 0x01;
- sprintf(desc, "SId=0x%X, PNum=0x%X ", SId, PNum);
- // Append PNum decoded string
- strcatPNum(desc, PNum);
+ r.msgs.push_back(strprintf("SId=0x%X", SId));
+ r.msgs.push_back(strprintf("PNum=0x%X ", PNum) + pnum_to_str(PNum));
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=%d invalid value", Rfa));
}
if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=0x%X invalid value", Rfu);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf(", Rfu=0x%X invalid value", Rfu));
}
- sprintf(tmpbuf, ", Continuation flag=%d the programme will %s, Update flag=%d %sre-direction",
- Continuation_flag, Continuation_flag?"be interrupted but continued later":"not be subject to a planned interruption",
- Update_flag, Update_flag?"":"no ");
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("Continuation flag=%d: the programme will %s",
+ Continuation_flag,
+ Continuation_flag ? "be interrupted but continued later" : "not be subject to a planned interruption"));
+ r.msgs.push_back(strprintf("Update flag=%d %sre-direction",
+ Update_flag, Update_flag ? "" : "no "));
i += 5;
if (Update_flag != 0) {
// In the case of a re-direction, the New SId and New PNum shall be appended
if (i < (fig0.figlen - 1)) {
New_SId = ((uint16_t)f[i] << 8) | ((uint16_t)f[i+1]);
- sprintf(tmpbuf, ", New SId=0x%X", New_SId);
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("New SId=0x%X", New_SId));
if (i < (fig0.figlen - 3)) {
New_PNum = ((uint16_t)f[i+2] << 8) | ((uint16_t)f[i+3]);
- sprintf(tmpbuf, ", New PNum=0x%X ", New_PNum);
- strcat(desc, tmpbuf);
- // Append New_PNum decoded string
- strcatPNum(desc, New_PNum);
+ r.msgs.push_back(strprintf("New PNum=0x%X ", New_PNum) + pnum_to_str(New_PNum));
}
else {
- sprintf(tmpbuf, ", missing New PNum !");
- strcat(desc, tmpbuf);
+ r.errors.push_back("missing New PNum !");
}
}
else {
- sprintf(tmpbuf, ", missing New SId and New PNum !");
- strcat(desc, tmpbuf);
+ r.errors.push_back("missing New SId and New PNum !");
}
i += 4;
}
-
- printbuf(desc, disp+1, NULL, 0);
}
- return complete;
+ return r;
}
diff --git a/src/fig0_17.cpp b/src/fig0_17.cpp
index 772b804..8eb2ba9 100644
--- a/src/fig0_17.cpp
+++ b/src/fig0_17.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -48,91 +48,90 @@ bool fig0_17_is_complete(int services_id)
// FIG 0/17 Programme Type
// ETSI EN 300 401 8.1.5
-bool fig0_17(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_17(fig0_common_t& fig0, const display_settings_t &disp)
{
uint16_t SId;
uint8_t i = 1, Rfa, Language, Int_code, Comp_code;
- char tmpbuf[512];
- char desc[512];
+ fig_result_t r;
bool SD_flag, PS_flag, L_flag, CC_flag, Rfu;
uint8_t* f = fig0.f;
- bool complete = false;
while (i < (fig0.figlen - 3)) {
// iterate over announcement support
SId = (f[i] << 8) | f[i+1];
- complete |= fig0_17_is_complete(SId);
+ r.complete |= fig0_17_is_complete(SId);
SD_flag = (f[i+2] >> 7);
PS_flag = ((f[i+2] >> 6) & 0x01);
L_flag = ((f[i+2] >> 5) & 0x01);
CC_flag = ((f[i+2] >> 4) & 0x01);
Rfa = (f[i+2] & 0x0F);
- sprintf(desc, "SId=0x%X, S/D=%d Programme Type codes and language (when present), %srepresent the current programme contents, P/S=%d %s service component, L flag=%d language field %s, CC flag=%d complementary code and preceding Rfa and Rfu fields %s",
- SId, SD_flag, SD_flag?"":"may not ", PS_flag, PS_flag?"secondary":"primary",
- L_flag, L_flag?"present":"absent", CC_flag, CC_flag?"present":"absent");
+ r.msgs.push_back(strprintf("SId=0x%X", SId));
+ r.msgs.push_back(strprintf(
+ "S/D=%d Programme Type codes and language (when present), %srepresent the current programme contents",
+ SD_flag, SD_flag?"":"may not "));
+ r.msgs.push_back(strprintf("P/S=%d %s service component",
+ PS_flag, PS_flag?"secondary":"primary"));
+ r.msgs.push_back(strprintf("L flag=%d language field %s",
+ L_flag, L_flag?"present":"absent"));
+ r.msgs.push_back(strprintf("CC flag=%d complementary code and preceding Rfa and Rfu fields %s",
+ CC_flag, CC_flag?"present":"absent"));
+
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=0x%X invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=0x%X invalid value", Rfa));
}
+
i += 3;
if (L_flag != 0) {
if (i < fig0.figlen) {
Language = f[i];
- sprintf(tmpbuf, ", Language=0x%X %s", Language,
- get_language_name(Language));
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("Language=0x%X %s", Language,
+ get_language_name(Language)));
}
else {
- sprintf(tmpbuf, ", Language= invalid FIG length");
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Language= invalid FIG length"));
}
i++;
}
+
if (i < fig0.figlen) {
Rfa = f[i] >> 6;
Rfu = (f[i] >> 5) & 0x01;
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=0x%X invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=0x%X invalid value", Rfa));
}
if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=%d invalid value", Rfu);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfu=%d invalid value", Rfu));
}
Int_code = f[i] & 0x1F;
- sprintf(tmpbuf, ", Int code=0x%X %s", Int_code, get_programme_type(get_international_table() , Int_code));
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("Int code=0x%X %s", Int_code,
+ get_programme_type(get_international_table(), Int_code)));
i++;
}
else {
- sprintf(tmpbuf, ", Int code= invalid FIG length");
- strcat(desc, tmpbuf);
+ r.errors.push_back("Int code: invalid FIG length");
}
+
if (CC_flag != 0) {
if (i < fig0.figlen) {
Rfa = f[i] >> 6;
Rfu = (f[i] >> 5) & 0x01;
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=0x%X invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=0x%X invalid value", Rfa));
}
if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=%d invalid value", Rfu);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfu=%d invalid value", Rfu));
}
Comp_code = f[i] & 0x1F;
- sprintf(tmpbuf, ", Comp code=0x%X %s", Comp_code, get_programme_type(get_international_table() , Comp_code));
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("Comp code=0x%X %s", Comp_code,
+ get_programme_type(get_international_table(), Comp_code)));
i++;
}
else {
- sprintf(tmpbuf, ", Comp code= invalid FIG length");
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Comp code= invalid FIG length"));
}
}
- printbuf(desc, disp+1, NULL, 0);
}
- return complete;
+ return r;
}
diff --git a/src/fig0_18.cpp b/src/fig0_18.cpp
index abbf9f7..cc82bec 100644
--- a/src/fig0_18.cpp
+++ b/src/fig0_18.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -49,64 +49,54 @@ bool fig0_18_is_complete(int services_id)
// FIG 0/18 Announcement support
// ETSI EN 300 401 8.1.6.1
-bool fig0_18(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_18(fig0_common_t& fig0, const display_settings_t &disp)
{
uint32_t key;
uint16_t SId, Asu_flags;
uint8_t i = 1, j, Rfa, Number_clusters;
- char tmpbuf[256];
- char desc[256];
+ fig_result_t r;
uint8_t* f = fig0.f;
- const int figtype = 0;
- bool complete = false;
while (i < (fig0.figlen - 4)) {
// iterate over announcement support
// SId, Asu flags, Rfa, Number of clusters
SId = ((uint16_t)f[i] << 8) | (uint16_t)f[i+1];
- complete |= fig0_18_is_complete(SId);
+ r.complete |= fig0_18_is_complete(SId);
Asu_flags = ((uint16_t)f[i+2] << 8) | (uint16_t)f[i+3];
Rfa = (f[i+4] >> 5);
Number_clusters = (f[i+4] & 0x1F);
- sprintf(desc, "SId=0x%X, Asu flags=0x%04x", SId, Asu_flags);
+ r.msgs.push_back(strprintf("SId=0x%X", SId));
+ r.msgs.push_back(strprintf("Asu flags=0x%04x", Asu_flags));
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=%d invalid value", Rfa));
}
- sprintf(tmpbuf, ", Number of clusters=%d", Number_clusters);
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("Number of clusters=%d", Number_clusters));
+
key = ((uint32_t)fig0.oe() << 17) | ((uint32_t)fig0.pd() << 16) | (uint32_t)SId;
- sprintf(tmpbuf, ", database key=0x%05x", key);
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("database key=0x%05x", key));
// CEI Change Event Indication
if ((Number_clusters == 0) && (Asu_flags == 0)) {
- sprintf(tmpbuf, ", CEI");
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back("CEI");
}
- printbuf(desc, disp+1, NULL, 0);
i += 5;
for(j = 0; (j < Number_clusters) && (i < fig0.figlen); j++) {
// iterate over Cluster Id
- sprintf(desc, "Cluster Id=0x%X", f[i]);
- printbuf(desc, disp+2, NULL, 0);
+ r.msgs.emplace_back(1, strprintf("Cluster Id=0x%X", f[i]));
i++;
}
if (j < Number_clusters) {
- sprintf(desc, "missing Cluster Id, fig length too short !");
- printbuf(desc, disp+1, NULL, 0);
- fprintf(stderr, "WARNING: FIG %d/%d length %d too short !\n", figtype, fig0.ext(), fig0.figlen);
+ r.errors.push_back("missing Cluster Id, fig length too short !");
}
// decode announcement support types
- for(j = 0; j < 16; j++) {
+ for (j = 0; j < 16; j++) {
if (Asu_flags & (1 << j)) {
- sprintf(desc, "Announcement support=%s", get_announcement_type(j));
- printbuf(desc, disp+2, NULL, 0);
+ r.msgs.emplace_back(1, strprintf("Announcement support=%s", get_announcement_type(j)));
}
}
}
- return complete;
+ return r;
}
diff --git a/src/fig0_19.cpp b/src/fig0_19.cpp
index 272f230..5fef324 100644
--- a/src/fig0_19.cpp
+++ b/src/fig0_19.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -48,58 +48,52 @@ bool fig0_19_is_complete(int clusters_id)
// FIG 0/19 Announcement switching
// ETSI EN 300 401 8.1.6.2
-bool fig0_19(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_19(fig0_common_t& fig0, const display_settings_t &disp)
{
uint16_t Asw_flags;
uint8_t i = 1, j, Cluster_Id, SubChId, Rfa, RegionId_LP;
- char tmpbuf[256];
- char desc[256];
+ fig_result_t r;
bool New_flag, Region_flag;
uint8_t* f = fig0.f;
- const int figtype = 0;
- bool complete = false;
while (i < (fig0.figlen - 3)) {
// iterate over announcement switching
// Cluster Id, Asw flags, New flag, Region flag,
// SubChId, Rfa, Region Id Lower Part
Cluster_Id = f[i];
- complete |= fig0_19_is_complete(Cluster_Id);
+ r.complete |= fig0_19_is_complete(Cluster_Id);
Asw_flags = ((uint16_t)f[i+1] << 8) | (uint16_t)f[i+2];
New_flag = (f[i+3] >> 7);
Region_flag = (f[i+3] >> 6) & 0x1;
SubChId = (f[i+3] & 0x3F);
- sprintf(desc, "Cluster Id=0x%02x, Asw flags=0x%04x, New flag=%d %s, Region flag=%d last byte %s, SubChId=%d",
- Cluster_Id, Asw_flags, New_flag, (New_flag)?"new":"repeat", Region_flag, (Region_flag)?"present":"absent", SubChId);
+ r.msgs.push_back(strprintf("Cluster Id=0x%02x", Cluster_Id));
+ r.msgs.push_back(strprintf("Asw flags=0x%04x", Asw_flags));
+ r.msgs.push_back(strprintf("New flag=%d %s", New_flag, (New_flag)?"new":"repeat"));
+ r.msgs.push_back(strprintf("Region flag=%d last byte %s", Region_flag, (Region_flag)?"present":"absent"));
+ r.msgs.push_back(strprintf("SubChId=%d", SubChId));
if (Region_flag) {
if (i < (fig0.figlen - 4)) {
// read region lower part
Rfa = (f[i+4] >> 6);
RegionId_LP = (f[i+4] & 0x3F);
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=%d invalid value", Rfa));
}
- sprintf(tmpbuf, ", Region Lower Part=0x%02x", RegionId_LP);
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("Region Lower Part=0x%02x", RegionId_LP));
}
else {
- sprintf(tmpbuf, "missing Region Lower Part, fig length too short !");
- strcat(desc, tmpbuf);
- fprintf(stderr, "WARNING: FIG %d/%d length %d too short !\n", figtype, fig0.ext(), fig0.figlen);
+ r.errors.push_back("missing Region Lower Part, fig length too short !");
}
}
- printbuf(desc, disp+1, NULL, 0);
// decode announcement switching types
for(j = 0; j < 16; j++) {
if (Asw_flags & (1 << j)) {
- sprintf(desc, "Announcement switching=%s", get_announcement_type(j));
- printbuf(desc, disp+2, NULL, 0);
+ r.msgs.emplace_back(1, strprintf("Announcement switching=%s", get_announcement_type(j)));
}
}
i += (4 + Region_flag);
}
- return complete;
+ return r;
}
diff --git a/src/fig0_2.cpp b/src/fig0_2.cpp
index 128396e..85de44c 100644
--- a/src/fig0_2.cpp
+++ b/src/fig0_2.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -48,16 +48,14 @@ bool fig0_2_is_complete(int services_id)
// FIG 0/2 Basic service and service component definition
// ETSI EN 300 401 6.3.1
-bool fig0_2(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_2(fig0_common_t& fig0, const display_settings_t &disp)
{
uint16_t sref, sid;
uint8_t cid, ecc, local, caid, ncomp, timd, ps, ca, subchid, scty;
int k = 1;
std::string psdesc;
uint8_t* f = fig0.f;
- char sctydesc[32];
- char desc[256];
- bool complete = false;
+ fig_result_t r;
while (k < fig0.figlen) {
if (fig0.pd() == 0) {
@@ -82,29 +80,34 @@ bool fig0_2(fig0_common_t& fig0, const display_settings_t &disp)
k += 4;
}
- complete |= fig0_2_is_complete(sid);
+ r.complete |= fig0_2_is_complete(sid);
local = (f[k] & 0x80) >> 7;
caid = (f[k] & 0x70) >> 4;
ncomp = f[k] & 0x0F;
- if (fig0.pd() == 0)
- sprintf(desc,
- "Service ID=0x%X (Country id=%d, Service reference=%d), Number of components=%d, Local flag=%d, CAID=%d",
- sid, cid, sref, ncomp, local, caid);
- else
- sprintf(desc,
- "Service ID=0x%X (ECC=%d, Country id=%d, Service reference=%d), Number of components=%d, Local flag=%d, CAID=%d",
- sid, ecc, cid, sref, ncomp, local, caid);
- printbuf(desc, disp+1, NULL, 0);
+ if (fig0.pd() == 0) {
+ r.msgs.push_back(strprintf("Service ID=0x%X (Country id=%d, Service reference=%d)",
+ sid, cid, sref));
+ r.msgs.emplace_back(1, strprintf("Number of components=%d", ncomp));
+ r.msgs.emplace_back(1, strprintf("Local flag=%d", local));
+ r.msgs.emplace_back(1, strprintf("CAID=%d", caid));
+ }
+ else {
+ r.msgs.push_back(strprintf("Service ID=0x%X (ECC=%d, Country id=%d, Service reference=%d)",
+ sid, ecc, cid, sref));
+ r.msgs.emplace_back(1, strprintf("Number of components=%d", ncomp));
+ r.msgs.emplace_back(1, strprintf("Local flag=%d", local));
+ r.msgs.emplace_back(1, strprintf("CAID=%d", caid));
+ }
k++;
- for (int i=0; i<ncomp; i++) {
+ for (int i = 0; i < ncomp; i++) {
uint8_t scomp[2];
memcpy(scomp, f+k, 2);
- sprintf(desc, "Component[%d]", i);
- printbuf(desc, disp+2, scomp, 2, "");
+ r.msgs.emplace_back(1, strprintf("Component[%d]", i));
+
timd = (scomp[0] & 0xC0) >> 6;
ps = (scomp[1] & 0x02) >> 1;
ca = scomp[1] & 0x01;
@@ -128,41 +131,50 @@ bool fig0_2(fig0_common_t& fig0, const display_settings_t &disp)
if (timd == 0) {
//MSC stream audio
+ r.msgs.emplace_back(2, "Stream audio mode");
+ r.msgs.emplace_back(2, psdesc);
+
if (scty == 0)
- sprintf(sctydesc, "MPEG Foreground sound (%d)", scty);
+ r.msgs.emplace_back(2, strprintf("MPEG Foreground sound (%d)", scty));
else if (scty == 1)
- sprintf(sctydesc, "MPEG Background sound (%d)", scty);
+ r.msgs.emplace_back(2, strprintf("MPEG Background sound (%d)", scty));
else if (scty == 2)
- sprintf(sctydesc, "Multi Channel sound (%d)", scty);
+ r.msgs.emplace_back(2, strprintf("Multi Channel sound (%d)", scty));
else if (scty == 63)
- sprintf(sctydesc, "AAC sound (%d)", scty);
+ r.msgs.emplace_back(2, strprintf("AAC sound (%d)", scty));
else
- sprintf(sctydesc, "Unknown ASCTy (%d)", scty);
+ r.msgs.emplace_back(2, strprintf("Unknown ASCTy (%d)", scty));
- sprintf(desc, "Stream audio mode, %s, %s, SubChannel ID=%02X, CA=%d", psdesc.c_str(), sctydesc, subchid, ca);
- printbuf(desc, disp+3, NULL, 0);
+ r.msgs.emplace_back(2, strprintf("SubChannel ID=%02X", subchid));
+ r.msgs.emplace_back(2, strprintf("CA=%d", ca));
}
else if (timd == 1) {
// MSC stream data
- sprintf(sctydesc, "DSCTy=%d %s", scty, get_dscty_type(scty));
- sprintf(desc, "Stream data mode, %s, %s, SubChannel ID=%02X, CA=%d", psdesc.c_str(), sctydesc, subchid, ca);
- printbuf(desc, disp+3, NULL, 0);
+ r.msgs.emplace_back(2, "Stream data mode");
+ r.msgs.emplace_back(2, psdesc);
+ r.msgs.emplace_back(2, strprintf("DSCTy=%d %s", scty, get_dscty_type(scty)));
+ r.msgs.emplace_back(2, strprintf("SubChannel ID=%02X", subchid));
+ r.msgs.emplace_back(2, strprintf("CA=%d", ca));
}
else if (timd == 2) {
// FIDC
- sprintf(sctydesc, "DSCTy=%d %s", scty, get_dscty_type(scty));
- sprintf(desc, "FIDC mode, %s, %s, Fast Information Data Channel ID=%02X, CA=%d", psdesc.c_str(), sctydesc, subchid, ca);
- printbuf(desc, disp+3, NULL, 0);
+ r.msgs.emplace_back(2, "FIDC mode");
+ r.msgs.emplace_back(2, psdesc);
+ r.msgs.emplace_back(2, strprintf("DSCTy=%d %s", scty, get_dscty_type(scty)));
+ r.msgs.emplace_back(2, strprintf("Fast Information Data Channel ID=%02X", subchid));
+ r.msgs.emplace_back(2, strprintf("CA=%d", ca));
}
else if (timd == 3) {
// MSC Packet mode
- sprintf(desc, "MSC Packet Mode, %s, Service Component ID=%02X, CA=%d", psdesc.c_str(), subchid, ca);
- printbuf(desc, disp+3, NULL, 0);
+ r.msgs.emplace_back(2, "MSC Packet Mode");
+ r.msgs.emplace_back(2, psdesc);
+ r.msgs.emplace_back(2, strprintf("SubChannel ID=%02X", subchid));
+ r.msgs.emplace_back(2, strprintf("CA=%d", ca));
}
k += 2;
}
}
- return complete;
+ return r;
}
diff --git a/src/fig0_21.cpp b/src/fig0_21.cpp
index 088bb23..46a196f 100644
--- a/src/fig0_21.cpp
+++ b/src/fig0_21.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -49,7 +49,7 @@ bool fig0_21_is_complete(int region_id)
// FIG 0/21 Frequency Information
// ETSI EN 300 401 8.1.8
-bool fig0_21(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_21(fig0_common_t& fig0, const display_settings_t &disp)
{
float freq;
uint32_t ifreq;
@@ -57,20 +57,18 @@ bool fig0_21(fig0_common_t& fig0, const display_settings_t &disp)
uint16_t RegionId, Id_field;
uint8_t i = 1, j, k, Length_FI_list, RandM, Length_Freq_list, Control_field;
uint8_t Control_field_trans_mode, Id_field2;
- char tmpbuf[256];
- char desc[256];
+ fig_result_t r;
bool Continuity_flag;
uint8_t* f = fig0.f;
- bool complete = false;
while (i < (fig0.figlen - 1)) {
// iterate over frequency information
// decode RegionId, Length of FI list
RegionId = (f[i] << 3) | (f[i+1] >> 5);
- complete |= fig0_21_is_complete(RegionId);
+ r.complete |= fig0_21_is_complete(RegionId);
Length_FI_list = (f[i+1] & 0x1F);
- sprintf(desc, "RegionId=0x%03x", RegionId);
- printbuf(desc, disp+1, NULL, 0);
+ r.msgs.push_back(strprintf("RegionId=0x%03x", RegionId));
+ r.msgs.push_back(strprintf("Len=%d", Length_FI_list));
i += 2;
if ((i + Length_FI_list) <= fig0.figlen) {
j = i;
@@ -81,82 +79,85 @@ bool fig0_21(fig0_common_t& fig0, const display_settings_t &disp)
RandM = f[j+2] >> 4;
Continuity_flag = (f[j+2] >> 3) & 0x01;
Length_Freq_list = f[j+2] & 0x07;
- sprintf(desc, "Id_field=");
+ std::string idfield;
switch (RandM) {
case 0x0:
case 0x1:
- strcat(desc, "EId");
+ idfield += "EId";
break;
case 0x6:
- strcat(desc, "DRM Service Id");
+ idfield += "DRM Service Id";
break;
case 0x8:
- strcat(desc, "RDS PI");
+ idfield += "RDS PI";
break;
case 0x9:
case 0xa:
case 0xc:
- strcat(desc, "Dummy");
+ idfield += "Dummy";
break;
case 0xe:
- strcat(desc, "AMSS Service Id");
+ idfield += "AMSS Service Id";
break;
default:
- strcat(desc, "invalid");
+ idfield += "invalid";
+ r.errors.emplace_back("R&M invalid");
break;
}
- sprintf(tmpbuf, "=0x%X, R&M=0x%1x", Id_field, RandM);
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back(1, strprintf("ID field=0x%X", Id_field) + idfield);
+
+ std::string rm_str;
switch (RandM) {
case 0x0:
- strcat(desc, "=DAB ensemble, no local windows");
+ rm_str += " DAB ensemble, no local windows";
break;
case 0x6:
- strcat(desc, "=DRM");
+ rm_str += " DRM";
break;
case 0x8:
- strcat(desc, "=FM with RDS");
+ rm_str += " FM with RDS";
break;
case 0x9:
- strcat(desc, "=FM without RDS");
+ rm_str += " FM without RDS";
break;
case 0xa:
- strcat(desc, "=AM (MW in 9 kHz steps & LW)");
+ rm_str += " AM (MW in 9 kHz steps & LW)";
break;
case 0xc:
- strcat(desc, "=AM (MW in 5 kHz steps & SW)");
+ rm_str += " AM (MW in 5 kHz steps & SW)";
break;
case 0xe:
- strcat(desc, "=AMSS");
+ rm_str += " AMSS";
break;
default:
- strcat(desc, "=Rfu");
+ rm_str += " Rfu";
+ r.errors.emplace_back("R&M is Rfu");
break;
}
- sprintf(tmpbuf, ", Continuity flag=%d", Continuity_flag);
- strcat(desc, tmpbuf);
- if ((fig0.oe() == 0) || ((fig0.oe() == 1) && (RandM != 0x6) && \
+ r.msgs.emplace_back(1, strprintf("R&M=0x%1x", RandM) + rm_str);
+ std::string continuity_str;
+ if ((fig0.oe() == 0) || ((fig0.oe() == 1) && (RandM != 0x6) &&
((RandM < 0x8) || (RandM > 0xa)) && (RandM != 0xc) && (RandM != 0xe))) {
if (Continuity_flag == 0) {
switch (RandM) {
case 0x0:
case 0x1:
- strcat(desc, "=continuous output not expected");
+ continuity_str += "=continuous output not expected";
break;
case 0x6:
- strcat(desc, "=no compensating time delay on DRM audio signal");
+ continuity_str += "=no compensating time delay on DRM audio signal";
break;
case 0x8:
case 0x9:
- strcat(desc, "=no compensating time delay on FM audio signal");
+ continuity_str += "=no compensating time delay on FM audio signal";
break;
case 0xa:
case 0xc:
case 0xe:
- strcat(desc, "=no compensating time delay on AM audio signal");
+ continuity_str += "=no compensating time delay on AM audio signal";
break;
default:
- strcat(desc, "=Rfu");
+ continuity_str += "=Rfu";
break;
}
}
@@ -164,39 +165,42 @@ bool fig0_21(fig0_common_t& fig0, const display_settings_t &disp)
switch (RandM) {
case 0x0:
case 0x1:
- strcat(desc, "=continuous output possible");
+ continuity_str += "=continuous output possible";
break;
case 0x6:
- strcat(desc, "=compensating time delay on DRM audio signal");
+ continuity_str += "=compensating time delay on DRM audio signal";
break;
case 0x8:
case 0x9:
- strcat(desc, "=compensating time delay on FM audio signal");
+ continuity_str += "=compensating time delay on FM audio signal";
break;
case 0xa:
case 0xc:
case 0xe:
- strcat(desc, "=compensating time delay on AM audio signal");
+ continuity_str += "=compensating time delay on AM audio signal";
break;
default:
- strcat(desc, "=Rfu");
+ continuity_str += "=Rfu";
+ r.errors.emplace_back("continuity is Rfu");
break;
}
}
}
else { // fig0.oe() == 1
- strcat(desc, "=reserved for future addition");
+ continuity_str = "=reserved for future addition";
+ r.errors.emplace_back("Rfu");
}
+
+ r.msgs.emplace_back(1, strprintf("Continuity flag=%d ", Continuity_flag) + continuity_str);
+
key = ((uint64_t)fig0.oe() << 32) | ((uint64_t)fig0.pd() << 31) | \
((uint64_t)RegionId << 20) | ((uint64_t)Id_field << 4) | \
(uint64_t)RandM;
- sprintf(tmpbuf, ", database key=0x%09" PRId64, key);
+ r.msgs.emplace_back(1, strprintf("database key=0x%09" PRId64, key));
// CEI Change Event Indication
if (Length_Freq_list == 0) {
- strcat(tmpbuf, ", CEI");
+ r.msgs.emplace_back(1, "CEI");
}
- strcat(desc, tmpbuf);
- printbuf(desc, disp+2, NULL, 0);
j += 3; // add header
k = j;
@@ -210,33 +214,30 @@ bool fig0_21(fig0_common_t& fig0, const display_settings_t &disp)
Control_field = (f[k] >> 3);
Control_field_trans_mode = (Control_field >> 1) & 0x07;
if ((Control_field & 0x10) == 0) {
- sprintf(desc, "%d KHz, ", ifreq);
+ r.msgs.emplace_back(2, strprintf("%d KHz", ifreq));
if ((Control_field & 0x01) == 0) {
- strcat(desc, "geographically adjacent area, ");
+ r.msgs.emplace_back(2, "geographically adjacent area");
}
else { // (Control_field & 0x01) == 1
- strcat(desc, "no geographically adjacent area, ");
+ r.msgs.emplace_back(2, "no geographically adjacent area");
}
if (Control_field_trans_mode == 0) {
- strcat(desc, "no transmission mode signalled");
+ r.msgs.emplace_back(2, "no transmission mode signalled");
}
else if (Control_field_trans_mode <= 4) {
- sprintf(tmpbuf, "transmission mode %d", Control_field_trans_mode);
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back(2, strprintf("transmission mode %d", Control_field_trans_mode));
}
else { // Control_field_trans_mode > 4
- sprintf(tmpbuf, "invalid transmission mode 0x%x", Control_field_trans_mode);
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back(2, strprintf("invalid transmission mode 0x%x", Control_field_trans_mode));
}
}
else { // (Control_field & 0x10) == 0x10
- sprintf(desc, "%d KHz, invalid Control field b23 0x%x", ifreq, Control_field);
+ r.msgs.emplace_back(2, strprintf("%d KHz, invalid Control field b23 0x%x", ifreq, Control_field));
}
}
else {
- sprintf(desc, "Frequency not to be used (0)");
+ r.errors.emplace_back("Frequency not to be used (0)");
}
- printbuf(desc, disp+3, NULL, 0);
k += 3;
}
break;
@@ -253,17 +254,16 @@ bool fig0_21(fig0_common_t& fig0, const display_settings_t &disp)
else { // f[k] >= 16
ifreq = (387 + ((uint32_t)f[k] * 9));
}
- sprintf(desc, "%d KHz", ifreq);
+ r.msgs.emplace_back(2, strprintf("%d KHz", ifreq));
}
else { // RandM == 8 or 9
freq = (87.5 + ((float)f[k] * 0.1));
- sprintf(desc, "%.1f MHz", freq);
+ r.msgs.emplace_back(2, strprintf("%.1f MHz", freq));
}
}
else {
- sprintf(desc, "Frequency not to be used (0)");
+ r.errors.emplace_back("Frequency not to be used (0)");
}
- printbuf(desc, disp+3, NULL, 0);
k++;
}
break;
@@ -272,12 +272,11 @@ bool fig0_21(fig0_common_t& fig0, const display_settings_t &disp)
// iteration over Freq list
ifreq = (((uint32_t)f[k] << 8) | (uint32_t)f[k+1]) * 5;
if (ifreq != 0) {
- sprintf(desc, "%d KHz", ifreq);
+ r.msgs.emplace_back(2, strprintf("%d KHz", ifreq));
}
else {
- sprintf(desc, "Frequency not to be used (0)");
+ r.errors.emplace_back("Frequency not to be used (0)");
}
- printbuf(desc, disp+3, NULL, 0);
k += 2;
}
break;
@@ -288,24 +287,20 @@ bool fig0_21(fig0_common_t& fig0, const display_settings_t &disp)
Id_field2 = f[k];
ifreq = ((((uint32_t)f[k+1] & 0x7f) << 8) | (uint32_t)f[k+2]);
if (ifreq != 0) {
- sprintf(desc, "%d KHz", ifreq);
+ r.msgs.emplace_back(2, strprintf("%d KHz", ifreq));
}
else {
- sprintf(desc, "Frequency not to be used (0)");
+ r.errors.emplace_back("Frequency not to be used (0)");
}
if (RandM == 0x6) {
- sprintf(tmpbuf, ", DRM Service Id 0x%X", Id_field2);
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back(2, strprintf("DRM Service Id 0x%X", Id_field2));
}
else if (RandM == 0xe) {
- sprintf(tmpbuf, ", AMSS Service Id 0x%X", Id_field2);
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back(2, strprintf("AMSS Service Id 0x%X", Id_field2));
}
if ((f[k+1] & 0x80) == 0x80) {
- sprintf(tmpbuf, ", invalid Rfu b15 set to 1 instead of 0");
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back(2, strprintf("invalid Rfu b15 set to 1 instead of 0"));
}
- printbuf(desc, disp+3, NULL, 0);
k += 3;
}
break;
@@ -316,8 +311,12 @@ bool fig0_21(fig0_common_t& fig0, const display_settings_t &disp)
}
i += Length_FI_list;
}
+ else {
+ r.errors.push_back(strprintf("FIG0/21 FI Len error: expect %d + %d <= %d\n",
+ i , Length_FI_list, fig0.figlen));
+ }
}
- return complete;
+ return r;
}
diff --git a/src/fig0_22.cpp b/src/fig0_22.cpp
index c5e8c3f..ca9bb06 100644
--- a/src/fig0_22.cpp
+++ b/src/fig0_22.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -59,7 +59,7 @@ void fig0_22_cleardb()
// FIG 0/22 Transmitter Identification Information (TII) database
// ETSI EN 300 401 8.1.9
-bool fig0_22(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_22(fig0_common_t& fig0, const display_settings_t &disp)
{
Lat_Lng gps_pos = {0, 0};
double latitude_sub, longitude_sub;
@@ -68,39 +68,35 @@ bool fig0_22(fig0_common_t& fig0, const display_settings_t &disp)
int16_t Latitude_offset, Longitude_offset;
uint8_t i = 1, j, MainId = 0, Rfu, Nb_SubId_fields, SubId;
uint8_t Latitude_fine, Longitude_fine;
- char tmpbuf[256];
- char desc[256];
+ fig_result_t r;
bool MS;
const uint8_t Mode_Identity = get_mode_identity();
uint8_t* f = fig0.f;
- bool complete = false;
while (i < fig0.figlen) {
// iterate over Transmitter Identification Information (TII) fields
MS = f[i] >> 7;
MainId = f[i] & 0x7F;
- complete |= fig0_22_is_complete(MS, MainId);
+ r.complete |= fig0_22_is_complete(MS, MainId);
key = (fig0.oe() << 8) | (fig0.pd() << 7) | MainId;
- sprintf(desc, "M/S=%d %sidentifier, MainId=0x%X",
- MS, MS?"Sub-":"Main ", MainId);
+ r.msgs.push_back(strprintf("M/S=%d %sidentifier",
+ MS, MS?"Sub-":"Main "));
+ r.msgs.push_back(strprintf("MainId=0x%X", MainId));
// check MainId value
if ((Mode_Identity == 1) || (Mode_Identity == 2) || (Mode_Identity == 4)) {
if (MainId > 69) {
// The coding range shall be 0 to 69 for transmission modes I, II and IV
- sprintf(tmpbuf, " invalid value for transmission mode %d", Mode_Identity);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("invalid value for transmission mode %d", Mode_Identity));
}
}
else if (Mode_Identity == 3) {
if (MainId > 5) {
// The coding range shall be 0 to 5 for transmission modes I, II and IV
- sprintf(tmpbuf, " invalid value for transmission mode %d", Mode_Identity);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("invalid value for transmission mode %d", Mode_Identity));
}
}
// print database key
- sprintf(tmpbuf, ", database key=0x%X", key);
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("database key=0x%X", key));
i++;
if (MS == 0) {
// Main identifier
@@ -113,16 +109,14 @@ bool fig0_22(fig0_common_t& fig0, const display_settings_t &disp)
gps_pos.latitude = (double)((int32_t)((((int32_t)Latitude_coarse) << 4) | (uint32_t)Latitude_fine)) * 90 / 524288;
gps_pos.longitude = (double)((int32_t)((((int32_t)Longitude_coarse) << 4) | (uint32_t)Longitude_fine)) * 180 / 524288;
fig0_22_key_Lat_Lng[key] = gps_pos;
- sprintf(tmpbuf, ", Lat Lng coarse=0x%X 0x%X, Lat Lng fine=0x%X 0x%X => Lat Lng=%f, %f",
+ r.msgs.push_back(strprintf("Lat Lng coarse=0x%X 0x%X, Lat Lng fine=0x%X 0x%X => Lat Lng=%f, %f",
Latitude_coarse, Longitude_coarse, Latitude_fine, Longitude_fine,
- gps_pos.latitude, gps_pos.longitude);
- strcat(desc, tmpbuf);
+ gps_pos.latitude, gps_pos.longitude));
i += 5;
}
else {
- strcat(desc, ", invalid length of Latitude Longitude coarse fine");
+ r.errors.push_back("invalid length of Latitude Longitude coarse fine");
}
- printbuf(desc, disp+1, NULL, 0);
}
else { // MS == 1
// Sub-identifier
@@ -131,56 +125,49 @@ bool fig0_22(fig0_common_t& fig0, const display_settings_t &disp)
Rfu = f[i] >> 3;
Nb_SubId_fields = f[i] & 0x07;
if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=%d invalid value", Rfu);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfu=%d invalid value", Rfu));
}
- sprintf(tmpbuf, ", Number of SubId fields=%d%s",
- Nb_SubId_fields, (Nb_SubId_fields == 0)?", CEI":"");
- strcat(desc, tmpbuf);
- printbuf(desc, disp+1, NULL, 0);
+ r.msgs.push_back(strprintf("Number of SubId fields=%d%s",
+ Nb_SubId_fields, (Nb_SubId_fields == 0)?", CEI":""));
i++;
for(j = i; ((j < (i + (Nb_SubId_fields * 6))) && (j < (fig0.figlen - 5))); j += 6) {
// iterate over SubId fields
SubId = f[j] >> 3;
- sprintf(desc, "SubId=0x%X", SubId);
+ r.msgs.emplace_back(1, strprintf("SubId=0x%X", SubId));
// check SubId value
if ((SubId == 0) || (SubId > 23)) {
- strcat(desc, " invalid value");
+ r.errors.push_back("invalid value");
}
TD = ((f[j] & 0x03) << 8) | f[j+1];
Latitude_offset = (f[j+2] << 8) | f[j+3];
Longitude_offset = (f[j+4] << 8) | f[j+5];
- sprintf(tmpbuf, ", TD=%d us, Lat Lng offset=0x%X 0x%X",
- TD, Latitude_offset, Longitude_offset);
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back(1, strprintf("TD=%d us", TD));
+ r.msgs.emplace_back(1, strprintf("Lat Lng offset=0x%X 0x%X", Latitude_offset, Longitude_offset));
if (fig0_22_key_Lat_Lng.count(key) > 0) {
// latitude longitude available in database for Main Identifier
latitude_sub = (90 * (double)Latitude_offset / 524288) + fig0_22_key_Lat_Lng[key].latitude;
longitude_sub = (180 * (double)Longitude_offset / 524288) + fig0_22_key_Lat_Lng[key].longitude;
- sprintf(tmpbuf, " => Lat Lng=%f, %f", latitude_sub, longitude_sub);
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back(2, strprintf(" => Lat Lng=%f, %f", latitude_sub, longitude_sub));
}
else {
// latitude longitude not available in database for Main Identifier
latitude_sub = 90 * (double)Latitude_offset / 524288;
longitude_sub = 180 * (double)Longitude_offset / 524288;
- sprintf(tmpbuf, " => Lat Lng=%f, %f wrong value because Main identifier latitude/longitude not available in database", latitude_sub, longitude_sub);
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back(2, strprintf(" => Lat Lng=%f, %f wrong value because"
+ " Main identifier latitude/longitude not available in database", latitude_sub, longitude_sub));
}
- printbuf(desc, disp+2, NULL, 0);
}
i += (Nb_SubId_fields * 6);
}
else {
- strcat(desc, ", invalid fig length or Number of SubId fields length");
- printbuf(desc, disp+1, NULL, 0);
+ r.errors.emplace_back(strprintf("invalid fig length or Number of SubId fields length"));
}
}
}
- return complete;
+ return r;
}
diff --git a/src/fig0_24.cpp b/src/fig0_24.cpp
index d9d0284..24548e5 100644
--- a/src/fig0_24.cpp
+++ b/src/fig0_24.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -48,17 +48,15 @@ bool fig0_24_is_complete(int services_id)
// FIG 0/24 fig0.oe() Services
// ETSI EN 300 401 8.1.10.2
-bool fig0_24(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_24(fig0_common_t& fig0, const display_settings_t &disp)
{
uint64_t key;
uint32_t SId;
uint16_t EId;
uint8_t i = 1, j, Number_of_EIds, CAId;
- char tmpbuf[256];
- char desc[256];
+ fig_result_t r;
uint8_t* f = fig0.f;
bool Rfa;
- bool complete = false;
while (i < (fig0.figlen - (((uint8_t)fig0.pd() + 1) * 2))) {
// iterate over other ensembles services
@@ -71,39 +69,37 @@ bool fig0_24(fig0_common_t& fig0, const display_settings_t &disp)
((uint32_t)f[i+2] << 8) | (uint32_t)f[i+3];
i += 4;
}
- complete |= fig0_24_is_complete(SId);
+ r.complete |= fig0_24_is_complete(SId);
Rfa = (f[i] >> 7);
CAId = (f[i] >> 4);
Number_of_EIds = (f[i] & 0x0f);
key = ((uint64_t)fig0.oe() << 33) | ((uint64_t)fig0.pd() << 32) | \
(uint64_t)SId;
- if (fig0.pd() == 0) {
- sprintf(desc, "SId=0x%X, CAId=%d, Number of EId=%d, database key=%09" PRId64, SId, CAId, Number_of_EIds, key);
- }
- else { // fig0.pd() == 1
- sprintf(desc, "SId=0x%X, CAId=%d, Number of EId=%d, database key=%09" PRId64, SId, CAId, Number_of_EIds, key);
- }
+
+ r.msgs.push_back(strprintf("PD=%d", fig0.pd()));
+ r.msgs.push_back(strprintf("SId=0x%X", SId));
+ r.msgs.push_back(strprintf("CAId=%d", CAId));
+ r.msgs.push_back(strprintf("Number of EId=%d", Number_of_EIds));
+ r.msgs.push_back(strprintf("database key=%09" PRId64, key));
+
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=%d invalid value", Rfa));
}
+
// CEI Change Event Indication
if (Number_of_EIds == 0) {
- sprintf(tmpbuf, ", CEI");
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back("CEI");
}
- printbuf(desc, disp+1, NULL, 0);
i++;
- for(j = i; ((j < (i + (Number_of_EIds * 2))) && (j < fig0.figlen)); j += 2) {
+ for (j = i; ((j < (i + (Number_of_EIds * 2))) && (j < fig0.figlen)); j += 2) {
// iterate over EIds
EId = ((uint16_t)f[j] <<8) | (uint16_t)f[j+1];
- sprintf(desc, "EId 0x%04x", EId);
- printbuf(desc, disp+2, NULL, 0);
+ r.msgs.emplace_back(1, strprintf("EId 0x%04x", EId));
}
i += (Number_of_EIds * 2);
}
- return complete;
+ return r;
}
diff --git a/src/fig0_25.cpp b/src/fig0_25.cpp
index bd98f70..9aa64c0 100644
--- a/src/fig0_25.cpp
+++ b/src/fig0_25.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -49,64 +49,59 @@ bool fig0_25_is_complete(int services_id)
// FIG 0/25 fig0.oe() Announcement support
// ETSI EN 300 401 8.1.10.5.1
-bool fig0_25(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_25(fig0_common_t& fig0, const display_settings_t &disp)
{
uint32_t key;
uint16_t SId, Asu_flags, EId;
uint8_t i = 1, j, Rfu, Number_EIds;
- char tmpbuf[256];
- char desc[256];
+ fig_result_t r;
uint8_t* f = fig0.f;
- bool complete = false;
- while (i < (fig0.figlen - 4)) {
+ while (i < fig0.figlen - 4) {
// iterate over other ensembles announcement support
// SId, Asu flags, Rfu, Number of EIds
SId = ((uint16_t)f[i] << 8) | (uint16_t)f[i+1];
- complete |= fig0_25_is_complete(SId);
+ r.complete |= fig0_25_is_complete(SId);
Asu_flags = ((uint16_t)f[i+2] << 8) | (uint16_t)f[i+3];
Rfu = (f[i+4] >> 4);
Number_EIds = (f[i+4] & 0x0F);
- sprintf(desc, "SId=0x%X, Asu flags=0x%X", SId, Asu_flags);
+ r.msgs.push_back(strprintf("SId=0x%X", SId));
+ r.msgs.emplace_back(1, strprintf("Asu flags=0x%X", Asu_flags));
+ r.msgs.emplace_back(1, strprintf("Number of EIds=%d", Number_EIds));
+
if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=%d invalid value", Rfu);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfu=%d invalid value", Rfu));
}
- sprintf(tmpbuf, ", Number of EIds=%d", Number_EIds);
- strcat(desc, tmpbuf);
+
key = ((uint32_t)fig0.oe() << 17) | ((uint32_t)fig0.pd() << 16) | (uint32_t)SId;
- sprintf(tmpbuf, ", database key=0x%05x", key);
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back(1, strprintf("database key=0x%05x", key));
+
// CEI Change Event Indication
if (Number_EIds == 0) {
- sprintf(tmpbuf, ", CEI");
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back(1, "CEI");
}
- printbuf(desc, disp+1, NULL, 0);
i += 5;
- for(j = 0; (j < Number_EIds) && (i < (fig0.figlen - 1)); j++) {
+ for (j = 0; j < Number_EIds && i < fig0.figlen - 1; j++) {
// iterate over EIds
EId = ((uint16_t)f[i] << 8) | (uint16_t)f[i+1];
- sprintf(desc, "EId=0x%X", EId);
- printbuf(desc, disp+2, NULL, 0);
+ r.msgs.emplace_back(2, strprintf("EId=0x%X", EId));
i += 2;
}
+
if (j < Number_EIds) {
- sprintf(desc, "missing EId, fig length too short !");
- printbuf(desc, disp+1, NULL, 0);
- fprintf(stderr, "WARNING: FIG 0/%d length %d too short !\n", fig0.ext(), fig0.figlen);
+ r.errors.push_back("missing EId, fig length too short !");
}
// decode fig0.oe() announcement support types
- for(j = 0; j < 16; j++) {
+ for (j = 0; j < 16; j++) {
if (Asu_flags & (1 << j)) {
- sprintf(desc, "fig0.oe() Announcement support=%s", get_announcement_type(j));
- printbuf(desc, disp+2, NULL, 0);
+ r.msgs.emplace_back(2,
+ strprintf("fig0.oe() Announcement support=%s", get_announcement_type(j)));
}
}
}
- return complete;
+ return r;
}
diff --git a/src/fig0_26.cpp b/src/fig0_26.cpp
index 1ad85dc..332a900 100644
--- a/src/fig0_26.cpp
+++ b/src/fig0_26.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -49,31 +49,35 @@ bool fig0_26_is_complete(int cluster_id)
// FIG 0/26 fig0.oe() Announcement switching
// ETSI EN 300 401 8.1.10.5.2
-bool fig0_26(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_26(fig0_common_t& fig0, const display_settings_t &disp)
{
uint16_t Asw_flags, EId_Other_Ensemble;
uint8_t i = 1, j, Rfa, Cluster_Id_Current_Ensemble, Region_Id_Current_Ensemble;
uint8_t Cluster_Id_Other_Ensemble, Region_Id_Other_Ensemble;
bool New_flag, Region_flag;
- char tmpbuf[256];
- char desc[256];
+ fig_result_t r;
uint8_t* f = fig0.f;
- bool complete = false;
while (i < (fig0.figlen - 6)) {
// iterate over other ensembles announcement switching
Cluster_Id_Current_Ensemble = f[i];
- complete = fig0_26_is_complete(Cluster_Id_Current_Ensemble);
+ r.complete = fig0_26_is_complete(Cluster_Id_Current_Ensemble);
Asw_flags = ((uint16_t)f[i+1] << 8) | (uint16_t)f[i+2];
New_flag = f[i+3] >> 7;
Region_flag = (f[i+3] >> 6) & 0x01;
Region_Id_Current_Ensemble = f[i+3] & 0x3F;
EId_Other_Ensemble = ((uint16_t)f[i+4] << 8) | (uint16_t)f[i+5];
Cluster_Id_Other_Ensemble = f[i+6];
- sprintf(desc, "Cluster Id Current Ensemble=0x%X, Asw flags=0x%X, New flag=%d %s announcement, Region flag=%d last byte %s, Region Id Current Ensemble=0x%X, EId Other Ensemble=0x%X, Cluster Id Other Ensemble=0x%X",
- Cluster_Id_Current_Ensemble, Asw_flags, New_flag, New_flag?"newly introduced":"repeated",
- Region_flag, Region_flag?"present":"absent. The announcement concerns the whole service area",
- Region_Id_Current_Ensemble, EId_Other_Ensemble, Cluster_Id_Other_Ensemble);
+
+ r.msgs.push_back(strprintf("Cluster Id Current Ensemble=0x%X", Cluster_Id_Current_Ensemble));
+ r.msgs.emplace_back(1, strprintf("Asw flags=0x%X", Asw_flags));
+ r.msgs.emplace_back(1, strprintf("New flag=%d %s announcement", New_flag, New_flag?"newly introduced":"repeated"));
+ r.msgs.emplace_back(1, strprintf("Region flag=%d last byte %s",
+ Region_flag, Region_flag?"present":"absent. The announcement concerns the whole service area"));
+ r.msgs.emplace_back(1, strprintf("Region Id Current Ensemble=0x%X", Region_Id_Current_Ensemble));
+ r.msgs.emplace_back(1, strprintf("EId Other Ensemble=0x%X", EId_Other_Ensemble));
+ r.msgs.emplace_back(1, strprintf("Cluster Id Other Ensemble=0x%X", Cluster_Id_Other_Ensemble));
+
i += 7;
if (Region_flag != 0) {
if (i < fig0.figlen) {
@@ -81,29 +85,23 @@ bool fig0_26(fig0_common_t& fig0, const display_settings_t &disp)
Rfa = (f[i] >> 6);
Region_Id_Other_Ensemble = f[i] & 0x3F;
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=%d invalid value", Rfa));
}
- sprintf(tmpbuf, ", Region Id Other Ensemble=0x%X", Region_Id_Other_Ensemble);
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back(1, strprintf("Region Id Other Ensemble=0x%X", Region_Id_Other_Ensemble));
}
else {
- sprintf(tmpbuf, "missing Region Id Other Ensemble, fig length too short !");
- strcat(desc, tmpbuf);
- fprintf(stderr, "WARNING: FIG 0/%d length %d too short !\n", fig0.ext(), fig0.figlen);
+ r.errors.push_back("missing Region Id Other Ensemble, fig length too short !");
}
i++;
}
- printbuf(desc, disp+1, NULL, 0);
// decode announcement switching types
- for(j = 0; j < 16; j++) {
+ for (j = 0; j < 16; j++) {
if (Asw_flags & (1 << j)) {
- sprintf(desc, "Announcement switching=%s", get_announcement_type(j));
- printbuf(desc, disp+2, NULL, 0);
+ r.msgs.emplace_back(2, strprintf("Announcement switching=%s", get_announcement_type(j)));
}
}
}
- return complete;
+ return r;
}
diff --git a/src/fig0_27.cpp b/src/fig0_27.cpp
index dfe4468..2b37a85 100644
--- a/src/fig0_27.cpp
+++ b/src/fig0_27.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -49,56 +49,47 @@ bool fig0_27_is_complete(int services_id)
// FIG 0/27 FM Announcement support
// ETSI EN 300 401 8.1.11.2.1
-bool fig0_27(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_27(fig0_common_t& fig0, const display_settings_t &disp)
{
uint16_t SId, PI;
uint8_t i = 1, j, Rfu, Number_PI_codes, key;
- char tmpbuf[256];
- char desc[256];
+ fig_result_t r;
uint8_t* f = fig0.f;
- bool complete = false;
while (i < (fig0.figlen - 2)) {
// iterate over FM announcement support
SId = ((uint16_t)f[i] << 8) | (uint16_t)f[i+1];
- complete |= fig0_27_is_complete(SId);
+ r.complete |= fig0_27_is_complete(SId);
Rfu = f[i+2] >> 4;
Number_PI_codes = f[i+2] & 0x0F;
key = (fig0.oe() << 5) | (fig0.pd() << 4) | Number_PI_codes;
- sprintf(desc, "SId=0x%X", SId);
+ r.msgs.push_back(strprintf("SId=0x%X", SId));
if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=%d invalid value", Rfu);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfu=%d invalid value", Rfu));
}
- sprintf(tmpbuf, ", Number of PI codes=%d", Number_PI_codes);
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back(1, strprintf("Number of PI codes=%d", Number_PI_codes));
if (Number_PI_codes > 12) {
- strcat(desc, " above maximum value of 12");
- fprintf(stderr, "WARNING: FIG 0/%d Number of PI codes=%d > 12 (maximum value)\n", fig0.ext(), Number_PI_codes);
+ r.errors.push_back(strprintf("Number of PI codes=%d > 12 (maximum value)", Number_PI_codes));
}
- sprintf(tmpbuf, ", database key=0x%02X", key);
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back(1, strprintf("database key=0x%02X", key));
// CEI Change Event Indication
if (Number_PI_codes == 0) {
// The Change Event Indication (CEI) is signalled by the Number of PI codes field = 0
- strcat(desc, ", CEI");
+ r.msgs.emplace_back(1, "CEI");
}
- printbuf(desc, disp+1, NULL, 0);
i += 3;
- for(j = 0; (j < Number_PI_codes) && (i < (fig0.figlen - 1)); j++) {
+
+ for (j = 0; j < Number_PI_codes && i < fig0.figlen - 1; j++) {
// iterate over PI
PI = ((uint16_t)f[i] << 8) | (uint16_t)f[i+1];
- sprintf(desc, "PI=0x%X", PI);
- printbuf(desc, disp+2, NULL, 0);
+ r.msgs.emplace_back(2, strprintf("PI=0x%X", PI));
i += 2;
}
if (j != Number_PI_codes) {
- sprintf(desc, "fig length too short !");
- printbuf(desc, disp+2, NULL, 0);
- fprintf(stderr, "WARNING: FIG 0/%d length %d too short !\n", fig0.ext(), fig0.figlen);
+ r.errors.push_back("fig length too short !");
}
}
- return complete;
+ return r;
}
diff --git a/src/fig0_28.cpp b/src/fig0_28.cpp
index f0cbbdd..c729b03 100644
--- a/src/fig0_28.cpp
+++ b/src/fig0_28.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -49,42 +49,40 @@ bool fig0_28_is_complete(int cluster_id)
// FIG 0/28 FM Announcement switching
// ETSI EN 300 401 8.1.11.2.2
-bool fig0_28(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_28(fig0_common_t& fig0, const display_settings_t &disp)
{
uint16_t PI;
uint8_t i = 1, Cluster_Id_Current_Ensemble, Region_Id_Current_Ensemble;
bool New_flag, Rfa;
- char tmpbuf[256];
- char desc[256];
+ fig_result_t r;
uint8_t* f = fig0.f;
- bool complete = false;
- while (i < (fig0.figlen - 3)) {
+ while (i < fig0.figlen - 3) {
// iterate over FM announcement switching
Cluster_Id_Current_Ensemble = f[i];
- complete = fig0_28_is_complete(Cluster_Id_Current_Ensemble);
+ r.complete = fig0_28_is_complete(Cluster_Id_Current_Ensemble);
New_flag = f[i+1] >> 7;
Rfa = (f[i+1] >> 6) & 0x01;
Region_Id_Current_Ensemble = f[i+1] & 0x3F;
PI = ((uint16_t)f[i+2] << 8) | (uint16_t)f[i+3];
- sprintf(desc, "Cluster Id Current Ensemble=0x%X", Cluster_Id_Current_Ensemble);
+ r.msgs.push_back(strprintf("Cluster Id Current Ensemble=0x%X", Cluster_Id_Current_Ensemble));
+
if (Cluster_Id_Current_Ensemble == 0) {
- strcat(desc, " invalid value");
- fprintf(stderr, "WARNING: FIG 0/%d Cluster Id Current Ensemble invalid value 0\n", fig0.ext());
+ r.errors.push_back("Cluster Id Current Ensemble invalid value 0");
}
- sprintf(tmpbuf, ", New flag=%d %s announcement",
- New_flag, New_flag?"newly introduced":"repeated");
- strcat(desc, tmpbuf);
+
+ r.msgs.emplace_back(1, strprintf("New flag=%d %s announcement",
+ New_flag, New_flag?"newly introduced":"repeated"));
+
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=%d invalid value", Rfa));
}
- sprintf(tmpbuf, ", Region Id Current Ensemble=0x%X, PI=0x%X", Region_Id_Current_Ensemble, PI);
- strcat(desc, tmpbuf);
- printbuf(desc, disp+1, NULL, 0);
+
+ r.msgs.emplace_back(1, strprintf("Region Id Current Ensemble=0x%X", Region_Id_Current_Ensemble));
+ r.msgs.emplace_back(1, strprintf("PI=0x%X", PI));
i += 4;
}
- return complete;
+ return r;
}
diff --git a/src/fig0_3.cpp b/src/fig0_3.cpp
index 349b9e9..14e395f 100644
--- a/src/fig0_3.cpp
+++ b/src/fig0_3.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -48,21 +48,19 @@ bool fig0_3_is_complete(int components_id)
// FIG 0/3 Service component in packet mode with or without Conditional Access
// ETSI EN 300 401 6.3.2
-bool fig0_3(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_3(fig0_common_t& fig0, const display_settings_t &disp)
{
uint16_t SCId, Packet_address, CAOrg;
uint8_t i = 1, Rfa, DSCTy, SubChId, CAMode, SharedFlag;
- char tmpbuf[256];
- char desc[256];
+ fig_result_t r;
bool CAOrg_flag, DG_flag, Rfu;
- bool complete = false;
uint8_t* f = fig0.f;
- while (i < (fig0.figlen - 4)) {
+ while (i < fig0.figlen - 4) {
// iterate over service component in packet mode
SCId = ((uint16_t)f[i] << 4) | ((uint16_t)(f[i+1] >> 4) & 0x0F);
- complete |= fig0_3_is_complete(SCId);
+ r.complete |= fig0_3_is_complete(SCId);
Rfa = (f[i+1] >> 1) & 0x07;
CAOrg_flag = f[i+1] & 0x01;
DG_flag = (f[i+2] >> 7) & 0x01;
@@ -70,41 +68,38 @@ bool fig0_3(fig0_common_t& fig0, const display_settings_t &disp)
DSCTy = f[i+2] & 0x3F;
SubChId = (f[i+3] >> 2);
Packet_address = ((uint16_t)(f[i+3] & 0x03) << 8) | ((uint16_t)f[i+4]);
- sprintf(desc,
- "SCId=0x%X, CAOrg flag=%d CAOrg field %s, DG flag=%d"
- " data groups are %sused to transport the service component,"
- " DSCTy=%d %s, SubChId=0x%X, Packet address=0x%X",
- SCId, CAOrg_flag, CAOrg_flag?"present":"absent", DG_flag,
- DG_flag ? "not ": "",
- DSCTy, get_dscty_type(DSCTy), SubChId,
- Packet_address);
+ r.msgs.push_back(strprintf("SCId=0x%X", SCId));
+ r.msgs.push_back(strprintf("CAOrg flag=%d CAOrg field %s", CAOrg_flag, CAOrg_flag?"present":"absent"));
+ r.msgs.push_back(strprintf("DG flag=%d", DG_flag));
+ r.msgs.push_back(strprintf("data groups are %sused to transport the service component", DG_flag ? "not ": ""));
+ r.msgs.push_back(strprintf("DSCTy=%d %s", DSCTy, get_dscty_type(DSCTy)));
+ r.msgs.push_back(strprintf("SubChId=0x%X", SubChId));
+ r.msgs.push_back(strprintf("Packet address=0x%X", Packet_address));
+
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=%d invalid value", Rfa));
}
+
if (Rfu != 0) {
- sprintf(tmpbuf, ", Rfu=%d invalid value", Rfu);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfu=%d invalid value", Rfu));
}
+
i += 5;
if (CAOrg_flag) {
- if (i < (fig0.figlen - 1)) {
+ if (i < fig0.figlen - 1) {
CAOrg = ((uint16_t)f[i] << 8) | ((uint16_t)f[i+1]);
CAMode = (f[i] >> 5);
SharedFlag = f[i+1];
- sprintf(tmpbuf, ", CAOrg=0x%X CAMode=%d \"%s\" SharedFlag=0x%X%s",
- CAOrg, CAMode, get_ca_mode(CAMode), SharedFlag, (SharedFlag == 0) ? " invalid" : "");
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("CAOrg=0x%X CAMode=%d \"%s\" SharedFlag=0x%X%s",
+ CAOrg, CAMode, get_ca_mode(CAMode), SharedFlag, (SharedFlag == 0) ? " invalid" : ""));
}
else {
- sprintf(tmpbuf, ", invalid figlen");
- strcat(desc, tmpbuf);
+ r.errors.push_back("Invalid figlen");
}
i += 2;
}
- printbuf(desc, disp+1, NULL, 0);
}
- return complete;
+ return r;
}
diff --git a/src/fig0_31.cpp b/src/fig0_31.cpp
index 6d0a68c..46e5809 100644
--- a/src/fig0_31.cpp
+++ b/src/fig0_31.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -48,13 +48,12 @@ bool fig0_31_is_complete(uint64_t figtype_flags)
// FIG 0/31 FIC re-direction
// ETSI EN 300 401 8.1.12
-bool fig0_31(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_31(fig0_common_t& fig0, const display_settings_t &disp)
{
uint32_t FIG_type0_flag_field = 0, flag_field;
uint8_t i = 1, j, FIG_type1_flag_field = 0, FIG_type2_flag_field = 0;
- char desc[256];
+ fig_result_t r;
uint8_t* f = fig0.f;
- bool complete = false;
if (i < (fig0.figlen - 5)) {
// Read FIC re-direction
@@ -64,11 +63,11 @@ bool fig0_31(fig0_common_t& fig0, const display_settings_t &disp)
FIG_type2_flag_field = f[i+5];
uint64_t key = ((uint64_t)FIG_type1_flag_field << 32) | ((uint64_t)FIG_type2_flag_field << 40) | FIG_type0_flag_field;
- complete |= fig0_31_is_complete(key);
+ r.complete |= fig0_31_is_complete(key);
- sprintf(desc, "FIG type 0 flag field=0x%X, FIG type 1 flag field=0x%X, FIG type 2 flag field=0x%X",
- FIG_type0_flag_field, FIG_type1_flag_field, FIG_type2_flag_field);
- printbuf(desc, disp+1, NULL, 0);
+ r.msgs.push_back(strprintf("FIG type 0 flag field=0x%X", FIG_type0_flag_field));
+ r.msgs.push_back(strprintf("FIG type 1 flag field=0x%X", FIG_type1_flag_field));
+ r.msgs.push_back(strprintf("FIG type 2 flag field=0x%X", FIG_type2_flag_field));
for(j = 0; j < 32; j++) {
// iterate over FIG type 0 re-direction
@@ -76,23 +75,19 @@ bool fig0_31(fig0_common_t& fig0, const display_settings_t &disp)
if ((flag_field != 0) && ((j <= 5) || (j == 8) ||
(j == 10) || (j == 13) || (j == 14) ||
(j == 19) || (j == 26) || (j == 28))) {
- sprintf(desc, "fig0.oe()=%d FIG 0/%d carried in AIC, invalid configuration, shall always be carried entirely in the FIC",
- fig0.oe(), j);
- printbuf(desc, disp+2, NULL, 0);
- fprintf(stderr, "WARNING: FIG 0/%d FIG re-direction of fig0.oe()=%d FIG0/%d not allowed\n", fig0.ext(), fig0.oe(), j);
+ r.errors.push_back(strprintf("fig0.oe()=%d FIG 0/%d carried in AIC, invalid configuration, shall always be carried entirely in the FIC",
+ fig0.oe(), j));
}
else if ((flag_field != 0) && ((j == 21) || (j == 24))) {
- sprintf(desc, "fig0.oe()=%d FIG 0/%d carried in AIC, same shall be carried in FIC", fig0.oe(), j);
- printbuf(desc, disp+2, NULL, 0);
+ r.msgs.emplace_back(1, strprintf("fig0.oe()=%d FIG 0/%d carried in AIC, same shall be carried in FIC", fig0.oe(), j));
}
else if (flag_field != 0) {
if (fig0.oe() == 0) {
- sprintf(desc, "fig0.oe()=%d FIG 0/%d carried in AIC, same shall be carried in FIC", fig0.oe(), j);
+ r.msgs.emplace_back(1, strprintf("fig0.oe()=%d FIG 0/%d carried in AIC, same shall be carried in FIC", fig0.oe(), j));
}
else { // fig0.oe() == 1
- sprintf(desc, "fig0.oe()=%d FIG 0/%d carried in AIC, may be carried entirely in AIC", fig0.oe(), j);
+ r.msgs.emplace_back(1, strprintf("fig0.oe()=%d FIG 0/%d carried in AIC, may be carried entirely in AIC", fig0.oe(), j));
}
- printbuf(desc, disp+2, NULL, 0);
}
}
@@ -101,12 +96,11 @@ bool fig0_31(fig0_common_t& fig0, const display_settings_t &disp)
flag_field = FIG_type1_flag_field & ((uint32_t)1 << j);
if (flag_field != 0) {
if (fig0.oe() == 0) {
- sprintf(desc, "fig0.oe()=%d FIG 1/%d carried in AIC, same shall be carried in FIC", fig0.oe(), j);
+ r.msgs.emplace_back(1, strprintf("fig0.oe()=%d FIG 1/%d carried in AIC, same shall be carried in FIC", fig0.oe(), j));
}
else { // fig0.oe() == 1
- sprintf(desc, "fig0.oe()=%d FIG 1/%d carried in AIC, may be carried entirely in AIC", fig0.oe(), j);
+ r.msgs.emplace_back(1, strprintf("fig0.oe()=%d FIG 1/%d carried in AIC, may be carried entirely in AIC", fig0.oe(), j));
}
- printbuf(desc, disp+2, NULL, 0);
}
}
@@ -115,19 +109,18 @@ bool fig0_31(fig0_common_t& fig0, const display_settings_t &disp)
flag_field = FIG_type2_flag_field & ((uint32_t)1 << j);
if (flag_field != 0) {
if (fig0.oe() == 0) {
- sprintf(desc, "fig0.oe()=%d FIG 2/%d carried in AIC, same shall be carried in FIC", fig0.oe(), j);
+ r.msgs.emplace_back(1, strprintf("fig0.oe()=%d FIG 2/%d carried in AIC, same shall be carried in FIC", fig0.oe(), j));
}
else { // fig0.oe() == 1
- sprintf(desc, "fig0.oe()=%d FIG 2/%d carried in AIC, may be carried entirely in AIC", fig0.oe(), j);
+ r.msgs.emplace_back(1, strprintf("fig0.oe()=%d FIG 2/%d carried in AIC, may be carried entirely in AIC", fig0.oe(), j));
}
- printbuf(desc, disp+2, NULL, 0);
}
}
}
if (fig0.figlen != 7) {
- fprintf(stderr, "WARNING: FIG 0/%d invalid length %d, expecting 7\n", fig0.ext(), fig0.figlen);
+ r.errors.push_back(strprintf("invalid length %d, expecting 7", fig0.figlen));
}
- return complete;
+ return r;
}
diff --git a/src/fig0_5.cpp b/src/fig0_5.cpp
index d70cca1..485c479 100644
--- a/src/fig0_5.cpp
+++ b/src/fig0_5.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -48,67 +48,64 @@ bool fig0_5_is_complete(int components_id)
// FIG 0/5 Service component language
// ETSI EN 300 401 8.1.2
-bool fig0_5(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_5(fig0_common_t& fig0, const display_settings_t &disp)
{
uint16_t SCId;
uint8_t i = 1, SubChId, FIDCId, Language, Rfa;
- char tmpbuf[256];
- char desc[256];
+ fig_result_t r;
bool LS_flag, MSC_FIC_flag;
- bool complete = false;
uint8_t* f = fig0.f;
- while (i < (fig0.figlen - 1)) {
+ while (i < fig0.figlen - 1) {
// iterate over service component language
LS_flag = f[i] >> 7;
if (LS_flag == 0) {
// Short form (L/S = 0)
MSC_FIC_flag = (f[i] >> 6) & 0x01;
Language = f[i+1];
+ r.msgs.emplace_back("Short form");
+ r.msgs.push_back(strprintf("MSC/FIC flag=%d MSC", MSC_FIC_flag));
+
if (MSC_FIC_flag == 0) {
// 0: MSC in Stream mode and SubChId identifies the sub-channel
SubChId = f[i] & 0x3F;
- sprintf(desc, "L/S flag=%d short form, MSC/FIC flag=%d MSC, SubChId=0x%X, Language=0x%X %s",
- LS_flag, MSC_FIC_flag, SubChId, Language,
- get_language_name(Language));
+ r.msgs.push_back(strprintf("SubChId=0x%X", SubChId));
}
else {
// 1: FIC and FIDCId identifies the component
FIDCId = f[i] & 0x3F;
- sprintf(desc, "L/S flag=%d short form, MSC/FIC flag=%d FIC, FIDCId=0x%X, Language=0x%X %s",
- LS_flag, MSC_FIC_flag, FIDCId, Language,
- get_language_name(Language));
+ r.msgs.push_back(strprintf("FIDCId=0x%X", FIDCId));
}
+ r.msgs.push_back(strprintf("Language=0x%X %s",
+ Language, get_language_name(Language)));
int key = (MSC_FIC_flag << 7) | (f[i] % 0x3F);
- complete |= fig0_5_is_complete(key);
- printbuf(desc, disp+1, NULL, 0);
+ r.complete |= fig0_5_is_complete(key);
i += 2;
}
else {
// Long form (L/S = 1)
if (i < (fig0.figlen - 2)) {
+ r.msgs.emplace_back("Long form");
Rfa = (f[i] >> 4) & 0x07;
+
SCId = (((uint16_t)f[i] & 0x0F) << 8) | (uint16_t)f[i+1];
int key = (LS_flag << 15) | SCId;
- complete |= fig0_5_is_complete(key);
+ r.complete |= fig0_5_is_complete(key);
Language = f[i+2];
- sprintf(desc, "L/S flag=%d long form", LS_flag);
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=%d invalid value", Rfa));
}
- sprintf(tmpbuf, ", SCId=0x%X, Language=0x%X %s",
- SCId, Language,
- get_language_name(Language));
- strcat(desc, tmpbuf);
- printbuf(desc, disp+1, NULL, 0);
+
+ r.msgs.push_back(strprintf("SCId=0x%X", SCId));
+ r.msgs.push_back(strprintf("Language=0x%X %s",
+ Language, get_language_name(Language)));
}
i += 3;
}
}
- return complete;
+ return r;
}
diff --git a/src/fig0_6.cpp b/src/fig0_6.cpp
index 921e36d..a906b17 100644
--- a/src/fig0_6.cpp
+++ b/src/fig0_6.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -56,15 +56,13 @@ void fig0_6_cleardb()
// FIG 0/6 Service linking information
// ETSI EN 300 401 8.1.15
-bool fig0_6(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_6(fig0_common_t& fig0, const display_settings_t &disp)
{
uint32_t j;
uint16_t LSN, key;
uint8_t i = 1, Number_of_Ids, IdLQ;
- char signal_link[256];
- char desc[256];
+ fig_result_t r;
bool Id_list_flag, LA, SH, ILS, Shd;
- bool complete = false;
uint8_t* f = fig0.f;
@@ -76,30 +74,30 @@ bool fig0_6(fig0_common_t& fig0, const display_settings_t &disp)
ILS = (f[i] >> 4) & 0x01;
LSN = ((f[i] & 0x0F) << 8) | f[i+1];
key = (fig0.oe() << 15) | (fig0.pd() << 14) | (SH << 13) | (ILS << 12) | LSN;
- complete |= fig0_6_is_complete(key);
- strcpy(signal_link, "");
+ r.complete |= fig0_6_is_complete(key);
+
+ r.msgs.push_back(strprintf("Id list flag=%d", Id_list_flag));
+ r.msgs.push_back(strprintf("LA=%d %s", LA, LA ? "active" : "inactive"));
+ r.msgs.push_back(strprintf("S/H=%d %s", SH, SH ? "Hard" : "Soft"));
+ r.msgs.push_back(strprintf("ILS=%d %s", ILS, ILS ? "international" : "national"));
+ r.msgs.push_back(strprintf("LSN=%d", LSN));
+ r.msgs.push_back(strprintf("database key=0x%04x", key));
+
// check activation / deactivation
if ((fig0_6_key_la.count(key) > 0) && (fig0_6_key_la[key] != LA)) {
if (LA == 0) {
- strcat(signal_link, " deactivated");
+ r.msgs.emplace_back("deactivated");
}
else {
- strcat(signal_link, " activated");
+ r.msgs.emplace_back("activated");
}
}
fig0_6_key_la[key] = LA;
i += 2;
if (Id_list_flag == 0) {
if (fig0.cn() == 0) { // Id_list_flag=0 && fig0.cn()=0: CEI Change Event Indication
- strcat(signal_link, " CEI");
+ r.msgs.emplace_back("CEI");
}
- sprintf(desc, "Id list flag=%d, LA=%d %s, S/H=%d %s, ILS=%d %s, LSN=%d, database key=0x%04x%s",
- Id_list_flag,
- LA, LA ? "active" : "inactive",
- SH, SH ? "Hard" : "Soft",
- ILS, ILS ? "international" : "national",
- LSN, key, signal_link);
- printbuf(desc, disp+1, NULL, 0);
}
else { // Id_list_flag == 1
if (i < fig0.figlen) {
@@ -107,43 +105,36 @@ bool fig0_6(fig0_common_t& fig0, const display_settings_t &disp)
if (fig0.pd() == 0) {
IdLQ = (f[i] >> 5) & 0x03;
Shd = (f[i] >> 4) & 0x01;
- sprintf(desc, "Id list flag=%d, LA=%d %s, S/H=%d %s, ILS=%d %s, LSN=%d, "
- "database key=0x%04x, IdLQ=%d, Shd=%d %s, Number of Ids=%d%s",
- Id_list_flag,
- LA, (LA)?"active":"inactive",
- SH, (SH)?"Hard":"Soft",
- ILS, (ILS)?"international":"national",
- LSN, key, IdLQ,
- Shd, (Shd)?"b11-8 in 4-F are different services":"single service",
- Number_of_Ids, signal_link);
- printbuf(desc, disp+1, NULL, 0);
+ r.msgs.push_back(strprintf("IdLQ=%d", IdLQ));
+ r.msgs.push_back(strprintf("Shd=%d %s", Shd, (Shd)?"b11-8 in 4-F are different services":"single service"));
+ r.msgs.push_back(strprintf("Number of Ids=%d%s", Number_of_Ids));
+
if (ILS == 0) {
// read Id list
for(j = 0; ((j < Number_of_Ids) && ((i+2+(j*2)) < fig0.figlen)); j++) {
// ETSI EN 300 401 8.1.15. Some changes were introducted in spec V2
if (((j == 0) && (fig0.oe() == 0) && (fig0.cn() == 0)) ||
(IdLQ == 0)) {
- sprintf(desc, "DAB SId 0x%X",
- ((f[i+1+(j*2)] << 8) | f[i+2+(j*2)]));
+ r.msgs.emplace_back(1, strprintf("DAB SId 0x%X",
+ ((f[i+1+(j*2)] << 8) | f[i+2+(j*2)])));
}
else if (IdLQ == 1) {
- sprintf(desc, "RDS PI 0x%X",
- ((f[i+1+(j*2)] << 8) | f[i+2+(j*2)]));
+ r.msgs.emplace_back(1, strprintf("RDS PI 0x%X",
+ ((f[i+1+(j*2)] << 8) | f[i+2+(j*2)])));
}
else if (IdLQ == 2) {
- sprintf(desc, "(AM-FM legacy) 0x%X",
- ((f[i+1+(j*2)] << 8) | f[i+2+(j*2)]));
+ r.msgs.emplace_back(1, strprintf("(AM-FM legacy) 0x%X",
+ ((f[i+1+(j*2)] << 8) | f[i+2+(j*2)])));
}
else { // IdLQ == 3
- sprintf(desc, "DRM-AMSS service 0x%X",
- ((f[i+1+(j*2)] << 8) | f[i+2+(j*2)]));
+ r.msgs.emplace_back(1, strprintf("DRM-AMSS service 0x%X",
+ ((f[i+1+(j*2)] << 8) | f[i+2+(j*2)])));
}
- printbuf(desc, disp+2, NULL, 0);
}
+
// check deadlink
if ((Number_of_Ids == 0) && (IdLQ == 1)) {
- sprintf(desc, "deadlink");
- printbuf(desc, disp+2, NULL, 0);
+ r.errors.push_back("deadlink");
}
i += (Number_of_Ids * 2) + 1;
}
@@ -152,37 +143,36 @@ bool fig0_6(fig0_common_t& fig0, const display_settings_t &disp)
for(j = 0; ((j < Number_of_Ids) && ((i+3+(j*3)) < fig0.figlen)); j++) {
if (((j == 0) && (fig0.oe() == 0) && (fig0.cn() == 0)) ||
(IdLQ == 0)) {
- sprintf(desc, "DAB SId ecc 0x%02X Id 0x%04X", f[i+1+(j*3)], ((f[i+2+(j*3)] << 8) | f[i+3+(j*3)]));
+ r.msgs.emplace_back(1, strprintf("DAB SId ecc 0x%02X Id 0x%04X",
+ f[i+1+(j*3)], ((f[i+2+(j*3)] << 8) | f[i+3+(j*3)])));
}
else if (IdLQ == 1) {
- sprintf(desc, "RDS PI ecc 0x%02X Id 0x%04X", f[i+1+(j*3)], ((f[i+2+(j*3)] << 8) | f[i+3+(j*3)]));
+ r.msgs.emplace_back(1, strprintf("RDS PI ecc 0x%02X Id 0x%04X",
+ f[i+1+(j*3)], ((f[i+2+(j*3)] << 8) | f[i+3+(j*3)])));
}
else if (IdLQ == 2) {
- sprintf(desc, "(AM-FM legacy) ecc 0x%02X Id 0x%04X", f[i+1+(j*3)], ((f[i+2+(j*3)] << 8) | f[i+3+(j*3)]));
+ r.msgs.emplace_back(1, strprintf("(AM-FM legacy) ecc 0x%02X Id 0x%04X",
+ f[i+1+(j*3)], ((f[i+2+(j*3)] << 8) | f[i+3+(j*3)])));
}
else { // IdLQ == 3
- sprintf(desc, "DRM/AMSS service ecc 0x%02X Id 0x%04X", f[i+1+(j*3)], ((f[i+2+(j*3)] << 8) | f[i+3+(j*3)]));
+ r.msgs.emplace_back(1, strprintf("DRM/AMSS service ecc 0x%02X Id 0x%04X",
+ f[i+1+(j*3)], ((f[i+2+(j*3)] << 8) | f[i+3+(j*3)])));
}
- printbuf(desc, disp+2, NULL, 0);
}
// check deadlink
if ((Number_of_Ids == 0) && (IdLQ == 1)) {
- sprintf(desc, "deadlink");
- printbuf(desc, disp+2, NULL, 0);
+ r.errors.push_back("deadlink");
}
i += (Number_of_Ids * 3) + 1;
}
}
else { // fig0.pd() == 1
- sprintf(desc, "Id list flag=%d, LA=%d %s, S/H=%d %s, ILS=%d %s, LSN=%d, database key=0x%04x, Number of Ids=%d%s",
- Id_list_flag, LA, (LA)?"active":"inactive", SH, (SH)?"Hard":"Soft", ILS, (ILS)?"international":"national", LSN, key, Number_of_Ids, signal_link);
- printbuf(desc, disp+1, NULL, 0);
+ r.msgs.push_back(strprintf("Number of Ids=%d%s", Number_of_Ids));
if (Number_of_Ids > 0) {
// read Id list
for(j = 0; ((j < Number_of_Ids) && ((i+4+(j*4)) < fig0.figlen)); j++) {
- sprintf(desc, "SId 0x%X",
- ((f[i+1+(j*4)] << 24) | (f[i+2+(j*4)] << 16) | (f[i+3+(j*4)] << 8) | f[i+4+(j*4)]));
- printbuf(desc, disp+2, NULL, 0);
+ r.msgs.emplace_back(1, strprintf("SId 0x%X",
+ ((f[i+1+(j*4)] << 24) | (f[i+2+(j*4)] << 16) | (f[i+3+(j*4)] << 8) | f[i+4+(j*4)])));
}
}
i += (Number_of_Ids * 4) + 1;
@@ -191,6 +181,6 @@ bool fig0_6(fig0_common_t& fig0, const display_settings_t &disp)
}
}
- return complete;
+ return r;
}
diff --git a/src/fig0_8.cpp b/src/fig0_8.cpp
index eb157de..c283a52 100644
--- a/src/fig0_8.cpp
+++ b/src/fig0_8.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -57,16 +57,14 @@ bool fig0_8_is_complete(SId_t SId, SCIdS_t SCIdS)
// FIG 0/8 Service component global definition
// ETSI EN 300 401 6.3.5
-bool fig0_8(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_8(fig0_common_t& fig0, const display_settings_t &disp)
{
uint32_t SId;
uint16_t SCId;
uint8_t i = 1, Rfa, SCIdS, SubChId, FIDCId;
- char tmpbuf[256];
- char desc[256];
+ fig_result_t r;
bool Ext_flag, LS_flag, MSC_FIC_flag;
uint8_t* f = fig0.f;
- bool complete = false;
while (i < (fig0.figlen - (2 + (2 * fig0.pd())))) {
// iterate over service component global definition
@@ -84,19 +82,19 @@ bool fig0_8(fig0_common_t& fig0, const display_settings_t &disp)
Ext_flag = f[i] >> 7;
Rfa = (f[i] >> 4) & 0x7;
SCIdS = f[i] & 0x0F;
- complete |= fig0_8_is_complete(SId, SCIdS);
- sprintf(desc, "SId=0x%X, Ext flag=%d 8-bit Rfa %s", SId, Ext_flag, (Ext_flag)?"present":"absent");
+ r.complete |= fig0_8_is_complete(SId, SCIdS);
+ r.msgs.push_back(strprintf("SId=0x%X", SId));
+ r.msgs.push_back(strprintf("Ext flag=%d 8-bit Rfa %s",
+ Ext_flag, (Ext_flag)?"present":"absent"));
+
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=%d invalid value", Rfa));
}
- sprintf(tmpbuf, ", SCIdS=0x%X", SCIdS);
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("SCIdS=0x%X", SCIdS));
i++;
if (i < fig0.figlen) {
LS_flag = f[i] >> 7;
- sprintf(tmpbuf, ", L/S flag=%d %s", LS_flag, (LS_flag)?"Long form":"Short form");
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("L/S flag=%d %s", LS_flag, (LS_flag)?"Long form":"Short form"));
if (LS_flag == 0) {
// Short form
if (i < (fig0.figlen - Ext_flag)) {
@@ -104,21 +102,18 @@ bool fig0_8(fig0_common_t& fig0, const display_settings_t &disp)
if (MSC_FIC_flag == 0) {
// MSC in stream mode and SubChId identifies the sub-channel
SubChId = f[i] & 0x3F;
- sprintf(tmpbuf, ", MSC/FIC flag=%d MSC, SubChId=0x%X", MSC_FIC_flag, SubChId);
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("MSC/FIC flag=%d MSC, SubChId=0x%X", MSC_FIC_flag, SubChId));
}
else {
// FIC and FIDCId identifies the component
FIDCId = f[i] & 0x3F;
- sprintf(tmpbuf, ", MSC/FIC flag=%d FIC, FIDCId=0x%X", MSC_FIC_flag, FIDCId);
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("MSC/FIC flag=%d FIC, FIDCId=0x%X", MSC_FIC_flag, FIDCId));
}
if (Ext_flag == 1) {
// Rfa field present
Rfa = f[i+1];
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=0x%X invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=0x%X invalid value", Rfa));
}
}
}
@@ -130,18 +125,15 @@ bool fig0_8(fig0_common_t& fig0, const display_settings_t &disp)
Rfa = (f[i] >> 4) & 0x07;
SCId = (((uint16_t)f[i] & 0x0F) << 8) | (uint16_t)f[i+1];
if (Rfa != 0) {
- sprintf(tmpbuf, ", Rfa=%d invalid value", Rfa);
- strcat(desc, tmpbuf);
+ r.errors.push_back(strprintf("Rfa=%d invalid value", Rfa));
}
- sprintf(tmpbuf, ", SCId=0x%X", SCId);
- strcat(desc, tmpbuf);
+ r.msgs.push_back(strprintf("SCId=0x%X", SCId));
}
i += 2;
}
}
- printbuf(desc, disp+1, NULL, 0);
}
- return complete;
+ return r;
}
diff --git a/src/fig0_9.cpp b/src/fig0_9.cpp
index 6e642ee..7c41bdf 100644
--- a/src/fig0_9.cpp
+++ b/src/fig0_9.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -29,21 +29,17 @@
#include <cstring>
#include <map>
-// fig 0/9 global variables
-uint8_t Ensemble_ECC=0;
-int8_t Ensemble_LTO=0;
-bool LTO_uniq;
-
// FIG 0/9 Country, LTO and International table
// ETSI EN 300 401 8.1.3.2
-bool fig0_9(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_9(fig0_common_t& fig0, const display_settings_t &disp)
{
uint32_t SId;
+ uint8_t Ensemble_ECC=0;
uint8_t i = 1, j, key, Number_of_services, ECC;
int8_t LTO;
- char tmpbuf[256];
- char desc[256];
+ bool LTO_uniq;
+ fig_result_t r;
bool Ext_flag;
uint8_t* f = fig0.f;
@@ -52,26 +48,30 @@ bool fig0_9(fig0_common_t& fig0, const display_settings_t &disp)
key = ((uint8_t)fig0.oe() << 1) | (uint8_t)fig0.pd();
Ext_flag = f[i] >> 7;
LTO_uniq = (f[i]>> 6) & 0x01;
- Ensemble_LTO = f[i] & 0x3F;
+ int8_t Ensemble_LTO = f[i] & 0x3F;
if (Ensemble_LTO & 0x20) {
// negative Ensemble LTO
Ensemble_LTO |= 0xC0;
}
- sprintf(desc, "Ext flag=%d extended field %s, LTO uniq=%d %s, Ensemble LTO=0x%X %s%d:%02d",
- Ext_flag, Ext_flag?"present":"absent", LTO_uniq,
- LTO_uniq?"several time zones":"one time zone (time specified by Ensemble LTO)",
- (Ensemble_LTO & 0x3F), (Ensemble_LTO >= 0)?"":"-" , abs(Ensemble_LTO) >> 1, (Ensemble_LTO & 0x01) * 30);
+ r.msgs.push_back(strprintf("Ext flag=%d extended field %s",
+ Ext_flag, Ext_flag?"present":"absent"));
+ r.msgs.push_back(strprintf("LTO uniq=%d %s",
+ LTO_uniq,
+ LTO_uniq?"several time zones":"one time zone (time specified by Ensemble LTO)"));
+ r.msgs.push_back(strprintf("Ensemble LTO=0x%X %s%d:%02d",
+ (Ensemble_LTO & 0x3F), (Ensemble_LTO >= 0)?"":"-" , abs(Ensemble_LTO) >> 1, (Ensemble_LTO & 0x01) * 30));
+
if (abs(Ensemble_LTO) > 24) {
- sprintf(tmpbuf, " out of range -12 hours to +12 hours");
- strcat(desc, tmpbuf);
+ r.errors.push_back("LTO out of range -12 hours to +12 hours");
}
+
Ensemble_ECC = f[i+1];
uint8_t International_Table_Id = f[i+2];
set_international_table(International_Table_Id);
- sprintf(tmpbuf, ", Ensemble ECC=0x%X, International Table Id=0x%X, database key=0x%x",
- Ensemble_ECC, International_Table_Id, key);
- strcat(desc, tmpbuf);
- printbuf(desc, disp+1, NULL, 0);
+ r.msgs.push_back(strprintf("Ensemble ECC=0x%X", Ensemble_ECC));
+ r.msgs.push_back(strprintf("International Table Id=0x%X", International_Table_Id));
+ r.msgs.push_back(strprintf("database key=0x%x", key));
+
i += 3;
if (Ext_flag == 1) {
// extended field present
@@ -83,44 +83,40 @@ bool fig0_9(fig0_common_t& fig0, const display_settings_t &disp)
// negative LTO
LTO |= 0xC0;
}
- sprintf(desc, "Number of services=%d, LTO=0x%X %s%d:%02d",
- Number_of_services, (LTO & 0x3F), (LTO >= 0)?"":"-" , abs(LTO) >> 1, (LTO & 0x01) * 30);
+ r.msgs.push_back(strprintf("Number of services=%d", Number_of_services));
+ r.msgs.push_back(strprintf("LTO=0x%X %s%d:%02d",
+ (LTO & 0x3F), (LTO >= 0)?"":"-" , abs(LTO) >> 1, (LTO & 0x01) * 30));
if (abs(LTO) > 24) {
- sprintf(tmpbuf, " out of range -12 hours to +12 hours");
- strcat(desc, tmpbuf);
+ r.errors.push_back("LTO in extended field out of range -12 hours to +12 hours");
}
+
// CEI Change Event Indication
if ((Number_of_services == 0) && (LTO == 0) /* && (Ext_flag == 1) */) {
- sprintf(tmpbuf, ", CEI");
- strcat(desc, tmpbuf);
+ r.msgs.emplace_back("CEI");
}
i++;
+
if (fig0.pd() == 0) {
// Programme services, 16 bit SId
if (i < fig0.figlen) {
ECC = f[i];
- sprintf(tmpbuf, ", ECC=0x%X", ECC);
- strcat(desc, tmpbuf);
- printbuf(desc, disp+2, NULL, 0);
+ r.msgs.emplace_back(1, strprintf("ECC=0x%X", ECC));
i++;
for(j = i; ((j < (i + (Number_of_services * 2))) && (j < fig0.figlen)); j += 2) {
// iterate over SId
SId = ((uint32_t)f[j] << 8) | (uint32_t)f[j+1];
- sprintf(desc, "SId 0x%X", SId);
- printbuf(desc, disp+3, NULL, 0);
+ r.msgs.emplace_back(2, strprintf("SId 0x%X", SId));
}
i += (Number_of_services * 2);
}
}
else {
// Data services, 32 bit SId
- printbuf(desc, disp+2, NULL, 0);
for(j = i; ((j < (i + (Number_of_services * 4))) && (j < fig0.figlen)); j += 4) {
// iterate over SId
SId = ((uint32_t)f[j] << 24) | ((uint32_t)f[j+1] << 16) |
((uint32_t)f[j+2] << 8) | (uint32_t)f[j+3];
- sprintf(desc, "SId 0x%X", SId);
- printbuf(desc, disp+3, NULL, 0);
+ r.msgs.emplace_back(2, strprintf("SId 0x%X", SId));
}
i += (Number_of_services * 4);
}
@@ -128,6 +124,7 @@ bool fig0_9(fig0_common_t& fig0, const display_settings_t &disp)
}
}
- return true;
+ r.complete = true;
+ return r;
}
diff --git a/src/figs.cpp b/src/figs.cpp
index b418cc2..cd557bf 100644
--- a/src/figs.cpp
+++ b/src/figs.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -74,7 +74,7 @@ void figs_cleardb()
}
-bool fig0_select(fig0_common_t& fig0, const display_settings_t &disp)
+fig_result_t fig0_select(fig0_common_t& fig0, const display_settings_t &disp)
{
switch (fig0.ext()) {
case 0: return fig0_0(fig0, disp); break;
@@ -101,14 +101,11 @@ bool fig0_select(fig0_common_t& fig0, const display_settings_t &disp)
case 27: return fig0_27(fig0, disp); break;
case 28: return fig0_28(fig0, disp); break;
case 31: return fig0_31(fig0, disp); break;
- default: {
- char desc[256];
- sprintf(desc, "FIG 0/%d: unknown", fig0.ext());
- printbuf(desc, disp, fig0.f+1, fig0.figlen-1);
- break;
- }
+ default: break;
}
- return false;
+ fig_result_t r;
+ r.errors.push_back("FIG 0/" + std::to_string(fig0.ext()) + " unknown");
+ return r;
}
diff --git a/src/figs.hpp b/src/figs.hpp
index f8f8d97..5986f80 100644
--- a/src/figs.hpp
+++ b/src/figs.hpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -27,10 +27,28 @@
#pragma once
#include <cstdint>
+#include <vector>
+#include <string>
+#include <memory>
#include "utils.hpp"
#include "tables.hpp"
#include "watermarkdecoder.hpp"
+struct fig_result_t {
+ struct msg_info_t {
+ msg_info_t(int level_, const std::string& msg_) :
+ level(level_), msg(msg_) {}
+ msg_info_t(const std::string& msg_) :
+ level(0), msg(msg_) {}
+ int level = 0;
+ std::string msg;
+ };
+
+ std::vector<msg_info_t> msgs;
+ std::vector<std::string> errors;
+ bool complete = false;
+};
+
void figs_cleardb(void);
struct fig0_common_t {
@@ -80,34 +98,34 @@ void set_international_table(size_t intl_table);
void set_mode_identity(uint8_t mid);
uint8_t get_mode_identity();
-bool fig0_select(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_select(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_0(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_1(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_2(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_3(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_5(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_0(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_1(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_2(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_3(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_5(fig0_common_t& fig0, const display_settings_t &disp);
void fig0_6_cleardb();
-bool fig0_6(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_8(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_9(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_10(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_11(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_13(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_14(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_16(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_17(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_18(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_19(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_21(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_6(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_8(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_9(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_10(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_11(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_13(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_14(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_16(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_17(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_18(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_19(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_21(fig0_common_t& fig0, const display_settings_t &disp);
void fig0_22_cleardb();
-bool fig0_22(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_24(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_25(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_26(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_27(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_28(fig0_common_t& fig0, const display_settings_t &disp);
-bool fig0_31(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_22(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_24(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_25(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_26(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_27(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_28(fig0_common_t& fig0, const display_settings_t &disp);
+fig_result_t fig0_31(fig0_common_t& fig0, const display_settings_t &disp);
bool fig1_select(fig1_common_t& fig1, const display_settings_t &disp);
diff --git a/src/utils.cpp b/src/utils.cpp
index 7ea00bb..75aa880 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -29,6 +29,7 @@
#include "utils.hpp"
#include <cstring>
+#include <stdarg.h>
using namespace std;
@@ -49,6 +50,29 @@ display_settings_t display_settings_t::operator+(int indent_offset) const
return display_settings_t(print, indent+indent_offset);
}
+std::string strprintf(const char* fmt, ...)
+{
+ int size = 512;
+ std::string str;
+ va_list ap;
+ while (1) {
+ str.resize(size);
+ va_start(ap, fmt);
+ int n = vsnprintf((char *)str.c_str(), size, fmt, ap);
+ va_end(ap);
+ if (n > -1 && n < size) {
+ str.resize(n);
+ break;
+ }
+ if (n > -1)
+ size = n + 1;
+ else
+ size *= 2;
+ }
+
+ return str;
+}
+
void printbuf(std::string header,
int indent,
uint8_t* buffer,
@@ -143,34 +167,33 @@ int sprintfMJD(char *dst, int mjd) {
return strftime(dst, 256, "%a %b %d %Y", &timeDate);
}
-char *strcatPNum(char *dest_str, uint16_t Programme_Number) {
+std::string pnum_to_str(uint16_t Programme_Number)
+{
uint8_t day, hour, minute;
- char tempbuf[256];
minute = (uint8_t)(Programme_Number & 0x003F);
hour = (uint8_t)((Programme_Number >> 6) & 0x001F);
day = (uint8_t)((Programme_Number >> 11) & 0x001F);
if (day != 0) {
- sprintf(tempbuf, "day of month=%d time=%02d:%02d", day, hour, minute);
+ return strprintf("day of month=%d time=%02d:%02d", day, hour, minute);
}
else { // day == 0
// Special codes are allowed when the date part of the PNum field
// signals date = "0". In this case, the hours and minutes part of
// the field shall contain a special code, as follows
if ((hour == 0) && (minute == 0)) {
- sprintf(tempbuf, "Status code: no meaningful PNum is currently provided");
+ return "Status code: no meaningful PNum is currently provided";
}
else if ((hour == 0) && (minute == 1)) {
- sprintf(tempbuf, "Blank code: the current programme is not worth recording");
+ return "Blank code: the current programme is not worth recording";
}
else if ((hour == 0) && (minute == 2)) {
- sprintf(tempbuf, "Interrupt code: the interrupt is unplanned (for example a traffic announcement)");
+ return "Interrupt code: the interrupt is unplanned "
+ "(for example a traffic announcement)";
}
else {
- sprintf(tempbuf, "invalid value");
+ return "invalid value";
}
}
- return strcat(dest_str, tempbuf);
}
-
diff --git a/src/utils.hpp b/src/utils.hpp
index 557453d..8c72e8b 100644
--- a/src/utils.hpp
+++ b/src/utils.hpp
@@ -1,6 +1,6 @@
/*
Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/)
- Copyright (C) 2016 Matthias P. Braendli (http://www.opendigitalradio.org)
+ Copyright (C) 2017 Matthias P. Braendli (http://www.opendigitalradio.org)
Copyright (C) 2015 Data Path
This program is free software: you can redistribute it and/or modify
@@ -46,6 +46,7 @@ struct display_settings_t {
int indent;
};
+std::string strprintf(const char* fmt, ...);
void printbuf(std::string header,
const display_settings_t &disp,
@@ -69,9 +70,9 @@ void printinfo(const std::string &header,
// sprintfMJD: convert MJD (Modified Julian Date) into date string
int sprintfMJD(char *dst, int mjd);
-// strcatPNum decode Programme_Number into string and append it to dest_str
+// Convert Programme Number to string
// Programme_Number: this 16-bit field shall define the date and time at which
// a programme begins or will be continued. This field is coded in the same way
// as the RDS "Programme Item Number (PIN)" feature (EN 62106).
-char *strcatPNum(char *dest_str, uint16_t Programme_Number);
+std::string pnum_to_str(uint16_t Programme_Number);