5.2 KiB
Issue: MUTED Indicator Not Appearing in Spectrum Analyzer After Navigation
Description
The "MUTED" notification in the spectrum analyzer does not appear after navigating between pages using AJAX in frameset mode. The indicator shows correctly on initial page load, but after navigating to another page and back, muting the audio stream does not display the "MUTED" text overlay on the spectrum analyzer canvas.
Steps to Reproduce
- Navigate to
/asteroid/frameset - Mute the audio stream - "MUTED" indicator appears correctly ✓
- Click "Player" to navigate to the player page
- Mute the audio stream - "MUTED" indicator does NOT appear ✗
- Navigate back to the home page
- Mute the audio stream - "MUTED" indicator does NOT appear ✗
Expected Behavior
The "MUTED" indicator should:
- Display prominently on the spectrum analyzer canvas when audio is muted
- Work consistently across all pages with a spectrum analyzer
- Continue working after AJAX navigation
- Update in real-time when mute state changes
Root Cause
Multiple issues are causing this problem:
1. Stale Audio Element Reference
The spectrum analyzer stores a reference to the audio element in *current-audio-element* during initialization. After AJAX navigation:
- The DOM is replaced with new content
- The old audio element reference becomes stale
- The spectrum analyzer is still checking the muted property of the old (no longer valid) element
- The animation loop continues running but with outdated references
2. Frame Access Method
In frameset mode, the audio element lives in the player-frame while the spectrum analyzer canvas is in the content-frame. The code is using window.parent.frames.namedItem() which is not a standard method and causes errors:
TypeError: window.parent.frames.namedItem is not a function
3. No Re-initialization After Navigation
When content is loaded via AJAX, the spectrum analyzer initialization function runs but:
- The animation loop is already running from the previous page
- The new audio element reference is stored but the running loop doesn't pick it up
- The analyzer needs to be stopped and restarted with the fresh reference
Proposed Solution
1. Fix Frame Access
Change from namedItem() to standard property access:
;; Before (broken):
(let ((player-frame (ps:chain (ps:@ window parent frames) (named-item "player-frame"))))
;; After (working):
(let ((player-frame (ps:getprop (ps:@ window parent frames) "player-frame")))
2. Proper Initialization Order
Update the audio element lookup to check the current document first, then fall back to parent frame:
;; Try current document first
(setf audio-element (or (ps:chain document (get-element-by-id "live-audio"))
(ps:chain document (get-element-by-id "persistent-audio"))))
;; If not found and we're in a frame, try parent frame (frameset mode)
(when (and (not audio-element)
(ps:@ window parent)
(not (eq (ps:@ window parent) window)))
(ps:try
(let ((player-frame (ps:getprop (ps:@ window parent frames) "player-frame")))
(when player-frame
(setf audio-element (ps:chain player-frame document (get-element-by-id "persistent-audio")))))))
3. Restart Analyzer After Re-initialization
Modify initialize-spectrum-analyzer() to:
- Stop the existing animation loop
- Update the audio element reference
- Restart the analyzer if audio is already playing
(defun initialize-spectrum-analyzer ()
;; Stop existing analyzer if running
(when *animation-id*
(ps:chain window (cancel-animation-frame *animation-id*))
(setf *animation-id* nil))
;; ... find and store audio element ...
;; If audio is already playing, restart the analyzer with new reference
(when (and (not (ps:@ audio-element paused))
(ps:chain document (get-element-by-id "spectrum-canvas")))
(init-spectrum-analyzer)))
4. Call Re-initialization After AJAX Navigation
Add call to initializeSpectrumAnalyzer() in the loadInFrame() function:
// Re-initialize spectrum analyzer after navigation
if (window.initializeSpectrumAnalyzer) {
setTimeout(() => window.initializeSpectrumAnalyzer(), 100);
}
Files to Modify
parenscript/spectrum-analyzer.lisp- Fix frame access, initialization order, and restart logictemplate/front-page-content.ctml- Add re-initialization calltemplate/player-content.ctml- Add re-initialization calltemplate/admin-content.ctml- Add re-initialization calltemplate/profile-content.ctml- Add re-initialization calltemplate/login-content.ctml- Add re-initialization calltemplate/status-content.ctml- Add re-initialization call
Testing Plan
After implementing the fix:
- Navigate to
/asteroid/frameset - Mute audio - verify "MUTED" appears
- Navigate to player page
- Mute audio - verify "MUTED" appears
- Navigate to any other page
- Mute audio - verify "MUTED" appears
- Unmute and remute - verify indicator updates in real-time
Additional Benefits
This fix will also ensure:
- Spectrum analyzer theme/style preferences persist across navigation
- Canvas border colors update correctly
- All spectrum analyzer features work consistently across pages
- Proper resource cleanup when switching pages