diff --git a/routes/sstv.py b/routes/sstv.py index 1a92772..b46bea5 100644 --- a/routes/sstv.py +++ b/routes/sstv.py @@ -13,6 +13,7 @@ from typing import Generator from flask import Blueprint, jsonify, request, Response, send_file +import app as app_module from utils.logging import get_logger from utils.sse import format_sse from utils.sstv import ( @@ -30,6 +31,9 @@ sstv_bp = Blueprint('sstv', __name__, url_prefix='/sstv') # Queue for SSE progress streaming _sstv_queue: queue.Queue = queue.Queue(maxsize=100) +# Track which device is being used +sstv_active_device: int | None = None + def _progress_callback(progress: DecodeProgress) -> None: """Callback to queue progress updates for SSE stream.""" @@ -158,6 +162,17 @@ def start_decoder(): latitude = None longitude = None + # Claim SDR device + global sstv_active_device + device_int = int(device_index) + error = app_module.claim_sdr_device(device_int, 'sstv') + if error: + return jsonify({ + 'status': 'error', + 'error_type': 'DEVICE_BUSY', + 'message': error + }), 409 + # Set callback and start decoder.set_callback(_progress_callback) success = decoder.start( @@ -168,6 +183,8 @@ def start_decoder(): ) if success: + sstv_active_device = device_int + result = { 'status': 'started', 'frequency': frequency, @@ -181,6 +198,8 @@ def start_decoder(): return jsonify(result) else: + # Release device on failure + app_module.release_sdr_device(device_int) return jsonify({ 'status': 'error', 'message': 'Failed to start decoder' @@ -195,8 +214,15 @@ def stop_decoder(): Returns: JSON confirmation. """ + global sstv_active_device decoder = get_sstv_decoder() decoder.stop() + + # Release device from registry + if sstv_active_device is not None: + app_module.release_sdr_device(sstv_active_device) + sstv_active_device = None + return jsonify({'status': 'stopped'}) diff --git a/static/js/modes/sstv.js b/static/js/modes/sstv.js index ec51f87..6bafdb0 100644 --- a/static/js/modes/sstv.js +++ b/static/js/modes/sstv.js @@ -521,6 +521,11 @@ const SSTV = (function() { const frequency = parseFloat(freqInput?.value || ISS_FREQ); const device = parseInt(deviceSelect?.value || '0', 10); + // Check if device is available + if (typeof checkDeviceAvailability === 'function' && !checkDeviceAvailability('sstv')) { + return; + } + updateStatusUI('connecting', 'Starting...'); try { @@ -534,6 +539,9 @@ const SSTV = (function() { 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`); @@ -555,6 +563,9 @@ const SSTV = (function() { try { await fetch('/sstv/stop', { method: 'POST' }); isRunning = false; + if (typeof releaseDevice === 'function') { + releaseDevice('sstv'); + } stopStream(); updateStatusUI('idle', 'Stopped'); showNotification('SSTV', 'Decoder stopped');