diff --git a/server/helpers.js b/server/helpers.js index 33cc2a0..9544023 100644 --- a/server/helpers.js +++ b/server/helpers.js @@ -20,7 +20,7 @@ function parseMarkdown(parsed) { parsed = parsed.replace(italicRegex, '$1'); var linkRegex = /\[([^\]]+)]\(([^)]+)\)/g; - parsed = parsed.replace(linkRegex, '$1'); + parsed = parsed.replace(linkRegex, '$1'); parsed = parsed.replace(/\n/g, '
'); diff --git a/server/stream/parser.js b/server/stream/parser.js index 48299f1..d0142bc 100644 --- a/server/stream/parser.js +++ b/server/stream/parser.js @@ -1,7 +1,7 @@ 'use strict'; const exec = require('child_process').exec; -const fs = require('fs'); +const fs = require('fs').promises; // Use the Promise-based fs API const ffmpeg = require('ffmpeg-static'); const filePath = '/proc/asound/cards'; const platform = process.platform; @@ -16,106 +16,97 @@ function parseAudioDevice(options, callback) { options = null; } options = options || {}; - const ffmpegPath = "\"" + ffmpeg.replace(/\\/g, '\\\\') + "\""; + const ffmpegPath = `"${ffmpeg.replace(/\\/g, '\\\\')}"`; const callbackExists = typeof callback === 'function'; - - let inputDevice, prefix, audioSeparator, alternativeName, deviceParams; - switch (platform) { - case 'win32': - inputDevice = 'dshow'; - prefix = /\[dshow/; - audioSeparator = /DirectShow\saudio\sdevices/; - alternativeName = /Alternative\sname\s*?\"(.*?)\"/; - deviceParams = /\"(.*?)\"/; - break; - case 'darwin': - inputDevice = 'avfoundation'; - prefix = /^\[AVFoundation/; - audioSeparator = /AVFoundation\saudio\sdevices/; - deviceParams = /^\[AVFoundation.*?\]\s\[(\d*?)\]\s(.*)$/; - break; - case 'linux': - fs.readFile(filePath, 'utf8', (err, data) => { - if (err) { - console.error(`Error reading file: ${err.message}`); - return; - } - - // Extract values between square brackets, trim whitespace, and prefix with 'hw:' - const regex = /\[([^\]]+)\]/g; - const matches = (data.match(regex) || []).map(match => 'hw:' + match.replace(/\s+/g, '').slice(1, -1)); - - if (matches.length > 0) { - // Process the extracted values - matches.forEach(function(match) { - if (typeof match === 'string') { - audioDevices.push({ name: match }); - } else if (typeof match === 'object' && match.name) { - audioDevices.push(match); - } - }); - } else { - logWarn('No audio devices have been found.'); - } - }); - break; - } - - - const searchPrefix = (line) => (line.search(prefix) > -1); - const searchAudioSeparator = (line) => isVideo && (line.search(audioSeparator) > -1); - const searchAlternativeName = (line) => (platform === 'win32') && (line.search(/Alternative\sname/) > -1); - - const execute = (fulfill, reject) => { - exec(`${ffmpegPath} -f ${inputDevice} -list_devices true -i ""`, (err, stdout, stderr) => { - stderr.split("\n") - .filter(searchPrefix) - .forEach((line) => { - const deviceList = isVideo ? videoDevices : audioDevices; - if (searchAudioSeparator(line)) { - isVideo = false; - return; + const execute = async (fulfill, reject) => { + try { + if (platform === 'linux') { + try { + const data = await fs.readFile(filePath, 'utf8'); + const regex = /\[([^\]]+)\]/g; + const matches = (data.match(regex) || []).map(match => 'hw:' + match.replace(/\s+/g, '').slice(1, -1)); + + matches.forEach(match => { + if (typeof match === 'string') { + audioDevices.push({ name: match }); + } + }); + } catch (err) { + console.error(`Error reading file: ${err.message}`); } - if (searchAlternativeName(line)) { - const lastDevice = deviceList[deviceList.length - 1]; - lastDevice.alternativeName = line.match(alternativeName)[1]; - return; - } - const params = line.match(deviceParams); - if (params) { - let device; - switch (platform) { - case 'win32': - device = { - name: params[1] - }; - break; - case 'darwin': - device = { - id: parseInt(params[1]), - name: params[2] - }; - break; - case 'linux': - device = { - name: params[1] - }; - break; - } - deviceList.push(device); - } - }); - audioDevices = audioDevices.filter(device => device.name !== undefined); - const result = { videoDevices, audioDevices }; - if (callbackExists) { - callback(result); - } else { - fulfill(result); + + // Linux doesn't support the `-list_devices` ffmpeg command like macOS/Windows, + // so skip the ffmpeg exec for Linux + const result = { videoDevices: [], audioDevices }; + if (callbackExists) return callback(result); + return fulfill(result); } - }); + + let inputDevice, prefix, audioSeparator, alternativeName, deviceParams; + + switch (platform) { + case 'win32': + inputDevice = 'dshow'; + prefix = /\[dshow/; + audioSeparator = /DirectShow\saudio\sdevices/; + alternativeName = /Alternative\sname\s*?"(.*?)"/; + deviceParams = /"(.*?)"/; + break; + case 'darwin': + inputDevice = 'avfoundation'; + prefix = /^\[AVFoundation/; + audioSeparator = /AVFoundation\saudio\sdevices/; + deviceParams = /^\[AVFoundation.*?]\s\[(\d+)]\s(.*)$/; + break; + } + + exec(`${ffmpegPath} -f ${inputDevice} -list_devices true -i ""`, (err, stdout, stderr) => { + stderr.split("\n") + .filter(line => line.search(prefix) > -1) + .forEach(line => { + const deviceList = isVideo ? videoDevices : audioDevices; + if (line.search(audioSeparator) > -1) { + isVideo = false; + return; + } + + if (platform === 'win32' && line.search(/Alternative\sname/) > -1) { + const lastDevice = deviceList[deviceList.length - 1]; + const alt = line.match(alternativeName); + if (lastDevice && alt) { + lastDevice.alternativeName = alt[1]; + } + return; + } + + const params = line.match(deviceParams); + if (params) { + let device; + switch (platform) { + case 'win32': + device = { name: params[1] }; + break; + case 'darwin': + device = { id: parseInt(params[1]), name: params[2] }; + break; + } + deviceList.push(device); + } + }); + + audioDevices = audioDevices.filter(device => device.name !== undefined); + const result = { videoDevices, audioDevices }; + if (callbackExists) return callback(result); + return fulfill(result); + }); + } catch (err) { + console.error('Unexpected error:', err); + if (callbackExists) callback({ videoDevices: [], audioDevices: [] }); + else reject(err); + } }; - + if (callbackExists) { execute(); } else { diff --git a/web/index.ejs b/web/index.ejs index 5cce173..49a5da4 100644 --- a/web/index.ejs +++ b/web/index.ejs @@ -23,8 +23,6 @@ - - @@ -267,6 +265,19 @@
+
+ <% if (antennas.enabled == true) { %> + + <% } %> +

RADIOTEXT

@@ -287,7 +298,7 @@ [] - kW [] + kW []
@@ -346,17 +357,6 @@
<% } %> - <% if (antennas.enabled == true) { %> - - <% } %>

Filters

@@ -409,10 +409,10 @@