diff --git a/csdr/chain/redsea.py b/csdr/chain/redsea.py index 1af492e4..a2222561 100644 --- a/csdr/chain/redsea.py +++ b/csdr/chain/redsea.py @@ -10,5 +10,5 @@ class Redsea(Chain): super().__init__([ Convert(Format.FLOAT, Format.SHORT), RedseaModule(sampleRate), - JsonParser("RDS"), + JsonParser("WFM"), ]) diff --git a/htdocs/css/openwebrx.css b/htdocs/css/openwebrx.css index f7c8115b..aef79c2e 100644 --- a/htdocs/css/openwebrx.css +++ b/htdocs/css/openwebrx.css @@ -1331,4 +1331,20 @@ img.openwebrx-mirror-img .openwebrx-waterfall-container > * { flex: 0 0 auto; +} + +#openwebrx-panel-metadata-wfm { + width: 619px; + min-height: 180px; +} + +.rds-container { + width: 100%; + text-align: center; +} + +.rds-container .rds-ps { + font-family: roboto-mono; + font-size: 18pt; + padding: 10px 0; } \ No newline at end of file diff --git a/htdocs/index.html b/htdocs/index.html index d1eb1564..5bf143ce 100644 --- a/htdocs/index.html +++ b/htdocs/index.html @@ -149,6 +149,7 @@ +
diff --git a/htdocs/lib/MetaPanel.js b/htdocs/lib/MetaPanel.js index 8eabece9..26e65f00 100644 --- a/htdocs/lib/MetaPanel.js +++ b/htdocs/lib/MetaPanel.js @@ -10,6 +10,10 @@ MetaPanel.prototype.isSupported = function(data) { return this.modes.includes(data.protocol); }; +MetaPanel.prototype.isEnabled = function() { + return true; +}; + MetaPanel.prototype.clear = function() { this.el.find(".openwebrx-meta-slot").removeClass("active").removeClass("sync"); }; @@ -359,12 +363,89 @@ M17MetaPanel.prototype.clear = function() { this.setDestination(); }; +function WfmMetaPanel(el) { + MetaPanel.call(this, el); + this.modes = ['WFM']; + this.enabled = false; + this.pi = ''; + this.timeout = false; + // callsigns are only available in RBDS mode (US) + this.callsign = false; + this.clear(); +} + +WfmMetaPanel.prototype = new MetaPanel(); + +WfmMetaPanel.prototype.update = function(data) { + var me = this; + + // automatically clear metadata panel when no RDS data is received for more than ten seconds + if (this.timeout) clearTimeout(this.timeout); + this.timeout = setTimeout(function(){ + me.clear(); + }, 10000); + + if (!this.isSupported(data)) return; + if ('pi' in data && data.pi !== this.pi) { + this.clear(); + this.pi = data.pi; + } + + var $el = $(this.el); + ['ps', 'prog_type', 'radiotext'].forEach(function(key) { + if (key in data) { + $el.find('.rds-' + key).text(data[key]); + } + }); + + if ('callsign' in data) { + this.callsign = true; + $el.find('.rds-identifier').text(data.callsign); + } + + if ('pi' in data && !this.callsign) { + $el.find('.rds-identifier').text('PI: ' + data.pi); + } +}; + +WfmMetaPanel.prototype.isSupported = function(data) { + return this.modes.includes(data.mode); +}; + +WfmMetaPanel.prototype.setEnabled = function(enabled) { + if (enabled === this.enabled) return; + this.enabled = enabled; + if (enabled) { + $(this.el).html( + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + ); + } else { + $(this.el).emtpy() + } +}; + +WfmMetaPanel.prototype.isEnabled = function() { + return this.enabled; +}; + +WfmMetaPanel.prototype.clear = function() { + $(this.el).find('.rds-identifier, .rds-ps, .rds-prog_type, .rds-radiotext').text(''); + // display PI until we get the next callsign + this.callsign = false; +}; + MetaPanel.types = { dmr: DmrMetaPanel, ysf: YsfMetaPanel, dstar: DStarMetaPanel, nxdn: NxdnMetaPanel, m17: M17MetaPanel, + wfm: WfmMetaPanel, }; $.fn.metaPanel = function() { diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js index a2df2d8f..41520336 100644 --- a/htdocs/openwebrx.js +++ b/htdocs/openwebrx.js @@ -827,6 +827,9 @@ function on_ws_recv(evt) { break; case "features": Modes.setFeatures(json['value']); + $('#openwebrx-panel-metadata-wfm').metaPanel().each(function() { + this.setEnabled(!!json.value.redsea); + }); break; case "metadata": $('.openwebrx-meta-panel').metaPanel().each(function(){