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 pull request #66 from AmateurAudioDude/fixes/v1.2.2-several-fixes
Several fixes
This commit is contained in:
@@ -21,22 +21,39 @@ function parsePluginConfig(filePath) {
|
||||
// Check if pluginConfig has frontEndPath defined
|
||||
if (pluginConfig.frontEndPath) {
|
||||
const sourcePath = path.join(path.dirname(filePath), pluginConfig.frontEndPath);
|
||||
const destinationDir = path.join(path.dirname(filePath), '../web/js/plugins', pluginConfig.frontEndPath, '..');
|
||||
const destinationDir = path.join(__dirname, '../web/js/plugins', path.dirname(pluginConfig.frontEndPath));
|
||||
|
||||
// Check if the source path exists
|
||||
if (!fs.existsSync(sourcePath)) {
|
||||
console.error(`Error: source path ${sourcePath} does not exist.`);
|
||||
return pluginConfig;
|
||||
}
|
||||
|
||||
// Check if the destination directory exists, if not, create it
|
||||
if (!fs.existsSync(destinationDir)) {
|
||||
fs.mkdirSync(destinationDir, { recursive: true }); // Create directory recursively
|
||||
}
|
||||
|
||||
// Copy the file to the destination directory
|
||||
const destinationFile = path.join(destinationDir, path.basename(sourcePath));
|
||||
fs.copyFileSync(sourcePath, destinationFile);
|
||||
console.log(`File copied from ${sourcePath} to ${destinationFile}`);
|
||||
|
||||
// Platform-specific handling for symlinks/junctions
|
||||
if (process.platform !== 'win32') {
|
||||
// On Linux, create a symlink
|
||||
try {
|
||||
if (fs.existsSync(destinationFile)) {
|
||||
fs.unlinkSync(destinationFile); // Remove existing file/symlink
|
||||
}
|
||||
fs.symlinkSync(sourcePath, destinationFile);
|
||||
console.log(`Symlink created from ${sourcePath} to ${destinationFile}`);
|
||||
} catch (err) {
|
||||
console.error(`Error creating symlink at ${destinationFile}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error(`Error: frontEndPath is not defined in ${filePath}`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`Error parsing plugin config from ${filePath}: ${err}`);
|
||||
console.error(`Error parsing plugin config from ${filePath}: ${err.message}`);
|
||||
}
|
||||
|
||||
return pluginConfig;
|
||||
@@ -59,9 +76,35 @@ function collectPluginConfigs() {
|
||||
return pluginConfigs;
|
||||
}
|
||||
|
||||
// Ensure the web/js/plugins directory exists
|
||||
const webJsPluginsDir = path.join(__dirname, '../web/js/plugins');
|
||||
if (!fs.existsSync(webJsPluginsDir)) {
|
||||
fs.mkdirSync(webJsPluginsDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Main function to create symlinks/junctions for plugins
|
||||
function createLinks() {
|
||||
const pluginsDir = path.join(__dirname, '../plugins');
|
||||
const destinationPluginsDir = path.join(__dirname, '../web/js/plugins');
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
// On Windows, create a junction
|
||||
try {
|
||||
if (fs.existsSync(destinationPluginsDir)) {
|
||||
fs.rmSync(destinationPluginsDir, { recursive: true });
|
||||
}
|
||||
fs.symlinkSync(pluginsDir, destinationPluginsDir, 'junction');
|
||||
console.log(`Junction created from ${pluginsDir} to ${destinationPluginsDir}`);
|
||||
} catch (err) {
|
||||
console.error(`Error creating junction at ${destinationPluginsDir}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Usage example
|
||||
const allPluginConfigs = collectPluginConfigs();
|
||||
createLinks();
|
||||
|
||||
module.exports = {
|
||||
allPluginConfigs
|
||||
}
|
||||
};
|
||||
|
||||
@@ -490,6 +490,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="js/websocket.js"></script>
|
||||
<script src="js/webserver.js"></script>
|
||||
<% plugins?.forEach(function(plugin) { %>
|
||||
<script src="js/plugins/<%= plugin %>"></script>
|
||||
|
||||
@@ -45,6 +45,7 @@ var _3LAS = /** @class */ (function () {
|
||||
};
|
||||
_3LAS.prototype.Start = function () {
|
||||
this.ConnectivityFlag = false;
|
||||
this.Stop(); // Attempt to mitigate the 0.5x speed/multiple stream bug
|
||||
|
||||
// This is stupid, but required for Android.... thanks Google :(
|
||||
if (this.WakeLock)
|
||||
@@ -128,11 +129,50 @@ var _3LAS = /** @class */ (function () {
|
||||
this.ConnectivityFlag = false;
|
||||
if (this.ConnectivityCallback)
|
||||
this.ConnectivityCallback(false);
|
||||
}
|
||||
|
||||
if (shouldReconnect) {
|
||||
if (!this.ConnectivityFlag) {
|
||||
console.log("Initial reconnect attempt...");
|
||||
this.Stop(); // Attempt to mitigate the 0.5x speed/multiple stream bug
|
||||
this.Start();
|
||||
}
|
||||
this.Start();
|
||||
};
|
||||
|
||||
// Delay launch of subsequent reconnect attempts by 3 seconds
|
||||
setTimeout(() => {
|
||||
|
||||
let streamReconnecting = false;
|
||||
|
||||
let intervalReconnect = setInterval(() => {
|
||||
if (this.ConnectivityFlag || typeof Stream === 'undefined' || Stream === null) {
|
||||
console.log("Reconnect attempts aborted.");
|
||||
clearInterval(intervalReconnect);
|
||||
} else if (!streamReconnecting) {
|
||||
streamReconnecting = true;
|
||||
console.log("Attempting to restart stream...");
|
||||
this.Stop(); // Attempt to mitigate the 0.5x speed/multiple stream bug
|
||||
this.Start();
|
||||
// Wait for reconnect attempt
|
||||
setTimeout(() => {
|
||||
streamReconnecting = false;
|
||||
}, 3000);
|
||||
}
|
||||
// Restore user set volume
|
||||
if (Stream && typeof newVolumeGlobal !== 'undefined' && newVolumeGlobal !== null) {
|
||||
Stream.Volume = newVolumeGlobal;
|
||||
console.log(`User volume restored: ${Math.round(newVolumeGlobal * 100)}%`);
|
||||
}
|
||||
}, 3000);
|
||||
|
||||
}, 3000);
|
||||
|
||||
} else {
|
||||
this.Logger.Log("Reconnection is disabled.");
|
||||
}
|
||||
};
|
||||
|
||||
_3LAS.prototype.OnSocketDataReady = function (data) {
|
||||
this.Fallback.OnSocketDataReady(data);
|
||||
};
|
||||
return _3LAS;
|
||||
}());
|
||||
}());
|
||||
|
||||
@@ -1,43 +1,69 @@
|
||||
const DefaultVolume = 0.5;
|
||||
let Stream;
|
||||
let shouldReconnect = true;
|
||||
let newVolumeGlobal = 1;
|
||||
|
||||
function Init(_ev) {
|
||||
try {
|
||||
const settings = new _3LAS_Settings();
|
||||
if (!Stream) { // Ensure Stream is not re-initialized
|
||||
Stream = new _3LAS(null, settings);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
|
||||
Stream.ConnectivityCallback = OnConnectivityCallback;
|
||||
$(".playbutton").off('click').on('click', OnPlayButtonClick); // Ensure only one event handler is attached
|
||||
$("#volumeSlider").off("input").on("input", updateVolume); // Ensure only one event handler is attached
|
||||
}
|
||||
|
||||
function createStream() {
|
||||
try {
|
||||
const settings = new _3LAS_Settings();
|
||||
Stream = new _3LAS(null, settings);
|
||||
Stream.ConnectivityCallback = OnConnectivityCallback;
|
||||
} catch (error) {
|
||||
console.error("Initialization Error: ", error);
|
||||
}
|
||||
}
|
||||
|
||||
function destroyStream() {
|
||||
if (Stream) {
|
||||
Stream.Stop();
|
||||
Stream = null;
|
||||
}
|
||||
}
|
||||
|
||||
function OnConnectivityCallback(isConnected) {
|
||||
Stream.Volume = isConnected ? 1.0 : DefaultVolume;
|
||||
console.log("Connectivity changed:", isConnected);
|
||||
if (Stream) {
|
||||
Stream.Volume = isConnected ? 1.0 : DefaultVolume;
|
||||
} else {
|
||||
console.warn("Stream is not initialized.");
|
||||
}
|
||||
}
|
||||
|
||||
function OnPlayButtonClick(_ev) {
|
||||
const $playbutton = $('.playbutton');
|
||||
$playbutton.find('.fa-solid').toggleClass('fa-play fa-stop');
|
||||
|
||||
if (Stream.ConnectivityFlag) {
|
||||
Stream.Stop();
|
||||
if (Stream) {
|
||||
console.log("Stopping stream...");
|
||||
shouldReconnect = false;
|
||||
destroyStream();
|
||||
$playbutton.find('.fa-solid').toggleClass('fa-stop fa-play');
|
||||
} else {
|
||||
console.log("Starting stream...");
|
||||
shouldReconnect = true;
|
||||
createStream();
|
||||
Stream.Start();
|
||||
$playbutton.addClass('bg-gray').prop('disabled', true);
|
||||
setTimeout(() => {
|
||||
$playbutton.removeClass('bg-gray').prop('disabled', false);
|
||||
}, 3000);
|
||||
$playbutton.find('.fa-solid').toggleClass('fa-play fa-stop');
|
||||
}
|
||||
$playbutton.addClass('bg-gray').prop('disabled', true);
|
||||
setTimeout(() => {
|
||||
$playbutton.removeClass('bg-gray').prop('disabled', false);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
function updateVolume() {
|
||||
Stream.Volume = $(this).val();
|
||||
if (Stream) {
|
||||
const newVolume = $(this).val();
|
||||
newVolumeGlobal = newVolume;
|
||||
console.log("Volume updated to:", newVolume);
|
||||
Stream.Volume = newVolume;
|
||||
} else {
|
||||
console.warn("Stream is not initialized.");
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(Init);
|
||||
$(document).ready(Init);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var url = new URL('text', window.location.href);
|
||||
url.protocol = url.protocol.replace('http', 'ws');
|
||||
var socketAddress = url.href;
|
||||
var socket = new WebSocket(socketAddress);
|
||||
// WebSocket connection located in ./websocket.js
|
||||
|
||||
|
||||
|
||||
var parsedData, signalChart, previousFreq;
|
||||
var signalData = [];
|
||||
var data = [];
|
||||
@@ -10,7 +10,7 @@ let updateCounter = 0;
|
||||
const europe_programmes = [
|
||||
"No PTY", "News", "Current Affairs", "Info",
|
||||
"Sport", "Education", "Drama", "Culture", "Science", "Varied",
|
||||
"Pop M", "Rock M", "Easy Listening", "Light Classical",
|
||||
"Pop Music", "Rock Music", "Easy Listening", "Light Classical",
|
||||
"Serious Classical", "Other Music", "Weather", "Finance",
|
||||
"Children's Programmes", "Social Affairs", "Religion", "Phone-in",
|
||||
"Travel", "Leisure", "Jazz Music", "Country Music", "National Music",
|
||||
@@ -881,7 +881,7 @@ function initTooltips() {
|
||||
// Add a delay of 500 milliseconds before creating and appending the tooltip
|
||||
$(this).data('timeout', setTimeout(() => {
|
||||
var tooltip = $('<div class="tooltiptext"></div>').html(tooltipText);
|
||||
$('body').append(tooltip);
|
||||
if ($('.tooltiptext').length === 0) { $('body').append(tooltip); } // Don't allow more than one tooltip
|
||||
|
||||
var posX = e.pageX;
|
||||
var posY = e.pageY;
|
||||
@@ -896,6 +896,7 @@ function initTooltips() {
|
||||
// Clear the timeout if the mouse leaves before the delay completes
|
||||
clearTimeout($(this).data('timeout'));
|
||||
$('.tooltiptext').remove();
|
||||
setTimeout(() => { $('.tooltiptext').remove(); }, 500); // Ensure no tooltips remain stuck
|
||||
}).mousemove(function(e){
|
||||
var tooltipWidth = $('.tooltiptext').outerWidth();
|
||||
var tooltipHeight = $('.tooltiptext').outerHeight();
|
||||
|
||||
30
web/js/websocket.js
Normal file
30
web/js/websocket.js
Normal file
@@ -0,0 +1,30 @@
|
||||
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
|
||||
});
|
||||
|
||||
// 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;
|
||||
Reference in New Issue
Block a user