diff --git a/csdr/module/hdradio.py b/csdr/module/hdradio.py index cf57e6ae..d7895805 100644 --- a/csdr/module/hdradio.py +++ b/csdr/module/hdradio.py @@ -32,12 +32,13 @@ class StationLocation(LatLngLocation): class HdRadioModule(ThreadModule): def __init__(self, program: int = 0, amMode: bool = False): + self.metaLock = threading.Lock() self.metaWriter = None self.meta = {} self.program = 0 - self.frequency = -1 + self.frequency = 0 self.radio = NRSC5(lambda evt_type, evt: self.callback(evt_type, evt)) - self.setFrequency(0) + self._clearMeta() # Crashes things? # self.radio.set_mode(Mode.AM if amMode else Mode.FM) super().__init__() @@ -54,32 +55,28 @@ class HdRadioModule(ThreadModule): # Change program def setProgram(self, program: int) -> None: if program != self.program: - logger.info("Now playing program #{0}".format(program)) self.program = program + logger.info("Now playing program #{0}".format(self.program)) # Clear program metadata - if "title" in self.meta: - del self.meta["title"] - if "artist" in self.meta: - del self.meta["artist"] - if "album" in self.meta: - del self.meta["album"] - if "genre" in self.meta: - del self.meta["genre"] - self.meta["program"] = self.program - self._writeMeta() + with self.metaLock: + self.meta["program"] = self.program + if "title" in self.meta: + del self.meta["title"] + if "artist" in self.meta: + del self.meta["artist"] + if "album" in self.meta: + del self.meta["album"] + if "genre" in self.meta: + del self.meta["genre"] + self._writeMeta() # Change frequency def setFrequency(self, frequency: int) -> None: if frequency != self.frequency: - logger.info("Now decoding at {0}MHz".format(frequency / 1000000)) self.frequency = frequency - # Clear all metadata - self.meta = { - "mode" : "HDR", - "frequency" : self.frequency, - "program" : self.program - } - self._writeMeta() + self.program = 0 + logger.info("Now playing program #{0} at {1}MHz".format(self.program, self.frequency / 1000000)) + self._clearMeta() # Set metadata consumer def setMetaWriter(self, writer: Writer) -> None: @@ -91,6 +88,16 @@ class HdRadioModule(ThreadModule): logger.debug("Metadata: {0}".format(self.meta)) self.metaWriter.write(pickle.dumps(self.meta)) + # Clear all metadata + def _clearMeta(self) -> None: + with self.metaLock: + self.meta = { + "mode" : "HDR", + "frequency" : self.frequency, + "program" : self.program + } + self._writeMeta() + # Update existing metadata def _updateMeta(self, data) -> None: # Update station location on the map @@ -98,14 +105,15 @@ class HdRadioModule(ThreadModule): loc = StationLocation(data) Map.getSharedInstance().updateLocation(data["station"], loc, "HDR") # Update any new or different values - changes = 0 - for key in data.keys(): - if key not in self.meta or self.meta[key] != data[key]: - self.meta[key] = data[key] - changes = changes + 1 - # If anything changed, write metadata to the buffer - if changes > 0: - self._writeMeta() + with self.metaLock: + changes = 0 + for key in data.keys(): + if key not in self.meta or self.meta[key] != data[key]: + self.meta[key] = data[key] + changes = changes + 1 + # If anything changed, write metadata to the buffer + if changes > 0: + self._writeMeta() def run(self): # Start NRSC5 decoder @@ -223,11 +231,11 @@ class HdRadioModule(ThreadModule): meta["lon"] = evt.longitude meta["altitude"] = round(evt.altitude) for audio_service in evt.audio_services: - logger.info("Audio program %s: %s, type: %s, sound experience %s", - audio_service.program, - "public" if audio_service.access == Access.PUBLIC else "restricted", - self.radio.program_type_name(audio_service.type), - audio_service.sound_exp) + #logger.info("Audio program %s: %s, type: %s, sound experience %s", + # audio_service.program, + # "public" if audio_service.access == Access.PUBLIC else "restricted", + # self.radio.program_type_name(audio_service.type), + # audio_service.sound_exp) meta["audio_services"] += [{ "id" : audio_service.program, "type" : audio_service.type.value, @@ -236,10 +244,10 @@ class HdRadioModule(ThreadModule): "experience" : audio_service.sound_exp }] for data_service in evt.data_services: - logger.info("Data service: %s, type: %s, MIME type %03x", - "public" if data_service.access == Access.PUBLIC else "restricted", - self.radio.service_data_type_name(data_service.type), - data_service.mime_type) + #logger.info("Data service: %s, type: %s, MIME type %03x", + # "public" if data_service.access == Access.PUBLIC else "restricted", + # self.radio.service_data_type_name(data_service.type), + # data_service.mime_type) meta["data_services"] += [{ "mime" : data_service.mime_type, "type" : data_service.type.value, diff --git a/htdocs/css/openwebrx.css b/htdocs/css/openwebrx.css index 9bd63e17..76e46fff 100644 --- a/htdocs/css/openwebrx.css +++ b/htdocs/css/openwebrx.css @@ -1806,7 +1806,8 @@ img.openwebrx-mirror-img padding: 5px 0 5px 0; } -.hdr-container .hdr-selector { +.hdr-container .hdr-selector, +.hdr-container .hdr-genre { float: left; } diff --git a/htdocs/lib/MapMarkers.js b/htdocs/lib/MapMarkers.js index 996bbb8e..5dd07a19 100644 --- a/htdocs/lib/MapMarkers.js +++ b/htdocs/lib/MapMarkers.js @@ -569,10 +569,6 @@ AprsMarker.prototype.getInfoHTML = function(name, receiverMarker = null) { } } - // Linkify title based on what it is (vessel or HAM callsign) - var title = this.mode === 'AIS'? - Utils.linkifyVessel(name) : Utils.linkifyCallsign(name); - if (detailsString.length > 0) { detailsString = '
' + Utils.makeListTitle('Details') + detailsString + '
'; } @@ -591,9 +587,11 @@ AprsMarker.prototype.getInfoHTML = function(name, receiverMarker = null) { + hops.join(', ') + ' '; } - // Linkify title based on what it is (vessel or HAM callsign) - var title = this.mode === 'AIS'? - Utils.linkifyVessel(name) : Utils.linkifyCallsign(name); + // Linkify title based on what it is (station, vessel, or HAM callsign) + var title = + this.mode === 'HDR'? Utils.linkifyFM(name) + : this.mode === 'AIS'? Utils.linkifyVessel(name) + : Utils.linkifyCallsign(name); // Combine everything into info box contents return '

' + title + distance + '

' diff --git a/htdocs/lib/MetaPanel.js b/htdocs/lib/MetaPanel.js index 735c4964..c002460f 100644 --- a/htdocs/lib/MetaPanel.js +++ b/htdocs/lib/MetaPanel.js @@ -565,33 +565,28 @@ function HdrMetaPanel(el) { var $container = $( '
' + '
' + - '' + - '' + + '' + + '' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '' + '
' + - '
' + - '
' + - '
' + - '
' + '
' ); $(this.el).append($container); - // Create program selector - this.$select = $( - '' - ); - this.$select.on("change", function() { + var $select = $('#hdr-program-id'); + $select.hide(); + $select.on("change", function() { var id = parseInt($(this).val()); $('#openwebrx-panel-receiver').demodulatorPanel().getDemodulator().setAudioServiceId(id); }); - - $('.hdr-selector').append(this.$select); } HdrMetaPanel.prototype = new MetaPanel(); @@ -604,7 +599,7 @@ HdrMetaPanel.prototype.update = function(data) { if ('fcc_id' in data) { fcc_id = data.fcc_id.toString(16).toUpperCase(); fcc_id = '0x' + ('0000' + fcc_id).slice(-4); - fcc_id = ('country' in data? data.country + '-' : '') + fcc_id; + fcc_id = ('country' in data? data.country + ':' : '') + fcc_id; } // Update panel @@ -614,17 +609,22 @@ HdrMetaPanel.prototype.update = function(data) { $el.find('.hdr-message').text(data.alert || data.message || data.slogan || ''); $el.find('.hdr-title').text(data.title || ''); $el.find('.hdr-artist').text(data.artist || ''); + $el.find('.hdr-genre').text(data.genre || ''); + $el.find('.hdr-album').text(data.album || ''); // Update program selector - if ('audio_services' in data) { - this.$select.html(data.audio_services.map(function(pgm) { - return ''; + var $select = $('#hdr-program-id'); + if (!data.audio_services) { + $select.hide(); + $select.html(''); + } else { + $select.html(data.audio_services.map(function(pgm) { + var selected = data.program == pgm.id? ' selected' : ''; + return ''; }).join()); + $select.show(); } - - // Update program - if ('program' in data) this.$select.val(data.program); }; HdrMetaPanel.prototype.isSupported = function(data) { diff --git a/htdocs/lib/Utils.js b/htdocs/lib/Utils.js index 27aef7b0..62a970bf 100644 --- a/htdocs/lib/Utils.js +++ b/htdocs/lib/Utils.js @@ -4,6 +4,7 @@ function Utils() {} +Utils.fm_url = 'https://www.google.com/search?q={}+FM'; Utils.callsign_url = null; Utils.vessel_url = null; Utils.flight_url = null; @@ -96,6 +97,11 @@ Utils.linkify = function(id, url = null, content = null, tip = null) { } }; +// Create link to an FM station +Utils.linkifyFM = function(name) { + return this.linkify(name, this.fm_url); +}; + // Create link to a callsign, with country tooltip, etc. Utils.linkifyCallsign = function(callsign) { // Strip callsign of modifiers