mirror of
https://github.com/KubaPro010/fm-dx-webserver.git
synced 2026-07-30 08:49:16 +02:00
console rework / af list update / font update / tuning buttons
This commit is contained in:
+12
-23
@@ -1,7 +1,5 @@
|
|||||||
const koffi = require('koffi');
|
const koffi = require('koffi');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
//const lib = koffi.load(path.join(__dirname, "librds.so"));
|
|
||||||
//const lib = koffi.load(path.join(__dirname, "librds.dll"));
|
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
const win32 = (os.platform() == "win32");
|
const win32 = (os.platform() == "win32");
|
||||||
const unicode_type = (win32 ? 'int16_t' : 'int32_t');
|
const unicode_type = (win32 ? 'int16_t' : 'int32_t');
|
||||||
@@ -56,8 +54,8 @@ const decode_unicode = function(string)
|
|||||||
|
|
||||||
const callbacks = {
|
const callbacks = {
|
||||||
pi: koffi.register(rds => (
|
pi: koffi.register(rds => (
|
||||||
value = rdsparser.get_pi(rds),
|
value = rdsparser.get_pi(rds)
|
||||||
console.log('PI: ' + value.toString(16).toUpperCase())
|
//console.log('PI: ' + value.toString(16).toUpperCase())
|
||||||
), 'callback_pi *'),
|
), 'callback_pi *'),
|
||||||
|
|
||||||
pty: koffi.register(rds => (
|
pty: koffi.register(rds => (
|
||||||
@@ -71,13 +69,13 @@ const callbacks = {
|
|||||||
), 'callback_tp *'),
|
), 'callback_tp *'),
|
||||||
|
|
||||||
ta: koffi.register(rds => (
|
ta: koffi.register(rds => (
|
||||||
value = rdsparser.get_ta(rds),
|
value = rdsparser.get_ta(rds)
|
||||||
console.log('TA: ' + value)
|
//console.log('TA: ' + value)
|
||||||
), 'callback_ta *'),
|
), 'callback_ta *'),
|
||||||
|
|
||||||
ms: koffi.register(rds => (
|
ms: koffi.register(rds => (
|
||||||
value = rdsparser.get_ms(rds),
|
value = rdsparser.get_ms(rds)
|
||||||
console.log('MS: ' + value)
|
//console.log('MS: ' + value)
|
||||||
), 'callback_ms *'),
|
), 'callback_ms *'),
|
||||||
|
|
||||||
af: koffi.register((rds, value) => (
|
af: koffi.register((rds, value) => (
|
||||||
@@ -85,8 +83,8 @@ const callbacks = {
|
|||||||
), 'callback_af *'),
|
), 'callback_af *'),
|
||||||
|
|
||||||
ecc: koffi.register(rds => (
|
ecc: koffi.register(rds => (
|
||||||
value = rdsparser.get_ecc(rds),
|
value = rdsparser.get_ecc(rds)
|
||||||
console.log('ECC: ' + value.toString(16).toUpperCase())
|
//console.log('ECC: ' + value.toString(16).toUpperCase())
|
||||||
), 'callback_ecc *'),
|
), 'callback_ecc *'),
|
||||||
|
|
||||||
ps: koffi.register(rds => (
|
ps: koffi.register(rds => (
|
||||||
@@ -131,8 +129,8 @@ const clientUpdateIntervals = new Map(); // Store update intervals for each clie
|
|||||||
// Initialize the data object
|
// Initialize the data object
|
||||||
var dataToSend = {
|
var dataToSend = {
|
||||||
pi: '?',
|
pi: '?',
|
||||||
freq: 0,
|
freq: 87.500.toFixed(3),
|
||||||
signal: '',
|
signal: 0,
|
||||||
st: false,
|
st: false,
|
||||||
rds: '',
|
rds: '',
|
||||||
ps: '',
|
ps: '',
|
||||||
@@ -145,8 +143,8 @@ var dataToSend = {
|
|||||||
|
|
||||||
const initialData = {
|
const initialData = {
|
||||||
pi: '?',
|
pi: '?',
|
||||||
freq: 0,
|
freq: 87.500.toFixed(3),
|
||||||
signal: '',
|
signal: 0,
|
||||||
st: false,
|
st: false,
|
||||||
rds: '',
|
rds: '',
|
||||||
ps: '',
|
ps: '',
|
||||||
@@ -246,15 +244,6 @@ function handleData(ws, receivedData) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*setInterval(function () {
|
|
||||||
// some code
|
|
||||||
if (rdsBuffer.length > 50) {
|
|
||||||
handleBuffer();
|
|
||||||
//console.log("handling buffer");
|
|
||||||
}
|
|
||||||
//console.log(rdsBuffer.length);
|
|
||||||
}, 150);*/
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
handleData
|
handleData
|
||||||
};
|
};
|
||||||
@@ -10,6 +10,11 @@ const crypto = require('crypto');
|
|||||||
|
|
||||||
let receivedSalt = '';
|
let receivedSalt = '';
|
||||||
let receivedPassword = false;
|
let receivedPassword = false;
|
||||||
|
let currentUsers = 0;
|
||||||
|
|
||||||
|
const infoMsg = "\x1b[32m[INFO]\x1b[0m";
|
||||||
|
const debugMsg = "\x1b[36m[DEBUG]\x1b[0m";
|
||||||
|
|
||||||
// Other JS files
|
// Other JS files
|
||||||
const dataHandler = require('./datahandler');
|
const dataHandler = require('./datahandler');
|
||||||
const config = require('./userconfig');
|
const config = require('./userconfig');
|
||||||
@@ -17,7 +22,6 @@ const config = require('./userconfig');
|
|||||||
/* Server settings */
|
/* Server settings */
|
||||||
const webServerHost = config.webServerHost; // IP of the web server
|
const webServerHost = config.webServerHost; // IP of the web server
|
||||||
const webServerPort = config.webServerPort; // web server port
|
const webServerPort = config.webServerPort; // web server port
|
||||||
|
|
||||||
const xdrdServerHost = config.xdrdServerHost; // xdrd server iP
|
const xdrdServerHost = config.xdrdServerHost; // xdrd server iP
|
||||||
const xdrdServerPort = config.xdrdServerPort; // xdrd server port
|
const xdrdServerPort = config.xdrdServerPort; // xdrd server port
|
||||||
const xdrdPassword = config.xdrdPassword;
|
const xdrdPassword = config.xdrdPassword;
|
||||||
@@ -30,16 +34,27 @@ const httpServer = http.createServer(app);
|
|||||||
const client = new net.Socket();
|
const client = new net.Socket();
|
||||||
|
|
||||||
/* webSocket handlers */
|
/* webSocket handlers */
|
||||||
wss.on('connection', (ws) => {
|
wss.on('connection', (ws, request) => {
|
||||||
console.log('WebSocket client connected');
|
const clientIp = request.connection.remoteAddress;
|
||||||
|
currentUsers++;
|
||||||
|
console.log(infoMsg, `WebSocket client connected\nIP: ${clientIp}\nUsers online: ${currentUsers}`);
|
||||||
|
|
||||||
ws.on('message', (message) => {
|
ws.on('message', (message) => {
|
||||||
console.log('Received message from client:', message.toString());
|
if(config.verboseMode === true) {
|
||||||
|
console.log(debugMsg,'Received message from client:', message.toString());
|
||||||
|
}
|
||||||
newFreq = message.toString() * 1000;
|
newFreq = message.toString() * 1000;
|
||||||
client.write("T" + newFreq + '\n');
|
client.write("T" + newFreq + '\n');
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
|
ws.on('close', (code, reason) => {
|
||||||
|
currentUsers--;
|
||||||
|
console.log(infoMsg, `WebSocket client disconnected\nIP: ${clientIp}\nCode: ${code} ${reason}\nUsers online: ${currentUsers}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.on('error', console.error);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
// Serve static files from the "web" folder
|
// Serve static files from the "web" folder
|
||||||
app.use(express.static(path.join(__dirname, 'web')));
|
app.use(express.static(path.join(__dirname, 'web')));
|
||||||
@@ -64,7 +79,7 @@ function authenticateWithXdrd(client, salt, password) {
|
|||||||
|
|
||||||
// WebSocket client connection
|
// WebSocket client connection
|
||||||
client.connect(xdrdServerPort, xdrdServerHost, () => {
|
client.connect(xdrdServerPort, xdrdServerHost, () => {
|
||||||
console.log('Connected to xdrd');
|
console.log(infoMsg, 'Connected to xdrd successfully.');
|
||||||
|
|
||||||
client.once('data', (data) => {
|
client.once('data', (data) => {
|
||||||
const receivedData = data.toString();
|
const receivedData = data.toString();
|
||||||
@@ -82,18 +97,6 @@ client.connect(xdrdServerPort, xdrdServerHost, () => {
|
|||||||
client.on('data', (data) => {
|
client.on('data', (data) => {
|
||||||
const receivedData = data.toString();
|
const receivedData = data.toString();
|
||||||
|
|
||||||
const lines = receivedData.split('\n');
|
|
||||||
|
|
||||||
// If there's at least one line, set it as the received salt
|
|
||||||
/*if (lines.length > 0 && receivedPassword === false) {
|
|
||||||
receivedSalt = lines[0].trim(); // Trim any leading or trailing whitespace
|
|
||||||
console.log('Received Salt:', receivedSalt);
|
|
||||||
|
|
||||||
// Authentication logic
|
|
||||||
authenticateWithXdrd(client, receivedSalt, xdrdPassword);
|
|
||||||
receivedPassword = true;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
wss.clients.forEach((client) => {
|
wss.clients.forEach((client) => {
|
||||||
if (client.readyState === WebSocket.OPEN) {
|
if (client.readyState === WebSocket.OPEN) {
|
||||||
dataHandler.handleData(client, receivedData);
|
dataHandler.handleData(client, receivedData);
|
||||||
@@ -115,7 +118,7 @@ httpServer.on('upgrade', (request, socket, head) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
httpServer.listen(webServerPort, webServerHost, () => {
|
httpServer.listen(webServerPort, webServerHost, () => {
|
||||||
console.log(`Web server is running at http://${webServerHost}:${webServerPort}`);
|
console.log(infoMsg, `Web server is running at \x1b[34mhttp://${webServerHost}:${webServerPort}\x1b[0m.`);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Audio */
|
/* Audio */
|
||||||
|
|||||||
+3
-1
@@ -5,6 +5,8 @@ const xdrdServerHost = '192.168.1.15'; // xdrd server iP
|
|||||||
const xdrdServerPort = 7373; // xdrd server port
|
const xdrdServerPort = 7373; // xdrd server port
|
||||||
const xdrdPassword = ''; // xdrd password (optional)
|
const xdrdPassword = ''; // xdrd password (optional)
|
||||||
|
|
||||||
|
const verboseMode = false; // if true, console will display extra messages
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
webServerHost, webServerPort, xdrdServerHost, xdrdServerPort, xdrdPassword
|
webServerHost, webServerPort, xdrdServerHost, xdrdServerPort, xdrdPassword, verboseMode
|
||||||
};
|
};
|
||||||
+80
-67
@@ -8,76 +8,89 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<canvas id="signal-canvas" width="1024" height="200" style="margin-top: 120px;"></canvas>
|
<canvas id="signal-canvas" width="1240" height="200" style="margin-top: 80px;"></canvas>
|
||||||
|
|
||||||
<div class="flex-container">
|
|
||||||
<div class="panel-75" style="height: 110px;">
|
|
||||||
<span class="text-big" id="data-ps"></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="panel-33">
|
|
||||||
<h2 style="padding-top: 18px;">
|
|
||||||
<span id="data-pty" style="color: #eee;"></span>
|
|
||||||
<span style="margin-left: 30px;" id="data-tp">TP</span>
|
|
||||||
<span style="margin-left: 15px; color: #ff5776;" id="data-st"></span>
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="flex-container">
|
|
||||||
<div class="panel-33">
|
|
||||||
<h2>PI CODE</h2>
|
|
||||||
<span id="data-pi" class="text-big"></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="panel-33">
|
|
||||||
<h2>FREQUENCY</h2>
|
|
||||||
<span id="data-frequency" class="text-big"></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="panel-33">
|
|
||||||
<h2>SIGNAL</h2>
|
|
||||||
<span class="text-big">
|
|
||||||
<span id="data-signal"></span>
|
|
||||||
<span id="signal-units" class="text-medium-big">dBf</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex-container">
|
<div class="flex-container">
|
||||||
<div class="panel-33" style="height: 48px;">
|
<div class="panel-90 no-bg">
|
||||||
<audio id="myAudio" preload="none" autoplay></audio>
|
<div class="flex-container">
|
||||||
<input type="range" id="volumeSlider" min="0" max="1" step="0.01" value="1">
|
<div class="panel-75" style="height: 110px;">
|
||||||
|
<span class="text-big" id="data-ps"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-33">
|
||||||
|
<h2 style="padding-top: 18px;">
|
||||||
|
<span id="data-pty" style="color: #eee;"></span>
|
||||||
|
<span style="margin-left: 30px;" id="data-tp">TP</span>
|
||||||
|
<span style="margin-left: 15px; color: #ff5776;" id="data-st"></span>
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="flex-container">
|
||||||
|
<div class="panel-33">
|
||||||
|
<h2>PI CODE</h2>
|
||||||
|
<span id="data-pi" class="text-big"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-33">
|
||||||
|
<h2>FREQUENCY</h2>
|
||||||
|
<span id="data-frequency" class="text-big"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-33">
|
||||||
|
<h2>SIGNAL</h2>
|
||||||
|
<span class="text-big">
|
||||||
|
<span id="data-signal"></span>
|
||||||
|
<span id="signal-units" class="text-medium-big">dBf</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex-container">
|
||||||
|
<div class="panel-33" style="height: 48px;">
|
||||||
|
<audio id="myAudio" preload="none" autoplay></audio>
|
||||||
|
<input type="range" id="volumeSlider" min="0" max="1" step="0.01" value="1">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-33 flex-container flex-phone" id="tune-buttons" style="opacity: 1;">
|
||||||
|
<!--<button id="playButton">play</button>-->
|
||||||
|
<button id="freq-down">◀</button>
|
||||||
|
<input type="text" id="commandinput" inputmode="numeric" placeholder="Frequency">
|
||||||
|
<button id="freq-up">▶</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-33" style="height: 48px;">
|
||||||
|
<label class="toggleSwitch nolabel" onclick="">
|
||||||
|
<input id="signal-units-toggle" type="checkbox"/>
|
||||||
|
<a></a>
|
||||||
|
<span>
|
||||||
|
<span class="left-span">dBf</span>
|
||||||
|
<span class="right-span">dBµV</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="panel-100">
|
||||||
|
<h2 style="margin: 0;">RADIOTEXT</h2>
|
||||||
|
<div id="data-rt0"></div>
|
||||||
|
<div id="data-rt1"></div>
|
||||||
|
<div id="data-container" style="display: none;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="panel-33" style="opacity: 1;">
|
<div class="panel-10 no-bg">
|
||||||
<!--<button id="playButton">play</button>-->
|
<div class="panel-100" style="height: 100%;">
|
||||||
<input type="text" id="commandinput" inputmode="numeric" placeholder="Frequency">
|
<h2>AF</h2>
|
||||||
|
<div id="af-list" style="text-align: center;">
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="panel-33" style="height: 48px;">
|
|
||||||
<label class="toggleSwitch nolabel" onclick="">
|
|
||||||
<input id="signal-units-toggle" type="checkbox"/>
|
|
||||||
<a></a>
|
|
||||||
<span>
|
|
||||||
<span class="left-span">dBf</span>
|
|
||||||
<span class="right-span">dBµV</span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="panel-100">
|
|
||||||
<h2 style="margin: 0;">RADIOTEXT</h2>
|
|
||||||
<div id="data-rt0"></div>
|
|
||||||
<div id="data-rt1"></div>
|
|
||||||
<div id="data-container" style="display: none;"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="panel-100" style="overflow: hidden">
|
|
||||||
<h2 style="margin: 0;">AF</h2>
|
|
||||||
<div id="data-af" style="text-align: center;"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -87,7 +100,7 @@
|
|||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<span class="modal-title">Settings</span>
|
<span class="modal-title">Settings</span>
|
||||||
<span class="close" id="closeModal"><i class="fa-solid fa-xmark"></i></span>
|
<span class="close" id="closeModal"><i class="fa-solid fa-xmark"></i></span>
|
||||||
|
|
||||||
<label for="themes" style="margin-top: 50px;"><i class="fa-solid fa-palette"></i> Theme:</label>
|
<label for="themes" style="margin-top: 50px;"><i class="fa-solid fa-palette"></i> Theme:</label>
|
||||||
<select name="themes" style="margin-bottom: 50px;" id="theme-selector">
|
<select name="themes" style="margin-bottom: 50px;" id="theme-selector">
|
||||||
<option value="theme1">Blurple</option>
|
<option value="theme1">Blurple</option>
|
||||||
|
|||||||
+63
-11
@@ -135,17 +135,42 @@ function divideByHundred(a) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updatePanels(parsedData) {
|
function updatePanels(parsedData) {
|
||||||
sortedAf = parsedData.af.sort(compareNumbers);
|
// Assuming sortedAf is your array
|
||||||
|
const sortedAf = parsedData.af.sort(compareNumbers);
|
||||||
sortedAf.forEach((element, index, array) => {
|
|
||||||
array[index] = element / 1000;
|
|
||||||
|
|
||||||
// Check if it's the last element in the array
|
// Convert the values in the array (dividing by 1000)
|
||||||
if (index === array.length - 1) {
|
const scaledArray = sortedAf.map(element => element / 1000);
|
||||||
document.querySelector('#data-af').innerHTML = array;
|
|
||||||
}
|
// Get the container element where you want to display the list
|
||||||
|
const listContainer = document.querySelector('#af-list');
|
||||||
|
|
||||||
|
// Preserve the current scroll position
|
||||||
|
const scrollTop = listContainer.scrollTop;
|
||||||
|
|
||||||
|
// Get the existing ul element
|
||||||
|
const ul = listContainer.querySelector('ul');
|
||||||
|
|
||||||
|
// If ul doesn't exist, create a new one
|
||||||
|
if (!ul) {
|
||||||
|
ul = document.createElement('ul');
|
||||||
|
listContainer.appendChild(ul);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove existing list items
|
||||||
|
ul.innerHTML = '';
|
||||||
|
|
||||||
|
// Create an array of list items
|
||||||
|
const listItems = scaledArray.map(element => {
|
||||||
|
const li = document.createElement('li');
|
||||||
|
li.textContent = element.toFixed(1);
|
||||||
|
return li;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Append the list items to the unordered list
|
||||||
|
listItems.forEach(li => ul.appendChild(li));
|
||||||
|
|
||||||
|
// Restore the scroll position
|
||||||
|
listContainer.scrollTop = scrollTop;
|
||||||
document.querySelector('#data-frequency').textContent = parsedData.freq;
|
document.querySelector('#data-frequency').textContent = parsedData.freq;
|
||||||
document.querySelector('#data-pi').innerHTML = parsedData.pi === '?' ? "<span class='text-gray'>?</span>" : parsedData.pi;
|
document.querySelector('#data-pi').innerHTML = parsedData.pi === '?' ? "<span class='text-gray'>?</span>" : parsedData.pi;
|
||||||
document.querySelector('#data-ps').innerHTML = parsedData.ps === '?' ? "<span class='text-gray'>?</span>" : parsedData.ps;
|
document.querySelector('#data-ps').innerHTML = parsedData.ps === '?' ? "<span class='text-gray'>?</span>" : parsedData.ps;
|
||||||
@@ -212,9 +237,8 @@ document.onkeydown = checkKey;
|
|||||||
|
|
||||||
function checkKey(e) {
|
function checkKey(e) {
|
||||||
e = e || window.event;
|
e = e || window.event;
|
||||||
currentFreq = document.getElementById("data-frequency").textContent;
|
|
||||||
currentFreq = parseFloat(currentFreq).toFixed(3);
|
getCurrentFreq();
|
||||||
currentFreq = parseFloat(currentFreq);
|
|
||||||
|
|
||||||
if (socket.readyState === WebSocket.OPEN) {
|
if (socket.readyState === WebSocket.OPEN) {
|
||||||
if (e.keyCode == '38') {
|
if (e.keyCode == '38') {
|
||||||
@@ -230,4 +254,32 @@ function checkKey(e) {
|
|||||||
socket.send((currentFreq + 0.10).toFixed(3));
|
socket.send((currentFreq + 0.10).toFixed(3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentFreq() {
|
||||||
|
currentFreq = document.getElementById("data-frequency").textContent;
|
||||||
|
currentFreq = parseFloat(currentFreq).toFixed(3);
|
||||||
|
currentFreq = parseFloat(currentFreq);
|
||||||
|
|
||||||
|
return currentFreq;
|
||||||
|
}
|
||||||
|
|
||||||
|
freqUpButton = document.getElementById('freq-up');
|
||||||
|
freqDownButton = document.getElementById('freq-down');
|
||||||
|
|
||||||
|
freqUpButton.addEventListener("click", tuneUp);
|
||||||
|
freqDownButton.addEventListener("click", tuneDown);
|
||||||
|
|
||||||
|
function tuneUp() {
|
||||||
|
if (socket.readyState === WebSocket.OPEN) {
|
||||||
|
getCurrentFreq();
|
||||||
|
socket.send((currentFreq + 0.10).toFixed(3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function tuneDown() {
|
||||||
|
if (socket.readyState === WebSocket.OPEN) {
|
||||||
|
getCurrentFreq();
|
||||||
|
socket.send((currentFreq - 0.10).toFixed(3));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+73
-9
@@ -1,4 +1,5 @@
|
|||||||
@import url('https://fonts.googleapis.com/css2?family=Titillium+Web:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700&display=swap');
|
@import url('https://fonts.googleapis.com/css2?family=Titillium+Web:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700&display=swap');
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Monomaniac+One&display=swap');
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--color-main: #1d1838;
|
--color-main: #1d1838;
|
||||||
@@ -34,7 +35,7 @@ a {
|
|||||||
#wrapper {
|
#wrapper {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
width: auto;
|
width: auto;
|
||||||
max-width: 1024px;
|
max-width: 1240px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#color-settings, #settings {
|
#color-settings, #settings {
|
||||||
@@ -71,6 +72,21 @@ h2 {
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.no-bg {
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-10 {
|
||||||
|
width: 10%;
|
||||||
|
background: var(--color-1);
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
border-radius: 30px;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 30px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
.panel-33 {
|
.panel-33 {
|
||||||
width: 33%;
|
width: 33%;
|
||||||
background: var(--color-1);
|
background: var(--color-1);
|
||||||
@@ -91,6 +107,16 @@ h2 {
|
|||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.panel-90 {
|
||||||
|
width: 88%;
|
||||||
|
background: var(--color-1);
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
border-radius: 30px;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.panel-100 {
|
.panel-100 {
|
||||||
width: 98%;
|
width: 98%;
|
||||||
@@ -103,13 +129,23 @@ h2 {
|
|||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#af-list ul {
|
||||||
|
display:list-item;
|
||||||
|
padding: 0;
|
||||||
|
list-style-type: none;
|
||||||
|
height: 425px;
|
||||||
|
overflow: scroll;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.auto {
|
.auto {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-big {
|
.text-big {
|
||||||
font-size: 72px;
|
font-size: 72px;
|
||||||
font-weight: 600;
|
font-weight: 300;
|
||||||
|
/*font-family: "Monomaniac One", sans-serif;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-medium-big {
|
.text-medium-big {
|
||||||
@@ -130,32 +166,60 @@ h2 {
|
|||||||
background: #100d1f;
|
background: #100d1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"] {
|
#tune-buttons input[type="text"] {
|
||||||
width: 100%;
|
width: 50%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 46px;
|
min-height: 46px;
|
||||||
border-radius: 30px;
|
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: 0;
|
border: 2px solid transparent;
|
||||||
|
outline: 0;
|
||||||
color: white;
|
color: white;
|
||||||
background-color: var(--color-1);
|
background-color: var(--color-1);
|
||||||
font-family: 'Titillium Web', sans-serif;
|
font-family: 'Titillium Web', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"]:focus {
|
input[type="text"]:hover {
|
||||||
outline: 2px solid var(--color-main-bright);
|
border: 2px solid var(--color-main-bright);
|
||||||
|
}
|
||||||
|
|
||||||
|
#tune-buttons button {
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: var(--color-4);
|
||||||
|
border: 0;
|
||||||
|
color: var(--color-1);
|
||||||
|
width: 25%;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
padding: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tune-buttons button:hover {
|
||||||
|
background-color: var(--color-main-bright);
|
||||||
|
}
|
||||||
|
|
||||||
|
#freq-down {
|
||||||
|
border-radius: 30px 0 0 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#freq-up {
|
||||||
|
border-radius: 0 30px 30px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 768px) {
|
@media only screen and (max-width: 768px) {
|
||||||
.flex-container {
|
.flex-container {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
.flex-phone {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
.modal-content {
|
.modal-content {
|
||||||
max-width: 90%;
|
max-width: 90%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
.panel-33 {
|
.panel-10, .panel-33, .panel-90 {
|
||||||
width: 90%;
|
width: 90%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|||||||
Reference in New Issue
Block a user