class VTUtils{static random(t,e){let a=Math.random();if(void 0===t)return a;if(void 0===e)return t instanceof Array?t[Math.floor(a*t.length)]:a*t;if(t>e){let a=t;t=e,e=a}return a*(e-t)+t}static randomInt(t,e){return Math.floor(VTUtils.random(t,e))}static normalize(t,e,a){return(t-a)/(e-a)}static distance(t,e,a,i){let s=t-a,l=e-i;return Math.sqrt(s*s+l*l)}static map(t,e,a,i,s,l){let r=(t-e)/(a-e)*(s-i)+i;return l?it.json()).then(e=>{let a;if(t){let t=Object.keys(e);a=new Float32Array(t.length);for(let i=0;i{let i=t.target;if(i.matches(e))a(t,i);else{let s=i.closest(e);s&&a(t,s)}})},Node.prototype.hasClass=function(t){let e=t.split(","),a=null;for(let t of e){if(!1===a)break;a=this.classList.contains(t.trim())}return!0===a},Node.prototype.addClass=function(t){let e=t.split(",");for(let t of e)this.classList.add(t.trim());return this},Node.prototype.removeClass=function(t){let e=t.split(",");for(let t of e)this.classList.remove(t.trim());return this},Node.prototype.toggleClass=function(t,e){let a=t.split(",");for(let t of a)this.classList.toggle(t.trim(),e)},Node.prototype.switchClass=function(t,e,a){let i=this.classList;a?(i.remove(t),i.add(e)):(i.remove(e),i.add(t))},Node.prototype.toggleCheck=function(t,e){let a=this.classList,i=t.split(",");for(let t of i){let i=t.trim();e?a.add(i):a.remove(i)}},File.prototype.toBase64=function(t){const e=new FileReader;e.onloadend=t,e.readAsDataURL(this)};class TDUtils{static multiply(t,e){let a=e[0],i=e[1],s=e[2],l=e[3],r=e[4],n=e[5],o=e[6],d=e[7],h=e[8],c=e[9],u=e[10],g=e[11],p=e[12],f=e[13],m=e[14],y=e[15],w=t[0],v=t[1],S=t[2],T=t[3],x=t[4],A=t[5],C=t[6],U=t[7],b=t[8],R=t[9],L=t[10],D=t[11],F=t[12],E=t[13],M=t[14],P=t[15];return[a*w+i*x+s*b+l*F,a*v+i*A+s*R+l*E,a*S+i*C+s*L+l*M,a*T+i*U+s*D+l*P,r*w+n*x+o*b+d*F,r*v+n*A+o*R+d*E,r*S+n*C+o*L+d*M,r*T+n*U+o*D+d*P,h*w+c*x+u*b+g*F,h*v+c*A+u*R+g*E,h*S+c*C+u*L+g*M,h*T+c*U+u*D+g*P,p*w+f*x+m*b+y*F,p*v+f*A+m*R+y*E,p*S+f*C+m*L+y*M,p*T+f*U+m*D+y*P]}static translate(t,e,a,i,s){s=s||new Float32Array(16);let l=t[0],r=t[1],n=t[2],o=t[3],d=t[4],h=t[5],c=t[6],u=t[7],g=t[8],p=t[9],f=t[10],m=t[11],y=t[12],w=t[13],v=t[14],S=t[15];return s[0]=l,s[1]=r,s[2]=n,s[3]=o,s[4]=d,s[5]=h,s[6]=c,s[7]=u,s[8]=g,s[9]=p,s[10]=f,s[11]=m,s[12]=l*e+d*a+g*i+y,s[13]=r*e+h*a+p*i+w,s[14]=n*e+c*a+f*i+v,s[15]=o*e+u*a+m*i+S,s}static xRotation(t){let e=Math.cos(t),a=Math.sin(t);return[1,0,0,0,0,e,a,0,0,-a,e,0,0,0,0,1]}static yRotation(t){let e=Math.cos(t),a=Math.sin(t);return[e,0,-a,0,0,1,0,0,a,0,e,0,0,0,0,1]}static zRotation(t){let e=Math.cos(t),a=Math.sin(t);return[e,a,0,0,-a,e,0,0,0,0,1,0,0,0,0,1]}static degToRad(t){return t*Math.PI/180}static scale(t,e,a,i){return(i=i||new Float32Array(16))[0]=t,i[5]=e,i[10]=a,i}static lookAt(t,e,a,i){i=i||new Float32Array(16);let s=TDUtils.normalize(TDUtils.subtractVectors(t,e)),l=TDUtils.normalize(TDUtils.cross(a,s)),r=TDUtils.normalize(TDUtils.cross(s,l));return i[0]=l[0],i[1]=l[1],i[2]=l[2],i[4]=r[0],i[5]=r[1],i[6]=r[2],i[8]=s[0],i[9]=s[1],i[10]=s[2],i[12]=t[0],i[13]=t[1],i[14]=t[2],i[15]=1,i}static cross(t,e,a){return(a=a||new Float32Array(3))[0]=t[1]*e[2]-t[2]*e[1],a[1]=t[2]*e[0]-t[0]*e[2],a[2]=t[0]*e[1]-t[1]*e[0],a}static normalize(t,e){e=e||new Float32Array(3);let a=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);return a>1e-5&&(e[0]=t[0]/a,e[1]=t[1]/a,e[2]=t[2]/a),e}static subtractVectors(t,e,a){return(a=a||new Float32Array(3))[0]=t[0]-e[0],a[1]=t[1]-e[1],a[2]=t[2]-e[2],a}static perspective(t,e,a,i,s){s=s||new Float32Array(16);let l=Math.tan(.5*Math.PI-.5*t),r=1/(a-i);return s[0]=l/e,s[5]=l,s[10]=(a+i)*r,s[11]=-1,s[14]=a*i*r*2,s}static inverse(t,e){e=e||new Float32Array(16);let a=t[0],i=t[1],s=t[2],l=t[3],r=t[4],n=t[5],o=t[6],d=t[7],h=t[8],c=t[9],u=t[10],g=t[11],p=t[12],f=t[13],m=t[14],y=t[15],w=u*y,v=m*g,S=o*y,T=m*d,x=o*g,A=u*d,C=s*y,U=m*l,b=s*g,R=u*l,L=s*d,D=o*l,F=h*f,E=p*c,M=r*f,P=p*n,H=r*c,V=h*n,I=a*f,N=p*i,k=a*c,B=h*i,z=a*n,$=r*i,_=w*n+T*c+x*f-(v*n+S*c+A*f),O=v*i+C*c+R*f-(w*i+U*c+b*f),j=S*i+U*n+L*f-(T*i+C*n+D*f),G=A*i+b*n+D*c-(x*i+R*n+L*c),W=1/(a*_+r*O+h*j+p*G);return e[0]=W*_,e[1]=W*O,e[2]=W*j,e[3]=W*G,e[4]=W*(v*r+S*h+A*p-(w*r+T*h+x*p)),e[5]=W*(w*a+U*h+b*p-(v*a+C*h+R*p)),e[6]=W*(T*a+C*r+D*p-(S*a+U*r+L*p)),e[7]=W*(x*a+R*r+L*h-(A*a+b*r+D*h)),e[8]=W*(F*d+P*g+H*y-(E*d+M*g+V*y)),e[9]=W*(E*l+I*g+B*y-(F*l+N*g+k*y)),e[10]=W*(M*l+N*d+z*y-(P*l+I*d+$*y)),e[11]=W*(V*l+k*d+$*g-(H*l+B*d+z*g)),e[12]=W*(M*u+V*m+E*o-(H*m+F*o+P*u)),e[13]=W*(k*m+F*s+N*u-(I*u+B*m+E*s)),e[14]=W*(I*o+$*m+P*s-(z*m+M*s+N*o)),e[15]=W*(z*u+H*s+B*o-(k*o+$*u+V*s)),e}static aspectView(t){return[1*t,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}static lastMatrix={m:null};static getMatrix(t,e,a,i,s,l){let r=this.lastMatrix,n=TDUtils;if(!(n.isSame("fov",t)&&n.isSame("aspect",e)&&n.isSame("near",a)&&n.isSame("far",i)&&n.isSame("cam",s)&&n.isSame("radius",l))){let n=TDUtils.perspective(TDUtils.degToRad(t),e,a,i),o=TDUtils.yRotation(TDUtils.degToRad(s));o=TDUtils.translate(o,0,0,1.5*l);let d=TDUtils.inverse(o);n=TDUtils.multiply(n,d),r.m=n}return r.m}static isSame(t,e){let a=this.lastMatrix;return a[t]===e||(a[t]=e,!1)}}class Template{constructor(){this.tpl={}}async loadTemplate(t){let e=this;this.tpl[t]||await fetch(templateDir+t+".tpl").then(t=>t.text()).then(a=>{e.tpl[t]=a})}async loadArray(t){for(let e of t)await this.loadTemplate(e)}parseTemplate(t,e){if(!this.tpl[t])return"";let a,i=this.tpl[t];for(;null!==(a=templateEx.exec(i));){a.index===templateEx.lastIndex&&templateEx.lastIndex++;let t=a[0];i=i.replace(t,e[a[1]]||"")}return i}parseFromAPI(t,e,a){fetch(t).then(t=>t.json()).then(t=>{a(this.parseTemplate(e,t))}).catch(console.error)}}const templateEx=/\$(.*?)\$/gm,templateDir="out/tpl/";class ShaderHandler{constructor(t){this.gl=t,this.shaderNames=[],this.shaders={},this.programs={}}setGL(t){this.gl=t}async loadShader(t,e){this.shaderNames.push(t),await this.load(t,e+t+".vert",this.gl.VERTEX_SHADER),await this.load(t,e+t+".frag",this.gl.FRAGMENT_SHADER)}async load(t,e,a){let i=t+"_"+a;if(!this.shaders[i]){let t=await fetch(e),s=this.createShader(await t.text(),a);s&&(this.shaders[i]=s)}return!!this.shaders[i]}getShader(t,e){let a=t+"_"+e;return this.shaders[a]}getAllShaders(){return this.shaderNames}async createProgramForEach(t){t=t||this.shaderNames;for(let e=0;e{window.dispatchEvent(new CustomEvent("playSong"))}).catch(t=>{player.nextSong()})}getIntArray(t){let e=new Uint8Array(t);return this.analyser.getByteFrequencyData(e),e}getFloatArray(){let t=new Float32Array(this.analyser.fftSize);return this.analyser.getFloatTimeDomainData(t),t}}class Player{async init(){this.playlist=new Playlist}nextSong(){let t=this.playlist.getNext();audioHandler.loadSong(t.file)}prevSong(){let t=this.playlist.getPrevious();audioHandler.loadSong(t.file)}playStop(){if(!audioHandler.lastSong){let t=this.playlist.getCurrent();return void audioHandler.loadSong(t.file)}let t=audioHandler.audioFile;t.paused?t.play():t.pause(),window.dispatchEvent(new CustomEvent("playSong"))}playByID(t){this.playlist.index=t;let e=this.playlist.getCurrent();audioHandler.loadSong(e.file)}}const PAGINATIONLIMIT=50;class Playlist{constructor(){this.list=[],this.shuffled=[],this.index=0,this.page=0,this.isShuffle=!1,$("body").addDelegatedEventListener("change",'input[type="file"]',this.changeFiles.bind(this)),$("body").addDelegatedEventListener("click",".pagination .item",this.handlePagination.bind(this))}shuffle(){let t=this.list.length;t<3&&(this.shuffled=this.list);for(let e=0;ee&&(a=0),this.index=a,t[a]}getPrevious(){let t=this.isShuffle?this.shuffled:this.list,e=t.length-1,a=this.index-1;return a<0&&(a=e),this.index=a,t[a]}getCurrent(){return(this.isShuffle?this.shuffled:this.list)[this.index]}setPlaylist(t){this.index=0,this.list=t,this.shuffle()}handlePagination(t,e){e.hasClass("inactive")||(e.hasClass("next-site")?this.renderPagination(this.page+1):this.renderPagination(this.page-1))}renderPagination(t){let e=this.list.length,a=Math.ceil(e/50)-1;t<0&&(t=0),t>a&&(t=a);let i=50*t,s=i+50,l="";if(this.page=t,s>=e&&(s=e),e>0){let t=this.isShuffle?this.shuffled:this.list;for(let e=i;e1&&t0?"active":"inactive",nextActive:r?"active":"inactive",page:t+1+" / "+parseInt(a+1)}))}changeFiles(t,e){if("upload-dir"!==e.id)return;let a=[],i=0;for(let t of e.files)if(t&&-1!==t.type.indexOf("audio")&&null===t.name.match(".m3u")){let e=t.name.split(".");e.pop(),e=e.join("."),a.push({file:t,name:e,index:i++})}this.setPlaylist(a),a.length>0?this.renderPagination(0):alert("No Valid AudioFiles found!")}}class GUI{async init(){this.data={},this.modal=new Modal,await this.loadForVis(),await template.loadArray(["playlist-item","playlist","playlist-footer"]),this.initDropZone()}async loadForVis(){let t=visual.c;null==this.data[t]&&(this.data[t]=await fetch("out/gui/"+t+".json").then(t=>t.json()))}initDropZone(){"drag dragstart dragend dragover dragenter dragleave drop".split(" ").forEach(t=>{window.addEventListener(t,async t=>{t.preventDefault(),t.stopPropagation(),"drop"===t.type&&(t.dataTransfer.files.length>0?(t.dataTransfer.id="upload-dir",player.playlist.changeFiles(t,t.dataTransfer)):alert("Sorry you need to upload files!"))})})}}class Modal{constructor(){this.currentModal="",this.modal=$("#modal"),this.parent=this.modal.parentNode,this.modal.addDelegatedEventListener("click","header .close",this.closeModal.bind(this))}resetModal(){this.renderModal("","","")}renderModal(t,e,a){this.currentModal=t,this.renderHeader(t),this.renderContent(e),this.renderFooter(a)}renderHeader(t){$("header .headline",this.modal).innerHTML=t}renderContent(t){$("modal-content",this.modal).innerHTML=t}renderFooter(t){$("modal-footer",this.modal).innerHTML=t}closeModal(){this.parent.addClass("hide")}isCurrent(t){return t===this.currentModal}showModal(){this.parent.removeClass("hide")}}class Visual{constructor(){this.data=[],this.dataArray=[]}updateData(){}draw(){}setup(){}}class VisualDrawer{constructor(){this.visuals={sphere:new Sphere,wave:new Wave,water:new Water}}init(){this.switch("wave"),this.updateLoop()}switch(t){null!=this.visuals[t]&&(this.c=t,vConf.loadConfigByName(this.c),this.visuals[this.c].setup())}updateLoop(){let t=shaderHandler.use(this.c),e=this.visuals[this.c];e.updateData(),this.prepare(),e.draw(t),requestAnimationFrame(this.updateLoop.bind(this))}prepare(){c.width=window.innerWidth,c.height=window.innerHeight,gl.viewport(0,0,gl.canvas.width,gl.canvas.height),gl.clearColor(0,0,0,parseFloat(pConf.get("alphaValue",0))),gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT),gl.enable(gl.DEPTH_TEST),gl.depthFunc(gl.LEQUAL),gl.enable(gl.CULL_FACE)}}class ImageUploader{async init(){this.image=pConf.get("bgURL",""),this.color=pConf.get("bgColour","#000000"),this.alpha=pConf.get("alphaValue",.5),this.getRealImage(),this.applyValues(),$("#modal").addDelegatedEventListener("change",'#image-upload input:not([type="color"])',this.changeHandler.bind(this)),$("#modal").addDelegatedEventListener("input","#image-upload input#color",this.changeHandler.bind(this))}async renderModal(){await template.loadTemplate("image"),gui.modal.resetModal(),gui.modal.renderModal("Background-Image",template.parseTemplate("image",{value:this.image,bgValue:this.color,alphaValue:this.alpha}),""),gui.modal.showModal()}changeHandler(t,e){"color"===e.id?this.color=e.value:"alphaValue"===e.id?this.alpha=e.value:(pConf.set("bgMode",e.id),"image"===e.id?(e.files[0].toBase64((t,e)=>{e?alert("Error converting image!"):(pConf.set("bgURL",t.currentTarget.result),pConf.save())}),this.image=URL.createObjectURL(e.files[0])):(this.image=e.value,pConf.set("bgURL",this.image))),pConf.set("bgColour",this.color),pConf.set("alphaValue",this.alpha),this.applyValues(),pConf.save()}applyValues(){let t=$("body");t.style.backgroundImage="url("+this.image+")",t.style.backgroundColor=this.color;let e=$("#colorBlob");e&&(e.style.backgroundColor=this.color)}getRealImage(){let t=pConf.get("bgMode"),e=pConf.get("bgURL","");if("image"===t){if(""!==e&&e.startsWith("data:image")){let t=e.split(";"),a=t.shift(),i=t.join(";").replace("base64,","");this.image=URL.createObjectURL(b64toBlob(i,a))}}else this.image=e}}const imageUploader=new ImageUploader;class Notification{constructor(){}}class Config{constructor(){this.config={},this.name=""}loadConfigByName(t){this.save(),this.name="config-"+t;let e=localStorage.getItem(this.name);e&&(this.config=JSON.parse(e))}save(){""!==this.name&&localStorage.setItem(this.name,JSON.stringify(this.config))}set(t,e){this.config[t]=e}remove(t){delete this.config[t]}get(t,e){let a=this.config[t];return null==a&&(this.config[t]=e,a=e),a}}class Sphere extends Visual{draw(){}setup(){}}class Wave extends Visual{updateData(){if(window.stopUpdate)return;let t=audioHandler.getFloatArray(),e=2/t.length,a=-1,i=0;for(let s=0;s{player.playlist.renderPagination(player.playlist.page),gui.modal.showModal()}),t.addDelegatedEventListener("click",".playlist-item",(t,e)=>{let a=e.dataset.index;player.playByID(parseInt(a)),togglePlayButton("pause")}),t.addDelegatedEventListener("click",".controls button",(t,e)=>{switch(e.id){case"previous":player.prevSong();break;case"next":player.nextSong();break;case"play":player.playStop();break;case"shuffle":player.playlist.isShuffle=!player.playlist.isShuffle,toggleShuffle()}togglePlayButton(audioHandler.audioFile.paused?"play":"pause")}),window.addEventListener("playSong",setActiveOnPlaylist),$(".upload-image").addEventListener("click",imageUploader.renderModal.bind(imageUploader))}function setActiveOnPlaylist(t){let e=$('.playlist-item[data-index="'+player.playlist.index+'"]'),a=$(".playlist-item.active");a&&a.removeClass("active"),e&&e.addClass("active")}function toggleShuffle(){let t=player.playlist.isShuffle;$("#shuffle").toggleCheck("active",t)}function togglePlayButton(t){$$("#play .icon").forEach(e=>{e.dataset.name===t?e.removeClass("hide"):e.addClass("hide")})}const shaderHandler=new ShaderHandler(null),audioHandler=new AudioHandler,gui=new GUI,visual=new VisualDrawer,template=new Template,player=new Player,vConf=new Config,pConf=new Config;let c=null,gl=null;async function startUP(){if(pConf.loadConfigByName("default"),c=document.body.querySelector("#c"),gl=c.getContext("webgl2"),!gl)return alert("SORRY THE BROWSER DOESN'T SUPPORT WEBGL2"),!1;shaderHandler.setGL(gl),await shaderHandler.loadArray(["wave","sphere","water"],"shaders/"),await audioHandler.init(),await player.init(),await visual.init(),await gui.init(),await imageUploader.init(),await initHandler()}startUP().then(t=>{setTimeout(t=>{$(".loading-screen").remove()},100)});