1
0
mirror of https://github.com/KubaPro010/fm-dx-webserver.git synced 2026-02-26 22:13:53 +01:00

lotta bugfixes

This commit is contained in:
Marek Farkaš
2025-04-19 21:49:11 +02:00
parent cbefdb7c1f
commit 9f5f0522bb
15 changed files with 82 additions and 35 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "fm-dx-webserver", "name": "fm-dx-webserver",
"version": "1.3.6", "version": "1.3.6.1",
"description": "FM DX Webserver", "description": "FM DX Webserver",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View File

@@ -206,7 +206,6 @@ const updateInterval = 75;
var dataToSend = { var dataToSend = {
pi: '?', pi: '?',
freq: 87.500.toFixed(3), freq: 87.500.toFixed(3),
prevFreq: 87.500.toFixed(3),
sig: 0, sig: 0,
sigRaw: '', sigRaw: '',
sigTop: -Infinity, sigTop: -Infinity,

View File

@@ -43,6 +43,7 @@ let serverConfig = {
audioDevice: "Microphone (High Definition Audio Device)", audioDevice: "Microphone (High Definition Audio Device)",
audioChannels: 2, audioChannels: 2,
audioBitrate: "128k", audioBitrate: "128k",
audioBoost: false,
softwareMode: false, softwareMode: false,
startupVolume: "0.95" startupVolume: "0.95"
}, },

View File

@@ -9,7 +9,7 @@ function enableAudioStream() {
const flags = `-fflags +nobuffer+flush_packets -flags low_delay -rtbufsize 6192 -probesize 32`; const flags = `-fflags +nobuffer+flush_packets -flags low_delay -rtbufsize 6192 -probesize 32`;
const codec = `-acodec pcm_s16le -ar 48000 -ac ${serverConfig.audio.audioChannels}`; const codec = `-acodec pcm_s16le -ar 48000 -ac ${serverConfig.audio.audioChannels}`;
const output = `-f s16le -fflags +nobuffer+flush_packets -packetsize 384 -flush_packets 1 -bufsize 960`; const output = `${serverConfig.audio.audioBoost == true ? '$-af "volume=3.5"' : ''} -f s16le -fflags +nobuffer+flush_packets -packetsize 384 -flush_packets 1 -bufsize 960`;
if (process.platform === 'win32') { if (process.platform === 'win32') {
// Windows // Windows

View File

@@ -7,6 +7,8 @@ let lastFetchTime = 0;
const fetchInterval = 1000; const fetchInterval = 1000;
const esSwitchCache = {"lastCheck":0, "esSwitch":false}; const esSwitchCache = {"lastCheck":0, "esSwitch":false};
const esFetchInterval = 300000; const esFetchInterval = 300000;
var currentPiCode = '';
var currentRdsPs = '';
const usStatesGeoJsonUrl = "https://raw.githubusercontent.com/PublicaMundi/MappingAPI/master/data/geojson/us-states.json"; const usStatesGeoJsonUrl = "https://raw.githubusercontent.com/PublicaMundi/MappingAPI/master/data/geojson/us-states.json";
let usStatesGeoJson = null; // To cache the GeoJSON data for US states let usStatesGeoJson = null; // To cache the GeoJSON data for US states
@@ -73,7 +75,11 @@ async function fetchTx(freq, piCode, rdsPs) {
if (isNaN(freq)) { if (isNaN(freq)) {
return; return;
} }
if (now - lastFetchTime < fetchInterval || serverConfig.identification.lat.length < 2 || freq < 87) { if (now - lastFetchTime < fetchInterval
|| serverConfig.identification.lat.length < 2
|| freq < 87
|| (currentPiCode == piCode && currentRdsPs == rdsPs))
{
return Promise.resolve(); return Promise.resolve();
} }
@@ -90,7 +96,7 @@ async function fetchTx(freq, piCode, rdsPs) {
if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`); if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
const data = await response.json(); const data = await response.json();
cachedData[freq] = data; cachedData[freq] = data;
await loadUsStatesGeoJson(); if(serverConfig.webserver.rdsMode == true) await loadUsStatesGeoJson();
return processData(data, piCode, rdsPs); return processData(data, piCode, rdsPs);
} catch (error) { } catch (error) {
console.error("Error fetching data:", error); console.error("Error fetching data:", error);
@@ -106,6 +112,8 @@ async function processData(data, piCode, rdsPs) {
let maxDistance; let maxDistance;
let esMode = checkEs(); let esMode = checkEs();
let detectedByPireg = false; let detectedByPireg = false;
currentPiCode = piCode;
currentRdsPs = rdsPs;
function evaluateStation(station, city, distance) { function evaluateStation(station, city, distance) {
let weightDistance = distance.distanceKm; let weightDistance = distance.distanceKm;

View File

@@ -305,7 +305,7 @@ table .input-text {
.hide-phone { .hide-phone {
display: none; display: none;
} }
.m-0 { .m-0, .center-phone {
margin: auto !important; margin: auto !important;
} }
} }

View File

@@ -105,6 +105,10 @@ a:hover {
border-bottom: 1px solid var(--color-4); border-bottom: 1px solid var(--color-4);
} }
a.hide-underline:hover {
border-bottom: none;
}
hr { hr {
color: var(--color-4); color: var(--color-4);
} }

View File

@@ -345,7 +345,8 @@
<hr class="hide-desktop"> <hr class="hide-desktop">
</div> </div>
<div class="panel-33 hover-brighten tooltip" data-tooltip="This panel contains the current TX info when RDS is loaded.<br><strong>Clicking on this panel copies the info into the clipboard.</strong>"> <div class="panel-33 hover-brighten tooltip" style="min-height: 91px;"
data-tooltip="This panel contains the current TX info when RDS is loaded.<br><strong>Clicking on this panel copies the info into the clipboard.</strong>">
<div id="data-station-container"> <div id="data-station-container">
<h2 style="margin-top: 0;" class="mb-0"> <h2 style="margin-top: 0;" class="mb-0">
<span id="data-station-name"></span> <span id="data-station-name"></span>
@@ -362,7 +363,7 @@
</div> </div>
<div class="panel-10 no-bg" style="margin-left: 0; margin-top: 0; margin-right: 0;display:flex;"> <div class="panel-10 no-bg center-phone" style="margin-left: 0; margin-top: 0; margin-right: 0;display:flex;">
<div class="panel-100" style="margin-left: 0;"> <div class="panel-100" style="margin-left: 0;">
<h2 class="bottom-10">AF</h2> <h2 class="bottom-10">AF</h2>
<div id="af-list" style="text-align: center;"> <div id="af-list" style="text-align: center;">

View File

@@ -34,14 +34,20 @@ function OnConnectivityCallback(isConnected) {
} }
} }
function isIOS() {
return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
}
function OnPlayButtonClick(_ev) { function OnPlayButtonClick(_ev) {
const $playbutton = $('.playbutton'); const $playbutton = $('.playbutton');
const isiOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
if (Stream) { if (Stream) {
console.log("Stopping stream..."); console.log("Stopping stream...");
shouldReconnect = false; shouldReconnect = false;
destroyStream(); destroyStream();
$playbutton.find('.fa-solid').toggleClass('fa-stop fa-play'); $playbutton.find('.fa-solid').toggleClass('fa-stop fa-play');
if ('audioSession' in navigator) { if (isiOS && 'audioSession' in navigator) {
navigator.audioSession.type = "none"; navigator.audioSession.type = "none";
} }
} else { } else {
@@ -50,10 +56,11 @@ function OnPlayButtonClick(_ev) {
createStream(); createStream();
Stream.Start(); Stream.Start();
$playbutton.find('.fa-solid').toggleClass('fa-play fa-stop'); $playbutton.find('.fa-solid').toggleClass('fa-play fa-stop');
if ('audioSession' in navigator) { if (isiOS && 'audioSession' in navigator) {
navigator.audioSession.type = "playback"; // Android background play fix navigator.audioSession.type = "playback";
} }
} }
$playbutton.addClass('bg-gray').prop('disabled', true); $playbutton.addClass('bg-gray').prop('disabled', true);
setTimeout(() => { setTimeout(() => {
$playbutton.removeClass('bg-gray').prop('disabled', false); $playbutton.removeClass('bg-gray').prop('disabled', false);

View File

@@ -40,6 +40,7 @@ function tuneDown() {
} }
function tuneTo(freq) { function tuneTo(freq) {
previousFreq = getCurrentFreq();
socket.send("T" + ((freq).toFixed(1) * 1000)); socket.send("T" + ((freq).toFixed(1) * 1000));
} }

View File

@@ -96,6 +96,8 @@ function populateFields(data, prefix = "") {
$element.val(value); $element.val(value);
} }
}); });
updateIconState();
} }
function updateConfigData(data, prefix = "") { function updateConfigData(data, prefix = "") {

View File

@@ -1,9 +1,9 @@
var currentDate = new Date('Feb 23, 2025 15:30:00'); var currentDate = new Date('Apr 19, 2025 21:30:00');
var day = currentDate.getDate(); var day = currentDate.getDate();
var month = currentDate.getMonth() + 1; // Months are zero-indexed, so add 1 var month = currentDate.getMonth() + 1; // Months are zero-indexed, so add 1
var year = currentDate.getFullYear(); var year = currentDate.getFullYear();
var formattedDate = day + '/' + month + '/' + year; var formattedDate = day + '/' + month + '/' + year;
var currentVersion = 'v1.3.6 [' + formattedDate + ']'; var currentVersion = 'v1.3.6.1 [' + formattedDate + ']';
getInitialSettings(); getInitialSettings();
removeUrlParameters(); removeUrlParameters();

View File

@@ -722,7 +722,6 @@ function checkKey(e) {
// Handle default case if needed // Handle default case if needed
break; break;
} }
previousFreq = currentFreq;
} }
} }
@@ -1190,13 +1189,25 @@ function initTooltips(target = null) {
}); });
} }
function fillPresets() { function fillPresets() {
let hasAnyPreset = false;
for (let i = 1; i <= 4; i++) { for (let i = 1; i <= 4; i++) {
let presetText = localStorage.getItem(`preset${i}`); let presetText = localStorage.getItem(`preset${i}`);
$(`#preset${i}-text`).text(presetText);
$(`#preset${i}`).click(function() { if (presetText != "null") {
tuneTo(Number(presetText)); hasAnyPreset = true;
}); $(`#preset${i}-text`).text(presetText);
$(`#preset${i}`).click(function() {
tuneTo(Number(presetText));
});
} else {
$(`#preset${i}`).hide();
}
} }
}
if (!hasAnyPreset) {
$('#preset1').parent().hide();
}
}

View File

@@ -166,12 +166,10 @@ $(document).ready(() => {
$('.version-string').text(currentVersion); $('.version-string').text(currentVersion);
setBg(); setBg();
updateIconState();
// Update icons when the checkbox state changes // Update icons when the checkbox state changes
$('input[type="checkbox"]').change(function() { $('input[type="checkbox"]').change(function() {
updateIconState(); updateIconState(this);
}); });
}); });
@@ -180,15 +178,27 @@ function getQueryParameter(name) {
return urlParams.get(name); return urlParams.get(name);
} }
function updateIconState() { function updateIconState(el) {
$('input[type="checkbox"]').each(function() { // If an element is passed, update only that one
var icon = $(this).siblings('label').find('i'); if (el) {
if ($(this).is(':checked')) { var $checkbox = $(el);
var icon = $checkbox.siblings('label').find('i');
if ($checkbox.is(':checked')) {
icon.removeClass('fa-toggle-off').addClass('fa-toggle-on'); icon.removeClass('fa-toggle-off').addClass('fa-toggle-on');
} else { } else {
icon.removeClass('fa-toggle-on').addClass('fa-toggle-off'); icon.removeClass('fa-toggle-on').addClass('fa-toggle-off');
} }
}); } else {
// Otherwise, update all checkboxes
$('input[type="checkbox"]').each(function() {
var icon = $(this).siblings('label').find('i');
if ($(this).is(':checked')) {
icon.removeClass('fa-toggle-off').addClass('fa-toggle-on');
} else {
icon.removeClass('fa-toggle-on').addClass('fa-toggle-off');
}
});
}
} }
function setTheme(themeName) { function setTheme(themeName) {

View File

@@ -85,8 +85,7 @@
</div> </div>
</div> </div>
<div class="flex-container"> <div class="panel-100-real p-bottom-20" style="overflow-x: auto;">
<div class="panel-50 p-bottom-20" style="overflow-x: auto;">
<h3>Current users</h3> <h3>Current users</h3>
<table class="table-big"> <table class="table-big">
<thead> <thead>
@@ -120,7 +119,7 @@
</table> </table>
</div> </div>
<div class="panel-50 p-bottom-20"> <div class="panel-100-real p-bottom-20">
<h3>Quick settings</h3> <h3>Quick settings</h3>
<div class="flex-container flex-center" style="margin: 30px;"> <div class="flex-container flex-center" style="margin: 30px;">
<%- include('_components', {component: 'checkbox', cssClass: '', label: 'Public Tuner', id: 'publicTuner'}) %> <%- include('_components', {component: 'checkbox', cssClass: '', label: 'Public Tuner', id: 'publicTuner'}) %>
@@ -130,7 +129,6 @@
<%- include('_components', {component: 'text', cssClass: 'w-150 br-15', placeholder: '', label: 'Tune password', id: 'password-tunePass', password: true}) %> <%- include('_components', {component: 'text', cssClass: 'w-150 br-15', placeholder: '', label: 'Tune password', id: 'password-tunePass', password: true}) %>
<%- include('_components', {component: 'text', cssClass: 'w-150 br-15', placeholder: '', label: 'Admin password', id: 'password-adminPass', password: true}) %><br> <%- include('_components', {component: 'text', cssClass: 'w-150 br-15', placeholder: '', label: 'Admin password', id: 'password-adminPass', password: true}) %><br>
</div> </div>
</div>
<div class="flex-container"> <div class="flex-container">
<div class="panel-100-real p-bottom-20 bottom-20"> <div class="panel-100-real p-bottom-20 bottom-20">
@@ -208,8 +206,13 @@
</div> </div>
<div class="flex-container"> <div class="flex-container">
<div class="panel-100-real p-bottom-20"> <div class="panel-50 p-bottom-20">
<h3>Miscellaneous</h3> <h3>Volume</h3>
<p>This option will boost the audio volume globally, recommended for the Headless TEF.</p>
<%- include('_components', {component: 'checkbox', cssClass: '', label: 'Audio Boost', id: 'audio-audioBoost'}) %>
</div>
<div class="panel-50 p-bottom-20">
<h3>Experimental</h3>
<p>If you use an USB audio card on Linux, enabling this option might fix your audio issues.</p> <p>If you use an USB audio card on Linux, enabling this option might fix your audio issues.</p>
<%- include('_components', {component: 'checkbox', cssClass: '', label: 'ALSA Software mode', id: 'audio-softwareMode'}) %> <%- include('_components', {component: 'checkbox', cssClass: '', label: 'ALSA Software mode', id: 'audio-softwareMode'}) %>
</div> </div>
@@ -524,7 +527,7 @@
</div> </div>
<div class="panel-100 p-bottom-20"> <div class="panel-100 p-bottom-20">
<h3>Tunnel</h3> <h3>Tunnel</h3>
<p>When you become a <a href="https://buymeacoffee.com/fmdx" target="_blank"><strong>FMDX.org supporter</strong></a>, you can host your webserver without the need of a public IP address.<br> <p>When you become an <a href="https://buymeacoffee.com/fmdx" target="_blank"><strong>FMDX.org supporter</strong></a>, you can host your webserver without the need of a public IP address & port forwarding.<br>
When you become a supporter, you can message the Founders on Discord for your login details.</p> When you become a supporter, you can message the Founders on Discord for your login details.</p>
<%- include('_components', {component: 'checkbox', cssClass: 'm-right-10', label: 'Enable tunnel', id: 'tunnel-enabled'}) %><br> <%- include('_components', {component: 'checkbox', cssClass: 'm-right-10', label: 'Enable tunnel', id: 'tunnel-enabled'}) %><br>