Async gUM headset detection

by jib1

HTML

<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
<audio id="audio" width="160" height="120" autoplay controls></audio><br>
<div id="div2"></div><br>
<div id="div" style="white-space: pre;"></div>

JavaScript

(async () => {
  try {
    audio.srcObject = await navigator.mediaDevices.getUserMedia({audio: true});
    let [track] = audio.srcObject.getAudioTracks();
    let devices = await navigator.mediaDevices.enumerateDevices();
    setInterval(() => update(info(track, devices)), 500);
    let oldDevices = devices;
    track.onended = () => oldDevices = [];
    let eventCounter = 0;
    navigator.mediaDevices.ondevicechange = async () => {
      try {
        const id = ++eventCounter;
        console.log("devicechange");
        devices = await navigator.mediaDevices.enumerateDevices();
        if (id != eventCounter) return; // Work around trigger-happy Chrome
        const newDevices = devices.filter(d => !oldDevices.find(({deviceId}) => deviceId == d.deviceId));
        oldDevices = devices;
        const mic = newDevices.find(({kind}) => kind == "audioinput");
        const action = `${(track.readyState == "live")? "inserted" : "removed"}`;
        if (mic) {
          console.log(`mic ${action}`);
          track.stop(); // work around Firefox concurrent mic limit
          audio.srcObject = await navigator.mediaDevices.getUserMedia({audio: {
            deviceId: {exact: mic.deviceId}
          }});
          [track] = audio.srcObject.getAudioTracks();
          track.onended = () => oldDevices = [];
        }
        const speaker = newDevices.find(({kind}) => kind == "audiooutput");
        if (speaker) {
          console.log(`speaker ${action}`);
          if ("setSinkId" in audio) {
            await audio.setSinkId(speaker.deviceId);
          }
        }
        if (audio.sinkId && !devices.find(({deviceId}) => deviceId == audio.sinkId)) {
          audio.setSinkId(null);
        }
      } catch(e) {
        console.log(e);
      }
    };
  } catch(e) {
    console.log(e);
  }
})();

const console = { log: msg => div.innerHTML += msg + "<br>" };
const update = msg => div2.innerHTML = msg;
const info = (track, devices) => `${track.kind == "video" ? "Camera"...