/* * * * WebAudio-Controls is based on * webaudio-knob by Eiji Kitamura http://google.com/+agektmr * webaudio-slider by RYoya Kawai https://plus.google.com/108242669191458983485/posts * webaudio-switch by Keisuke Ai http://d.hatena.ne.jp/aike/ * Integrated and enhanced by g200kg http://www.g200kg.com/ * * Copyright 2013 Eiji Kitamura / Ryoya KAWAI / Keisuke Ai / g200kg(Tatsuya Shinyagaito) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * */ if(window.customElements){ let styles=document.createElement("style"); styles.innerHTML= `#webaudioctrl-context-menu { display: none; position: absolute; z-index: 10; padding: 0; width: 100px; color:#eee; background-color: #268; border: solid 1px #888; box-shadow: 1px 1px 2px #888; font-family: sans-serif; font-size: 11px; line-height:1.7em; text-align:center; cursor:pointer; color:#fff; list-style: none; } #webaudioctrl-context-menu.active { display: block; } .webaudioctrl-context-menu__item { display: block; margin: 0; padding: 0; color: #000; background-color:#eee; text-decoration: none; } .webaudioctrl-context-menu__title{ font-weight:bold; } .webaudioctrl-context-menu__item:last-child { margin-bottom: 0; } .webaudioctrl-context-menu__item:hover { background-color: #b8b8b8; } `; document.head.appendChild(styles); let midimenu=document.createElement("ul"); midimenu.id="webaudioctrl-context-menu"; midimenu.innerHTML= `
  • MIDI Learn
  • Learn
  • Clear
  • Close
  • `; let opt={ useMidi:0, midilearn:0, mididump:0, outline:0, knobSrc:null, knobSprites:0, knobWidth:0, knobHeight:0, knobDiameter:64, knobColors:"#e00;#000;#000", sliderSrc:null, sliderKnobsrc:null, sliderWidth:0, sliderHeight:0, sliderKnobwidth:0, sliderKnobheight:0, sliderDitchlength:0, sliderColors:"#e00;#000;#fcc", switchWidth:0, switchHeight:0, switchDiameter:24, switchColors:"#e00;#000;#fcc", paramWidth:32, paramHeight:16, paramColors:"#fff;#000", xypadColors:"#e00;#000;#fcc", }; if(window.WebAudioControlsOptions) Object.assign(opt,window.WebAudioControlsOptions); class WebAudioControlsWidget extends HTMLElement{ constructor(){ super(); this.addEventListener("keydown",this.keydown); this.addEventListener("mousedown",this.pointerdown,{passive:false}); this.addEventListener("touchstart",this.pointerdown,{passive:false}); this.addEventListener("wheel",this.wheel); this.addEventListener("mouseover",this.pointerover); this.addEventListener("mouseout",this.pointerout); this.addEventListener("contextmenu",this.contextMenu); this.hover=this.drag=0; document.body.appendChild(midimenu); this.basestyle=` .webaudioctrl-tooltip{ display:inline-block; position:absolute; margin:0 -1000px; z-index: 999; background:#eee; color:#000; border:1px solid #666; border-radius:4px; padding:5px 10px; text-align:center; left:0; top:0; font-size:11px; opacity:0; visibility:hidden; } .webaudioctrl-tooltip:before{ content: ""; position: absolute; top: 100%; left: 50%; margin-left: -8px; border: 8px solid transparent; border-top: 8px solid #666; } .webaudioctrl-tooltip:after{ content: ""; position: absolute; top: 100%; left: 50%; margin-left: -6px; border: 6px solid transparent; border-top: 6px solid #eee; } `; } sendEvent(ev){ let event; event=document.createEvent("HTMLEvents"); event.initEvent(ev,false,true); this.dispatchEvent(event); } getAttr(n,def){ let v=this.getAttribute(n); if(v==""||v==null) return def; switch(typeof(def)){ case "number": if(v=="true") return 1; v=+v; if(isNaN(v)) return 0; return v; } return v; } showtip(d){ function valstr(x,c,type){ switch(type){ case "x": return (x|0).toString(16); case "X": return (x|0).toString(16).toUpperCase(); case "d": return (x|0).toString(); case "f": return x.toFixed(c); case "s": return x.toString(); } return ""; } function numformat(s,x){ if(typeof(x)=="undefined") return; let i=s.indexOf("%"); let c=[0,0],type=0,m=0,r="",j=i+1; for(;j=0){ type=s[j]; break; } if(s[j]==".") m=1; else c[m]=c[m]*10+parseInt(s[j]); } if(typeof(x)=="number") r=valstr(x,c[1],type); else r=valstr(x.x,c[1],type)+","+valstr(x.y,c[1],type); if(c[0]>0) r=(" "+r).slice(-c[0]); r=s.replace(/%.*[xXdfs]/,r); return r; } let s=this.tooltip; if(this.drag||this.hover){ if(this.valuetip){ if(s==null) s=`%.${this.digits}f`; else if(s.indexOf("%")<0) s+=` : %.${this.digits}f`; } if(s){ this.ttframe.innerHTML=numformat(s,this.convValue); this.ttframe.style.display="inline-block"; this.ttframe.style.width="auto"; this.ttframe.style.height="auto"; this.ttframe.style.transition="opacity 0.5s "+d+"s,visibility 0.5s "+d+"s"; this.ttframe.style.opacity=0.9; this.ttframe.style.visibility="visible"; let rc=this.getBoundingClientRect(),rc2=this.ttframe.getBoundingClientRect(),rc3=document.documentElement.getBoundingClientRect(); this.ttframe.style.left=((rc.width-rc2.width)*0.5+1000)+"px"; this.ttframe.style.top=(-rc2.height-8)+"px"; return; } } this.ttframe.style.transition="opacity 0.1s "+d+"s,visibility 0.1s "+d+"s"; this.ttframe.style.opacity=0; this.ttframe.style.visibility="hidden"; } pointerover(e) { this.hover=1; this.showtip(0.6); } pointerout(e) { this.hover=0; this.showtip(0); } contextMenu(e){ if(window.webAudioControlsMidiManager && this.midilearn) webAudioControlsMidiManager.contextMenuOpen(e,this); e.preventDefault(); e.stopPropagation(); } setMidiController(channel, cc) { if (this.listeningToThisMidiController(channel, cc)) return; this.midiController={ 'channel': channel, 'cc': cc}; console.log("Added mapping for channel=" + channel + " cc=" + cc + " tooltip=" + this.tooltip); } listeningToThisMidiController(channel, cc) { const c = this.midiController; if((c.channel === channel || c.channel < 0) && c.cc === cc) return true; return false; } processMidiEvent(event){ const channel = event.data[0] & 0xf; const controlNumber = event.data[1]; if(this.midiMode == 'learn') { this.setMidiController(channel, controlNumber); webAudioControlsMidiManager.contextMenuClose(); this.midiMode = 'normal'; } if(this.listeningToThisMidiController(channel, controlNumber)) { if(this.tagName=="WEBAUDIO-SWITCH"){ switch(this.type){ case "toggle": if(event.data[2]>=64) this.setValue(1-this.value,true); break; case "kick": this.setValue(event.data[2]>=64?1:0); break; case "radio": let els=document.querySelectorAll("webaudio-switch[type='radio'][group='"+this.group+"']"); for(let i=0;i ${this.basestyle} webaudio-knob{ display:inline-block; position:relative; margin:0; padding:0; cursor:pointer; font-family: sans-serif; font-size: 11px; } .webaudio-knob-body{ display:inline-block; position:relative; margin:0; padding:0; vertical-align:bottom; }
    `; this.elem=root.childNodes[2]; this.ttframe=root.childNodes[3]; this.enable=this.getAttr("enable",1); this._src=this.getAttr("src",opt.knobSrc); Object.defineProperty(this,"src",{get:()=>{return this._src},set:(v)=>{this._src=v;this.setupImage()}}); this._value=this.getAttr("value",0); Object.defineProperty(this,"value",{get:()=>{return this._value},set:(v)=>{this._value=v;this.redraw()}}); this.defvalue=this.getAttr("defvalue",0); this._min=this.getAttr("min",0); Object.defineProperty(this,"min",{get:()=>{return this._min},set:(v)=>{this._min=+v;this.redraw()}}); this._max=this.getAttr("max",100); Object.defineProperty(this,"max",{get:()=>{return this._max},set:(v)=>{this._max=+v;this.redraw()}}); this._step=this.getAttr("step",1); Object.defineProperty(this,"step",{get:()=>{return this._step},set:(v)=>{this._step=+v;this.redraw()}}); this._sprites=this.getAttr("sprites",opt.knobSprites); Object.defineProperty(this,"sprites",{get:()=>{return this._sprites},set:(v)=>{this._sprites=v;this.setupImage()}}); this._width=this.getAttr("width",opt.knobWidth); Object.defineProperty(this,"width",{get:()=>{return this._width},set:(v)=>{this._width=v;this.setupImage()}}); this._height=this.getAttr("height",opt.knobHeight); Object.defineProperty(this,"height",{get:()=>{return this._height},set:(v)=>{this._height=v;this.setupImage()}}); this._diameter=this.getAttr("diameter",opt.knobDiameter); Object.defineProperty(this,"diameter",{get:()=>{return this._diameter},set:(v)=>{this._diameter=v;this.setupImage()}}); this._colors=this.getAttr("colors",opt.knobColors); Object.defineProperty(this,"colors",{get:()=>{return this._colors},set:(v)=>{this._colors=v;this.setupImage()}}); this.outline=this.getAttr("outline",opt.outline); this.sensitivity=this.getAttr("sensitivity",1); this.valuetip=this.getAttr("valuetip",1); this.tooltip=this.getAttr("tooltip",null); this.conv=this.getAttr("conv",null); if(this.conv) this.convValue=eval(this.conv)(this._value); else this.convValue=this._value; this.midilearn=this.getAttr("midilearn",opt.midilearn); this.midicc=this.getAttr("midicc",null); this.midiController={}; this.midiMode="normal"; if(this.midicc) { let ch = parseInt(this.midicc.substring(0, this.midicc.lastIndexOf("."))) - 1; let cc = parseInt(this.midicc.substring(this.midicc.lastIndexOf(".") + 1)); this.setMidiController(ch, cc); } this.setupImage(); this.digits=0; this.coltab=["#e00","#000","#000"]; if(window.webAudioControlsMidiManager) // window.webAudioControlsMidiManager.updateWidgets(); window.webAudioControlsMidiManager.addWidget(this); } disconnectedCallback(){} setupImage(){ this.kw=this.width||this.diameter; this.kh=this.height||this.diameter; if(!this.src){ if(this.colors) this.coltab = this.colors.split(";"); if(!this.coltab) this.coltab=["#e00","#000","#000"]; let svg= ` `; for(let i=0;i<101;++i){ svg += ``; svg += ``; } svg += ""; this.elem.style.backgroundImage = "url(data:image/svg+xml;base64,"+btoa(svg)+")"; // this.elem.style.backgroundSize = "100% 10100%"; this.elem.style.backgroundSize = `${this.kw}px ${this.kh*101}px`; } else{ this.elem.style.backgroundImage = "url("+(this.src)+")"; if(!this.sprites) this.elem.style.backgroundSize = "100% 100%"; else{ // this.elem.style.backgroundSize = `100% ${(this.sprites+1)*100}%`; this.elem.style.backgroundSize = `${this.kw}px ${this.kh*(this.sprites+1)}px`; } } this.elem.style.outline=this.outline?"":"none"; this.elem.style.width=this.kw+"px"; this.elem.style.height=this.kh+"px"; this.style.height=this.kh+"px"; this.redraw(); } redraw() { this.digits=0; if(this.step && this.step < 1) { for(let n = this.step ; n < 1; n *= 10) ++this.digits; } if(this.valuethis.max){ this.value=this.max; return; } let range = this.max - this.min; let style = this.elem.style; let sp = this.src?this.sprites:100; if(sp>=1){ let offset = ((sp * (this.value - this.min) / range) | 0); style.backgroundPosition = "0px " + (-offset*this.kh) + "px"; style.transform = 'rotate(0deg)'; } else { let deg = 270 * ((this.value - this.min) / range - 0.5); style.backgroundPosition="0px 0px"; style.transform = 'rotate(' + deg + 'deg)'; } } _setValue(v){ if(this.step) v=(Math.round((v-this.min)/this.step))*this.step+this.min; this._value=Math.min(this.max,Math.max(this.min,v)); if(this._value!=this.oldvalue){ this.oldvalue=this._value; if(this.conv) this.convValue=eval(this.conv)(this._value); else this.convValue=this._value; this.redraw(); this.showtip(0); return 1; } return 0; } setValue(v,f){ if(this._setValue(v) && f) this.sendEvent("input"),this.sendEvent("change"); } wheel(e) { let delta=(this.max-this.min)*0.01; delta=e.deltaY>0?-delta:delta; if(!e.shiftKey) delta*=5; if(Math.abs(delta) < this.step) delta = (delta > 0) ? +this.step : -this.step; this.setValue(+this.value+delta,true); e.preventDefault(); e.stopPropagation(); } pointerdown(ev){ if(!this.enable) return; let e=ev; if(ev.touches){ e = ev.changedTouches[0]; this.identifier=e.identifier; } else { if(e.buttons!=1 && e.button!=0) return; } this.elem.focus(); this.drag=1; this.showtip(0); let pointermove=(ev)=>{ let e=ev; if(ev.touches){ for(let i=0;i{ let e=ev; if(ev.touches){ for(let i=0;;){ if(ev.changedTouches[i].identifier==this.identifier){ break; } if(++i>=ev.changedTouches.length) return; } } this.drag=0; this.showtip(0); this.startPosX = this.startPosY = null; window.removeEventListener('mousemove', pointermove); window.removeEventListener('touchmove', pointermove, {passive:false}); window.removeEventListener('mouseup', pointerup); window.removeEventListener('touchend', pointerup); window.removeEventListener('touchcancel', pointerup); document.body.removeEventListener('touchstart', preventScroll,{passive:false}); this.sendEvent("change"); } let preventScroll=(e)=>{ e.preventDefault(); } if(e.ctrlKey || e.metaKey) this.setValue(this.defvalue,true); else { this.startPosX = e.pageX; this.startPosY = e.pageY; this.startVal = this.value; window.addEventListener('mousemove', pointermove); window.addEventListener('touchmove', pointermove, {passive:false}); } window.addEventListener('mouseup', pointerup); window.addEventListener('touchend', pointerup); window.addEventListener('touchcancel', pointerup); document.body.addEventListener('touchstart', preventScroll,{passive:false}); ev.preventDefault(); ev.stopPropagation(); return false; } }); } catch(error){ console.log("webaudio-knob already defined"); } try{ customElements.define("webaudio-slider", class WebAudioSlider extends WebAudioControlsWidget { constructor(){ super(); } connectedCallback(){ let root; // if(this.attachShadow) // root=this.attachShadow({mode: 'open'}); // else root=this; root.innerHTML= `
    `; this.elem=root.childNodes[2]; this.knob=this.elem.childNodes[0]; this.ttframe=root.childNodes[3]; this.enable=this.getAttr("enable",1); this._src=this.getAttr("src",opt.sliderSrc); Object.defineProperty(this,"src",{get:()=>{return this._src},set:(v)=>{this._src=v;this.setupImage()}}); this._knobsrc=this.getAttr("knobsrc",opt.sliderKnobsrc); Object.defineProperty(this,"knobsrc",{get:()=>{return this._knobsrc},set:(v)=>{this._knobsrc=v;this.setupImage()}}); this._value=this.getAttr("value",0); Object.defineProperty(this,"value",{get:()=>{return this._value},set:(v)=>{this._value=v;this.redraw()}}); this.defvalue=this.getAttr("defvalue",0); this._min=this.getAttr("min",0); Object.defineProperty(this,"min",{get:()=>{return this._min},set:(v)=>{this._min=v;this.redraw()}}); this._max=this.getAttr("max",100); Object.defineProperty(this,"max",{get:()=>{return this._max},set:(v)=>{this._max=v;this.redraw()}}); this._step=this.getAttr("step",1); Object.defineProperty(this,"step",{get:()=>{return this._step},set:(v)=>{this._step=v;this.redraw()}}); this._sprites=this.getAttr("sprites",0); Object.defineProperty(this,"sprites",{get:()=>{return this._sprites},set:(v)=>{this._sprites=v;this.setupImage()}}); this._direction=this.getAttr("direction",null); Object.defineProperty(this,"direction",{get:()=>{return this._direction},set:(v)=>{this._direction=v;this.setupImage()}}); this._width=this.getAttr("width",opt.sliderWidth); Object.defineProperty(this,"width",{get:()=>{return this._width},set:(v)=>{this._width=v;this.setupImage()}}); this._height=this.getAttr("height",opt.sliderHeight); Object.defineProperty(this,"height",{get:()=>{return this._height},set:(v)=>{this._height=v;this.setupImage()}}); if(this._direction=="horz"){ if(this._width==0) this._width=128; if(this._height==0) this._height=24; } else{ if(this._width==0) this._width=24; if(this._height==0) this._height=128; } this._knobwidth=this.getAttr("knobwidth",opt.sliderKnobwidth); Object.defineProperty(this,"knobwidth",{get:()=>{return this._knobwidth},set:(v)=>{this._knobwidth=v;this.setupImage()}}); this._knobheight=this.getAttr("knbheight",opt.sliderKnobheight); Object.defineProperty(this,"knobheight",{get:()=>{return this._knobheight},set:(v)=>{this._knobheight=v;this.setupImage()}}); this._ditchlength=this.getAttr("ditchlength",opt.sliderDitchlength); Object.defineProperty(this,"ditchlength",{get:()=>{return this._ditchlength},set:(v)=>{this._ditchlength=v;this.setupImage()}}); this._colors=this.getAttr("colors",opt.sliderColors); Object.defineProperty(this,"colors",{get:()=>{return this._colors},set:(v)=>{this._colors=v;this.setupImage()}}); this.outline=this.getAttr("outline",opt.outline); this.sensitivity=this.getAttr("sensitivity",1); this.valuetip=this.getAttr("valuetip",1); this.tooltip=this.getAttr("tooltip",null); this.conv=this.getAttr("conv",null); if(this.conv) this.convValue=eval(this.conv)(this._value); else this.convValue=this._value; this.midilearn=this.getAttr("midilearn",opt.midilearn); this.midicc=this.getAttr("midicc",null); this.midiController={}; this.midiMode="normal"; if(this.midicc) { let ch = parseInt(this.midicc.substring(0, this.midicc.lastIndexOf("."))) - 1; let cc = parseInt(this.midicc.substring(this.midicc.lastIndexOf(".") + 1)); this.setMidiController(ch, cc); } this.setupImage(); this.digits=0; if(window.webAudioControlsMidiManager) // window.webAudioControlsMidiManager.updateWidgets(); window.webAudioControlsMidiManager.addWidget(this); this.elem.onclick=(e)=>{e.stopPropagation()}; } disconnectedCallback(){} setupImage(){ this.coltab = this.colors.split(";"); this.dr=this.direction; this.dlen=this.ditchlength; if(!this.width){ if(this.dr=="horz") this.width=128; else this.width=24; } if(!this.height){ if(this.dr=="horz") this.height=24; else this.height=128; } if(!this.dr) this.dr=(this.width<=this.height)?"vert":"horz"; if(this.dr=="vert"){ if(!this.dlen) this.dlen=this.height-this.width; } else{ if(!this.dlen) this.dlen=this.width-this.height; } this.knob.style.backgroundSize = "100% 100%"; this.elem.style.backgroundSize = "100% 100%"; this.elem.style.width=this.width+"px"; this.elem.style.height=this.height+"px"; this.style.height=this.height+"px"; this.kwidth=this.knobwidth||(this.dr=="horz"?this.height:this.width); this.kheight=this.knobheight||(this.dr=="horz"?this.height:this.width); this.knob.style.width = this.kwidth+"px"; this.knob.style.height = this.kheight+"px"; if(!this.src){ let r=Math.min(this.width,this.height)*0.5; let svgbody= ` `; this.elem.style.backgroundImage = "url(data:image/svg+xml;base64,"+btoa(svgbody)+")"; } else{ this.elem.style.backgroundImage = "url("+(this.src)+")"; } if(!this.knobsrc){ let svgthumb= ` `; this.knob.style.backgroundImage = "url(data:image/svg+xml;base64,"+btoa(svgthumb)+")"; } else{ this.knob.style.backgroundImage = "url("+(this.knobsrc)+")"; } this.elem.style.outline=this.outline?"":"none"; this.redraw(); } redraw() { this.digits=0; if(this.step && this.step < 1) { for(let n = this.step ; n < 1; n *= 10) ++this.digits; } if(this.valuethis.max){ this.value=this.max; return; } let range = this.max - this.min; let style = this.knob.style; if(this.dr=="vert"){ style.left=(this.width-this.kwidth)*0.5+"px"; style.top=(1-(this.value-this.min)/range)*this.dlen+"px"; this.sensex=0; this.sensey=1; } else{ style.top=(this.height-this.kheight)*0.5+"px"; style.left=(this.value-this.min)/range*this.dlen+"px"; this.sensex=1; this.sensey=0; } } _setValue(v){ v=(Math.round((v-this.min)/this.step))*this.step+this.min; this._value=Math.min(this.max,Math.max(this.min,v)); if(this._value!=this.oldvalue){ this.oldvalue=this._value; if(this.conv) this.convValue=eval(this.conv)(this._value); else this.convValue=this._value; this.redraw(); this.showtip(0); return 1; } return 0; } setValue(v,f){ if(this._setValue(v)&&f) this.sendEvent("input"),this.sendEvent("change"); } wheel(e) { let delta=(this.max-this.min)*0.01; delta=e.deltaY>0?-delta:delta; if(!e.shiftKey) delta*=5; if(Math.abs(delta) < this.step) delta = (delta > 0) ? +this.step : -this.step; this.setValue(+this.value+delta,true); e.preventDefault(); e.stopPropagation(); this.redraw(); } pointerdown(ev){ if(!this.enable) return; let e=ev; if(ev.touches){ e = ev.changedTouches[0]; this.identifier=e.identifier; } else { if(e.buttons!=1 && e.button!=0) return; } this.elem.focus(); this.drag=1; this.showtip(0); let pointermove=(ev)=>{ let e=ev; if(ev.touches){ for(let i=0;i{ let e=ev; if(ev.touches){ for(let i=0;;){ if(ev.changedTouches[i].identifier==this.identifier){ break; } if(++i>=ev.changedTouches.length) return; } } this.drag=0; this.showtip(0); this.startPosX = this.startPosY = null; window.removeEventListener('mousemove', pointermove); window.removeEventListener('touchmove', pointermove, {passive:false}); window.removeEventListener('mouseup', pointerup); window.removeEventListener('touchend', pointerup); window.removeEventListener('touchcancel', pointerup); document.body.removeEventListener('touchstart', preventScroll,{passive:false}); this.sendEvent("change"); } let preventScroll=(e)=>{ e.preventDefault(); } if(e.touches) e = e.touches[0]; if(e.ctrlKey || e.metaKey) this.setValue(this.defvalue,true); else { this.startPosX = e.pageX; this.startPosY = e.pageY; this.startVal = this.value; window.addEventListener('mousemove', pointermove); window.addEventListener('touchmove', pointermove, {passive:false}); } window.addEventListener('mouseup', pointerup); window.addEventListener('touchend', pointerup); window.addEventListener('touchcancel', pointerup); document.body.addEventListener('touchstart', preventScroll,{passive:false}); e.preventDefault(); e.stopPropagation(); return false; } }); } catch(error){ console.log("webaudio-slider already defined"); } try{ customElements.define("webaudio-switch", class WebAudioSwitch extends WebAudioControlsWidget { constructor(){ super(); } connectedCallback(){ let root; // if(this.attachShadow) // root=this.attachShadow({mode: 'open'}); // else root=this; root.innerHTML= `
    `; this.elem=root.childNodes[2]; this.ttframe=this.elem.childNodes[0]; this.enable=this.getAttr("enable",1); this._src=this.getAttr("src",null); Object.defineProperty(this,"src",{get:()=>{return this._src},set:(v)=>{this._src=v;this.setupImage()}}); this._value=this.getAttr("value",0); Object.defineProperty(this,"value",{get:()=>{return this._value},set:(v)=>{this._value=v;this.redraw()}}); this.defvalue=this.getAttr("defvalue",0); this.type=this.getAttr("type","toggle"); this.group=this.getAttr("group",""); this._width=this.getAttr("width",0); Object.defineProperty(this,"width",{get:()=>{return this._width},set:(v)=>{this._width=v;this.setupImage()}}); this._height=this.getAttr("height",0); Object.defineProperty(this,"height",{get:()=>{return this._height},set:(v)=>{this._height=v;this.setupImage()}}); this._diameter=this.getAttr("diameter",0); Object.defineProperty(this,"diameter",{get:()=>{return this._diameter},set:(v)=>{this._diameter=v;this.setupImage()}}); this.invert=this.getAttr("invert",0); this._colors=this.getAttr("colors",opt.switchColors); Object.defineProperty(this,"colors",{get:()=>{return this._colors},set:(v)=>{this._colors=v;this.setupImage()}}); this.outline=this.getAttr("outline",opt.outline); this.valuetip=0; this.tooltip=this.getAttr("tooltip",null); this.midilearn=this.getAttr("midilearn",opt.midilearn); this.midicc=this.getAttr("midicc",null); this.midiController={}; this.midiMode="normal"; if(this.midicc) { let ch = parseInt(this.midicc.substring(0, this.midicc.lastIndexOf("."))) - 1; let cc = parseInt(this.midicc.substring(this.midicc.lastIndexOf(".") + 1)); this.setMidiController(ch, cc); } this.setupImage(); this.digits=0; if(window.webAudioControlsMidiManager) // window.webAudioControlsMidiManager.updateWidgets(); window.webAudioControlsMidiManager.addWidget(this); this.elem.onclick=(e)=>{e.stopPropagation()}; } disconnectedCallback(){} setupImage(){ let w=this.width||this.diameter||opt.switchWidth||opt.switchDiameter; let h=this.height||this.diameter||opt.switchHeight||opt.switchDiameter; if(!this.src){ this.coltab = this.colors.split(";"); let mm=Math.min(w,h); let svg= ` `; this.elem.style.backgroundImage = "url(data:image/svg+xml;base64,"+btoa(svg)+")"; this.elem.style.backgroundSize = "100% 200%"; } else{ this.elem.style.backgroundImage = "url("+(this.src)+")"; if(!this.sprites) this.elem.style.backgroundSize = "100% 200%"; else this.elem.style.backgroundSize = `100% ${(this.sprites+1)*100}%`; } this.elem.style.width=w+"px"; this.elem.style.height=h+"px"; this.style.height=h+"px"; this.elem.style.outline=this.outline?"":"none"; this.redraw(); } redraw() { let style = this.elem.style; if(this.value^this.invert) style.backgroundPosition = "0px -100%"; else style.backgroundPosition = "0px 0px"; } setValue(v,f){ this.value=v; this.checked=(!!v); if(this.value!=this.oldvalue){ this.redraw(); this.showtip(0); if(f){ this.sendEvent("input"); this.sendEvent("change"); } this.oldvalue=this.value; } } pointerdown(ev){ if(!this.enable) return; let e=ev; if(ev.touches){ e = ev.changedTouches[0]; this.identifier=e.identifier; } else { if(e.buttons!=1 && e.button!=0) return; } this.elem.focus(); this.drag=1; this.showtip(0); let pointermove=(e)=>{ e.preventDefault(); e.stopPropagation(); return false; } let pointerup=(e)=>{ this.drag=0; this.showtip(0); window.removeEventListener('mousemove', pointermove); window.removeEventListener('touchmove', pointermove, {passive:false}); window.removeEventListener('mouseup', pointerup); window.removeEventListener('touchend', pointerup); window.removeEventListener('touchcancel', pointerup); document.body.removeEventListener('touchstart', preventScroll,{passive:false}); if(this.type=="kick"){ this.value=0; this.checked=false; this.redraw(); this.sendEvent("change"); } this.sendEvent("click"); e.preventDefault(); e.stopPropagation(); } let preventScroll=(e)=>{ e.preventDefault(); } switch(this.type){ case "kick": this.setValue(1); this.sendEvent("change"); break; case "toggle": if(e.ctrlKey || e.metaKey) this.value=defvalue; else this.value=1-this.value; this.checked=!!this.value; this.sendEvent("change"); break; case "radio": let els=document.querySelectorAll("webaudio-switch[type='radio'][group='"+this.group+"']"); for(let i=0;i ${this.basestyle} webaudio-param{ display:inline-block; user-select:none; margin:0; padding:0; font-family: sans-serif; font-size: 8px; cursor:pointer; position:relative; vertical-align:baseline; } .webaudio-param-body{ display:inline-block; position:relative; text-align:center; border:1px solid #888; background:none; border-radius:4px; margin:0; padding:0; font-family:sans-serif; font-size:11px; vertical-align:bottom; }
    `; this.elem=root.childNodes[2]; this.ttframe=root.childNodes[3]; this.enable=this.getAttr("enable",1); this._value=this.getAttr("value",0); Object.defineProperty(this,"value",{get:()=>{return this._value},set:(v)=>{this._value=v;this.redraw()}}); this.defvalue=this.getAttr("defvalue",0); this._fontsize=this.getAttr("fontsize",9); Object.defineProperty(this,"fontsize",{get:()=>{return this._fontsize},set:(v)=>{this._fontsize=v;this.setupImage()}}); this._src=this.getAttr("src",null); Object.defineProperty(this,"src",{get:()=>{return this._src},set:(v)=>{this._src=v;this.setupImage()}}); this.link=this.getAttr("link",""); this._width=this.getAttr("width",32); Object.defineProperty(this,"width",{get:()=>{return this._width},set:(v)=>{this._width=v;this.setupImage()}}); this._height=this.getAttr("height",20); Object.defineProperty(this,"height",{get:()=>{return this._height},set:(v)=>{this._height=v;this.setupImage()}}); this._colors=this.getAttr("colors","#fff;#000"); Object.defineProperty(this,"colors",{get:()=>{return this._colors},set:(v)=>{this._colors=v;this.setupImage()}}); this.outline=this.getAttr("outline",opt.outline); this.midiController={}; this.midiMode="normal"; if(this.midicc) { let ch = parseInt(this.midicc.substring(0, this.midicc.lastIndexOf("."))) - 1; let cc = parseInt(this.midicc.substring(this.midicc.lastIndexOf(".") + 1)); this.setMidiController(ch, cc); } this.setupImage(); if(window.webAudioControlsMidiManager) // window.webAudioControlsMidiManager.updateWidgets(); window.webAudioControlsMidiManager.addWidget(this); this.fromLink=((e)=>{ this.setValue(e.target.convValue.toFixed(e.target.digits)); }).bind(this); this.elem.onchange=()=>{ this.value=this.elem.value; let le=document.getElementById(this.link); if(le) le.setValue(+this.elem.value); } } disconnectedCallback(){} setupImage(){ this.coltab = this.colors.split(";"); this.elem.style.color=this.coltab[0]; if(!this.src){ this.elem.style.backgroundColor=this.coltab[1]; } else{ this.elem.style.backgroundImage = "url("+(this.src)+")"; this.elem.style.backgroundSize = "100% 100%"; } this.elem.style.width=this.width+"px"; this.elem.style.height=this.height+"px"; this.elem.style.fontSize=this.fontsize+"px"; this.elem.style.outline=this.outline?"":"none"; let l=document.getElementById(this.link); if(l&&typeof(l.value)!="undefined"){ this.setValue(l.value.toFixed(l.digits)); l.addEventListener("input",(e)=>{this.setValue(l.value.toFixed(l.digits))}); } this.redraw(); } redraw() { this.elem.value=this.value; } setValue(v,f){ this.value=v; if(this.value!=this.oldvalue){ this.redraw(); this.showtip(0); if(f){ let event=document.createEvent("HTMLEvents"); event.initEvent("change",false,true); this.dispatchEvent(event); } this.oldvalue=this.value; } } pointerdown(ev){ if(!this.enable) return; let e=ev; if(ev.touches) e = ev.touches[0]; else { if(e.buttons!=1 && e.button!=0) return; } this.elem.focus(); this.redraw(); } }); } catch(error){ console.log("webaudio-param already defined"); } try{ customElements.define("webaudio-keyboard", class WebAudioKeyboard extends WebAudioControlsWidget { constructor(){ super(); } connectedCallback(){ let root; // if(this.attachShadow) // root=this.attachShadow({mode: 'open'}); // else root=this; root.innerHTML= `
    `; this.cv=root.childNodes[2]; this.ttframe=root.childNodes[3]; this.ctx=this.cv.getContext("2d"); this._values=[]; this.enable=this.getAttr("enable",1); this._width=this.getAttr("width",480); Object.defineProperty(this,"width",{get:()=>{return this._width},set:(v)=>{this._width=v;this.setupImage()}}); this._height=this.getAttr("height",128); Object.defineProperty(this,"height",{get:()=>{return this._height},set:(v)=>{this._height=v;this.setupImage()}}); this._min=this.getAttr("min",0); Object.defineProperty(this,"min",{get:()=>{return this._min},set:(v)=>{this._min=+v;this.redraw()}}); this._keys=this.getAttr("keys",25); Object.defineProperty(this,"keys",{get:()=>{return this._keys},set:(v)=>{this._keys=+v;this.setupImage()}}); this._colors=this.getAttr("colors","#222;#eee;#ccc;#333;#000;#e88;#c44;#c33;#800"); Object.defineProperty(this,"colors",{get:()=>{return this._colors},set:(v)=>{this._colors=v;this.setupImage()}}); this.outline=this.getAttr("outline",opt.outline); this.midilearn=this.getAttr("midilearn",0); this.midicc=this.getAttr("midicc",null); this.press=0; this.keycodes1=[90,83,88,68,67,86,71,66,72,78,74,77,188,76,190,187,191,226]; this.keycodes2=[81,50,87,51,69,82,53,84,54,89,55,85,73,57,79,48,80,192,222,219]; this.addEventListener("keyup",this.keyup); this.midiController={}; this.midiMode="normal"; if(this.midicc) { let ch = parseInt(this.midicc.substring(0, this.midicc.lastIndexOf("."))) - 1; let cc = parseInt(this.midicc.substring(this.midicc.lastIndexOf(".") + 1)); this.setMidiController(ch, cc); } this.setupImage(); this.digits=0; if(window.webAudioControlsMidiManager) window.webAudioControlsMidiManager.addWidget(this); } disconnectedCallback(){} setupImage(){ this.cv.style.width=this.width+"px"; this.cv.style.height=this.height+"px"; this.bheight = this.height * 0.55; this.kp=[0,7/12,1,3*7/12,2,3,6*7/12,4,8*7/12,5,10*7/12,6]; this.kf=[0,1,0,1,0,0,1,0,1,0,1,0]; this.ko=[0,0,(7*2)/12-1,0,(7*4)/12-2,(7*5)/12-3,0,(7*7)/12-4,0,(7*9)/12-5,0,(7*11)/12-6]; this.kn=[0,2,4,5,7,9,11]; this.coltab=this.colors.split(";"); this.cv.width = this.width; this.cv.height = this.height; this.cv.style.width = this.width+'px'; this.cv.style.height = this.height+'px'; this.style.height = this.height+'px'; this.cv.style.outline=this.outline?"":"none"; this.bheight = this.height * 0.55; this.max=this.min+this.keys-1; this.dispvalues=[]; this.valuesold=[]; if(this.kf[this.min%12]) --this.min; if(this.kf[this.max%12]) ++this.max; this.redraw(); } redraw(){ function rrect(ctx, x, y, w, h, r, c1, c2) { if(c2) { let g=ctx.createLinearGradient(x,y,x+w,y); g.addColorStop(0,c1); g.addColorStop(1,c2); ctx.fillStyle=g; } else ctx.fillStyle=c1; ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(x+w, y); ctx.lineTo(x+w, y+h-r); ctx.quadraticCurveTo(x+w, y+h, x+w-r, y+h); ctx.lineTo(x+r, y+h); ctx.quadraticCurveTo(x, y+h, x, y+h-r); ctx.lineTo(x, y); ctx.fill(); } this.ctx.fillStyle = this.coltab[0]; this.ctx.fillRect(0,0,this.width,this.height); let x0=7*((this.min/12)|0)+this.kp[this.min%12]; let x1=7*((this.max/12)|0)+this.kp[this.max%12]; let n=x1-x0; this.wwidth=(this.width-1)/(n+1); this.bwidth=this.wwidth*7/12; let h2=this.bheight; let r=Math.min(8,this.wwidth*0.2); for(let i=this.min,j=0;i<=this.max;++i) { if(this.kf[i%12]==0) { let x=this.wwidth*(j++)+1; if(this.dispvalues.indexOf(i)>=0) rrect(this.ctx,x,1,this.wwidth-1,this.height-2,r,this.coltab[5],this.coltab[6]); else rrect(this.ctx,x,1,this.wwidth-1,this.height-2,r,this.coltab[1],this.coltab[2]); } } r=Math.min(8,this.bwidth*0.3); for(let i=this.min;i=0) rrect(this.ctx,x,1,this.bwidth,h2,r,this.coltab[7],this.coltab[8]); else rrect(this.ctx,x,1,this.bwidth,h2,r,this.coltab[3],this.coltab[4]); this.ctx.strokeStyle=this.coltab[0]; this.ctx.stroke(); } } } _setValue(v){ if(this.step) v=(Math.round((v-this.min)/this.step))*this.step+this.min; this._value=Math.min(this.max,Math.max(this.min,v)); if(this._value!=this.oldvalue){ this.oldvalue=this._value; this.redraw(); this.showtip(0); return 1; } return 0; } setValue(v,f){ if(this._setValue(v) && f) this.sendEvent("input"),this.sendEvent("change"); } wheel(e){} keydown(e){ let m=Math.floor((this.min+11)/12)*12; let k=this.keycodes1.indexOf(e.keyCode); if(k<0) { k=this.keycodes2.indexOf(e.keyCode); if(k>=0) k+=12; } if(k>=0){ k+=m; if(this.currentKey!=k){ this.currentKey=k; this.sendEventFromKey(1,k); this.setNote(1,k); } } } keyup(e){ let m=Math.floor((this.min+11)/12)*12; let k=this.keycodes1.indexOf(e.keyCode); if(k<0) { k=this.keycodes2.indexOf(e.keyCode); if(k>=0) k+=12; } if(k>=0){ k+=m; this.currentKey=-1; this.sendEventFromKey(0,k); this.setNote(0,k); } } pointerdown(ev){ this.cv.focus(); if(this.enable) { ++this.press; } let pointermove=(ev)=>{ if(!this.enable) return; let r=this.getBoundingClientRect(); let v=[],p; if(ev.touches) p=ev.targetTouches; else if(this.press) p=[ev]; else p=[]; if(p.length>0) this.drag=1; for(let i=0;i=0&&py=this.min&&k<=this.max) v.push(k); } } v.sort(); this.values=v; this.sendevent(); this.redraw(); } let pointerup=(ev)=>{ if(this.enable) { if(ev.touches) this.press=ev.touches.length; else this.press=0; pointermove(ev); this.sendevent(); if(this.press==0){ window.removeEventListener('mousemove', pointermove); window.removeEventListener('touchmove', pointermove, {passive:false}); window.removeEventListener('mouseup', pointerup); window.removeEventListener('touchend', pointerup); window.removeEventListener('touchcancel', pointerup); document.body.removeEventListener('touchstart', preventScroll,{passive:false}); } this.redraw(); } this.drag=0; ev.preventDefault(); } let preventScroll=(ev)=>{ ev.preventDefault(); } window.addEventListener('mousemove', pointermove); window.addEventListener('touchmove', pointermove, {passive:false}); window.addEventListener('mouseup', pointerup); window.addEventListener('touchend', pointerup); window.addEventListener('touchcancel', pointerup); document.body.addEventListener('touchstart', preventScroll,{passive:false}); pointermove(ev); ev.preventDefault(); ev.stopPropagation(); } sendEventFromKey(s,k){ let ev=document.createEvent('HTMLEvents'); ev.initEvent('change',true,true); ev.note=[s,k]; this.dispatchEvent(ev); } sendevent(){ let notes=[]; for(let i=0,j=this.valuesold.length;i=0) this.dispvalues.splice(n,1); } } setNote(state,note) { this.setdispvalues(state,note); this.redraw(); } }); } catch(error){ console.log("webaudio-keyboard already defined"); } try{ customElements.define("webaudio-xypad", class WebAudioXYPad extends WebAudioControlsWidget { constructor(){ super(); } connectedCallback(){ let root; // if(this.attachShadow) // root=this.attachShadow({mode: 'open'}); // else root=this; root.innerHTML= `
    `; this.elem=root.childNodes[2]; this.knob=this.elem.childNodes[0]; this.ttframe=root.childNodes[3]; this.enable=this.getAttr("enable",1); this._src=this.getAttr("src",opt.sliderSrc); Object.defineProperty(this,"src",{get:()=>{return this._src},set:(v)=>{this._src=v;this.setupImage()}}); this._knobsrc=this.getAttr("knobsrc",opt.sliderKnobsrc); Object.defineProperty(this,"knobsrc",{get:()=>{return this._knobsrc},set:(v)=>{this._knobsrc=v;this.setupImage()}}); this._x=this.getAttr("x",50); Object.defineProperty(this,"x",{get:()=>{return this._x},set:(v)=>{this._x=v;this.redraw()}}); this._y=this.getAttr("y",50); Object.defineProperty(this,"y",{get:()=>{return this._y},set:(v)=>{this._y=v;this.redraw()}}); this.defx=this.getAttr("defx",50); this.defy=this.getAttr("defy",50); this._min=this.getAttr("min",0); Object.defineProperty(this,"min",{get:()=>{return this._min},set:(v)=>{this._min=v;this.redraw()}}); this._max=this.getAttr("max",100); Object.defineProperty(this,"max",{get:()=>{return this._max},set:(v)=>{this._max=v;this.redraw()}}); this._step=this.getAttr("step",1); Object.defineProperty(this,"step",{get:()=>{return this._step},set:(v)=>{this._step=v;this.redraw()}}); this._sprites=this.getAttr("sprites",0); Object.defineProperty(this,"sprites",{get:()=>{return this._sprites},set:(v)=>{this._sprites=v;this.setupImage()}}); this._width=this.getAttr("width",128); Object.defineProperty(this,"width",{get:()=>{return this._width},set:(v)=>{this._width=v;this.setupImage()}}); this._height=this.getAttr("height",128); Object.defineProperty(this,"height",{get:()=>{return this._height},set:(v)=>{this._height=v;this.setupImage()}}); this._knobwidth=this.getAttr("knobwidth",28); Object.defineProperty(this,"knobwidth",{get:()=>{return this._knobwidth},set:(v)=>{this._knobwidth=v;this.setupImage()}}); this._knobheight=this.getAttr("knbheight",28); Object.defineProperty(this,"knobheight",{get:()=>{return this._knobheight},set:(v)=>{this._knobheight=v;this.setupImage()}}); this._colors=this.getAttr("colors",opt.sliderColors); Object.defineProperty(this,"colors",{get:()=>{return this._colors},set:(v)=>{this._colors=v;this.setupImage()}}); this.outline=this.getAttr("outline",opt.outline); this.valuetip=this.getAttr("valuetip",1); this.tooltip=this.getAttr("tooltip",null); this.conv=this.getAttr("conv",null); if(this.conv){ this.convValue={x:eval(this.conv)(this._x),y:eval(this.conv)(this._y)}; } else this.convValue={x:this._x,y:this._y}; this.midilearn=this.getAttr("midilearn",opt.midilearn); this.midicc=this.getAttr("midicc",null); this.midiController={}; this.midiMode="normal"; if(this.midicc) { let ch = parseInt(this.midicc.substring(0, this.midicc.lastIndexOf("."))) - 1; let cc = parseInt(this.midicc.substring(this.midicc.lastIndexOf(".") + 1)); this.setMidiController(ch, cc); } this.setupImage(); this.digits=0; if(window.webAudioControlsMidiManager) // window.webAudioControlsMidiManager.updateWidgets(); window.webAudioControlsMidiManager.addWidget(this); this.elem.onclick=(e)=>{e.stopPropagation()}; } disconnectedCallback(){} setupImage(){ this.coltab = this.colors.split(";"); this.dr=this.direction; this.dlen=this.ditchlength; if(!this.width) this.width=256; if(!this.height) this.height=256; this.knob.style.backgroundSize = "100% 100%"; this.elem.style.backgroundSize = "100% 100%"; this.elem.style.width=this.width+"px"; this.elem.style.height=this.height+"px"; this.kwidth=this.knobwidth||(this.width*0.15|0); this.kheight=this.knobheight||(this.height*0.15|0); this.knob.style.width = this.kwidth+"px"; this.knob.style.height = this.kheight+"px"; if(!this.src){ let r=Math.min(this.width,this.height)*0.02; let svgbody= ` `; this.elem.style.backgroundImage = "url(data:image/svg+xml;base64,"+btoa(svgbody)+")"; } else{ this.elem.style.backgroundImage = "url("+(this.src)+")"; } if(!this.knobsrc){ let svgthumb= ` `; this.knob.style.backgroundImage = "url(data:image/svg+xml;base64,"+btoa(svgthumb)+")"; } else{ this.knob.style.backgroundImage = "url("+(this.knobsrc)+")"; } this.elem.style.outline=this.outline?"":"none"; this.redraw(); } redraw() { this.digits=0; if(this.step && this.step < 1) { for(let n = this.step ; n < 1; n *= 10) ++this.digits; } if(this.valuethis.max){ this.value=this.max; return; } let range = this.max - this.min; let style = this.knob.style; style.left=(this.width-this.kwidth)*(this._x-this.min)/(this.max-this.min)+"px"; style.top=(this.height-this.kheight)*(1-(this._y-this.min)/(this.max-this.min))+"px"; this.sensex=0; this.sensey=1; } _setX(v){ v=(Math.round((v-this.min)/this.step))*this.step+this.min; this._x=Math.min(this.max,Math.max(this.min,v)); if(this._x!=this.oldx){ this.oldx=this._x; if(this.conv){ this.convValue={x:eval(this.conv)(this._x),y:eval(this.conv)(this._y)}; } else this.convValue={x:this._x,y:this._y}; this.redraw(); this.showtip(0); return 1; } return 0; } _setY(v){ v=(Math.round((v-this.min)/this.step))*this.step+this.min; this._y=Math.min(this.max,Math.max(this.min,v)); if(this._y!=this.oldy){ this.oldy=this._y; if(this.conv){ this.convValue={x:eval(this.conv)(this._x),y:eval(this.conv)(this._y)}; } else this.convValue={x:this._x,y:this._y}; this.redraw(); this.showtip(0); return 1; } return 0; } setX(v,f){ if(this._setX(v)&&f) this.sendEvent("input"),this.sendEvent("change"); } setY(v,f){ if(this._setY(v)&&f) this.sendEvent("input"),this.sendEvent("change"); } wheel(e) { let delta=(this.max-this.min)*0.01; delta=e.deltaY>0?-delta:delta; if(!e.shiftKey) delta*=5; if(Math.abs(delta) < this.step) delta = (delta > 0) ? +this.step : -this.step; this.setValue(+this.value+delta,true); e.preventDefault(); e.stopPropagation(); this.redraw(); } pointerdown(ev){ if(!this.enable) return; let e=ev; if(ev.touches){ e = ev.changedTouches[0]; this.identifier=e.identifier; } else { if(e.buttons!=1 && e.button!=0) return; } this.elem.focus(); this.drag=1; this.showtip(0); let pointermove=(ev)=>{ let e=ev; if(ev.touches){ for(let i=0;i{ let e=ev; if(ev.touches){ for(let i=0;;){ if(ev.changedTouches[i].identifier==this.identifier){ break; } if(++i>=ev.changedTouches.length) return; } } this.drag=0; this.showtip(0); this.startPosX = this.startPosY = null; window.removeEventListener('mousemove', pointermove); window.removeEventListener('touchmove', pointermove, {passive:false}); window.removeEventListener('mouseup', pointerup); window.removeEventListener('touchend', pointerup); window.removeEventListener('touchcancel', pointerup); document.body.removeEventListener('touchstart', preventScroll,{passive:false}); this.sendEvent("change"); } pointermove(ev); let preventScroll=(e)=>{ e.preventDefault(); } if(e.touches) e = e.touches[0]; if(e.ctrlKey || e.metaKey) this.setValue(this.defvalue,true); else { this.startPosX = e.pageX; this.startPosY = e.pageY; this.startVal = this.value; window.addEventListener('mousemove', pointermove); window.addEventListener('touchmove', pointermove, {passive:false}); } window.addEventListener('mouseup', pointerup); window.addEventListener('touchend', pointerup); window.addEventListener('touchcancel', pointerup); document.body.addEventListener('touchstart', preventScroll,{passive:false}); e.preventDefault(); e.stopPropagation(); return false; } }); } catch(error){ console.log("webaudio-xypad already defined"); } // FOR MIDI LEARN class WebAudioControlsMidiManager { constructor(){ this.midiAccess = null; this.listOfWidgets = []; this.listOfExternalMidiListeners = []; this.updateWidgets(); this.initWebAudioControls(); } addWidget(w){ this.listOfWidgets.push(w); } updateWidgets(){ // this.listOfWidgets = document.querySelectorAll("webaudio-knob,webaudio-slider,webaudio-switch"); } initWebAudioControls() { if(navigator.requestMIDIAccess) { navigator.requestMIDIAccess().then( (ma)=>{this.midiAccess = ma,this.enableInputs()}, (err)=>{ console.log("MIDI not initialized - error encountered:" + err.code)} ); } } enableInputs() { let inputs = this.midiAccess.inputs.values(); console.log("Found " + this.midiAccess.inputs.size + " MIDI input(s)"); for(let input = inputs.next(); input && !input.done; input = inputs.next()) { console.log("Connected input: " + input.value.name); input.value.onmidimessage = this.handleMIDIMessage.bind(this); } } midiConnectionStateChange(e) { console.log("connection: " + e.port.name + " " + e.port.connection + " " + e.port.state); enableInputs(); } onMIDIStarted(midi) { this.midiAccess = midi; midi.onstatechange = this.midiConnectionStateChange; enableInputs(midi); } // Add hooks for external midi listeners support addMidiListener(callback) { this.listOfExternalMidiListeners.push(callback); } getCurrentConfigAsJSON() { return currentConfig.stringify(); } handleMIDIMessage(event) { this.listOfExternalMidiListeners.forEach(function (externalListener) { externalListener(event); }); if(((event.data[0] & 0xf0) == 0xf0) || ((event.data[0] & 0xf0) == 0xb0 && event.data[1] >= 120)) return; for(let w of this.listOfWidgets) { if(w.processMidiEvent) w.processMidiEvent(event); } if(opt.mididump) console.log(event.data); } contextMenuOpen(e,knob){ if(!this.midiAccess) return; let menu=document.getElementById("webaudioctrl-context-menu"); menu.style.left=e.pageX+"px"; menu.style.top=e.pageY+"px"; menu.knob=knob; menu.classList.add("active"); menu.knob.focus(); // document.activeElement.onblur=this.contextMenuClose; menu.knob.addEventListener("keydown",this.contextMenuCloseByKey.bind(this)); } contextMenuCloseByKey(e){ if(e.keyCode==27) this.contextMenuClose(); } contextMenuClose(){ let menu=document.getElementById("webaudioctrl-context-menu"); menu.knob.removeEventListener("keydown",this.contextMenuCloseByKey); menu.classList.remove("active"); let menuItemLearn=document.getElementById("webaudioctrl-context-menu-learn"); menuItemLearn.innerHTML = 'Learn'; menu.knob.midiMode = 'normal'; } contextMenuLearn(){ let menu=document.getElementById("webaudioctrl-context-menu"); let menuItemLearn=document.getElementById("webaudioctrl-context-menu-learn"); menuItemLearn.innerHTML = 'Listening...'; menu.knob.midiMode = 'learn'; } contextMenuClear(e){ let menu=document.getElementById("webaudioctrl-context-menu"); menu.knob.midiController={}; this.contextMenuClose(); } } if(window.UseWebAudioControlsMidi||opt.useMidi) window.webAudioControlsMidiManager = new WebAudioControlsMidiManager(); }