diff --git a/media_server/services/audio_analyzer.py b/media_server/services/audio_analyzer.py index 997351f..285dd98 100644 --- a/media_server/services/audio_analyzer.py +++ b/media_server/services/audio_analyzer.py @@ -17,8 +17,8 @@ def _load_numpy(): try: import numpy as np _np = np - except ImportError: - logger.info("numpy not installed - audio visualizer unavailable") + except Exception as e: + logger.warning("numpy unavailable - audio visualizer disabled: %s", e) return _np @@ -28,8 +28,8 @@ def _load_soundcard(): try: import soundcard as sc _sc = sc - except ImportError: - logger.info("soundcard not installed - audio visualizer unavailable") + except Exception as e: + logger.warning("soundcard unavailable - audio visualizer disabled: %s", e) return _sc diff --git a/media_server/static/js/player.js b/media_server/static/js/player.js index d5b303f..d85f5ac 100644 --- a/media_server/static/js/player.js +++ b/media_server/static/js/player.js @@ -485,7 +485,20 @@ export async function loadAudioDevices() { }); _audioDeviceIconSelect.setValue(select.value, false); + // Sync visualizerAvailable from the fetched status so that + // applyVisualizerMode() and the toggle button are consistent. + visualizerAvailable = status.available; + const btn = document.getElementById('visualizerToggle'); + if (btn) btn.style.display = visualizerAvailable ? '' : 'none'; + updateAudioDeviceStatus(status); + + // Re-subscribe the WebSocket if the user had the visualizer enabled. + if (visualizerEnabled && visualizerAvailable) { + if (ws && ws.readyState === WebSocket.OPEN) { + ws.send(JSON.stringify({ type: 'enable_visualizer' })); + } + } } catch (e) { section.style.display = 'none'; } diff --git a/media_server/static/js/websocket.js b/media_server/static/js/websocket.js index 39ee4d0..f90c214 100644 --- a/media_server/static/js/websocket.js +++ b/media_server/static/js/websocket.js @@ -8,7 +8,7 @@ import { WS_MAX_RECONNECT_ATTEMPTS, WS_PING_INTERVAL_MS, authRequired, showUpdateBanner, } from './core.js'; -import { updateUI, visualizerEnabled, visualizerAvailable, setFrequencyData, stopPositionInterpolation, loadAudioDevices } from './player.js'; +import { updateUI, setFrequencyData, stopPositionInterpolation, loadAudioDevices } from './player.js'; import { loadScripts, loadScriptsTable, displayQuickAccess } from './scripts.js'; import { loadCallbacksTable } from './callbacks.js'; import { loadHeaderLinks, loadLinksTable } from './links.js'; @@ -81,9 +81,6 @@ export function connectWebSocket(token) { loadLinksTable(); loadHeaderLinks(); loadAudioDevices(); - if (visualizerEnabled && visualizerAvailable) { - newWs.send(JSON.stringify({ type: 'enable_visualizer' })); - } }; newWs.onmessage = (event) => {