From 9a99ed90c291fd55e9f165be248136aa37eb1316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20P=C3=B6schel?= Date: Thu, 8 Dec 2022 00:01:21 +0100 Subject: [PATCH] GTK: add support for alarm announcements Also derive EId from FIG 0/0 instead of 1/0. --- README.md | 3 +++ src/dablin_gtk.cpp | 16 +++++++++++++--- src/fic_decoder.cpp | 33 ++++++++++++++++++++++++++++----- src/fic_decoder.h | 6 +++++- 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index c346ff7..4613ef7 100644 --- a/README.md +++ b/README.md @@ -355,6 +355,9 @@ different subchannel leads to cyan highlighting instead e.g. if traffic news of a different channel shall affect also listeners of a different service (which does not have its own announcements). +The GTK version indicates an active alarm announcement on ensemble level +by the suffix "Alarm" after the ensemble label, highlighted in red. + ### Hotkeys (GTK GUI version) diff --git a/src/dablin_gtk.cpp b/src/dablin_gtk.cpp index 61d497c..50868e2 100644 --- a/src/dablin_gtk.cpp +++ b/src/dablin_gtk.cpp @@ -1076,12 +1076,13 @@ void DABlinGTK::FICChangeEnsembleEmitted() { ensemble = fic_change_ensemble.Pop(); std::string charset_name; - std::string label = FICDecoder::ConvertLabelToUTF8(ensemble.label, &charset_name); + std::string label = Glib::Markup::escape_text(FICDecoder::ConvertLabelToUTF8(ensemble.label, &charset_name)); std::string tooltip_text = "Short label: \"" + FICDecoder::DeriveShortLabelUTF8(label, ensemble.label.short_label_mask) + "\"\n" "Label charset: " + charset_name + "\n" - "EId: " + StringTools::IntToHex(ensemble.eid, 4); + "EId: " + StringTools::IntToHex(ensemble.eid, 4) + "\n" + "Alarm flag: " + (ensemble.al_flag ? "true" : "false"); if(ensemble.ecc != FIC_ENSEMBLE::ecc_none) tooltip_text += "\n" "ECC: " + StringTools::IntToHex(ensemble.ecc, 2); if(ensemble.lto != FIC_ENSEMBLE::lto_none) @@ -1089,7 +1090,16 @@ void DABlinGTK::FICChangeEnsembleEmitted() { if(ensemble.inter_table_id != FIC_ENSEMBLE::inter_table_id_none) tooltip_text += "\n" "International table ID: " + StringTools::IntToHex(ensemble.inter_table_id, 2) + " (" + FICDecoder::ConvertInterTableIDToString(ensemble.inter_table_id) + ")"; - label_ensemble.set_label(label); + // indicate active alarm announcement + if(ensemble.al_flag) { + asw_clusters_t::const_iterator cl_it = ensemble.asw_clusters.find(0xFF); + if(cl_it != ensemble.asw_clusters.end() && (cl_it->second.asw_flags & 0x01)) { + label += " Alarm "; + tooltip_text += "\n" "Alarm SubChId: " + std::to_string(cl_it->second.subchid); + } + } + + label_ensemble.set_markup(label); frame_label_ensemble.set_tooltip_text(tooltip_text); } diff --git a/src/fic_decoder.cpp b/src/fic_decoder.cpp index e98e0fe..7bf25d6 100644 --- a/src/fic_decoder.cpp +++ b/src/fic_decoder.cpp @@ -1,6 +1,6 @@ /* DABlin - capital DAB experience - Copyright (C) 2015-2020 Stefan Pöschel + Copyright (C) 2015-2022 Stefan Pöschel 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 @@ -87,6 +87,9 @@ void FICDecoder::ProcessFIG0(const uint8_t *data, size_t len) { // handle extension switch(header.extension) { + case 0: + ProcessFIG0_0(data, len); + break; case 1: ProcessFIG0_1(data, len); break; @@ -122,6 +125,27 @@ void FICDecoder::ProcessFIG0(const uint8_t *data, size_t len) { } } +void FICDecoder::ProcessFIG0_0(const uint8_t *data, size_t len) { + // FIG 0/0 - Ensemble information + // EId and alarm flag only + + if(len < 4) + return; + + FIC_ENSEMBLE new_ensemble = ensemble; + new_ensemble.eid = data[0] << 8 | data[1]; + new_ensemble.al_flag = data[2] & 0x20; + + if(ensemble != new_ensemble) { + ensemble = new_ensemble; + + fprintf(stderr, "FICDecoder: EId 0x%04X: alarm flag: %s\n", + ensemble.eid, ensemble.al_flag ? "true" : "false"); + + UpdateEnsemble(); + } +} + void FICDecoder::ProcessFIG0_1(const uint8_t *data, size_t len) { // FIG 0/1 - Basic sub-channel organization @@ -620,8 +644,7 @@ void FICDecoder::ProcessFIG1(const uint8_t *data, size_t len) { } void FICDecoder::ProcessFIG1_0(uint16_t eid, const FIC_LABEL& label) { - if(ensemble.eid != eid || ensemble.label != label) { - ensemble.eid = eid; + if(ensemble.label != label) { ensemble.label = label; std::string label_str = ConvertLabelToUTF8(label, nullptr); @@ -777,8 +800,8 @@ int FICDecoder::GetSLSAppType(const ua_data_t& ua_data) { } void FICDecoder::UpdateEnsemble() { - // abort update, if label not yet present - if(ensemble.label.IsNone()) + // abort update, if EId or label not yet present + if(ensemble.IsNone() || ensemble.label.IsNone()) return; // forward to observer diff --git a/src/fic_decoder.h b/src/fic_decoder.h index 14fa638..605f1f3 100644 --- a/src/fic_decoder.h +++ b/src/fic_decoder.h @@ -1,6 +1,6 @@ /* DABlin - capital DAB experience - Copyright (C) 2015-2020 Stefan Pöschel + Copyright (C) 2015-2022 Stefan Pöschel 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 @@ -145,6 +145,7 @@ struct FIC_DAB_DT { struct FIC_ENSEMBLE { int eid; + bool al_flag; FIC_LABEL label; int ecc; int lto; @@ -160,6 +161,7 @@ struct FIC_ENSEMBLE { FIC_ENSEMBLE() : eid(eid_none), + al_flag(false), ecc(ecc_none), lto(lto_none), inter_table_id(inter_table_id_none) @@ -168,6 +170,7 @@ struct FIC_ENSEMBLE { bool operator==(const FIC_ENSEMBLE & ensemble) const { return eid == ensemble.eid && + al_flag == ensemble.al_flag && label == ensemble.label && ecc == ensemble.ecc && lto == ensemble.lto && @@ -287,6 +290,7 @@ class FICDecoder { void ProcessFIB(const uint8_t *data); void ProcessFIG0(const uint8_t *data, size_t len); + void ProcessFIG0_0(const uint8_t *data, size_t len); void ProcessFIG0_1(const uint8_t *data, size_t len); void ProcessFIG0_2(const uint8_t *data, size_t len); void ProcessFIG0_5(const uint8_t *data, size_t len);