zebra-report: swap fresh <audio> in listener click — Firefox Android fix
Mirror of zebra-report 1de3f2c.
This commit is contained in:
parent
c81e7e00f2
commit
2c5d2618d6
1 changed files with 46 additions and 7 deletions
|
|
@ -4661,17 +4661,39 @@ function applyMuteState(){
|
|||
if (mm){ mm.muted = muted; renderRoom(); }
|
||||
}
|
||||
$('btn-mute').addEventListener('click', () => {
|
||||
/* listener path: toggle output mute. The click itself is the
|
||||
* user gesture mobile browsers wait for — even if listenerOutput-
|
||||
* Muted was already false, applyAudioMute() will re-call play()
|
||||
* inside this gesture and unblock any audio element that's been
|
||||
* waiting. */
|
||||
if (myRole === 'listener'){
|
||||
listenerOutputMuted = !listenerOutputMuted;
|
||||
logLine('', 'play-button: listenerOutputMuted=' + listenerOutputMuted +
|
||||
' remoteAudio=' + remoteAudio.size +
|
||||
' streamAudio=' + streamAudio.size +
|
||||
' audioPath=' + audioPath.size);
|
||||
/* Firefox Android internalisation defect: an <audio> created with
|
||||
* muted=true and later unmuted reports paused=false rs=4 srcObject=true
|
||||
* but emits zero output. Same shape as the video supplant defect we
|
||||
* fixed earlier with swapFreshVideoElement. Inside the click gesture,
|
||||
* swap every audio element with a fresh one (created UNMUTED) and
|
||||
* re-attach the source. play() fires inside the gesture so autoplay
|
||||
* is allowed. */
|
||||
if (!listenerOutputMuted){
|
||||
for (const [uuid, oldA] of [...remoteAudio]){
|
||||
const stream = oldA.srcObject;
|
||||
const fresh = swapFreshAudioElement(oldA);
|
||||
fresh.muted = false;
|
||||
applySinkTo(fresh);
|
||||
fresh.srcObject = stream;
|
||||
remoteAudio.set(uuid, fresh);
|
||||
try { const p = fresh.play(); if (p && p.catch) p.catch(e => logLine('err','swap rtc '+uuid+': '+e.message)); } catch(_){}
|
||||
}
|
||||
for (const [uuid, oldA] of [...streamAudio]){
|
||||
const src = oldA.src;
|
||||
const fresh = swapFreshAudioElement(oldA);
|
||||
fresh.muted = false;
|
||||
applySinkTo(fresh);
|
||||
if (src) fresh.src = src;
|
||||
streamAudio.set(uuid, fresh);
|
||||
try { const p = fresh.play(); if (p && p.catch) p.catch(e => logLine('err','swap dj '+uuid+': '+e.message)); } catch(_){}
|
||||
}
|
||||
}
|
||||
applyAudioMute();
|
||||
const btn = $('btn-mute');
|
||||
btn.textContent = listenerOutputMuted ? 'play' : 'mute';
|
||||
|
|
@ -4684,6 +4706,23 @@ $('btn-mute').addEventListener('click', () => {
|
|||
applyMuteState();
|
||||
sendMicState();
|
||||
});
|
||||
|
||||
/* Audio-element analogue of swapFreshVideoElement — replace an <audio>
|
||||
* with a freshly-built one in the same DOM slot. Used to dodge the
|
||||
* Firefox-Android internal routing defect where an element created
|
||||
* muted=true silently stays silent after .muted=false. */
|
||||
function swapFreshAudioElement(oldA){
|
||||
if (!oldA) return oldA;
|
||||
const fresh = document.createElement('audio');
|
||||
fresh.autoplay = true; fresh.playsInline = true; fresh.preload = 'auto';
|
||||
if (oldA.parentNode){
|
||||
try { oldA.srcObject = null; oldA.removeAttribute('src'); oldA.load(); } catch(_){}
|
||||
oldA.parentNode.replaceChild(fresh, oldA);
|
||||
} else {
|
||||
document.body.appendChild(fresh);
|
||||
}
|
||||
return fresh;
|
||||
}
|
||||
$('mic-select').addEventListener('change', async (e) => {
|
||||
micDeviceId = e.target.value;
|
||||
try { localStorage.setItem(MIC_DEV_KEY, micDeviceId); } catch(_){}
|
||||
|
|
@ -4932,8 +4971,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');
|
|||
|
||||
<footer style="margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
|
||||
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> · built <span class="stamp-date">2026-06-04</span><br>
|
||||
md5 <span class="stamp-md5">71493d3cbf0438797dcf8c1b4948202f</span><br>
|
||||
sha256 <span class="stamp-sha">2a12f6f390f0592daa5ee6ad23f8a661d558ece7a57cce51567ddc34adc89a7d</span><br>
|
||||
md5 <span class="stamp-md5">eac4e2b4b8c40c4adbdd03c004eb8cc4</span><br>
|
||||
sha256 <span class="stamp-sha">d2ca231a1a04199c5e5cc01215e6a82ab4949119d5ac40bd5150a7805fd3cdf1</span><br>
|
||||
<span style="color:#bbb">hashes are of this page with these two fields zeroed — to verify, blank them and re-hash</span><br>
|
||||
<span style="color:#bbb">one self-contained file — <strong>save a copy</strong> and verify against these hashes; point at your own servers with ?signal= and ?turncred=, or <a href="host-your-own.html" style="color:#999">host your own community</a></span>
|
||||
</footer>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue