mirror of
https://github.com/smittix/intercept.git
synced 2026-04-24 06:40:00 -07:00
Resume waterfall after listen and sync to mode frequency
This commit is contained in:
@@ -88,6 +88,9 @@ function startDmr() {
|
||||
if (typeof reserveDevice === 'function') {
|
||||
reserveDevice(parseInt(device), 'dmr');
|
||||
}
|
||||
if (typeof syncWaterfallToFrequency === 'function') {
|
||||
syncWaterfallToFrequency(frequency, { autoStart: true, restartIfRunning: true, silent: true });
|
||||
}
|
||||
if (typeof showNotification === 'function') {
|
||||
showNotification('DMR', `Decoding ${frequency} MHz (${protocol.toUpperCase()})`);
|
||||
}
|
||||
|
||||
@@ -2367,8 +2367,7 @@ async function _startDirectListenInternal() {
|
||||
isWaterfallRunning = true;
|
||||
const waterfallPanel = document.getElementById('waterfallPanel');
|
||||
if (waterfallPanel) waterfallPanel.style.display = 'block';
|
||||
document.getElementById('startWaterfallBtn').style.display = 'none';
|
||||
document.getElementById('stopWaterfallBtn').style.display = 'block';
|
||||
setWaterfallControlButtons(true);
|
||||
startAudioWaterfall();
|
||||
}
|
||||
updateDirectListenUI(true, freq);
|
||||
@@ -2537,7 +2536,7 @@ async function startWebSocketListen(config, audioPlayer) {
|
||||
/**
|
||||
* Stop direct listening
|
||||
*/
|
||||
function stopDirectListen() {
|
||||
async function stopDirectListen() {
|
||||
console.log('[LISTEN] Stopping');
|
||||
|
||||
// Clear all pending state
|
||||
@@ -2572,7 +2571,7 @@ function stopDirectListen() {
|
||||
}
|
||||
|
||||
// Also stop via HTTP (fallback)
|
||||
fetch('/listening/audio/stop', { method: 'POST' }).catch(() => {});
|
||||
const audioStopPromise = fetch('/listening/audio/stop', { method: 'POST' }).catch(() => {});
|
||||
|
||||
isDirectListening = false;
|
||||
currentSignalLevel = 0;
|
||||
@@ -2585,11 +2584,15 @@ function stopDirectListen() {
|
||||
|
||||
if (resumeRfWaterfallAfterListening) {
|
||||
isWaterfallRunning = false;
|
||||
setWaterfallControlButtons(false);
|
||||
await Promise.race([
|
||||
audioStopPromise,
|
||||
new Promise(resolve => setTimeout(resolve, 400))
|
||||
]);
|
||||
scheduleWaterfallResume();
|
||||
} else if (waterfallMode === 'audio' && isWaterfallRunning) {
|
||||
isWaterfallRunning = false;
|
||||
document.getElementById('startWaterfallBtn').style.display = 'block';
|
||||
document.getElementById('stopWaterfallBtn').style.display = 'none';
|
||||
setWaterfallControlButtons(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3072,6 +3075,7 @@ const WATERFALL_RESUME_MAX_ATTEMPTS = 8;
|
||||
const WATERFALL_RESUME_RETRY_MS = 350;
|
||||
const WATERFALL_ZOOM_MIN_MHZ = 0.1;
|
||||
const WATERFALL_ZOOM_MAX_MHZ = 500;
|
||||
const WATERFALL_DEFAULT_SPAN_MHZ = 2.0;
|
||||
|
||||
function resizeCanvasToDisplaySize(canvas) {
|
||||
if (!canvas) return false;
|
||||
@@ -3142,6 +3146,14 @@ function initWaterfallCanvas() {
|
||||
}
|
||||
}
|
||||
|
||||
function setWaterfallControlButtons(running) {
|
||||
const startBtn = document.getElementById('startWaterfallBtn');
|
||||
const stopBtn = document.getElementById('stopWaterfallBtn');
|
||||
if (!startBtn || !stopBtn) return;
|
||||
startBtn.style.display = running ? 'none' : 'block';
|
||||
stopBtn.style.display = running ? 'block' : 'none';
|
||||
}
|
||||
|
||||
function getWaterfallRangeFromInputs() {
|
||||
const startInput = document.getElementById('waterfallStartFreq');
|
||||
const endInput = document.getElementById('waterfallEndFreq');
|
||||
@@ -3200,6 +3212,33 @@ function getWaterfallCenterForZoom(start, end) {
|
||||
return (start + end) / 2;
|
||||
}
|
||||
|
||||
async function syncWaterfallToFrequency(freq, options = {}) {
|
||||
const { autoStart = false, restartIfRunning = true, silent = true } = options;
|
||||
const numericFreq = parseFloat(freq);
|
||||
if (!Number.isFinite(numericFreq) || numericFreq <= 0) return { started: false };
|
||||
|
||||
const { start, end } = getWaterfallRangeFromInputs();
|
||||
const span = (Number.isFinite(start) && Number.isFinite(end) && end > start)
|
||||
? (end - start)
|
||||
: WATERFALL_DEFAULT_SPAN_MHZ;
|
||||
|
||||
setWaterfallRange(numericFreq, span);
|
||||
|
||||
if (!autoStart) return { started: false };
|
||||
if (isDirectListening || waterfallMode === 'audio') return { started: false };
|
||||
|
||||
if (isWaterfallRunning && waterfallMode === 'rf' && restartIfRunning) {
|
||||
await stopWaterfall();
|
||||
return await startWaterfall({ silent: silent });
|
||||
}
|
||||
|
||||
if (!isWaterfallRunning) {
|
||||
return await startWaterfall({ silent: silent });
|
||||
}
|
||||
|
||||
return { started: true };
|
||||
}
|
||||
|
||||
async function zoomWaterfall(direction) {
|
||||
const { start, end } = getWaterfallRangeFromInputs();
|
||||
if (!Number.isFinite(start) || !Number.isFinite(end) || end <= start) return;
|
||||
@@ -3497,9 +3536,9 @@ async function startWaterfall(options = {}) {
|
||||
isWaterfallRunning = true;
|
||||
const waterfallPanel = document.getElementById('waterfallPanel');
|
||||
if (waterfallPanel) waterfallPanel.style.display = 'block';
|
||||
document.getElementById('startWaterfallBtn').style.display = 'none';
|
||||
document.getElementById('stopWaterfallBtn').style.display = 'block';
|
||||
setWaterfallControlButtons(true);
|
||||
startAudioWaterfall();
|
||||
resumeRfWaterfallAfterListening = true;
|
||||
return { started: true };
|
||||
}
|
||||
|
||||
@@ -3544,13 +3583,15 @@ async function startWaterfall(options = {}) {
|
||||
}
|
||||
|
||||
isWaterfallRunning = true;
|
||||
document.getElementById('startWaterfallBtn').style.display = 'none';
|
||||
document.getElementById('stopWaterfallBtn').style.display = 'block';
|
||||
setWaterfallControlButtons(true);
|
||||
const waterfallPanel = document.getElementById('waterfallPanel');
|
||||
if (waterfallPanel) waterfallPanel.style.display = 'block';
|
||||
lastWaterfallDraw = 0;
|
||||
initWaterfallCanvas();
|
||||
connectWaterfallSSE();
|
||||
if (typeof reserveDevice === 'function') {
|
||||
reserveDevice(parseInt(device), 'waterfall');
|
||||
}
|
||||
if (resume || resumeRfWaterfallAfterListening) {
|
||||
resumeRfWaterfallAfterListening = false;
|
||||
}
|
||||
@@ -3572,8 +3613,7 @@ async function stopWaterfall() {
|
||||
if (waterfallMode === 'audio') {
|
||||
stopAudioWaterfall();
|
||||
isWaterfallRunning = false;
|
||||
document.getElementById('startWaterfallBtn').style.display = 'block';
|
||||
document.getElementById('stopWaterfallBtn').style.display = 'none';
|
||||
setWaterfallControlButtons(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3581,8 +3621,10 @@ async function stopWaterfall() {
|
||||
await fetch('/listening/waterfall/stop', { method: 'POST' });
|
||||
isWaterfallRunning = false;
|
||||
if (waterfallEventSource) { waterfallEventSource.close(); waterfallEventSource = null; }
|
||||
document.getElementById('startWaterfallBtn').style.display = 'block';
|
||||
document.getElementById('stopWaterfallBtn').style.display = 'none';
|
||||
setWaterfallControlButtons(false);
|
||||
if (typeof releaseDevice === 'function') {
|
||||
releaseDevice('waterfall');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[WATERFALL] Stop error:', err);
|
||||
}
|
||||
@@ -3665,3 +3707,4 @@ window.guessSignal = guessSignal;
|
||||
window.startWaterfall = startWaterfall;
|
||||
window.stopWaterfall = stopWaterfall;
|
||||
window.zoomWaterfall = zoomWaterfall;
|
||||
window.syncWaterfallToFrequency = syncWaterfallToFrequency;
|
||||
|
||||
@@ -98,6 +98,9 @@ const SSTVGeneral = (function() {
|
||||
updateStatusUI('listening', `${frequency} MHz ${modulation.toUpperCase()}`);
|
||||
startStream();
|
||||
showNotification('SSTV', `Listening on ${frequency} MHz ${modulation.toUpperCase()}`);
|
||||
if (typeof syncWaterfallToFrequency === 'function') {
|
||||
syncWaterfallToFrequency(frequency, { autoStart: true, restartIfRunning: true, silent: true });
|
||||
}
|
||||
|
||||
// Update strip
|
||||
const stripFreq = document.getElementById('sstvGeneralStripFreq');
|
||||
|
||||
@@ -537,15 +537,18 @@ const SSTV = (function() {
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.status === 'started' || data.status === 'already_running') {
|
||||
isRunning = true;
|
||||
if (typeof reserveDevice === 'function') {
|
||||
reserveDevice(device, 'sstv');
|
||||
}
|
||||
updateStatusUI('listening', `${frequency} MHz`);
|
||||
startStream();
|
||||
showNotification('SSTV', `Listening on ${frequency} MHz`);
|
||||
} else {
|
||||
if (data.status === 'started' || data.status === 'already_running') {
|
||||
isRunning = true;
|
||||
if (typeof reserveDevice === 'function') {
|
||||
reserveDevice(device, 'sstv');
|
||||
}
|
||||
updateStatusUI('listening', `${frequency} MHz`);
|
||||
startStream();
|
||||
if (typeof syncWaterfallToFrequency === 'function') {
|
||||
syncWaterfallToFrequency(frequency, { autoStart: true, restartIfRunning: true, silent: true });
|
||||
}
|
||||
showNotification('SSTV', `Listening on ${frequency} MHz`);
|
||||
} else {
|
||||
updateStatusUI('idle', 'Start failed');
|
||||
showStatusMessage(data.message || 'Failed to start decoder', 'error');
|
||||
}
|
||||
|
||||
@@ -2859,6 +2859,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
function getModeWaterfallFrequency(mode) {
|
||||
const lookup = {
|
||||
pager: 'frequency',
|
||||
sensor: 'sensorFrequency',
|
||||
rtlamr: 'rtlamrFrequency',
|
||||
dmr: 'dmrFrequency',
|
||||
sstv: 'sstvFrequency',
|
||||
sstv_general: 'sstvGeneralFrequency',
|
||||
listening: 'radioScanStart'
|
||||
};
|
||||
const id = lookup[mode];
|
||||
if (!id) return NaN;
|
||||
const el = document.getElementById(id);
|
||||
const value = parseFloat(el?.value);
|
||||
return Number.isFinite(value) ? value : NaN;
|
||||
}
|
||||
|
||||
// Mode switching
|
||||
function switchMode(mode, options = {}) {
|
||||
const { updateUrl = true } = options;
|
||||
@@ -3069,6 +3086,12 @@
|
||||
const running = (typeof isWaterfallRunning !== 'undefined' && isWaterfallRunning);
|
||||
waterfallPanel.style.display = (waterfallSupported && running) ? 'block' : 'none';
|
||||
}
|
||||
if (waterfallSupported && typeof syncWaterfallToFrequency === 'function' && typeof isWaterfallRunning !== 'undefined' && isWaterfallRunning) {
|
||||
const modeFreq = getModeWaterfallFrequency(mode);
|
||||
if (Number.isFinite(modeFreq)) {
|
||||
syncWaterfallToFrequency(modeFreq, { autoStart: true, restartIfRunning: true, silent: true });
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle mode-specific tool status displays
|
||||
const toolStatusPager = document.getElementById('toolStatusPager');
|
||||
@@ -3164,6 +3187,9 @@
|
||||
// Sensor frequency
|
||||
function setSensorFreq(freq) {
|
||||
document.getElementById('sensorFrequency').value = freq;
|
||||
if (typeof syncWaterfallToFrequency === 'function') {
|
||||
syncWaterfallToFrequency(freq, { autoStart: typeof isWaterfallRunning !== 'undefined' && isWaterfallRunning });
|
||||
}
|
||||
if (isSensorRunning) {
|
||||
fetch('/stop_sensor', { method: 'POST' })
|
||||
.then(() => setTimeout(() => startSensorDecoding(), 500));
|
||||
@@ -3248,6 +3274,9 @@
|
||||
reserveDevice(parseInt(device), 'sensor');
|
||||
setSensorRunning(true);
|
||||
startSensorStream();
|
||||
if (!remoteConfig && typeof syncWaterfallToFrequency === 'function') {
|
||||
syncWaterfallToFrequency(freq, { autoStart: true, restartIfRunning: true, silent: true });
|
||||
}
|
||||
|
||||
// Initialize sensor filter bar
|
||||
const filterContainer = document.getElementById('filterBarContainer');
|
||||
@@ -3501,6 +3530,9 @@
|
||||
|
||||
function setRtlamrFreq(freq) {
|
||||
document.getElementById('rtlamrFrequency').value = freq;
|
||||
if (typeof syncWaterfallToFrequency === 'function') {
|
||||
syncWaterfallToFrequency(freq, { autoStart: typeof isWaterfallRunning !== 'undefined' && isWaterfallRunning });
|
||||
}
|
||||
}
|
||||
|
||||
// RTLAMR mode polling timer for agent mode
|
||||
@@ -3556,6 +3588,9 @@
|
||||
}
|
||||
setRtlamrRunning(true);
|
||||
startRtlamrStream(isAgentMode);
|
||||
if (!isAgentMode && typeof syncWaterfallToFrequency === 'function') {
|
||||
syncWaterfallToFrequency(freq, { autoStart: true, restartIfRunning: true, silent: true });
|
||||
}
|
||||
|
||||
// Initialize meter filter bar (reuse sensor filter bar since same structure)
|
||||
const filterContainer = document.getElementById('filterBarContainer');
|
||||
@@ -4327,6 +4362,9 @@
|
||||
}
|
||||
setRunning(true);
|
||||
startStream(isAgentMode);
|
||||
if (!isAgentMode && !remoteConfig && typeof syncWaterfallToFrequency === 'function') {
|
||||
syncWaterfallToFrequency(freq, { autoStart: true, restartIfRunning: true, silent: true });
|
||||
}
|
||||
|
||||
// Initialize filter bar
|
||||
const filterContainer = document.getElementById('filterBarContainer');
|
||||
|
||||
Reference in New Issue
Block a user