mirror of
https://github.com/KubaPro010/fm-dx-webserver.git
synced 2026-07-30 16:59:15 +02:00
something
This commit is contained in:
@@ -1,10 +1 @@
|
|||||||
require('./server/index.js');
|
require('./server/index.js');
|
||||||
|
|
||||||
/**
|
|
||||||
* FM-DX Webserver
|
|
||||||
*
|
|
||||||
* Github repo: https://github.com/KubaPro010/fm-dx-webserver
|
|
||||||
* Server files: /server
|
|
||||||
* Client files (web): /web
|
|
||||||
* Plugin files: /plugins
|
|
||||||
*/
|
|
||||||
+4
-6
@@ -19,11 +19,6 @@ function createChatServer(storage) {
|
|||||||
const clientIp = helpers.getIpAddress(request);
|
const clientIp = helpers.getIpAddress(request);
|
||||||
const userCommandHistory = {};
|
const userCommandHistory = {};
|
||||||
|
|
||||||
if (serverConfig.webserver.banlist?.includes(clientIp)) {
|
|
||||||
ws.close(1008, 'Banned IP');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send chat history safely
|
// Send chat history safely
|
||||||
storage.chatHistory.forEach((message) => {
|
storage.chatHistory.forEach((message) => {
|
||||||
const historyMessage = { ...message, history: true };
|
const historyMessage = { ...message, history: true };
|
||||||
@@ -77,7 +72,10 @@ function createChatServer(storage) {
|
|||||||
const now = new Date();
|
const now = new Date();
|
||||||
messageData.time = String(now.getHours()).padStart(2, '0') + ":" + String(now.getMinutes()).padStart(2, '0');
|
messageData.time = String(now.getHours()).padStart(2, '0') + ":" + String(now.getMinutes()).padStart(2, '0');
|
||||||
|
|
||||||
if (serverConfig.webserver.banlist?.includes(clientIp)) return;
|
if (serverConfig.webserver.banlist?.includes(clientIp)) {
|
||||||
|
ws.close(1008, 'Banned IP');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (request.session?.isAdminAuthenticated === true) messageData.admin = true;
|
if (request.session?.isAdminAuthenticated === true) messageData.admin = true;
|
||||||
if (messageData.nickname?.length > 32) messageData.nickname = messageData.nickname.substring(0, 32);
|
if (messageData.nickname?.length > 32) messageData.nickname = messageData.nickname.substring(0, 32);
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@ const path = require('path');
|
|||||||
const https = require('https');
|
const https = require('https');
|
||||||
|
|
||||||
// File Imports
|
// File Imports
|
||||||
const { parseAudioDevice } = require('./stream/parser');
|
const parseAudioDevice = require('./stream/parser');
|
||||||
const { configName, serverConfig, configUpdate, configSave, configExists, configPath } = require('./server_config');
|
const { configName, serverConfig, configUpdate, configSave, configExists, configPath } = require('./server_config');
|
||||||
const helpers = require('./helpers');
|
const helpers = require('./helpers');
|
||||||
const storage = require('./storage');
|
const storage = require('./storage');
|
||||||
|
|||||||
+12
-35
@@ -42,7 +42,7 @@ const plugins = findServerFiles(serverConfig.plugins);
|
|||||||
if (plugins.length > 0) {
|
if (plugins.length > 0) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
startPluginsWithDelay(plugins, 3000); // Start plugins with 3 seconds interval
|
startPluginsWithDelay(plugins, 3000); // Start plugins with 3 seconds interval
|
||||||
}, 3000); // Initial delay of 3 seconds for the first plugin
|
}, 4000); // Initial delay of 4 seconds for the first plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
const terminalWidth = readline.createInterface({input: process.stdin, output: process.stdout}).output.columns;
|
const terminalWidth = readline.createInterface({input: process.stdin, output: process.stdout}).output.columns;
|
||||||
@@ -52,8 +52,7 @@ console.log('\x1b[32m\x1b[2mby Noobish @ \x1b[4mFMDX.org + KubaPro010\x1b[0m');
|
|||||||
console.log("v" + pjson.version)
|
console.log("v" + pjson.version)
|
||||||
console.log('\x1b[90m' + '─'.repeat(terminalWidth - 1) + '\x1b[0m');
|
console.log('\x1b[90m' + '─'.repeat(terminalWidth - 1) + '\x1b[0m');
|
||||||
|
|
||||||
const audioWss = require('./stream/ws.js');
|
require('./stream/ws.js');
|
||||||
storage.websocket_delegation.set("/audio", audioWss);
|
|
||||||
require('./stream/index');
|
require('./stream/index');
|
||||||
require('./plugins');
|
require('./plugins');
|
||||||
|
|
||||||
@@ -97,16 +96,13 @@ setInterval(() => {
|
|||||||
function connectToSerial() {
|
function connectToSerial() {
|
||||||
if (serverConfig.xdrd.wirelessConnection === true) return;
|
if (serverConfig.xdrd.wirelessConnection === true) return;
|
||||||
|
|
||||||
// Configure the SerialPort with DTR and RTS options
|
|
||||||
serialport = new SerialPort({
|
serialport = new SerialPort({
|
||||||
path: serverConfig.xdrd.comPort,
|
path: serverConfig.xdrd.comPort,
|
||||||
baudRate: 115200,
|
baudRate: 115200,
|
||||||
autoOpen: false, // Prevents automatic opening
|
autoOpen: false,
|
||||||
dtr: false, // Disable DTR
|
dtr: false, rts: false
|
||||||
rts: false // Disable RTS
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Open the port manually after configuring DTR and RTS
|
|
||||||
serialport.open((err) => {
|
serialport.open((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logError('Error opening port: ' + err.message);
|
logError('Error opening port: ' + err.message);
|
||||||
@@ -121,7 +117,7 @@ function connectToSerial() {
|
|||||||
pluginsApi.setOutput(serialport);
|
pluginsApi.setOutput(serialport);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
serialport.write('x\n');
|
serialport.write('x\n');
|
||||||
}, 3000);
|
}, 2500);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
serialport.write('Q0\n');
|
serialport.write('Q0\n');
|
||||||
@@ -141,13 +137,8 @@ function connectToSerial() {
|
|||||||
serialport.write('F-1\n');
|
serialport.write('F-1\n');
|
||||||
serialport.write('W0\n');
|
serialport.write('W0\n');
|
||||||
serverConfig.webserver.rdsMode ? serialport.write('D1\n') : serialport.write('D0\n');
|
serverConfig.webserver.rdsMode ? serialport.write('D1\n') : serialport.write('D0\n');
|
||||||
// cEQ and iMS combinations
|
serialport.write(`G${serverConfig.ceqStartup}${serverConfig.imsStartup}\n`);
|
||||||
if (serverConfig.ceqStartup === "0" && serverConfig.imsStartup === "0") serialport.write("G00\n"); // Both Disabled
|
serialport.write(`B${serverConfig.stereoStartup}\n`); // Mono
|
||||||
else if (serverConfig.ceqStartup === "1" && serverConfig.imsStartup === "0") serialport.write(`G10\n`);
|
|
||||||
else if (serverConfig.ceqStartup === "0" && serverConfig.imsStartup === "1") serialport.write(`G01\n`);
|
|
||||||
else if (serverConfig.ceqStartup === "1" && serverConfig.imsStartup === "1") serialport.write("G11\n"); // Both Enabled
|
|
||||||
// Handle stereo mode
|
|
||||||
if (serverConfig.stereoStartup === "1") serialport.write("B1\n"); // Mono
|
|
||||||
serverConfig.audio.startupVolume
|
serverConfig.audio.startupVolume
|
||||||
? serialport.write('Y' + (serverConfig.audio.startupVolume * 100).toFixed(0) + '\n')
|
? serialport.write('Y' + (serverConfig.audio.startupVolume * 100).toFixed(0) + '\n')
|
||||||
: serialport.write('Y100\n');
|
: serialport.write('Y100\n');
|
||||||
@@ -223,11 +214,10 @@ client.on('data', (data) => {
|
|||||||
authFlags.authMsg = true;
|
authFlags.authMsg = true;
|
||||||
logInfo('Authentication with xdrd successful.');
|
logInfo('Authentication with xdrd successful.');
|
||||||
} else if (line.startsWith('G')) {
|
} else if (line.startsWith('G')) {
|
||||||
const value = line.substring(1);
|
dataHandler.initialData.eq = line.charAt(1);
|
||||||
dataHandler.initialData.eq = value.charAt(0);
|
dataHandler.dataToSend.eq = line.charAt(1);
|
||||||
dataHandler.dataToSend.eq = value.charAt(0);
|
dataHandler.initialData.ims = line.charAt(2);
|
||||||
dataHandler.initialData.ims = value.charAt(1);
|
dataHandler.dataToSend.ims = line.charAt(2);
|
||||||
dataHandler.dataToSend.ims = value.charAt(1);
|
|
||||||
} else if (line.startsWith('Z')) {
|
} else if (line.startsWith('Z')) {
|
||||||
let modifiedLine = line.slice(1);
|
let modifiedLine = line.slice(1);
|
||||||
dataHandler.initialData.ant = modifiedLine;
|
dataHandler.initialData.ant = modifiedLine;
|
||||||
@@ -307,13 +297,6 @@ wss.on('connection', (ws, request) => {
|
|||||||
let clientIp = helpers.getIpAddress(request);
|
let clientIp = helpers.getIpAddress(request);
|
||||||
const userCommandHistory = {};
|
const userCommandHistory = {};
|
||||||
|
|
||||||
if (clientIp && serverConfig.webserver.banlist?.includes(clientIp)) {
|
|
||||||
ws.close(1008, 'Banned IP');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clientIp && clientIp.includes(',')) clientIp = clientIp.split(',')[0].trim();
|
|
||||||
|
|
||||||
// Per-IP limit connection open
|
// Per-IP limit connection open
|
||||||
if (clientIp) {
|
if (clientIp) {
|
||||||
const isLocalIp = (
|
const isLocalIp = (
|
||||||
@@ -490,10 +473,6 @@ wss.on('connection', (ws, request) => {
|
|||||||
pluginsWss.on('connection', (ws, request) => {
|
pluginsWss.on('connection', (ws, request) => {
|
||||||
const clientIp = helpers.getIpAddress(request);
|
const clientIp = helpers.getIpAddress(request);
|
||||||
const userCommandHistory = {};
|
const userCommandHistory = {};
|
||||||
if (serverConfig.webserver.banlist?.includes(clientIp)) {
|
|
||||||
ws.close(1008, 'Banned IP');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Anti-spam tracking for each client
|
// Anti-spam tracking for each client
|
||||||
const userCommands = {};
|
const userCommands = {};
|
||||||
let lastWarn = { time: 0 };
|
let lastWarn = { time: 0 };
|
||||||
@@ -528,8 +507,7 @@ pluginsWss.on('connection', (ws, request) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
httpServer.on('upgrade', (request, socket, head) => {
|
httpServer.on('upgrade', (request, socket, head) => {
|
||||||
const clientIp = helpers.getIpAddress(request);
|
if (serverConfig.webserver.banlist?.includes(helpers.getIpAddress(request))) {
|
||||||
if (serverConfig.webserver.banlist?.includes(clientIp)) {
|
|
||||||
socket.destroy();
|
socket.destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -565,4 +543,3 @@ const startServer = (address) => {
|
|||||||
startServer(ipv4Address);
|
startServer(ipv4Address);
|
||||||
tunnel.connect();
|
tunnel.connect();
|
||||||
fmdxList.update();
|
fmdxList.update();
|
||||||
module.exports = { wss, pluginsWss, httpServer, serverConfig };
|
|
||||||
@@ -3,6 +3,7 @@ const { serverConfig } = require('../server_config');
|
|||||||
const { logDebug, logError, logInfo, logWarn, logFfmpeg } = require('../console');
|
const { logDebug, logError, logInfo, logWarn, logFfmpeg } = require('../console');
|
||||||
const checkFFmpeg = require('./checkFFmpeg');
|
const checkFFmpeg = require('./checkFFmpeg');
|
||||||
const { PassThrough } = require('stream');
|
const { PassThrough } = require('stream');
|
||||||
|
const storage = require('../storage');
|
||||||
|
|
||||||
const consoleLogTitle = '[Audio Stream]';
|
const consoleLogTitle = '[Audio Stream]';
|
||||||
|
|
||||||
@@ -41,14 +42,14 @@ checkFFmpeg().then((ffmpegPath) => {
|
|||||||
else inputArgs = ["-f", "alsa", "-i", device];
|
else inputArgs = ["-f", "alsa", "-i", device];
|
||||||
|
|
||||||
return [
|
return [
|
||||||
"-fflags", "+nobuffer",
|
"-fflags", "+nobuffer+flush_packets",
|
||||||
"-flags", "low_delay",
|
"-flags", "low_delay",
|
||||||
"-rtbufsize", "6144",
|
"-rtbufsize", "4096",
|
||||||
"-probesize", "256",
|
"-probesize", "128",
|
||||||
|
|
||||||
...inputArgs,
|
...inputArgs,
|
||||||
|
|
||||||
"-thread_queue_size", "2048",
|
"-thread_queue_size", "1024",
|
||||||
"-ar", String(sampleRate),
|
"-ar", String(sampleRate),
|
||||||
"-ac", String(channels),
|
"-ac", String(channels),
|
||||||
|
|
||||||
@@ -62,7 +63,7 @@ checkFFmpeg().then((ffmpegPath) => {
|
|||||||
"-id3v2_version", "0",
|
"-id3v2_version", "0",
|
||||||
|
|
||||||
"-fflags", "+nobuffer",
|
"-fflags", "+nobuffer",
|
||||||
// "-flush_packets", "1",
|
"-flush_packets", "1",
|
||||||
|
|
||||||
"pipe:1"
|
"pipe:1"
|
||||||
];
|
];
|
||||||
@@ -139,4 +140,4 @@ checkFFmpeg().then((ffmpegPath) => {
|
|||||||
logError(`${consoleLogTitle} Error: ${err.message}`);
|
logError(`${consoleLogTitle} Error: ${err.message}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = audio_pipe;
|
storage.websocket_delegation.set("/audio", audioWss);
|
||||||
@@ -107,4 +107,4 @@ function parseAudioDevice(options, callback) {
|
|||||||
else return new Promise(execute);
|
else return new Promise(execute);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { parseAudioDevice };
|
module.exports = parseAudioDevice;
|
||||||
@@ -5,15 +5,6 @@ const { getIpAddress } = require("../helpers.js")
|
|||||||
|
|
||||||
const audioWss = new WebSocket.Server({ noServer: true, skipUTF8Validation: true });
|
const audioWss = new WebSocket.Server({ noServer: true, skipUTF8Validation: true });
|
||||||
|
|
||||||
audioWss.on('connection', (ws, request) => {
|
|
||||||
const clientIp = getIpAddress(request);
|
|
||||||
|
|
||||||
if (serverConfig.webserver.banlist?.includes(clientIp)) {
|
|
||||||
ws.close(1008, 'Banned IP');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
audio_pipe.on('data', (chunk) => {
|
audio_pipe.on('data', (chunk) => {
|
||||||
audioWss.clients.forEach((client) => {
|
audioWss.clients.forEach((client) => {
|
||||||
if (client.readyState === WebSocket.OPEN) client.send(chunk, {binary: true, compress: false});
|
if (client.readyState === WebSocket.OPEN) client.send(chunk, {binary: true, compress: false});
|
||||||
|
|||||||
+1
-6
@@ -4,7 +4,7 @@ const consoleCmd = require('./console');
|
|||||||
|
|
||||||
let localDb = {};
|
let localDb = {};
|
||||||
let nextLocalDbUpdate = 0;
|
let nextLocalDbUpdate = 0;
|
||||||
const localDbUpdateInterval = 7 * 24 * 60 * 60 * 1000; // 7-day database update interval
|
const localDbUpdateInterval = 3 * 24 * 60 * 60 * 1000; // 3-day database update interval
|
||||||
let awaitingTxInfo = true;
|
let awaitingTxInfo = true;
|
||||||
let lastFetchTime = 0;
|
let lastFetchTime = 0;
|
||||||
let piFreqIndex = {}; // Indexing for speedier PI+Freq combinations
|
let piFreqIndex = {}; // Indexing for speedier PI+Freq combinations
|
||||||
@@ -18,11 +18,6 @@ let usStatesGeoJson = null; // To cache the GeoJSON data for US states
|
|||||||
let Latitude = serverConfig.identification.lat;
|
let Latitude = serverConfig.identification.lat;
|
||||||
let Longitude = serverConfig.identification.lon;
|
let Longitude = serverConfig.identification.lon;
|
||||||
|
|
||||||
// Create WebSocket URL for GPS lat/lon update.
|
|
||||||
const webserverPort = serverConfig.webserver.webserverPort || 8080; // Fallback to port 8080
|
|
||||||
const externalWsUrl = `ws://127.0.0.1:${webserverPort}/data_plugins`;
|
|
||||||
const WebSocket = require('ws');
|
|
||||||
|
|
||||||
// Get weighting values based on algorithm setting.
|
// Get weighting values based on algorithm setting.
|
||||||
// Defaults = algorithm 1
|
// Defaults = algorithm 1
|
||||||
let weightedErp = 10;
|
let weightedErp = 10;
|
||||||
|
|||||||
+1
-3
@@ -20,9 +20,7 @@
|
|||||||
<div class="panel-100 p-10">
|
<div class="panel-100 p-10">
|
||||||
<br>
|
<br>
|
||||||
<i class="text-big fa-solid fa-exclamation-triangle color-4"></i>
|
<i class="text-big fa-solid fa-exclamation-triangle color-4"></i>
|
||||||
<p>
|
<p>Service refused, please try again later.</p>
|
||||||
Service refused..<br>
|
|
||||||
Please try again later.</p>
|
|
||||||
|
|
||||||
<% if (reason) { %>
|
<% if (reason) { %>
|
||||||
<p><strong>Reason:</strong> <%= reason %></p>
|
<p><strong>Reason:</strong> <%= reason %></p>
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title><%= tunerName %> - FM-DX Webserver</title>
|
<title><%= tunerName %> - FM-DX Webserver</title>
|
||||||
<link href="css/entry.css" type="text/css" rel="stylesheet">
|
<link href="css/entry.css" type="text/css" rel="stylesheet">
|
||||||
<link href="css/flags.min.css" type="text/css" rel="stylesheet">
|
<link href="css/flags.min.css" type="text/css" rel="stylesheet">
|
||||||
<link href="css/libs/fontawesome.css" type="text/css" rel="stylesheet">
|
<link href="css/libs/fontawesome.css" type="text/css" rel="stylesheet">
|
||||||
<link href="css/libs/jquery-ui.min.css" type="text/css" rel="stylesheet">
|
<link href="css/libs/jquery-ui.min.css" type="text/css" rel="stylesheet">
|
||||||
<!--<link href="css/libs/jquery-ui.theme.min.css" type="text/css" rel="stylesheet">-->
|
|
||||||
<script src="js/libs/jquery.min.js"></script>
|
<script src="js/libs/jquery.min.js"></script>
|
||||||
<script src="js/libs/jquery-ui.min.js"></script>
|
<script src="js/libs/jquery-ui.min.js"></script>
|
||||||
<script src="js/libs/chart.umd.min.js"></script>
|
<script src="js/libs/chart.umd.min.js"></script>
|
||||||
@@ -26,7 +24,6 @@
|
|||||||
<script src="js/audio.js"></script>
|
<script src="js/audio.js"></script>
|
||||||
<script src="js/3las_helper.js"></script>
|
<script src="js/3las_helper.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
window.addEventListener('load', Init, false);
|
|
||||||
document.ontouchmove = function(e) {
|
document.ontouchmove = function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
@@ -550,9 +547,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-panel-content">
|
<div class="modal-panel-content">
|
||||||
<div class="hover-brighten br-0 bg-color-1" style="height: 50px;padding:12px;" onclick="window.open('https://buymeacoffee.com/noobish')">
|
|
||||||
<strong>Support</strong> the developer!
|
|
||||||
</div>
|
|
||||||
<div class="hover-brighten br-0 bg-color-1" style="height: 50px;padding:12px;" onclick="window.open('https://discord.gg/cY66nt6UhV')">
|
<div class="hover-brighten br-0 bg-color-1" style="height: 50px;padding:12px;" onclick="window.open('https://discord.gg/cY66nt6UhV')">
|
||||||
Join our <strong>FMDX.org Discord</strong> community!
|
Join our <strong>FMDX.org Discord</strong> community!
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+19
-45
@@ -11,18 +11,12 @@ var isBSD;
|
|||||||
var isMacOSX;
|
var isMacOSX;
|
||||||
var isInternetExplorer;
|
var isInternetExplorer;
|
||||||
var isEdge;
|
var isEdge;
|
||||||
;
|
|
||||||
var isSafari;
|
var isSafari;
|
||||||
;
|
|
||||||
var isOpera;
|
var isOpera;
|
||||||
;
|
|
||||||
var isChrome;
|
var isChrome;
|
||||||
;
|
|
||||||
var isFirefox;
|
var isFirefox;
|
||||||
;
|
|
||||||
var webkitVer;
|
var webkitVer;
|
||||||
var isNativeChrome;
|
var isNativeChrome;
|
||||||
;
|
|
||||||
var BrowserName;
|
var BrowserName;
|
||||||
var OSName;
|
var OSName;
|
||||||
{
|
{
|
||||||
@@ -43,39 +37,23 @@ var OSName;
|
|||||||
webkitVer = parseInt((/WebKit\/([0-9]+)/.exec(navigator.appVersion) || ["", "0"])[1], 10) || void 0; // also match AppleWebKit
|
webkitVer = parseInt((/WebKit\/([0-9]+)/.exec(navigator.appVersion) || ["", "0"])[1], 10) || void 0; // also match AppleWebKit
|
||||||
isNativeChrome = isAndroid && webkitVer <= 537 && navigator.vendor.toLowerCase().indexOf('google') == 0;
|
isNativeChrome = isAndroid && webkitVer <= 537 && navigator.vendor.toLowerCase().indexOf('google') == 0;
|
||||||
BrowserName = "Unknown";
|
BrowserName = "Unknown";
|
||||||
if (isInternetExplorer)
|
if (isInternetExplorer) BrowserName = "IE";
|
||||||
BrowserName = "IE";
|
else if (isEdge) BrowserName = "Edge";
|
||||||
else if (isEdge)
|
else if (isSafari) BrowserName = "Safari";
|
||||||
BrowserName = "Edge";
|
else if (isOpera) BrowserName = "Opera";
|
||||||
else if (isSafari)
|
else if (isChrome) BrowserName = "Chrome";
|
||||||
BrowserName = "Safari";
|
else if (isFirefox) BrowserName = "Firefox";
|
||||||
else if (isOpera)
|
else if (isNativeChrome) BrowserName = "NativeChrome";
|
||||||
BrowserName = "Opera";
|
else BrowserName = "Unknown";
|
||||||
else if (isChrome)
|
|
||||||
BrowserName = "Chrome";
|
|
||||||
else if (isFirefox)
|
|
||||||
BrowserName = "Firefox";
|
|
||||||
else if (isNativeChrome)
|
|
||||||
BrowserName = "NativeChrome";
|
|
||||||
else
|
|
||||||
BrowserName = "Unknown";
|
|
||||||
OSName = "Unknown";
|
OSName = "Unknown";
|
||||||
if (isAndroid)
|
if (isAndroid) OSName = "Android";
|
||||||
OSName = "Android";
|
else if (isIOS) OSName = "iOS";
|
||||||
else if (isIOS)
|
else if (isIPadOS) OSName = "iPadOS";
|
||||||
OSName = "iOS";
|
else if (isWindows) OSName = "Windows";
|
||||||
else if (isIPadOS)
|
else if (isLinux) OSName = "Linux";
|
||||||
OSName = "iPadOS";
|
else if (isBSD) OSName = "BSD";
|
||||||
else if (isWindows)
|
else if (isMacOSX) OSName = "MacOSX";
|
||||||
OSName = "Windows";
|
else OSName = "Unknown";
|
||||||
else if (isLinux)
|
|
||||||
OSName = "Linux";
|
|
||||||
else if (isBSD)
|
|
||||||
OSName = "BSD";
|
|
||||||
else if (isMacOSX)
|
|
||||||
OSName = "MacOSX";
|
|
||||||
else
|
|
||||||
OSName = "Unknown";
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
var WakeLock = /** @class */ (function () {
|
var WakeLock = /** @class */ (function () {
|
||||||
@@ -91,8 +69,7 @@ var WakeLock = /** @class */ (function () {
|
|||||||
WakeLock.AddSourceToVideo(video, 'mp4', 'data:video/mp4;base64,' + WakeLock.VideoMp4);
|
WakeLock.AddSourceToVideo(video, 'mp4', 'data:video/mp4;base64,' + WakeLock.VideoMp4);
|
||||||
document.body.appendChild(video);
|
document.body.appendChild(video);
|
||||||
this.LockElement = video;
|
this.LockElement = video;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
this.Logger.Log("Using WakeLock API.");
|
this.Logger.Log("Using WakeLock API.");
|
||||||
this.LockElement = null;
|
this.LockElement = null;
|
||||||
}
|
}
|
||||||
@@ -109,8 +86,7 @@ var WakeLock = /** @class */ (function () {
|
|||||||
_this.Logger.Log("WakeLock request failed.");
|
_this.Logger.Log("WakeLock request failed.");
|
||||||
console.log("WakeLock request failed.");
|
console.log("WakeLock request failed.");
|
||||||
});
|
});
|
||||||
}
|
} catch (err) {
|
||||||
catch (err) {
|
|
||||||
this.Logger.Log("WakeLock request failed.");
|
this.Logger.Log("WakeLock request failed.");
|
||||||
console.log("WakeLock request failed.");
|
console.log("WakeLock request failed.");
|
||||||
}
|
}
|
||||||
@@ -123,9 +99,7 @@ var WakeLock = /** @class */ (function () {
|
|||||||
_this.LockElement.play().catch(err => {
|
_this.LockElement.play().catch(err => {
|
||||||
console.error("LockElement failed:", err);
|
console.error("LockElement failed:", err);
|
||||||
});
|
});
|
||||||
} else {
|
} else console.warn("LockElement not a media element or already assigned.");
|
||||||
console.warn("LockElement not a media element or already assigned.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
WakeLock.AddSourceToVideo = function (element, type, dataURI) {
|
WakeLock.AddSourceToVideo = function (element, type, dataURI) {
|
||||||
|
|||||||
+7
-9
@@ -1,12 +1,12 @@
|
|||||||
|
|
||||||
function tuneUp() {
|
function tuneUp() {
|
||||||
if (socket.readyState === WebSocket.OPEN) {
|
if (socket.readyState === WebSocket.OPEN) {
|
||||||
getCurrentFreq();
|
getCurrentFreq();
|
||||||
let addVal = 0;
|
let addVal = 0;
|
||||||
if (currentFreq < 0.52) addVal = 9 - (Math.round(currentFreq*1000) % 9);
|
if (currentFreq < 0.52) addVal = 9 - (Math.round(currentFreq*1000) % 9);
|
||||||
else if (currentFreq < 1.71) {
|
else if (currentFreq < 1.71) {
|
||||||
// TODO: Rework to replace 9 with 9 or 10 based on regionalisation setting
|
var step = 9;
|
||||||
addVal = 9 - (Math.round(currentFreq*1000) % 9);
|
if(localStorage.getItem('rdsMode') == 'true') step = 10
|
||||||
|
addVal = step - (Math.round(currentFreq*1000) % step);
|
||||||
} else if (currentFreq < 29.6) addVal = 5 - (Math.round(currentFreq*1000) % 5);
|
} else if (currentFreq < 29.6) addVal = 5 - (Math.round(currentFreq*1000) % 5);
|
||||||
else if (currentFreq >= 65.9 && currentFreq < 74) addVal = 30 - ((Math.round(currentFreq*1000) - 65900) % 30);
|
else if (currentFreq >= 65.9 && currentFreq < 74) addVal = 30 - ((Math.round(currentFreq*1000) - 65900) % 30);
|
||||||
else addVal = 100 - (Math.round(currentFreq*1000) % 100);
|
else addVal = 100 - (Math.round(currentFreq*1000) % 100);
|
||||||
@@ -20,8 +20,9 @@ function tuneDown() {
|
|||||||
let subVal = 0;
|
let subVal = 0;
|
||||||
if (currentFreq < 0.52) subVal = (Math.round(currentFreq*1000) % 9 == 0) ? 9 : (Math.round(currentFreq*1000) % 9);
|
if (currentFreq < 0.52) subVal = (Math.round(currentFreq*1000) % 9 == 0) ? 9 : (Math.round(currentFreq*1000) % 9);
|
||||||
else if (currentFreq < 1.71) {
|
else if (currentFreq < 1.71) {
|
||||||
// TODO: Rework to replace 9 with 9 or 10 based on regionalisation setting (Americans use 10, because of dumbfuckinstan)
|
var step = 9;
|
||||||
subVal = (Math.round(currentFreq*1000) % 9 == 0) ? 9 : (Math.round(currentFreq*1000) % 9);
|
if(localStorage.getItem('rdsMode') == 'true') step = 10
|
||||||
|
subVal = (Math.round(currentFreq*1000) % step == 0) ? step : (Math.round(currentFreq*1000) % step);
|
||||||
} else if (currentFreq < 29.6) subVal = (Math.round(currentFreq*1000) % 5 == 0) ? 5 : (Math.round(currentFreq*1000) % 5);
|
} else if (currentFreq < 29.6) subVal = (Math.round(currentFreq*1000) % 5 == 0) ? 5 : (Math.round(currentFreq*1000) % 5);
|
||||||
else if (currentFreq > 65.9 && currentFreq <= 74) subVal = ((Math.round(currentFreq*1000) - 65900) % 30 == 0) ? 30 : ((Math.round(currentFreq*1000) - 65900) % 30);
|
else if (currentFreq > 65.9 && currentFreq <= 74) subVal = ((Math.round(currentFreq*1000) - 65900) % 30 == 0) ? 30 : ((Math.round(currentFreq*1000) - 65900) % 30);
|
||||||
else subVal = (Math.round(currentFreq*1000) % 100 == 0) ? 100 : (Math.round(currentFreq*1000) % 100);
|
else subVal = (Math.round(currentFreq*1000) % 100 == 0) ? 100 : (Math.round(currentFreq*1000) % 100);
|
||||||
@@ -39,9 +40,6 @@ function resetRDS() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getCurrentFreq() {
|
function getCurrentFreq() {
|
||||||
currentFreq = $('#data-frequency').text();
|
currentFreq = Math.round(parseFloat($('#data-frequency').text()) * 1000) / 1000;
|
||||||
currentFreq = parseFloat(currentFreq).toFixed(3);
|
|
||||||
currentFreq = parseFloat(currentFreq);
|
|
||||||
|
|
||||||
return currentFreq;
|
return currentFreq;
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-2
@@ -9,6 +9,12 @@ class WebSocketAudioPlayer {
|
|||||||
this.started = false;
|
this.started = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_trimBuffer() {
|
||||||
|
if (!this.sourceBuffer.updating && this.audio.currentTime > 5) {
|
||||||
|
this.sourceBuffer.remove(0, this.audio.currentTime - 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
this.audio = new Audio();
|
this.audio = new Audio();
|
||||||
this.mediaSource = new MediaSource();
|
this.mediaSource = new MediaSource();
|
||||||
@@ -20,11 +26,11 @@ class WebSocketAudioPlayer {
|
|||||||
|
|
||||||
this.ws = new WebSocket(this.url);
|
this.ws = new WebSocket(this.url);
|
||||||
this.ws.binaryType = 'arraybuffer';
|
this.ws.binaryType = 'arraybuffer';
|
||||||
this.ws.onopen = () => this.ws.send(JSON.stringify({ type: 'fallback', data: 'mp3' }));
|
|
||||||
this.ws.onmessage = (event) => {
|
this.ws.onmessage = (event) => {
|
||||||
this.queue.push(event.data);
|
this.queue.push(event.data);
|
||||||
this._appendNext();
|
this._appendNext();
|
||||||
if (!this.started && this.queue.length === 0) { this.audio.play(); this.started = true; }
|
if (!this.started && this.queue.length === 0) { this.audio.play(); this.started = true; }
|
||||||
|
this._trimBuffer();
|
||||||
};
|
};
|
||||||
this.ws.onclose = () => {
|
this.ws.onclose = () => {
|
||||||
if (this.mediaSource.readyState === 'open') this.mediaSource.endOfStream();
|
if (this.mediaSource.readyState === 'open') this.mediaSource.endOfStream();
|
||||||
@@ -99,7 +105,7 @@ function OnPlayButtonClick(_ev) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$playbutton.addClass('bg-gray').prop('disabled', true);
|
$playbutton.addClass('bg-gray').prop('disabled', true);
|
||||||
setTimeout(() => $playbutton.removeClass('bg-gray').prop('disabled', false), 3000);
|
setTimeout(() => $playbutton.removeClass('bg-gray').prop('disabled', false), 2500);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateVolume() {
|
function updateVolume() {
|
||||||
@@ -109,3 +115,4 @@ function updateVolume() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(Init);
|
$(document).ready(Init);
|
||||||
|
window.addEventListener('load', Init, false);
|
||||||
@@ -1,7 +1,3 @@
|
|||||||
// WebSocket connection located in ./websocket.js
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var parsedData, signalChart, previousFreq;
|
var parsedData, signalChart, previousFreq;
|
||||||
var data = [];
|
var data = [];
|
||||||
var signalData = [];
|
var signalData = [];
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ function checkScroll() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
let $container = $(".scrollable-container");
|
let $container = $(".scrollable-container");
|
||||||
let $leftArrow = $(".scroll-left");
|
let $leftArrow = $(".scroll-left");
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
const versionDate = new Date('Feb 24, 2026 15:00:00');
|
const versionDate = new Date('Apr 3, 2026 9:30:00');
|
||||||
const currentVersion = `v1.4.0a [${versionDate.getDate()}/${versionDate.getMonth() + 1}/${versionDate.getFullYear()}]`;
|
const currentVersion = `v1.4.0a [${versionDate.getDate()}/${versionDate.getMonth() + 1}/${versionDate.getFullYear()}]`;
|
||||||
+1
-1
@@ -16,7 +16,7 @@ function updateWizardContent() {
|
|||||||
$('.btn-prev').toggle(visibleStepIndex !== 0);
|
$('.btn-prev').toggle(visibleStepIndex !== 0);
|
||||||
$('.btn-next').text(visibleStepIndex === 4 ? 'Save' : 'Next');
|
$('.btn-next').text(visibleStepIndex === 4 ? 'Save' : 'Next');
|
||||||
|
|
||||||
visibleStepIndex === 3 && mapReload();
|
visibleStepIndex === 3 && mapReload(); // What is this? Javascript? Toy?
|
||||||
}
|
}
|
||||||
|
|
||||||
function navigateStep(isNext) {
|
function navigateStep(isNext) {
|
||||||
|
|||||||
Reference in New Issue
Block a user