You've already forked fm-dx-webserver
mirror of
https://github.com/KubaPro010/fm-dx-webserver.git
synced 2026-02-26 22:13:53 +01:00
Merge branch 'main' into main
This commit is contained in:
@@ -547,7 +547,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="toast-container"></div>
|
||||
<div id="toast-container" aria-live="polite"></div>
|
||||
<script src="js/websocket.js"></script>
|
||||
<script src="js/webserver.js"></script>
|
||||
<% if (!noPlugins) { %>
|
||||
|
||||
@@ -41,7 +41,7 @@ function tuneDown() {
|
||||
|
||||
function tuneTo(freq) {
|
||||
previousFreq = getCurrentFreq();
|
||||
socket.send("T" + ((parseFloat(freq)) * 1000).toFixed(3));
|
||||
socket.send("T" + ((parseFloat(freq)) * 1000).toFixed(0));
|
||||
}
|
||||
|
||||
function resetRDS() {
|
||||
|
||||
@@ -6,6 +6,7 @@ var parsedData, signalChart, previousFreq;
|
||||
var data = [];
|
||||
var signalData = [];
|
||||
let updateCounter = 0;
|
||||
let lastReconnectAttempt = 0;
|
||||
let messageCounter = 0; // Count for WebSocket data length returning 0
|
||||
let messageData = 800; // Initial value anything above 0
|
||||
let messageLength = 800; // Retain value of messageData until value is updated
|
||||
@@ -375,10 +376,16 @@ function sendPingRequest() {
|
||||
messageCounter = 0;
|
||||
}
|
||||
|
||||
// Automatic reconnection on WebSocket close
|
||||
if (socket.readyState === WebSocket.CLOSED || socket.readyState === WebSocket.CLOSING) {
|
||||
// Automatic reconnection on WebSocket close with cooldown
|
||||
const now = Date.now();
|
||||
if (
|
||||
(socket.readyState === WebSocket.CLOSED || socket.readyState === WebSocket.CLOSING) &&
|
||||
(now - lastReconnectAttempt > TIMEOUT_DURATION)
|
||||
) {
|
||||
lastReconnectAttempt = now;
|
||||
|
||||
socket = new WebSocket(socketAddress);
|
||||
|
||||
|
||||
socket.onopen = () => {
|
||||
sendToast('info', 'Connected', 'Reconnected successfully!', false, false);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const versionDate = new Date('May 30, 2025 21:00:00');
|
||||
const currentVersion = `v1.3.9 [${versionDate.getDate()}/${versionDate.getMonth() + 1}/${versionDate.getFullYear()}]`;
|
||||
const versionDate = new Date('Aug 30, 2025 21:00:00');
|
||||
const currentVersion = `v1.3.10 [${versionDate.getDate()}/${versionDate.getMonth() + 1}/${versionDate.getFullYear()}]`;
|
||||
|
||||
|
||||
function loadScript(src) {
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
var url = new URL('text', window.location.href);
|
||||
url.protocol = url.protocol.replace('http', 'ws');
|
||||
var socketAddress = url.href;
|
||||
var socket = new WebSocket(socketAddress);
|
||||
if (!window.socket || window.socket.readyState === WebSocket.CLOSED || window.socket.readyState === WebSocket.CLOSING) {
|
||||
var url = new URL('text', window.location.href);
|
||||
url.protocol = url.protocol.replace('http', 'ws');
|
||||
var socketAddress = url.href;
|
||||
var socket = new WebSocket(socketAddress);
|
||||
|
||||
const socketPromise = new Promise((resolve, reject) => {
|
||||
// Event listener for when the WebSocket connection is open
|
||||
socket.addEventListener('open', () => {
|
||||
console.log('WebSocket connection open');
|
||||
resolve(socket); // Resolve the promise with the WebSocket instance
|
||||
window.socket = socket;
|
||||
|
||||
const socketPromise = new Promise((resolve, reject) => {
|
||||
socket.addEventListener('open', () => {
|
||||
console.log('WebSocket connection open');
|
||||
resolve(socket);
|
||||
});
|
||||
|
||||
socket.addEventListener('error', (error) => {
|
||||
console.error('WebSocket error', error);
|
||||
reject(error);
|
||||
});
|
||||
|
||||
socket.addEventListener('close', () => {
|
||||
setTimeout(() => {
|
||||
console.warn('WebSocket connection closed');
|
||||
}, 100);
|
||||
reject(new Error('WebSocket connection closed'));
|
||||
});
|
||||
});
|
||||
|
||||
// Event listener for WebSocket errors
|
||||
socket.addEventListener('error', (error) => {
|
||||
console.error('WebSocket error', error);
|
||||
reject(error); // Reject the promise on error
|
||||
});
|
||||
|
||||
// Event listener for WebSocket connection closure
|
||||
socket.addEventListener('close', () => {
|
||||
console.warn('WebSocket connection closed');
|
||||
reject(new Error('WebSocket connection closed')); // Reject with closure warning
|
||||
});
|
||||
});
|
||||
|
||||
// Assign the socketPromise to window.socketPromise for global access
|
||||
window.socketPromise = socketPromise;
|
||||
|
||||
// Assign the socket instance to window.socket for global access
|
||||
window.socket = socket;
|
||||
window.socketPromise = socketPromise;
|
||||
}
|
||||
|
||||
134
web/setup.ejs
134
web/setup.ejs
@@ -39,6 +39,9 @@
|
||||
<li role="tab" data-panel="users" tabindex="0">
|
||||
<a href="#" role="tab" tabindex="-1" aria-controls="users"><i class="fa-solid fa-fw fa-user"></i> User management</a>
|
||||
</li>
|
||||
<li role="tab" data-panel="startup" tabindex="0">
|
||||
<a href="#" role="tab" tabindex="-1" aria-controls="startup"><i class="fa-solid fa-fw fa-plug"></i> Startup</a>
|
||||
</li>
|
||||
<li role="tab" data-panel="extras" tabindex="0">
|
||||
<a href="#" role="tab" tabindex="-1" aria-controls="extras"><i class="fa-solid fa-fw fa-star"></i> Extras</a>
|
||||
</li>
|
||||
@@ -76,6 +79,7 @@
|
||||
|
||||
<div class="panel-33 p-20">
|
||||
<span class="text-medium-big color-5"><%= memoryUsage %></span>
|
||||
<span class="text-small color-4" style="display: block; font-size: 1em; font-weight: 600; line-height: 0;">(<%= memoryHeap %> heap)</span>
|
||||
<p>Memory usage</p>
|
||||
</div>
|
||||
|
||||
@@ -217,18 +221,18 @@
|
||||
</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 a 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'}) %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-container">
|
||||
<div class="panel-50 p-bottom-20">
|
||||
<div class="panel-50 p-bottom-20 bottom-20">
|
||||
<h3>FFmpeg</h3>
|
||||
<p>Legacy option for Linux / macOS that could resolve audio issues, but will consume additional CPU and RAM usage.</p>
|
||||
<%- include('_components', {component: 'checkbox', cssClass: '', label: 'Additional FFmpeg', id: 'audio-ffmpeg'}) %>
|
||||
</div>
|
||||
<div class="panel-50 p-botom-20">
|
||||
<h3>Sample rate Offset</h3>
|
||||
<div class="panel-50 p-bottom-20 bottom-20">
|
||||
<h3>Sample rate offset</h3>
|
||||
<p>Using a negative value could eliminate audio buffering issues during long periods of listening. <br>
|
||||
However, a value that’s too low might increase the buffer over time.</p>
|
||||
<p><input class="panel-33 input-text w-100 auto" type="number" style="min-height: 40px; color: var(--color-text); padding: 10px; padding-left: 10px; box-sizing: border-box; border: 2px solid transparent; font-family: 'Titillium Web', sans-serif;" id="audio-samplerateOffset" min="-10" max="10" step="1" value="0" aria-label="Samplerate offset"></p>
|
||||
@@ -330,7 +334,7 @@
|
||||
|
||||
<%- include('_components', {component: 'text', cssClass: 'w-100', placeholder: '0', label: 'RDS Timeout', id: 'webserver-rdsTimeout'}) %>
|
||||
</div>
|
||||
<div class="panel-50 p-bottom-20" style="padding-left: 20px; padding-right: 20px;">
|
||||
<div class="panel-50 p-bottom-20" style="padding-left: 20px; padding-right: 20px; padding-bottom: 80px;">
|
||||
<h3>Transmitter Search Algorithm</h3>
|
||||
<p>Different modes may help with more accurate transmitter identification depending on your region.</p>
|
||||
<%- include('_components', { component: 'dropdown', id: 'server-tx-id-algo', inputId: 'webserver-txIdAlgorithm', label: 'Transmitter ID Algorithm', cssClass: '', placeholder: 'Algorithm 1',
|
||||
@@ -559,6 +563,126 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-full m-0 tab-content no-bg" id="startup" role="tabpanel">
|
||||
<h2>Startup settings</h2>
|
||||
<div class="flex-container">
|
||||
<div class="panel-100-real p-bottom-20" style="z-index: 10; padding-bottom: 120px;">
|
||||
<h3>On startup</h3>
|
||||
<p>These settings will be applied after a server launch or restart.</p>
|
||||
<div class="flex-container flex-center p-20">
|
||||
<% if (device === 'tef') { %>
|
||||
<%- include('_components', { component: 'dropdown', id: 'ceqStartup-dropdown', inputId: 'ceqStartup', label: 'cEQ', cssClass: '', placeholder: 'Disabled',
|
||||
options: [
|
||||
{ value: '0', label: 'Disabled' },
|
||||
{ value: '1', label: 'Enabled' },
|
||||
]
|
||||
}) %><br>
|
||||
<%- include('_components', { component: 'dropdown', id: 'imsStartup-dropdown', inputId: 'imsStartup', label: 'iMS', cssClass: '', placeholder: 'Disabled',
|
||||
options: [
|
||||
{ value: '0', label: 'Disabled' },
|
||||
{ value: '1', label: 'Enabled' },
|
||||
]
|
||||
}) %><br>
|
||||
<% } else if (device === 'xdr') { %>
|
||||
<%- include('_components', { component: 'dropdown', id: 'rfStartup-dropdown', inputId: 'ceqStartup', label: 'RF+', cssClass: '', placeholder: 'Disabled',
|
||||
options: [
|
||||
{ value: '0', label: 'Disabled' },
|
||||
{ value: '1', label: 'Enabled' },
|
||||
]
|
||||
}) %><br>
|
||||
<%- include('_components', { component: 'dropdown', id: 'ifStartup-dropdown', inputId: 'imsStartup', label: 'IF+', cssClass: '', placeholder: 'Disabled',
|
||||
options: [
|
||||
{ value: '0', label: 'Disabled' },
|
||||
{ value: '1', label: 'Enabled' },
|
||||
]
|
||||
}) %><br>
|
||||
<% } %>
|
||||
<%- include('_components', { component: 'dropdown', id: 'stereoStartup-dropdown', inputId: 'stereoStartup', label: 'Stereo Mode', cssClass: '', placeholder: 'Stereo (Default)',
|
||||
options: [
|
||||
{ value: '0', label: 'Stereo (Default)' },
|
||||
{ value: '1', label: 'Mono' },
|
||||
]
|
||||
}) %><br>
|
||||
</div>
|
||||
<div class="panel-100-real p-bottom-20 no-bg">
|
||||
<%- include('_components', { component: 'dropdown', id: 'antennaStartup-dropdown', inputId: 'antennaStartup', label: 'Antenna', cssClass: '', placeholder: 'Antenna 0 (Default)',
|
||||
options: [
|
||||
{ value: '0', label: 'Antenna 0 (Default)' },
|
||||
{ value: '1', label: 'Antenna 1' },
|
||||
{ value: '2', label: 'Antenna 2' },
|
||||
{ value: '3', label: 'Antenna 3' },
|
||||
]
|
||||
}) %><br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-container">
|
||||
<div class="panel-100-real p-bottom-20 bottom-20" style="z-index: 9; padding-bottom: 180px;">
|
||||
<h3>Empty server defaults</h3>
|
||||
<p>These settings will apply once the last user disconnects from the server, so the server can be ready for a new user with default settings.</p>
|
||||
<div class="flex-container flex-center p-20">
|
||||
<%- include('_components', { component: 'dropdown', id: 'bwAutoNoUsers-dropdown', inputId: 'bwAutoNoUsers', label: 'Auto BW', cssClass: '', placeholder: 'Unchanged',
|
||||
options: [
|
||||
{ value: '0', label: 'Unchanged' },
|
||||
{ value: '1', label: 'Enabled' },
|
||||
]
|
||||
}) %><br>
|
||||
<% if (device === 'tef') { %>
|
||||
<%- include('_components', { component: 'dropdown', id: 'ceqNoUsers-dropdown', inputId: 'ceqNoUsers', label: 'cEQ', cssClass: '', placeholder: 'Unchanged',
|
||||
options: [
|
||||
{ value: '0', label: 'Unchanged' },
|
||||
{ value: '1', label: 'Disabled' },
|
||||
{ value: '2', label: 'Enabled' },
|
||||
]
|
||||
}) %><br>
|
||||
<%- include('_components', { component: 'dropdown', id: 'imsNoUsers-dropdown', inputId: 'imsNoUsers', label: 'iMS', cssClass: '', placeholder: 'Unchanged',
|
||||
options: [
|
||||
{ value: '0', label: 'Unchanged' },
|
||||
{ value: '1', label: 'Disabled' },
|
||||
{ value: '2', label: 'Enabled' },
|
||||
]
|
||||
}) %><br>
|
||||
<% } else if (device === 'xdr') { %>
|
||||
<%- include('_components', { component: 'dropdown', id: 'rfNoUsers-dropdown', inputId: 'ceqNoUsers', label: 'RF+', cssClass: '', placeholder: 'Unchanged',
|
||||
options: [
|
||||
{ value: '0', label: 'Unchanged' },
|
||||
{ value: '1', label: 'Disabled' },
|
||||
{ value: '2', label: 'Enabled' },
|
||||
]
|
||||
}) %><br>
|
||||
<%- include('_components', { component: 'dropdown', id: 'ifNoUsers-dropdown', inputId: 'imsNoUsers', label: 'IF+', cssClass: '', placeholder: 'Unchanged',
|
||||
options: [
|
||||
{ value: '0', label: 'Unchanged' },
|
||||
{ value: '1', label: 'Disabled' },
|
||||
{ value: '2', label: 'Enabled' },
|
||||
]
|
||||
}) %><br>
|
||||
<% } %>
|
||||
<%- include('_components', { component: 'dropdown', id: 'stereoNoUsers-dropdown', inputId: 'stereoNoUsers', label: 'Stereo Mode', cssClass: '', placeholder: 'Unchanged',
|
||||
options: [
|
||||
{ value: '0', label: 'Unchanged' },
|
||||
{ value: '1', label: 'Stereo' },
|
||||
{ value: '2', label: 'Mono' },
|
||||
]
|
||||
}) %><br>
|
||||
</div>
|
||||
<div class="panel-100-real p-bottom-20 no-bg">
|
||||
<%- include('_components', {component: 'checkbox', cssClass: '', label: 'Delayed Antenna Change', id: 'antennaNoUsersDelay'}) %><br>
|
||||
<%- include('_components', { component: 'dropdown', id: 'antennaNoUsers-dropdown', inputId: 'antennaNoUsers', label: 'Antenna', cssClass: '', placeholder: 'Unchanged',
|
||||
options: [
|
||||
{ value: '0', label: 'Unchanged' },
|
||||
{ value: '1', label: 'Antenna 0' },
|
||||
{ value: '2', label: 'Antenna 1' },
|
||||
{ value: '3', label: 'Antenna 2' },
|
||||
{ value: '4', label: 'Antenna 3' },
|
||||
]
|
||||
}) %>
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-full m-0 tab-content no-bg" id="extras" role="tabpanel">
|
||||
<h2>Extras</h2>
|
||||
<div class="panel-100 p-bottom-20">
|
||||
|
||||
Reference in New Issue
Block a user