function w(n,e){n.style.cursor="pointer",n.title="Double-click to edit",n.addEventListener("dblclick",()=>{let s=!1,a=document.createElement("input");a.type="text",a.className=e.className??"nbplay-inline-edit",a.value=e.getValue(),a.style.width=Math.max(n.offsetWidth+8,48)+"px",n.replaceWith(a),a.focus(),a.select();function p(){if(s)return;s=!0;let l=e.parse(a.value.trim());l!==null&&e.apply(l),a.replaceWith(n),e.sync()}a.addEventListener("keydown",l=>{l.key==="Enter"&&(l.preventDefault(),p()),l.key==="Escape"&&(l.preventDefault(),s||(s=!0,a.replaceWith(n),e.sync()))}),a.addEventListener("blur",p)})}function F(n){return n<=0?-1/0:20*Math.log10(n)}function I(n){return Math.pow(10,n/20)}function v(n){if(n<=0)return"\u2212\u221E dB";let e=20*Math.log10(n);return e>=0?"+"+e.toFixed(1)+" dB":e.toFixed(1)+" dB"}function S(n){return Math.abs(n)<.01?"C":n<0?"L"+Math.round(Math.abs(n)*100):"R"+Math.round(n*100)}function N(n){let e=n.replace(/\s*db\s*$/i,"").trim();if(e==="\u2212\u221E"||e==="-inf"||e==="-Infinity")return 0;let s=parseFloat(e);if(isNaN(s))return null;let a=I(s);return Math.max(0,Math.min(2,Math.round(a*1e3)/1e3))}function V(){let n=null,e=null,s=[];return{init(){n||(n=new AudioContext,e=n.createGain(),e.connect(n.destination))},syncChannels(a,p){if(!n||!e)return;for(;s.length<a.length;){let u=n.createGain(),h=n.createStereoPanner();u.connect(h),h.connect(e),s.push({gain:u,pan:h})}for(;s.length>a.length;){let u=s.pop();u.gain.disconnect(),u.pan.disconnect()}let l=a.some(u=>u.solo);a.forEach((u,h)=>{let y=s[h],L=u.gain;(u.mute||l&&!u.solo)&&(L=0),y.gain.gain.value=L,y.pan.pan.value=u.pan}),e.gain.value=p},register(a){let p=globalThis;p.__nbplay||(p.__nbplay={}),p.__nbplay[a]={audioCtx:n,masterGain:e,channels:s}},destroy(a){let p=globalThis;p.__nbplay&&delete p.__nbplay[a],s.forEach(l=>{l.gain.disconnect(),l.pan.disconnect()}),s.length=0,e&&e.disconnect(),n&&n.state!=="closed"&&n.close(),n=null,e=null}}}function $(n,e){let s=document.createElement("div");return s.className="nbplay-mixer-strip",s.dataset.index=String(e),s.innerHTML=`
    <div class="nbplay-strip-name" title="${n.name}">${n.name}</div>
    <div class="nbplay-strip-fader-section">
      <div class="nbplay-strip-meter">
        <div class="nbplay-strip-meter-fill"></div>
      </div>
      <input type="range" class="nbplay-strip-fader" min="0" max="2" step="0.01"
             value="${n.gain}" orient="vertical" />
      <div class="nbplay-strip-gain-label">${v(n.gain)}</div>
    </div>
    <div class="nbplay-strip-pan-section">
      <span class="nbplay-strip-pan-label">${S(n.pan)}</span>
      <input type="range" class="nbplay-strip-pan" min="-1" max="1" step="0.01"
             value="${n.pan}" />
    </div>
    <div class="nbplay-strip-buttons">
      <button class="nbplay-strip-btn nbplay-mute-btn${n.mute?" active":""}">M</button>
      <button class="nbplay-strip-btn nbplay-solo-btn${n.solo?" active":""}">S</button>
    </div>
    <button class="nbplay-strip-remove" title="Remove channel">\xD7</button>
  `,s}function G(n){let e=document.createElement("div");return e.className="nbplay-mixer-strip nbplay-master-strip",e.innerHTML=`
    <div class="nbplay-strip-name">Master</div>
    <div class="nbplay-strip-fader-section">
      <div class="nbplay-strip-meter">
        <div class="nbplay-strip-meter-fill"></div>
      </div>
      <input type="range" class="nbplay-strip-fader nbplay-master-fader" min="0" max="2"
             step="0.01" value="${n}" orient="vertical" />
      <div class="nbplay-strip-gain-label">${v(n)}</div>
    </div>
  `,e}function R({model:n,el:e}){let s=document.createElement("div");s.className="nbplay-mixer",s.innerHTML=`
    <div class="nbplay-mixer-header">
      <h3>nbplay</h3>
      <span class="nbplay-badge">mixer</span>
      <button class="nbplay-mixer-add-btn" title="Add channel">+ Channel</button>
    </div>
    <div class="nbplay-mixer-console"></div>
  `,e.appendChild(s);let a=s.querySelector(".nbplay-mixer-console"),p=s.querySelector(".nbplay-mixer-add-btn"),l=V(),u=n.get("session_id");u&&(l.init(),l.syncChannels(n.get("channels")||[],n.get("master_gain")),l.register(u));let h=-1,y=!1,L=!1;function D(){let i=n.get("channels")||[];a.querySelectorAll(".nbplay-mixer-strip:not(.nbplay-master-strip)").forEach((o,r)=>{if(r>=i.length)return;let c=i[r],g=o.querySelector(".nbplay-strip-fader");g&&document.activeElement!==g&&(g.value=String(c.gain));let x=o.querySelector(".nbplay-strip-gain-label");x&&(x.textContent=v(c.gain));let m=o.querySelector(".nbplay-strip-pan");m&&document.activeElement!==m&&(m.value=String(c.pan));let C=o.querySelector(".nbplay-strip-pan-label");C&&(C.textContent=S(c.pan));let B=o.querySelector(".nbplay-mute-btn");B&&B.classList.toggle("active",!!c.mute);let k=o.querySelector(".nbplay-solo-btn");k&&k.classList.toggle("active",!!c.solo);let T=o.querySelector(".nbplay-strip-name");T&&(T.textContent=c.name,T.title=c.name)});let d=a.querySelector(".nbplay-master-fader");d&&document.activeElement!==d&&(d.value=String(n.get("master_gain")));let b=a.querySelector(".nbplay-master-strip .nbplay-strip-gain-label");b&&(b.textContent=v(n.get("master_gain")))}function H(){if(y){L=!0;return}a.innerHTML="";let i=n.get("channels")||[];h=i.length,i.forEach((o,r)=>{let c=$(o,r);a.appendChild(c);let g=c.querySelector(".nbplay-strip-fader"),x=c.querySelector(".nbplay-strip-gain-label");g.addEventListener("pointerdown",()=>{y=!0}),g.addEventListener("input",()=>{let t=parseFloat(g.value);x.textContent=v(t),M(r,"gain",t)}),g.addEventListener("pointerup",f),g.addEventListener("lostpointercapture",f),g.addEventListener("change",f),w(x,{className:"nbplay-mixer-inline-edit",getValue:()=>{let t=(n.get("channels")||[])[r],_=t?t.gain:.8,q=F(_);return isFinite(q)?(q>=0?"+":"")+q.toFixed(1):"-inf"},parse:t=>N(t),apply:t=>M(r,"gain",t),sync:()=>{let t=(n.get("channels")||[])[r];x.textContent=v(t?.gain??.8)}});let m=c.querySelector(".nbplay-strip-pan"),C=c.querySelector(".nbplay-strip-pan-label");m.addEventListener("pointerdown",()=>{y=!0}),m.addEventListener("input",()=>{let t=parseFloat(m.value);C.textContent=S(t),M(r,"pan",t)}),m.addEventListener("pointerup",f),m.addEventListener("lostpointercapture",f),m.addEventListener("change",f),w(C,{className:"nbplay-mixer-inline-edit",getValue:()=>{let t=(n.get("channels")||[])[r];return t?String(t.pan):"0"},parse:t=>{let _=parseFloat(t);return isNaN(_)?null:Math.max(-1,Math.min(1,Math.round(_*100)/100))},apply:t=>M(r,"pan",t),sync:()=>{let t=(n.get("channels")||[])[r];C.textContent=S(t?.pan??0)}}),c.querySelector(".nbplay-mute-btn").addEventListener("click",()=>{let t=(n.get("channels")||[])[r];t&&M(r,"mute",!t.mute)}),c.querySelector(".nbplay-solo-btn").addEventListener("click",()=>{let t=(n.get("channels")||[])[r];t&&M(r,"solo",!t.solo)}),c.querySelector(".nbplay-strip-remove").addEventListener("click",()=>{let t=[...n.get("channels")||[]];t.splice(r,1),n.set("channels",t),n.save_changes()})});let E=G(n.get("master_gain"));a.appendChild(E);let d=E.querySelector(".nbplay-master-fader"),b=E.querySelector(".nbplay-strip-gain-label");d.addEventListener("pointerdown",()=>{y=!0}),d.addEventListener("input",()=>{let o=parseFloat(d.value);b.textContent=v(o),n.set("master_gain",o),n.save_changes()}),d.addEventListener("pointerup",f),d.addEventListener("lostpointercapture",f),w(b,{className:"nbplay-mixer-inline-edit",getValue:()=>{let o=n.get("master_gain"),r=F(o);return isFinite(r)?(r>=0?"+":"")+r.toFixed(1):"-inf"},parse:o=>N(o),apply:o=>{n.set("master_gain",o),n.save_changes()},sync:()=>{b.textContent=v(n.get("master_gain"))}}),d.addEventListener("change",f)}function f(){y&&(y=!1,L&&(L=!1,H()))}function M(i,E,d){let b=[...n.get("channels")||[]];i<b.length&&(b[i]={...b[i],[E]:d},n.set("channels",b),n.save_changes())}function A(){let i=n.get("channels")||[];i.length!==h?H():D(),n.get("session_id")&&l.syncChannels(i,n.get("master_gain"))}return p.addEventListener("click",()=>{let i=[...n.get("channels")||[]],E=i.length+1;i.push({name:"Ch "+E,gain:.8,pan:0,mute:!1,solo:!1}),n.set("channels",i),n.save_changes()}),n.on("change:channels",A),n.on("change:master_gain",A),H(),()=>{let i=n.get("session_id");i&&l.destroy(i)}}var W={render:R};export{W as default};
//# sourceMappingURL=mixer.js.map
