diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ConfigParser.cpp | 15 | ||||
| -rw-r--r-- | src/ConfigParser.h | 8 | ||||
| -rw-r--r-- | src/DabMultiplexer.cpp | 196 | ||||
| -rw-r--r-- | src/DabMultiplexer.h | 77 | ||||
| -rw-r--r-- | src/DabMux.cpp | 137 | ||||
| -rw-r--r-- | src/DabMux.h | 45 | ||||
| -rw-r--r-- | src/Eti.cpp | 17 | ||||
| -rw-r--r-- | src/Eti.h | 18 | ||||
| -rw-r--r-- | src/Interleaver.cpp | 5 | ||||
| -rw-r--r-- | src/ManagementServer.cpp | 15 | ||||
| -rw-r--r-- | src/ManagementServer.h | 18 | ||||
| -rw-r--r-- | src/MuxElements.cpp | 9 | ||||
| -rw-r--r-- | src/MuxElements.h | 26 | ||||
| -rw-r--r-- | src/PcDebug.h | 62 | ||||
| -rw-r--r-- | src/fig/FIG0_6.h | 2 | ||||
| -rw-r--r-- | src/fig/FIG1.h | 13 | ||||
| -rw-r--r-- | src/fig/FIG2.h | 14 | ||||
| -rw-r--r-- | src/input/Edi.cpp | 7 | ||||
| -rw-r--r-- | src/input/File.cpp | 18 | ||||
| -rw-r--r-- | src/mpeg.h | 15 |
20 files changed, 282 insertions, 435 deletions
diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index 7d166b6..2d500b3 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -3,7 +3,7 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2022 + Copyright (C) 2025 Matthias P. Braendli, matthias.braendli@mpb.li http://www.opendigitalradio.org @@ -110,10 +110,10 @@ static void parse_fig2_label(ptree& pt, DabLabel& label) { } // Parse the linkage section -static void parse_linkage(ptree& pt, - std::shared_ptr<dabEnsemble> ensemble) +void parse_linkage( + const boost::optional<boost::property_tree::ptree&> pt_linking, + std::vector<std::shared_ptr<LinkageSet> >& linkageSets) { - auto pt_linking = pt.get_child_optional("linking"); if (pt_linking) { for (const auto& it : *pt_linking) { const string setuid = it.first; @@ -132,7 +132,7 @@ static void parse_linkage(ptree& pt, string service_uid = pt_set.get("keyservice", ""); auto linkageset = make_shared<LinkageSet>(setuid, lsn, active, hard, international); - linkageset->keyservice = service_uid; // TODO check if it exists + linkageset->keyservice = service_uid; // existence check is done in validate_linkage_sets() auto pt_list = pt_set.get_child_optional("list"); @@ -189,7 +189,7 @@ static void parse_linkage(ptree& pt, linkageset->id_list.push_back(link); } } - ensemble->linkagesets.push_back(linkageset); + linkageSets.push_back(linkageset); } } } @@ -910,7 +910,8 @@ void parse_ptree( } - parse_linkage(pt, ensemble); + const auto pt_linking = pt.get_child_optional("linking"); + parse_linkage(pt_linking, ensemble->linkagesets); parse_freq_info(pt, ensemble); parse_other_service_linking(pt, ensemble); } diff --git a/src/ConfigParser.h b/src/ConfigParser.h index 9ca6c81..038247b 100644 --- a/src/ConfigParser.h +++ b/src/ConfigParser.h @@ -3,7 +3,7 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2016 + Copyright (C) 2025 Matthias P. Braendli, matthias.braendli@mpb.li The Configuration parser sets up the ensemble according @@ -34,6 +34,10 @@ #include <boost/property_tree/ptree.hpp> #include <memory> -void parse_ptree(boost::property_tree::ptree& pt, +void parse_ptree( + boost::property_tree::ptree& pt, std::shared_ptr<dabEnsemble> ensemble); +void parse_linkage( + const boost::optional<boost::property_tree::ptree&> pt_linking, + std::vector<std::shared_ptr<LinkageSet> >& linkageSets); diff --git a/src/DabMultiplexer.cpp b/src/DabMultiplexer.cpp index e6e6782..7a8ac97 100644 --- a/src/DabMultiplexer.cpp +++ b/src/DabMultiplexer.cpp @@ -26,11 +26,15 @@ #include <cmath> #include <set> #include <memory> +#include <boost/property_tree/info_parser.hpp> +#include <boost/property_tree/json_parser.hpp> + #include "DabMultiplexer.h" #include "ConfigParser.h" #include "ManagementServer.h" #include "crc.h" #include "utils.h" +#include "Eti.h" using namespace std; @@ -47,22 +51,21 @@ static vector<string> split_pipe_separated_string(const std::string& s) return components; } -uint64_t MuxTime::init(uint32_t tist_at_fct0_us) +uint64_t MuxTime::init(uint32_t tist_at_fct0_ms, double tist_offset) { - m_tist_at_fct0_us = tist_at_fct0_us; - - /* At startup, derive edi_time, TIST and CIF count such that there is - * a consistency across mux restarts. Ensure edi_time and TIST represent - * current time. - * - * FCT and DLFC are directly derived from m_currentFrame. - * Every 6s, FCT overflows. DLFC overflows at 5000 every 120s. - * - * Keep a granularity of 24ms, which corresponds to the duration of an ETI - * frame, to get nicer timestamps. - */ + // Things we must guarantee, up to granularity of 24ms: + // Difference between current time and EDI time = tist_offset + // TIST of frame 0 = tist_at_fct0_ms + // In order to achieve the second, we calculate the initial + // counter value so that FCT0 corresponds to the desired TIST. + // + // Changing the tist_offset at runtime will throw off the TIST@FCT0 value + m_tist_offset_ms = std::lround(tist_offset * 1000); + using Sec = chrono::seconds; - const auto now = chrono::system_clock::now(); + const auto now = chrono::system_clock::now() + + chrono::milliseconds(std::lround(tist_offset * 1000.0)); + const auto offset = now - chrono::time_point_cast<Sec>(now); if (offset >= chrono::seconds(1)) { throw std::logic_error("Invalid startup offset calculation for TIST! " + @@ -70,43 +73,24 @@ uint64_t MuxTime::init(uint32_t tist_at_fct0_us) " ms"); } const time_t t_now = chrono::system_clock::to_time_t(chrono::time_point_cast<Sec>(now)); + const auto offset_ms = chrono::duration_cast<chrono::milliseconds>(offset).count(); - m_edi_time = t_now - (t_now % 6); - uint64_t currentFrame = 0; - time_t edi_time_at_cif0 = t_now - (t_now % 120); - while (edi_time_at_cif0 < m_edi_time) { - edi_time_at_cif0 += 6; - currentFrame += 250; - } + m_edi_time = t_now; + m_pps_offset_ms = std::lround(offset_ms / 24.0) * 24; - if (edi_time_at_cif0 != m_edi_time) { - throw std::logic_error("Invalid startup offset calculation for CIF!"); - } + const auto counter_offset = tist_at_fct0_ms / 24; + const auto offset_as_count = m_pps_offset_ms / 24; - int64_t offset_ms = chrono::duration_cast<chrono::milliseconds>(offset).count(); - offset_ms += 1000 * (t_now - m_edi_time); - - if (tist_at_fct0_us >= 1000000) { - etiLog.level(error) << "tist_at_fct0 may not be larger than 1s"; - throw MuxInitException(); - } - - m_timestamp = (uint64_t)tist_at_fct0_us * 16384 / 1000; - while (offset_ms >= 24) { - increment_timestamp(); - currentFrame++; - offset_ms -= 24; - } - return currentFrame; + return (250 - counter_offset + offset_as_count) % 250; } constexpr int TIMESTAMP_LEVEL_2_SHIFT = 14; void MuxTime::increment_timestamp() { - m_timestamp += 24 << TIMESTAMP_LEVEL_2_SHIFT; // Shift 24ms by 14 to Timestamp level 2 - if (m_timestamp > 0xf9FFff) { - m_timestamp -= 0xfa0000; // Subtract 16384000, corresponding to one second + m_pps_offset_ms += 24; + if (m_pps_offset_ms >= 1000) { + m_pps_offset_ms -= 1000; m_edi_time += 1; // Also update MNSC time for next time FP==0 @@ -114,27 +98,34 @@ void MuxTime::increment_timestamp() } } -std::pair<uint32_t, std::time_t> MuxTime::get_tist_seconds() +void MuxTime::set_tist_offset(double new_tist_offset) { - // The user-visible configuration tist_offset is the effective - // offset, but since we implicitly add the tist_at_fct0 to it, - // we must compensate. - double corrected_tist_offset = tist_offset - (m_tist_at_fct0_us / 1e6); - - // negative tist_offset not supported, because the calculation is annoying - if (corrected_tist_offset < 0) return {m_timestamp, m_edi_time}; - - double fractional_part = corrected_tist_offset - std::floor(corrected_tist_offset); - const size_t steps = std::lround(std::floor(fractional_part / 24e-3)); - uint32_t timestamp = m_timestamp + (24 << TIMESTAMP_LEVEL_2_SHIFT) * steps; - - std::time_t edi_time = m_edi_time + std::lround(std::floor(corrected_tist_offset)); - - if (timestamp > 0xf9FFff) { - edi_time += 1; + const int32_t new_tist_offset_ms = std::lround(new_tist_offset * 1000.0); + int32_t delta = m_tist_offset_ms - new_tist_offset_ms; + if (delta > 0) { + while (delta > 0) { + increment_timestamp(); + delta -= 24; + } } + else if (delta < 0) { + while (delta < 0) { + m_edi_time -= 1; + delta += 1000; + } + // compensate the we subtracted too much + while (delta > 0) { + increment_timestamp(); + delta -= 24; + } + } + m_tist_offset_ms = new_tist_offset_ms; +} - return {timestamp % 0xfa0000, edi_time}; +std::pair<uint32_t, std::time_t> MuxTime::get_tist_seconds() +{ + auto timestamp = m_pps_offset_ms * 16384; + return {timestamp % 0xfa0000, m_edi_time}; } std::pair<uint32_t, std::time_t> MuxTime::get_milliseconds_seconds() @@ -144,16 +135,35 @@ std::pair<uint32_t, std::time_t> MuxTime::get_milliseconds_seconds() } -DabMultiplexer::DabMultiplexer(boost::property_tree::ptree pt) : +void DabMultiplexerConfig::read(const std::string& filename) +{ + m_config_file = ""; + try { + if (stringEndsWith(filename, ".json")) { + read_json(filename, pt); + } + else { + read_info(filename, pt); + } + m_config_file = filename; + } + catch (const boost::property_tree::file_parser_error& e) + { + etiLog.level(warn) << "Failed to read " << filename; + } +} + +DabMultiplexer::DabMultiplexer(DabMultiplexerConfig& config) : RemoteControllable("mux"), - m_pt(pt), + m_config(config), m_time(), ensemble(std::make_shared<dabEnsemble>()), - m_clock_tai(split_pipe_separated_string(pt.get("general.tai_clock_bulletins", ""))), + m_clock_tai(split_pipe_separated_string(m_config.pt.get("general.tai_clock_bulletins", ""))), fig_carousel(ensemble, [&]() { return m_time.get_milliseconds_seconds(); }) { RC_ADD_PARAMETER(frames, "Show number of frames generated [read-only]"); - RC_ADD_PARAMETER(tist_offset, "Timestamp offset in fractional number of seconds"); + RC_ADD_PARAMETER(tist_offset, "Configured tist-offset"); + RC_ADD_PARAMETER(reload_linkagesets, "Write 1 to this parameter to trigger a reload of the linkage sets from the config [write-only]"); rcs.enrol(&m_clock_tai); } @@ -173,7 +183,7 @@ void DabMultiplexer::set_edi_config(const edi::configuration_t& new_edi_conf) // Run a set of checks on the configuration void DabMultiplexer::prepare(bool require_tai_clock) { - parse_ptree(m_pt, ensemble); + parse_ptree(m_config.pt, ensemble); rcs.enrol(this); rcs.enrol(ensemble.get()); @@ -199,12 +209,11 @@ void DabMultiplexer::prepare(bool require_tai_clock) throw MuxInitException(); } - const uint32_t tist_at_fct0_us = m_pt.get<double>("general.tist_at_fct0", 0); - currentFrame = m_time.init(tist_at_fct0_us); + const uint32_t tist_at_fct0_ms = m_config.pt.get<double>("general.tist_at_fct0", 0); + currentFrame = m_time.init(tist_at_fct0_ms, m_config.pt.get<double>("general.tist_offset", 0.0)); m_time.mnsc_increment_time = false; - bool tist_enabled = m_pt.get("general.tist", false); - m_time.tist_offset = m_pt.get<double>("general.tist_offset", 0.0); + bool tist_enabled = m_config.pt.get("general.tist", false); auto tist_edi_time = m_time.get_tist_seconds(); const auto timestamp = tist_edi_time.first; @@ -453,6 +462,32 @@ void DabMultiplexer::prepare_data_inputs() } } +void DabMultiplexer::reload_linkagesets() +{ + try { + DabMultiplexerConfig new_conf; + new_conf.read(m_config.config_file()); + if (new_conf.valid()) { + const auto pt_linking = new_conf.pt.get_child_optional("linking"); + std::vector<std::shared_ptr<LinkageSet> > linkagesets; + parse_linkage(pt_linking, linkagesets); + + etiLog.level(info) << "Validating " << linkagesets.size() << " new linkage sets."; + + if (ensemble->validate_linkage_sets(ensemble->services, linkagesets)) { + ensemble->linkagesets = linkagesets; + etiLog.level(info) << "Loaded new linkage sets."; + } + else { + etiLog.level(warn) << "New linkage set validation failed"; + } + } + } + catch (const std::exception& e) + { + etiLog.level(warn) << "Failed to update linkage sets: " << e.what(); + } +} /* Each call creates one ETI frame */ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs) @@ -472,7 +507,7 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs // The above Tag Items will be assembled into a TAG Packet edi::TagPacket edi_tagpacket(edi_conf.tagpacket_alignment); - const bool tist_enabled = m_pt.get("general.tist", false); + const bool tist_enabled = m_config.pt.get("general.tist", false); int tai_utc_offset = 0; if (tist_enabled and m_tai_clock_required) { @@ -487,6 +522,10 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs auto tist_edi_time = m_time.get_tist_seconds(); const auto timestamp = tist_edi_time.first; const auto edi_time = tist_edi_time.second; + /* + etiLog.level(debug) << "Frame " << currentFrame << " " << edi_time << + " + " << (timestamp >> TIMESTAMP_LEVEL_2_SHIFT); + */ // Initialise the ETI frame memset(etiFrame, 0, 6144); @@ -520,7 +559,6 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs eti_FC *fc = (eti_FC *) &etiFrame[4]; //****** FCT ******// - // Incremente for each frame, overflows at 249 fc->FCT = currentFrame % 250; edi_tagDETI.dlfc = currentFrame % 5000; @@ -729,7 +767,7 @@ void DabMultiplexer::mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs index = (FLtmp + 2 + 1) * 4; eti_TIST *tist = (eti_TIST *) & etiFrame[index]; - bool enableTist = m_pt.get("general.tist", false); + bool enableTist = m_config.pt.get("general.tist", false); if (enableTist) { tist->TIST = htonl(timestamp) | 0xff; edi_tagDETI.tsta = timestamp & 0xffffff; @@ -857,7 +895,10 @@ void DabMultiplexer::set_parameter(const std::string& parameter, throw ParameterError(ss.str()); } else if (parameter == "tist_offset") { - m_time.tist_offset = std::stod(value); + m_time.set_tist_offset(std::stod(value)); + } + else if (parameter == "reload_linkagesets") { + reload_linkagesets(); } else { stringstream ss; @@ -875,7 +916,12 @@ const std::string DabMultiplexer::get_parameter(const std::string& parameter) co ss << currentFrame; } else if (parameter == "tist_offset") { - ss << m_time.tist_offset; + ss << m_time.tist_offset(); + } + else if (parameter == "reload_linkagesets") { + ss << "Parameter '" << parameter << + "' is not write-only in controllable " << get_rc_name(); + throw ParameterError(ss.str()); } else { ss << "Parameter '" << parameter << @@ -890,7 +936,7 @@ const json::map_t DabMultiplexer::get_all_values() const { json::map_t map; map["frames"].v = currentFrame; - map["tist_offset"].v = m_time.tist_offset; + map["tist_offset"].v = m_time.tist_offset(); return map; } diff --git a/src/DabMultiplexer.h b/src/DabMultiplexer.h index 5a0d906..620e65d 100644 --- a/src/DabMultiplexer.h +++ b/src/DabMultiplexer.h @@ -45,46 +45,59 @@ constexpr uint32_t ETI_FSYNC1 = 0x49C5F8; class MuxTime { private: - uint32_t m_timestamp = 0; - std::time_t m_edi_time = 0; - uint32_t m_tist_at_fct0_us = 0; + std::time_t m_edi_time = 0; + uint32_t m_pps_offset_ms = 0; + int64_t m_tist_offset_ms = 0; public: - std::pair<uint32_t, std::time_t> get_tist_seconds(); - std::pair<uint32_t, std::time_t> get_milliseconds_seconds(); - - double tist_offset = 0; - - /* Pre v3 odr-dabmux did the MNSC calculation differently, - * which works with the easydabv2. The rework in odr-dabmux, - * deriving MNSC time from EDI time broke this. - * - * That's why we're now tracking MNSC time in separate variables, - * to get the same behaviour back. - * - * I'm not aware of any devices using MNSC time besides the - * easydab. ODR-DabMod now considers EDI seconds or ZMQ metadata. - */ - bool mnsc_increment_time = false; - std::time_t mnsc_time = 0; - - /* Setup the time and return the initial currentFrame counter value */ - uint64_t init(uint32_t tist_at_fct0_us); - void increment_timestamp(); + std::pair<uint32_t, std::time_t> get_tist_seconds(); + std::pair<uint32_t, std::time_t> get_milliseconds_seconds(); + + + /* Pre v3 odr-dabmux did the MNSC calculation differently, + * which works with the easydabv2. The rework in odr-dabmux, + * deriving MNSC time from EDI time broke this. + * + * That's why we're now tracking MNSC time in separate variables, + * to get the same behaviour back. + * + * I'm not aware of any devices using MNSC time besides the + * easydab. ODR-DabMod now considers EDI seconds or ZMQ metadata. + */ + bool mnsc_increment_time = false; + std::time_t mnsc_time = 0; + + /* Setup the time and return the initial currentFrame counter value */ + uint64_t init(uint32_t tist_at_fct0_ms, double tist_offset); + void increment_timestamp(); + double tist_offset() const { return m_tist_offset_ms / 1000.0; } + void set_tist_offset(double new_tist_offset); +}; + +class DabMultiplexerConfig { + public: + boost::property_tree::ptree pt; + + void read(const std::string& filename); + bool valid() const { return m_config_file != ""; } + std::string config_file() const { return m_config_file; } + + private: + std::string m_config_file; }; class DabMultiplexer : public RemoteControllable { public: - DabMultiplexer(boost::property_tree::ptree pt); + DabMultiplexer(DabMultiplexerConfig& config); DabMultiplexer(const DabMultiplexer& other) = delete; DabMultiplexer& operator=(const DabMultiplexer& other) = delete; - ~DabMultiplexer(); + virtual ~DabMultiplexer(); void prepare(bool require_tai_clock); void mux_frame(std::vector<std::shared_ptr<DabOutput> >& outputs); - void print_info(void); + void print_info(); void set_edi_config(const edi::configuration_t& new_edi_conf); @@ -98,11 +111,13 @@ class DabMultiplexer : public RemoteControllable { virtual const json::map_t get_all_values() const; private: - void prepare_subchannels(void); - void prepare_services_components(void); - void prepare_data_inputs(void); + void prepare_subchannels(); + void prepare_services_components(); + void prepare_data_inputs(); + + void reload_linkagesets(); - boost::property_tree::ptree m_pt; + DabMultiplexerConfig& m_config; MuxTime m_time; uint64_t currentFrame = 0; diff --git a/src/DabMux.cpp b/src/DabMux.cpp index bf525c1..7b5f5d6 100644 --- a/src/DabMux.cpp +++ b/src/DabMux.cpp @@ -29,83 +29,25 @@ # include "config.h" #endif -#include <stdlib.h> #include <memory> #include <boost/property_tree/ptree.hpp> -#include <boost/property_tree/info_parser.hpp> -#include <boost/property_tree/json_parser.hpp> +#include <ctime> +#include <cstdlib> #include <cstdio> -#include <iostream> -#include <fstream> -#include <iomanip> #include <cstring> +#include <cmath> #include <string> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> #include <fcntl.h> #include <signal.h> -// for basename -#include <libgen.h> - -#include <iterator> #include <vector> -#include <list> #include <set> -#include <map> -#include <functional> -#include <algorithm> - -#ifdef _WIN32 -# include <time.h> -# include <process.h> -# include <io.h> -# include <conio.h> -# include <winsock2.h> // For types... -typedef u_char uint8_t; -typedef WORD uint16_t; -typedef DWORD32 uint32_t; - -# ifndef __MINGW32__ -# include "xgetopt.h" -# endif -# define read _read -# define snprintf _snprintf -# define sleep(a) Sleep((a) * 1000) -#else -# include <netinet/in.h> -# include <unistd.h> -# include <sys/time.h> -# include <sys/wait.h> -# include <sys/socket.h> -# include <sys/ioctl.h> -# include <sys/times.h> -# include <sys/resource.h> - -#endif - -#include <time.h> - -#ifdef _WIN32 -# pragma warning ( disable : 4103 ) -# include "Eti.h" -# pragma warning ( default : 4103 ) -#else -# include "Eti.h" -#endif -#include "input/Prbs.h" -#include "input/Zmq.h" +#include "DabMultiplexer.h" #include "dabOutput/dabOutput.h" -#include "crc.h" -#include "Socket.h" -#include "PcDebug.h" -#include "DabMux.h" #include "MuxElements.h" #include "utils.h" -#include "ConfigParser.h" #include "ManagementServer.h" #include "Log.h" #include "RemoteControl.h" @@ -120,14 +62,10 @@ volatile sig_atomic_t running = 1; */ void signalHandler(int signum) { -#ifdef _WIN32 - fprintf(stderr, "\npid: %i\n", _getpid()); -#else fprintf(stderr, "\npid: %i, ppid: %i\n", getpid(), getppid()); -#endif + #define SIG_MSG "Signal received: " switch (signum) { -#ifndef _WIN32 case SIGHUP: fprintf(stderr, SIG_MSG "SIGHUP\n"); break; @@ -138,7 +76,6 @@ void signalHandler(int signum) fprintf(stderr, SIG_MSG "SIGPIPE\n"); return; break; -#endif case SIGINT: fprintf(stderr, SIG_MSG "SIGINT\n"); break; @@ -150,9 +87,7 @@ void signalHandler(int signum) default: fprintf(stderr, SIG_MSG "number %i\n", signum); } -#ifndef _WIN32 killpg(0, SIGPIPE); -#endif running = 0; } @@ -185,12 +120,6 @@ int main(int argc, char *argv[]) } } -#ifdef _WIN32 - if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST) == 0) { - etiLog.log(warn, "Can't increase priority: %s\n", - strerror(errno)); - } -#else // Use the lowest real-time priority for this thread, and switch to real-time scheduling const int policy = SCHED_RR; sched_param sp; @@ -199,15 +128,15 @@ int main(int argc, char *argv[]) if (thread_prio_ret != 0) { etiLog.level(error) << "Could not set real-time priority for thread:" << thread_prio_ret; } -#endif int returnCode = 0; - ptree pt; std::vector<std::shared_ptr<DabOutput> > outputs; try { string conf_file = ""; + DabMultiplexerConfig mux_conf; + if (argc == 2) { // Assume the only argument is a config file conf_file = argv[1]; @@ -224,8 +153,7 @@ int main(int argc, char *argv[]) } conf_file = argv[2]; - - read_info(conf_file, pt); + mux_conf.read(conf_file); } catch (runtime_error &e) { throw MuxInitException(e.what()); @@ -238,23 +166,18 @@ int main(int argc, char *argv[]) } try { - if (stringEndsWith(conf_file, ".json")) { - read_json(conf_file, pt); - } - else { - read_info(conf_file, pt); - } + mux_conf.read(conf_file); } catch (runtime_error &e) { throw MuxInitException(e.what()); } /* Enable Logging to syslog conditionally */ - if (pt.get<bool>("general.syslog", false)) { + if (mux_conf.pt.get<bool>("general.syslog", false)) { etiLog.register_backend(std::make_shared<LogToSyslog>()); } - const auto startupcheck = pt.get<string>("general.startupcheck", ""); + const auto startupcheck = mux_conf.pt.get<string>("general.startupcheck", ""); if (not startupcheck.empty()) { etiLog.level(info) << "Running startup check '" << startupcheck << "'"; int wstatus = system(startupcheck.c_str()); @@ -274,26 +197,26 @@ int main(int argc, char *argv[]) } } - int mgmtserverport = pt.get<int>("general.managementport", - pt.get<int>("general.statsserverport", 0) ); + int mgmtserverport = mux_conf.pt.get<int>("general.managementport", + mux_conf.pt.get<int>("general.statsserverport", 0) ); /* Management: stats and config server */ get_mgmt_server().open(mgmtserverport); /************** READ REMOTE CONTROL PARAMETERS *************/ - int telnetport = pt.get<int>("remotecontrol.telnetport", 0); + int telnetport = mux_conf.pt.get<int>("remotecontrol.telnetport", 0); if (telnetport != 0) { auto rc = std::make_shared<RemoteControllerTelnet>(telnetport); rcs.add_controller(rc); } - auto zmqendpoint = pt.get<string>("remotecontrol.zmqendpoint", ""); + auto zmqendpoint = mux_conf.pt.get<string>("remotecontrol.zmqendpoint", ""); if (not zmqendpoint.empty()) { auto rc = std::make_shared<RemoteControllerZmq>(zmqendpoint); rcs.add_controller(rc); } - DabMultiplexer mux(pt); + DabMultiplexer mux(mux_conf); etiLog.level(info) << PACKAGE_NAME << " " << @@ -310,7 +233,7 @@ int main(int argc, char *argv[]) /******************** READ OUTPUT PARAMETERS ***************/ set<string> all_output_names; bool output_require_tai_clock = false; - ptree pt_outputs = pt.get_child("outputs"); + ptree pt_outputs = mux_conf.pt.get_child("outputs"); for (auto ptree_pair : pt_outputs) { string outputuid = ptree_pair.first; @@ -352,10 +275,9 @@ int main(int argc, char *argv[]) pft_settings.enable_pft = pt.get<bool>("enable_pft", default_enable_pft); pft_settings.fec = pt.get<unsigned int>("fec", default_fec); pft_settings.fragment_spreading_factor = default_spreading_factor; - auto override_spread_percent = pt.get_optional<int>("packet_spread"); - if (override_spread_percent) { + if (auto override_spread_percent = pt.get_optional<int>("packet_spread")) pft_settings.fragment_spreading_factor = check_spreading_factor(*override_spread_percent); - } + pft_settings.verbose = pt.get<bool>("verbose", edi_conf.verbose); }; @@ -364,12 +286,12 @@ int main(int argc, char *argv[]) if (proto == "udp") { auto dest = make_shared<edi::udp_destination_t>(); dest->dest_addr = pt_edi_dest.second.get<string>("destination"); - dest->ttl = pt_edi_dest.second.get<unsigned int>("ttl", 1); + if (auto ttl = pt_edi_dest.second.get_optional<unsigned int>("ttl")) + dest->ttl = *ttl; dest->source_addr = pt_edi_dest.second.get<string>("source", ""); - dest->source_port = pt_edi_dest.second.get<unsigned int>("sourceport"); - - dest->dest_port = pt_edi_dest.second.get<unsigned int>("port", 0); + dest->source_port = pt_edi_dest.second.get<unsigned int>("sourceport", 0); + dest->dest_port = pt_edi_dest.second.get<unsigned int>("port", 0); if (dest->dest_port == 0) { // Compatiblity: we have removed the transport and addressing in the // PFT layer, which removed the requirement that all outputs must share @@ -515,7 +437,6 @@ int main(int argc, char *argv[]) } outputs.push_back(output); - } } @@ -535,7 +456,7 @@ int main(int argc, char *argv[]) edi_conf.print(); } - size_t limit = pt.get("general.nbframes", 0); + const size_t limit = mux_conf.pt.get("general.nbframes", 0); etiLog.level(info) << "Start loop"; /* Each iteration of the main loop creates one ETI frame */ @@ -544,6 +465,7 @@ int main(int argc, char *argv[]) mux.mux_frame(outputs); if (limit && currentFrame >= limit) { + etiLog.level(info) << "Max number of ETI frames reached: " << currentFrame; break; } @@ -562,17 +484,12 @@ int main(int argc, char *argv[]) mgmt_server.restart(); } - mgmt_server.update_ptree(pt); + mgmt_server.update_ptree(mux_conf.pt); } } - - if (limit) { - etiLog.level(info) << "Max number of ETI frames reached: " << currentFrame; - } } catch (const MuxInitException& except) { - etiLog.level(error) << "Multiplex initialisation aborted: " << - except.what(); + etiLog.level(error) << "Multiplex initialisation aborted: " << except.what(); returnCode = 1; } catch (const std::invalid_argument& except) { diff --git a/src/DabMux.h b/src/DabMux.h deleted file mode 100644 index 80b4881..0000000 --- a/src/DabMux.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011 Her Majesty the Queen in Right of Canada (Communications - Research Center Canada) - - Copyright (C) 2014 - Matthias P. Braendli, matthias.braendli@mpb.li - - This file declares several structures used in the multiplexer, - and defines default values for some parameters. - */ -/* - This file is part of ODR-DabMux. - - ODR-DabMux 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. - - ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. -*/ -#pragma once - -#include <stdint.h> -#include <string> -#include <vector> -#include "DabMultiplexer.h" -#include "RemoteControl.h" -#include "dabOutput/dabOutput.h" -#include "input/inputs.h" -#include "Eti.h" -#include "MuxElements.h" - -#ifdef _WIN32 -# include <time.h> -#else -# include <sys/time.h> -#endif - diff --git a/src/Eti.cpp b/src/Eti.cpp index e1b51fb..2f26f2d 100644 --- a/src/Eti.cpp +++ b/src/Eti.cpp @@ -22,19 +22,10 @@ along with ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. */ -#ifdef _WIN32 -# pragma warning ( disable : 4103 ) -# include "Eti.h" -# pragma warning ( default : 4103 ) -#else -# include "Eti.h" -# include <time.h> -#endif - +#include "Eti.h" //definitions des structures des champs du ETI(NI, G703) - unsigned short eti_FC::getFrameLength() { return (unsigned short)((FL_high << 8) | FL_low); @@ -80,7 +71,7 @@ void eti_MNSC_TIME_1::setFromTime(struct tm *time_tm) { second_unit = time_tm->tm_sec % 10; second_tens = time_tm->tm_sec / 10; - + minute_unit = time_tm->tm_min % 10; minute_tens = time_tm->tm_min / 10; } @@ -89,7 +80,7 @@ void eti_MNSC_TIME_2::setFromTime(struct tm *time_tm) { hour_unit = time_tm->tm_hour % 10; hour_tens = time_tm->tm_hour / 10; - + day_unit = time_tm->tm_mday % 10; day_tens = time_tm->tm_mday / 10; } @@ -98,7 +89,7 @@ void eti_MNSC_TIME_3::setFromTime(struct tm *time_tm) { month_unit = (time_tm->tm_mon + 1) % 10; month_tens = (time_tm->tm_mon + 1) / 10; - + // They didn't see the y2k bug coming, did they ? year_unit = (time_tm->tm_year - 100) % 10; year_tens = (time_tm->tm_year - 100) / 10; @@ -29,24 +29,12 @@ # include <config.h> #endif -#ifdef _WIN32 -# include <winsock2.h> // For types... -typedef WORD uint16_t; -typedef DWORD32 uint32_t; - -# define PACKED -# pragma pack(push, 1) -#else -# include <stdint.h> -# include <time.h> - -# define PACKED __attribute__ ((packed)) -#endif - +#include <cstdint> +#include <ctime> +#define PACKED __attribute__ ((packed)) //definitions des structures des champs du ETI(NI, G703) - struct eti_SYNC { uint32_t ERR:8; uint32_t FSYNC:24; diff --git a/src/Interleaver.cpp b/src/Interleaver.cpp index cf0d235..1786d08 100644 --- a/src/Interleaver.cpp +++ b/src/Interleaver.cpp @@ -23,11 +23,6 @@ #include <string.h> -#ifdef _WIN32 -# define bzero(a, b) memset((a), 0, (b)) -#endif // _WIN32 - - Interleaver::Interleaver(unsigned short I, unsigned short M, bool reverse) : I(I), M(M), diff --git a/src/ManagementServer.cpp b/src/ManagementServer.cpp index dff093a..7344b8b 100644 --- a/src/ManagementServer.cpp +++ b/src/ManagementServer.cpp @@ -95,11 +95,6 @@ INPUT_COUNTER_RESET_TIME = std::chrono::minutes(30); static constexpr int INPUT_UNSTABLE_THRESHOLD = 3; -/* For how long the input buffers must be empty before we move an input to the - * NoData state. */ -static constexpr auto -INPUT_NODATA_TIMEOUT = std::chrono::seconds(30); - /* Keep 30s of min/max buffer fill information so that we can catch meaningful * values even if we have a slow poller */ static constexpr auto @@ -478,7 +473,7 @@ void InputStat::notifyPeakLevels(int peak_left, int peak_right) } } -void InputStat::notifyUnderrun(void) +void InputStat::notifyUnderrun() { unique_lock<mutex> lock(m_mutex); @@ -497,7 +492,7 @@ void InputStat::notifyUnderrun(void) } } -void InputStat::notifyOverrun(void) +void InputStat::notifyOverrun() { unique_lock<mutex> lock(m_mutex); @@ -643,11 +638,7 @@ input_state_t InputStat::determineState() // STATE CALCULATION - /* If the buffer has been empty for more than - * INPUT_NODATA_TIMEOUT, we go to the NoData state. - * - * Consider an empty deque to be NoData too. - */ + /* Consider an empty deque to be NoData. */ if (std::all_of( m_buffer_fill_stats.begin(), m_buffer_fill_stats.end(), [](const fill_stat_t& fs) { return fs.bufsize == 0; }) ) { diff --git a/src/ManagementServer.h b/src/ManagementServer.h index c7a4222..93ad28c 100644 --- a/src/ManagementServer.h +++ b/src/ManagementServer.h @@ -50,7 +50,6 @@ # include "config.h" #endif -#include "Socket.h" #include "zmq.hpp" #include <string> #include <map> @@ -65,7 +64,6 @@ #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/json_parser.hpp> -#include <cmath> /*** State handing ***/ /* An input can be in one of the following three states: @@ -95,20 +93,20 @@ class InputStat InputStat(const InputStat& other) = delete; InputStat& operator=(const InputStat& other) = delete; ~InputStat(); - void registerAtServer(void); + void registerAtServer(); - std::string get_name(void) const { return m_name; } + std::string get_name() const { return m_name; } /* This function is called for every frame read by * the multiplexer */ void notifyBuffer(long bufsize); void notifyTimestampOffset(double offset); void notifyPeakLevels(int peak_left, int peak_right); - void notifyUnderrun(void); - void notifyOverrun(void); + void notifyUnderrun(); + void notifyOverrun(); void notifyVersion(const std::string& version, uint32_t uptime_s); - std::string encodeValuesJSON(void); - input_state_t determineState(void); + std::string encodeValuesJSON(); + input_state_t determineState(); private: std::string m_name; @@ -185,7 +183,7 @@ class ManagementServer void update_ptree(const boost::property_tree::ptree& pt); bool fault_detected() const { return m_fault; } - void restart(void); + void restart(); private: void restart_thread(long); @@ -194,7 +192,7 @@ class ManagementServer zmq::context_t m_zmq_context; zmq::socket_t m_zmq_sock; - void serverThread(void); + void serverThread(); void handle_message(zmq::message_t& zmq_message); bool isInputRegistered(std::string& id); diff --git a/src/MuxElements.cpp b/src/MuxElements.cpp index d17b283..1f02a6d 100644 --- a/src/MuxElements.cpp +++ b/src/MuxElements.cpp @@ -743,7 +743,14 @@ const json::map_t dabEnsemble::get_all_values() const return map; } -bool dabEnsemble::validate_linkage_sets() +bool dabEnsemble::validate_linkage_sets() const +{ + return validate_linkage_sets(services, linkagesets); +} + +bool dabEnsemble::validate_linkage_sets( + const vec_sp_service& services, + std::vector<std::shared_ptr<LinkageSet> > linkagesets) { for (const auto& ls : linkagesets) { const std::string keyserviceuid = ls->keyservice; diff --git a/src/MuxElements.h b/src/MuxElements.h index d118df9..dfc4380 100644 --- a/src/MuxElements.h +++ b/src/MuxElements.h @@ -33,16 +33,13 @@ #include <memory> #include <mutex> #include <string> -#include <functional> #include <exception> -#include <algorithm> #include <chrono> #include <optional> #include <stdint.h> #include "dabOutput/dabOutput.h" #include "input/inputs.h" #include "RemoteControl.h" -#include "Eti.h" // Protection levels and bitrates for UEP. const unsigned char ProtectionLevelTable[64] = { @@ -87,7 +84,7 @@ class MuxInitException : public std::exception MuxInitException(const std::string m = "ODR-DabMux initialisation error") throw() : msg(m) {} - ~MuxInitException(void) throw() {} + ~MuxInitException() throw() {} const char* what() const throw() { return msg.c_str(); } private: std::string msg; @@ -140,12 +137,12 @@ class AnnouncementCluster : public RemoteControllable { uint16_t flags = 0; std::string subchanneluid; - std::string tostring(void) const; + std::string tostring() const; /* Check if the activation/deactivation timeout occurred, * and return of if the Announcement is active */ - bool is_active(void); + bool is_active(); private: mutable std::mutex m_active_mutex; @@ -315,7 +312,10 @@ class dabEnsemble : public RemoteControllable { virtual const json::map_t get_all_values() const; /* Check if the Linkage Sets are valid */ - bool validate_linkage_sets(void); + bool validate_linkage_sets() const; + static bool validate_linkage_sets( + const vec_sp_service& services, + std::vector<std::shared_ptr<LinkageSet> > linkagesets); /* all fields are public, since this was a struct before */ uint16_t id = 0; @@ -372,7 +372,7 @@ struct dabProtectionEEP { // select EEP profile A and B. // Other values are for future use, see // EN 300 401 Clause 6.2.1 "Basic sub-channel organisation" - uint8_t GetOption(void) const { + uint8_t GetOption() const { return (this->profile == EEP_A) ? 0 : 1; } }; @@ -402,16 +402,16 @@ public: protection() { } // Calculate subchannel size in number of CU - unsigned short getSizeCu(void) const; + unsigned short getSizeCu() const; // Calculate subchannel size in number of bytes - unsigned short getSizeByte(void) const; + unsigned short getSizeByte() const; // Calculate subchannel size in number of uint32_t - unsigned short getSizeWord(void) const; + unsigned short getSizeWord() const; // Calculate subchannel size in number of uint64_t - unsigned short getSizeDWord(void) const; + unsigned short getSizeDWord() const; // Read from the input, using the correct buffer management size_t readFrame(uint8_t *buffer, size_t size, std::time_t seconds, int utco, uint32_t tsta); @@ -574,7 +574,7 @@ class LinkageSet { bool hard, bool international); - std::string get_name(void) const { return m_name; } + std::string get_name() const { return m_name; } std::list<ServiceLink> id_list; diff --git a/src/PcDebug.h b/src/PcDebug.h index d0b2b2c..68fceb8 100644 --- a/src/PcDebug.h +++ b/src/PcDebug.h @@ -19,8 +19,7 @@ along with ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef PC_DEBUG_ -#define PC_DEBUG_ +#pragma once #ifdef HAVE_CONFIG_H # include "config.h" @@ -31,49 +30,28 @@ #include <stdio.h> -#define LOG stderr +#define LOG stderr -#if !defined(_WIN32) || defined(__MINGW32__) -# ifndef PDEBUG -# ifdef DEBUG -# define PDEBUG(fmt, args...) fprintf (LOG, fmt , ## args) -# else -# define PDEBUG(fmt, args...) -# endif -# endif +#ifndef PDEBUG # ifdef DEBUG -# define PDEBUG_VERBOSE(level, verbosity, fmt, args...) if (level <= verbosity) { fprintf(LOG, fmt, ## args); fflush(LOG); } -# define PDEBUG0_VERBOSE(level, verbosity, txt) if (level <= verbosity) { fprintf(LOG, txt); fflush(LOG); } -# define PDEBUG1_VERBOSE(level, verbosity, txt, arg0) if (level <= verbosity) { fprintf(LOG, txt, arg0); fflush(LOG); } -# define PDEBUG2_VERBOSE(level, verbosity, txt, arg0, arg1) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1); fflush(LOG); } -# define PDEBUG3_VERBOSE(level, verbosity, txt, arg0, arg1, arg2) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1, arg2); fflush(LOG); } -# define PDEBUG4_VERBOSE(level, verbosity, txt, arg0, arg1, arg2, arg3) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1, arg2, arg3); fflush(LOG); } -# else -# define PDEBUG_VERBOSE(level, verbosity, fmt, args...) -# define PDEBUG0_VERBOSE(level, verbosity, txt) -# define PDEBUG1_VERBOSE(level, verbosity, txt, arg0) -# define PDEBUG2_VERBOSE(level, verbosity, txt, arg0, arg1) -# define PDEBUG3_VERBOSE(level, verbosity, txt, arg0, arg1, arg2) -# define PDEBUG4_VERBOSE(level, verbosity, txt, arg0, arg1, arg2, arg3) -# endif // DEBUG -#else // _WIN32 -# ifdef _DEBUG -# define PDEBUG -# define PDEBUG_VERBOSE -# define PDEBUG0_VERBOSE(level, verbosity, txt) if (level <= verbosity) { fprintf(LOG, txt); fflush(LOG); } -# define PDEBUG1_VERBOSE(level, verbosity, txt, arg0) if (level <= verbosity) { fprintf(LOG, txt, arg0); fflush(LOG); } -# define PDEBUG2_VERBOSE(level, verbosity, txt, arg0, arg1) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1); fflush(LOG); } -# define PDEBUG3_VERBOSE(level, verbosity, txt, arg0, arg1, arg2) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1, arg2); fflush(LOG); } -# define PDEBUG4_VERBOSE(level, verbosity, txt, arg0, arg1, arg2, arg3) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1, arg2, arg3); fflush(LOG); } +# define PDEBUG(fmt, args...) fprintf (LOG, fmt , ## args) # else -# define PDEBUG -# define PDEBUG_VERBOSE -# define PDEBUG0_VERBOSE(level, verbosity, txt) -# define PDEBUG1_VERBOSE(level, verbosity, txt, arg0) -# define PDEBUG2_VERBOSE(level, verbosity, txt, arg0, arg1) -# define PDEBUG3_VERBOSE(level, verbosity, txt, arg0, arg1, arg2) -# define PDEBUG4_VERBOSE(level, verbosity, txt, arg0, arg1, arg2, arg3) +# define PDEBUG(fmt, args...) # endif #endif +#ifdef DEBUG +# define PDEBUG_VERBOSE(level, verbosity, fmt, args...) if (level <= verbosity) { fprintf(LOG, fmt, ## args); fflush(LOG); } +# define PDEBUG0_VERBOSE(level, verbosity, txt) if (level <= verbosity) { fprintf(LOG, txt); fflush(LOG); } +# define PDEBUG1_VERBOSE(level, verbosity, txt, arg0) if (level <= verbosity) { fprintf(LOG, txt, arg0); fflush(LOG); } +# define PDEBUG2_VERBOSE(level, verbosity, txt, arg0, arg1) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1); fflush(LOG); } +# define PDEBUG3_VERBOSE(level, verbosity, txt, arg0, arg1, arg2) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1, arg2); fflush(LOG); } +# define PDEBUG4_VERBOSE(level, verbosity, txt, arg0, arg1, arg2, arg3) if (level <= verbosity) { fprintf(LOG, txt, arg0, arg1, arg2, arg3); fflush(LOG); } +#else +# define PDEBUG_VERBOSE(level, verbosity, fmt, args...) +# define PDEBUG0_VERBOSE(level, verbosity, txt) +# define PDEBUG1_VERBOSE(level, verbosity, txt, arg0) +# define PDEBUG2_VERBOSE(level, verbosity, txt, arg0, arg1) +# define PDEBUG3_VERBOSE(level, verbosity, txt, arg0, arg1, arg2) +# define PDEBUG4_VERBOSE(level, verbosity, txt, arg0, arg1, arg2, arg3) +#endif // DEBUG -#endif // PC_DEBUG_ diff --git a/src/fig/FIG0_6.h b/src/fig/FIG0_6.h index 770c4d5..96464d2 100644 --- a/src/fig/FIG0_6.h +++ b/src/fig/FIG0_6.h @@ -26,8 +26,6 @@ #pragma once #include <cstdint> -#include <vector> -#include <memory> namespace FIC { diff --git a/src/fig/FIG1.h b/src/fig/FIG1.h index 0fedffe..fe36717 100644 --- a/src/fig/FIG1.h +++ b/src/fig/FIG1.h @@ -23,8 +23,7 @@ along with ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef __FIG1_H_ -#define __FIG1_H_ +#pragma once #include <cstdint> @@ -103,10 +102,6 @@ class FIG1_5 : public IFIG vec_sp_service::iterator service; }; -#ifdef _WIN32 -# pragma pack(push) -#endif - struct FIGtype1_0 { uint8_t Length:5; uint8_t FIGtypeNumber:3; @@ -165,11 +160,5 @@ struct FIGtype1_4_data { } PACKED; -#ifdef _WIN32 -# pragma pack(pop) -#endif - } // namespace FIC -#endif // __FIG1_H_ - diff --git a/src/fig/FIG2.h b/src/fig/FIG2.h index ee3fed9..e69c5db 100644 --- a/src/fig/FIG2.h +++ b/src/fig/FIG2.h @@ -22,9 +22,7 @@ You should have received a copy of the GNU General Public License along with ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. */ - -#ifndef __FIG2_H_ -#define __FIG2_H_ +#pragma once #include <cstdint> #include <map> @@ -117,10 +115,6 @@ class FIG2_4 : public IFIG std::map<std::pair<uint32_t, uint8_t>, FIG2_Segments> segment_per_component; }; -#ifdef _WIN32 -# pragma pack(push) -#endif - struct FIGtype2 { uint8_t Length:5; uint8_t FIGtypeNumber:3; @@ -159,11 +153,5 @@ struct FIG2_Extended_Label_WithTextControl { uint8_t EncodingFlag:1; } PACKED; -#ifdef _WIN32 -# pragma pack(pop) -#endif - } // namespace FIC -#endif // __FIG2_H_ - diff --git a/src/input/Edi.cpp b/src/input/Edi.cpp index 141641f..b100f32 100644 --- a/src/input/Edi.cpp +++ b/src/input/Edi.cpp @@ -80,6 +80,7 @@ Edi::~Edi() { void Edi::open(const std::string& name) { const std::regex re_udp("udp://:([0-9]+)"); + const std::regex re_udp_bindto("udp://([^:]+):([0-9]+)"); const std::regex re_udp_multicast("udp://@([0-9.]+):([0-9]+)"); const std::regex re_udp_multicast_bindto("udp://([0-9.])+@([0-9.]+):([0-9]+)"); const std::regex re_tcp("tcp://(.*):([0-9]+)"); @@ -98,6 +99,12 @@ void Edi::open(const std::string& name) m_udp_sock.reinit(udp_port); m_udp_sock.setBlocking(false); } + else if (std::regex_match(name, m, re_udp_bindto)) { + const int udp_port = std::stoi(m[2].str()); + m_input_used = InputUsed::UDP; + m_udp_sock.reinit(udp_port, m[1].str()); + m_udp_sock.setBlocking(false); + } else if (std::regex_match(name, m, re_udp_multicast_bindto)) { const string bind_to = m[1].str(); const string multicast_address = m[2].str(); diff --git a/src/input/File.cpp b/src/input/File.cpp index d9fe02a..c70feee 100644 --- a/src/input/File.cpp +++ b/src/input/File.cpp @@ -28,9 +28,6 @@ #include <cstdio> #include <fcntl.h> #include <unistd.h> -#ifndef _WIN32 -# define O_BINARY 0 -#endif #include "input/File.h" #include "mpeg.h" #include "ReedSolomon.h" @@ -39,9 +36,6 @@ using namespace std; namespace Inputs { -#ifdef _WIN32 -# pragma pack(push, 1) -#endif struct packetHeader { unsigned char addressHigh:2; unsigned char last:1; @@ -52,11 +46,7 @@ struct packetHeader { unsigned char dataLength:7; unsigned char command; } -#ifdef _WIN32 -# pragma pack(pop) -#else __attribute((packed)) -#endif ; @@ -68,7 +58,7 @@ void FileBase::open(const std::string& name) load_entire_file(); } else { - int flags = O_RDONLY | O_BINARY; + int flags = O_RDONLY; if (m_nonblock) { flags |= O_NONBLOCK; } @@ -140,13 +130,13 @@ ssize_t FileBase::load_entire_file() { // Clear the buffer if the file open fails, this allows user to stop transmission // of the current data. - vector<uint8_t> old_file_contents = move(m_file_contents); + vector<uint8_t> old_file_contents = std::move(m_file_contents); m_file_contents.clear(); m_file_contents_offset = 0; // Read entire file in chunks of 4MiB constexpr size_t blocksize = 4 * 1024 * 1024; - constexpr int flags = O_RDONLY | O_BINARY; + constexpr int flags = O_RDONLY; m_fd = ::open(m_filename.c_str(), flags); if (m_fd == -1) { if (not m_file_open_alert_shown) { @@ -225,7 +215,7 @@ ssize_t FileBase::readFromFile(uint8_t *buffer, size_t size) vector<uint8_t> remaining_buf; copy(m_nonblock_buffer.begin() + size, m_nonblock_buffer.end(), back_inserter(remaining_buf)); - m_nonblock_buffer = move(remaining_buf); + m_nonblock_buffer = std::move(remaining_buf); return size; } @@ -18,23 +18,13 @@ You should have received a copy of the GNU General Public License along with ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. */ - -#ifndef _MPEG -#define _MPEG +#pragma once #ifdef HAVE_CONFIG_H # include "config.h" #endif -#ifdef _WIN32 -# include <stddef.h> -# include <basetsd.h> -# include <io.h> - -# define ssize_t SSIZE_T -#else -# include <unistd.h> -#endif +#include <unistd.h> #ifdef __cplusplus extern "C" { @@ -86,4 +76,3 @@ int checkDabMpegFrame(void* data); } #endif -#endif // _MPEG |
