From 4249e4a53950457394395555cd7dcdd6287b499b Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 14 Feb 2014 13:07:17 +0100 Subject: DabService labels can now be changed through the remote control --- src/DabMux.cpp | 8 ++-- src/MuxElements.cpp | 101 ++++++++++++++++++++++++++++++++++++++++++----- src/MuxElements.h | 32 ++++++++++++--- src/ParserCmdline.cpp | 4 +- src/ParserConfigfile.cpp | 63 +++++++++++++++++++++-------- src/dabInputZmq.cpp | 2 +- src/utils.cpp | 18 +++------ src/utils.h | 2 +- 8 files changed, 178 insertions(+), 52 deletions(-) diff --git a/src/DabMux.cpp b/src/DabMux.cpp index b7095c6..7bb44ba 100644 --- a/src/DabMux.cpp +++ b/src/DabMux.cpp @@ -275,10 +275,10 @@ int main(int argc, char *argv[]) ensemble->ecc = DEFAULT_ENSEMBLE_ECC; vector outputs; - vector::iterator service = ensemble->services.end(); - vector::iterator serviceProgramInd; - vector::iterator serviceDataInd; - vector::iterator servicePty; + vector::iterator service = ensemble->services.end(); + vector::iterator serviceProgramInd; + vector::iterator serviceDataInd; + vector::iterator servicePty; vector::iterator component = ensemble->components.end(); vector::iterator componentIndicatorProgram; vector::iterator componentIndicatorData; diff --git a/src/MuxElements.cpp b/src/MuxElements.cpp index 3ac63e3..13ce096 100644 --- a/src/MuxElements.cpp +++ b/src/MuxElements.cpp @@ -3,8 +3,8 @@ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Includes modifications - 2012, Matthias P. Braendli, matthias.braendli@mpb.li + Copyright (C) 2014 + Matthias P. Braendli, matthias.braendli@mpb.li */ /* This file is part of ODR-DabMux. @@ -26,6 +26,7 @@ #include #include "MuxElements.h" +#include const unsigned short Sub_Channel_SizeTable[64] = { 16, 21, 24, 29, 35, 24, 29, 35, @@ -48,9 +49,11 @@ int DabLabel::setLabel(const std::string& text) if (len > 16) return -3; - memset(m_text, 0, 16); + memset(m_text, 0, 17); memcpy(m_text, text.c_str(), len); + m_flag = 0xFF00; // truncate the label to the eight first characters + return 0; } @@ -58,7 +61,7 @@ int DabLabel::setLabel(const std::string& text, const std::string& short_label) { DabLabel newlabel; - memset(newlabel.m_text, 0, 16); + memset(newlabel.m_text, 0, 17); int len = text.length(); if (len > 16) return -3; @@ -70,7 +73,7 @@ int DabLabel::setLabel(const std::string& text, const std::string& short_label) return flag; // short label is valid. - memcpy(this->m_text, newlabel.m_text, len); + memcpy(this->m_text, newlabel.m_text, 17); this->m_flag = flag & 0xFFFF; return 0; @@ -127,6 +130,18 @@ int DabLabel::setShortLabel(const std::string& slabel) return flag; } +const string DabLabel::short_label() const +{ + stringstream shortlabel; + for (int i = 0; i < 32; ++i) { + if (m_flag & 0x8000 >> i) { + shortlabel << m_text[i]; + } + } + + return shortlabel.str(); +} + vector::iterator getSubchannel( vector& subchannels, int id) @@ -166,11 +181,11 @@ vector::iterator getComponent( return getComponent(components, serviceId, components.end()); } -vector::iterator getService( +vector::iterator getService( dabComponent* component, - vector& services) + vector& services) { - vector::iterator service; + vector::iterator service; for (service = services.begin(); service != services.end(); ++service) { if ((*service)->id == component->serviceId) { @@ -204,7 +219,7 @@ bool dabComponent::isPacketComponent(vector& subchannels) } -unsigned char dabService::getType(dabEnsemble* ensemble) +unsigned char DabService::getType(dabEnsemble* ensemble) { vector::iterator subchannel; vector::iterator component = @@ -220,7 +235,7 @@ unsigned char dabService::getType(dabEnsemble* ensemble) return (*subchannel)->type; } -unsigned char dabService::nbComponent(vector& components) +unsigned char DabService::nbComponent(vector& components) { int nb = 0; vector::iterator current; @@ -234,6 +249,72 @@ unsigned char dabService::nbComponent(vector& components) return nb; } +void DabService::set_parameter(string parameter, string value) +{ + stringstream ss(value); + ss.exceptions ( stringstream::failbit | stringstream::badbit ); + + if (parameter == "label") { + vector fields; + boost::split(fields, value, boost::is_any_of(",")); + if (fields.size() != 2) { + throw ParameterError("Parameter 'label' must have format" + " 'label,shortlabel'"); + } + int success = this->label.setLabel(fields[0], fields[1]); + stringstream ss; + switch (success) + { + case 0: + break; + case -1: + ss << "Ensemble short label " << + fields[1] << " is not subset of label '" << + fields[0] << "'"; + etiLog.level(warn) << ss.str(); + throw ParameterError(ss.str()); + case -2: + ss << "Ensemble short label " << + fields[1] << " is too long (max 8 characters)"; + etiLog.level(warn) << ss.str(); + throw ParameterError(ss.str()); + case -3: + ss << "Ensemble label " << + fields[0] << " is too long (max 16 characters)"; + etiLog.level(warn) << ss.str(); + throw ParameterError(ss.str()); + default: + ss << "Ensemble short label definition: program error !"; + etiLog.level(emerg) << ss.str(); + throw ParameterError(ss.str()); + } + } + else { + stringstream ss; + ss << "Parameter '" << parameter << + "' is not exported by controllable " << get_rc_name(); + throw ParameterError(ss.str()); + } +} + +string DabService::get_parameter(string parameter) +{ + stringstream ss; + if (parameter == "label") { + char l[17]; + l[16] = '\0'; + memcpy(l, label.text(), 16); + ss << l << "," << label.short_label(); + } + else { + ss << "Parameter '" << parameter << + "' is not exported by controllable " << get_rc_name(); + throw ParameterError(ss.str()); + } + return ss.str(); + +} + unsigned short getSizeCu(dabSubchannel* subchannel) { if (subchannel->protection.form == 0) { diff --git a/src/MuxElements.h b/src/MuxElements.h index 9658fb2..a0ee23a 100644 --- a/src/MuxElements.h +++ b/src/MuxElements.h @@ -35,6 +35,7 @@ #include #include "dabOutput/dabOutput.h" #include "dabInput.h" +#include "RemoteControl.h" #include "Eti.h" using namespace std; @@ -74,15 +75,18 @@ class DabLabel const char* text() const { return m_text; } uint16_t flag() const { return m_flag; } + const string short_label() const; private: - char m_text[16]; + // In the DAB standard, the label is 16 chars. + // We keep it here zero-terminated + char m_text[17]; uint16_t m_flag; int setShortLabel(const std::string& slabel); }; -struct dabService; +struct DabService; struct dabComponent; struct dabSubchannel; struct dabEnsemble { @@ -90,7 +94,7 @@ struct dabEnsemble { uint8_t ecc; DabLabel label; uint8_t mode; - vector services; + vector services; vector components; vector subchannels; }; @@ -177,8 +181,14 @@ struct dabComponent { -struct dabService +class DabService : public RemoteControllable { + public: + DabService(std::string uid) : RemoteControllable(uid) + { + RC_ADD_PARAMETER(label, "Label and shortlabel [label,short]"); + } + uint32_t id; unsigned char pty; unsigned char language; @@ -188,6 +198,16 @@ struct dabService unsigned char nbComponent(vector& components); DabLabel label; + + /* Remote control */ + virtual void set_parameter(string parameter, string value); + + /* Getting a parameter always returns a string. */ + virtual string get_parameter(string parameter); + + private: + const DabService& operator=(const DabService& other); + DabService(const DabService& other); }; vector::iterator getSubchannel( @@ -202,9 +222,9 @@ vector::iterator getComponent( vector& components, uint32_t serviceId); -vector::iterator getService( +vector::iterator getService( dabComponent* component, - vector& services); + vector& services); unsigned short getSizeCu(dabSubchannel* subchannel); diff --git a/src/ParserCmdline.cpp b/src/ParserCmdline.cpp index 9985d9a..2027bff 100644 --- a/src/ParserCmdline.cpp +++ b/src/ParserCmdline.cpp @@ -104,7 +104,7 @@ bool parse_cmdline(char **argv, vector::iterator output; vector::iterator subchannel = ensemble->subchannels.end(); vector::iterator component = ensemble->components.end(); - vector::iterator service = ensemble->services.end(); + vector::iterator service = ensemble->services.end(); dabProtection* protection = NULL; dabInputOperations operations; @@ -148,7 +148,7 @@ bool parse_cmdline(char **argv, service = ensemble->services.end(); break; case 'S': - ensemble->services.push_back(new dabService); + ensemble->services.push_back(new DabService("?")); subchannel = ensemble->subchannels.end(); protection = NULL; diff --git a/src/ParserConfigfile.cpp b/src/ParserConfigfile.cpp index 9262ed3..a6bbe63 100644 --- a/src/ParserConfigfile.cpp +++ b/src/ParserConfigfile.cpp @@ -105,7 +105,6 @@ using namespace std; int hexparse(std::string input) { int value; - fprintf(stderr, "**************************** %s\n", input.c_str()); if (input.find("0x") == 0) { value = strtoll(input.c_str() + 2, NULL, 16); } @@ -190,25 +189,35 @@ void parse_configfile(string configuration_file, /* Extended Country Code */ ensemble->ecc = hexparse(pt_ensemble.get("ecc", "0")); - string label = pt_ensemble.get("label"); - string short_label = pt_ensemble.get("shortlabel"); - int success = ensemble->label.setLabel(label, short_label); + int success = -5; + string ensemble_label = pt_ensemble.get("label"); + string ensemble_short_label(ensemble_label); + try { + ensemble_short_label = pt_ensemble.get("shortlabel"); + success = ensemble->label.setLabel(ensemble_label, ensemble_short_label); + } + catch (ptree_error &e) { + etiLog.level(warn) << "Ensemble short label undefined, " + "truncating label " << ensemble_label; + + success = ensemble->label.setLabel(ensemble_label); + } switch (success) { case 0: break; case -1: etiLog.level(error) << "Ensemble short label " << - short_label << " is not subset of label '" << - label << "'"; + ensemble_short_label << " is not subset of label '" << + ensemble_label << "'"; throw runtime_error("ensemble label definition error"); case -2: etiLog.level(error) << "Ensemble short label " << - short_label << " is too long (max 8 characters)"; + ensemble_short_label << " is too long (max 8 characters)"; throw runtime_error("ensemble label definition error"); case -3: etiLog.level(error) << "Ensemble label " << - label << " is too long (max 16 characters)"; + ensemble_label << " is too long (max 16 characters)"; throw runtime_error("ensemble label definition error"); default: etiLog.level(error) << @@ -219,22 +228,34 @@ void parse_configfile(string configuration_file, /******************** READ SERVICES PARAMETERS *************/ - map allservices; + map allservices; /* For each service, we keep a separate SCIdS counter */ - map SCIdS_per_service; + map SCIdS_per_service; ptree pt_services = pt.get_child("services"); for (ptree::iterator it = pt_services.begin(); it != pt_services.end(); ++it) { string serviceuid = it->first; ptree pt_service = it->second; - dabService* service = new dabService(); + DabService* service = new DabService(serviceuid); ensemble->services.push_back(service); + service->enrol_at(*rc); + + int success = -5; string servicelabel = pt_service.get("label"); - string serviceshortlabel = pt_service.get("shortlabel"); - int success = service->label.setLabel(label, short_label); + string serviceshortlabel(servicelabel); + try { + serviceshortlabel = pt_service.get("shortlabel"); + success = service->label.setLabel(servicelabel, serviceshortlabel); + } + catch (ptree_error &e) { + etiLog.level(warn) << "Service short label undefined, " + "truncating label " << servicelabel; + + success = service->label.setLabel(servicelabel); + } switch (success) { case 0: @@ -318,7 +339,7 @@ void parse_configfile(string configuration_file, string componentuid = it->first; ptree pt_comp = it->second; - dabService* service; + DabService* service; try { // Those two uids serve as foreign keys to select the service+subchannel string service_uid = pt_comp.get("service"); @@ -365,9 +386,19 @@ void parse_configfile(string configuration_file, component->SCIdS = SCIdS_per_service[service]++; component->type = component_type; + int success = -5; string componentlabel = pt_comp.get("label"); - string componentshortlabel = pt_comp.get("shortlabel"); - int success = component->label.setLabel(label, short_label); + string componentshortlabel(componentlabel); + try { + componentshortlabel = pt_comp.get("shortlabel"); + success = component->label.setLabel(componentlabel, componentshortlabel); + } + catch (ptree_error &e) { + etiLog.level(warn) << "Component short label undefined, " + "truncating label " << componentlabel; + + success = component->label.setLabel(componentlabel); + } switch (success) { case 0: diff --git a/src/dabInputZmq.cpp b/src/dabInputZmq.cpp index ab1aca1..c883f35 100644 --- a/src/dabInputZmq.cpp +++ b/src/dabInputZmq.cpp @@ -309,7 +309,7 @@ void DabInputZmqBase::set_parameter(string parameter, string value) ss.exceptions ( stringstream::failbit | stringstream::badbit ); if (parameter == "buffer") { - throw ParameterError("Parameter 'ntaps' is read-only"); + throw ParameterError("Parameter 'buffer' is read-only"); } else { stringstream ss; diff --git a/src/utils.cpp b/src/utils.cpp index b837009..157c3a7 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -296,9 +296,9 @@ void printOutputs(vector& outputs) } } -void printServices(vector& services) +void printServices(vector& services) { - vector::const_iterator current; + vector::const_iterator current; int index = 0; for (current = services.begin(); current != services.end(); ++current) { @@ -307,16 +307,10 @@ void printServices(vector& services) label[16] = 0; etiLog.log(info, "Service %i\n", index); - etiLog.log(info, " label: %s\n", label); - etiLog.log(info, " short label: "); - { - LogLine line = etiLog.level(info); - for (int i = 0; i < 32; ++i) { - if ((*current)->label.flag() & 0x8000 >> i) { - line << label[i]; - } - } - } + etiLog.log(info, " label: %s\n", + (*current)->label.text()); + etiLog.log(info, " short label: %s\n", + (*current)->label.short_label().c_str()); etiLog.log(info, " (0x%x)\n", (*current)->label.flag()); etiLog.log(info, " id: 0x%lx (%lu)\n", (*current)->id, (*current)->id); diff --git a/src/utils.h b/src/utils.h index 75d1b6e..8a9e264 100644 --- a/src/utils.h +++ b/src/utils.h @@ -51,7 +51,7 @@ void printUsageConfigfile(char *name, FILE* out = stderr); * resp. subchannels*/ void printOutputs(vector& outputs); -void printServices(vector& services); +void printServices(vector& services); void printComponents(vector& components); -- cgit v1.2.3