/* Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/) Copyright (C) 2018 Matthias P. Braendli (http://www.opendigitalradio.org) Copyright (C) 2015 Data Path This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . etisnoop.cpp Parse ETI NI G.703 file Authors: Sergio Sagliocco Matthias P. Braendli / | |- ')|) |-|_ _ (|,_ .| _ ,_ \ Data Path \(|(||_(|/_| (||_||(a)_||||(|||.(_()|||/ */ #include "utils.hpp" #include #include #include #include #include using namespace std; static int verbosity = 0; void set_verbosity(int v) { verbosity = v; } int get_verbosity() { return verbosity; } 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; } static void printyaml(const string& header, const display_settings_t &disp, uint8_t* buffer = nullptr, size_t size = 0, const std::string& desc = "", const std::string& value = "") { if (disp.print) { stringstream ss; for (int i = 0; i < disp.indent; i++) { ss << " "; } ss << header; ss << ":"; if (not value.empty() and desc.empty() and not buffer) { ss << " " << value; } else { if (not value.empty()) { ss << "\n"; for (int i = 0; i < disp.indent + 1; i++) { ss << " "; } ss << strprintf("value: %s", value.c_str()); } if (not desc.empty()) { ss << "\n"; for (int i = 0; i < disp.indent + 1; i++) { ss << " "; } ss << strprintf("desc: %s", desc.c_str()); } if (buffer and verbosity > 0) { if (size != 0) { ss << "\n"; for (int i = 0; i < disp.indent + 1; i++) { ss << " "; } ss << "data: ["; size_t num_printed = 0; for (size_t i = 0; i < size; i++) { if (i > 0) { ss << ","; num_printed++; } if (num_printed + disp.indent + 1 + 7 > 60 ) { ss << "\n"; for (int i = 0; i < disp.indent + 8; i++) { ss << " "; } num_printed = 2; } else if (i > 0) { ss << " "; num_printed++; } ss << strprintf("0x%02x", buffer[i]); num_printed += 3; } ss << "]"; } } } ss << "\n"; printf("%s", ss.str().c_str()); } } void printbuf(const std::string& header, int indent, uint8_t* buffer, size_t size, const std::string& desc, const std::string& value) { display_settings_t disp(true, indent); printyaml(header, disp, buffer, size, desc, value); } void printbuf(const string& header, const display_settings_t &disp, uint8_t* buffer, size_t size, const std::string& desc, const std::string& value) { display_settings_t d = disp; d.print = (verbosity > 0); printyaml(header, d, buffer, size, desc, value); } void printbuf(const std::string& header, int indent) { display_settings_t disp(true, indent); return printyaml(header, disp); } void printfig(const string& header, const display_settings_t &disp, uint8_t* buffer, size_t size, const std::string& desc, const std::string& value) { printyaml(header, disp, buffer, size, desc, value); } void printvalue(const std::string& header, const display_settings_t &disp, const std::string& desc, const std::string& value) { return printyaml(header, disp, nullptr, 0, desc, value); } void printvalue(const std::string& header, int indent, const std::string& desc, const std::string& value) { display_settings_t disp(true, indent); return printyaml(header, disp, nullptr, 0, desc, value); } void printinfo(const string &header, const display_settings_t &disp, int min_verb) { if (verbosity >= min_verb) { for (int i = 0; i < disp.indent; i++) { printf(" "); } printf("info: %s\n", header.c_str()); } } void printinfo(const std::string &header, int min_verb) { const display_settings_t disp(true, 0); printinfo(header, min_verb); } void printsequencestart(int indent) { for (int i = 0; i < indent; i++) { printf(" "); } printf("-\n"); } int sprintfMJD(char *dst, int mjd) { // EN 62106 Annex G // These formulas are applicable between the inclusive dates: 1st March 1900 to 28th February 2100 int y, m, k; struct tm timeDate; memset(&timeDate, 0, sizeof(struct tm)); // find Y, M, D from MJD y = (int)(((double)mjd - 15078.2) / 365.25); m = (int)(((double)mjd - 14956.1 - (int)((double)y * 365.25)) / 30.6001); timeDate.tm_mday = mjd - 14956 - (int)((double)y * 365.25) - (int)((double)m * 30.6001); if ((m == 14) || (m == 15)) { k = 1; } else { k = 0; } timeDate.tm_year = y + k; timeDate.tm_mon = (m - 1 - (k * 12)) - 1; // find WD from MJD timeDate.tm_wday = (((mjd + 2) % 7) + 1) % 7; //timeDate.tm_yday = 0; // Number of days since the first day of January not calculated timeDate.tm_isdst = -1; // No time print then information not available // print date string if ((timeDate.tm_mday < 0) || (timeDate.tm_mon < 0) || (timeDate.tm_year < 0)) { return sprintf(dst, "invalid MJD mday=%d mon=%d year=%d", timeDate.tm_mday, timeDate.tm_mon, timeDate.tm_year); } return strftime(dst, 256, "%a %b %d %Y", &timeDate); } std::string pnum_to_str(uint16_t Programme_Number) { uint8_t day, hour, minute; minute = (uint8_t)(Programme_Number & 0x003F); hour = (uint8_t)((Programme_Number >> 6) & 0x001F); day = (uint8_t)((Programme_Number >> 11) & 0x001F); if (day != 0) { 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)) { return "Status code: no meaningful PNum is currently provided"; } else if ((hour == 0) && (minute == 1)) { return "Blank code: the current programme is not worth recording"; } else if ((hour == 0) && (minute == 2)) { return "Interrupt code: the interrupt is unplanned " "(for example a traffic announcement)"; } else { return "invalid value"; } } } int absolute_to_dB(int16_t value) { const int16_t int16_max = std::numeric_limits::max(); return value ? round(20*log10((double)value / int16_max)) : -90; }