75 lines
49 KiB
JavaScript
75 lines
49 KiB
JavaScript
|
(()=>{"use strict";var e={305:(e,n,t)=>{t.d(n,{v:()=>_n});var o={};function r(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function a(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?r(Object(t),!0).forEach((function(n){i(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):r(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}t.r(o),t.d(o,{resolve:()=>qe,set:()=>Fe});var c=new Map;function l(e){var n=c.get(e);return void 0===n&&(n=e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),c.set(e,n)),n}function d(e,n){var t=window.ShadyCSS;return t&&!t.nativeShadow?e(t):n}function u(e){return"<".concat(String(e.tagName).toLowerCase(),">")}var s="ActiveXObject"in window,f=Promise.resolve(),p=new WeakMap;function b(e){return(b="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var v=function(e){return e},h=function(e){if("object"!==b(e))throw TypeError("Assigned value must be an object: ".concat(b(e)));return e&&Object.freeze(e)};function m(e,n){var t=b(e),o=v;switch(t){case"string":o=String;break;case"number":o=Number;break;case"boolean":o=Boolean;break;case"function":e=(o=e)();break;case"object":e&&Object.freeze(e),o=h}return{get:function(n){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:e;return t},set:function(e,n,t){return o(n,t)},connect:"object"!==t&&"undefined"!==t?function(t,r,a){if(t[r]===e){var i=l(r);if(t.hasAttribute(i)){var c=t.getAttribute(i);t[r]=""===c&&o===Boolean||c}}return n&&n(t,r,a)}:n}}function g(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);n&&(o=o.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,o)}return t}function y(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?g(Object(t),!0).forEach((function(n){w(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):g(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function w(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function x(e){return(x="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var S=new WeakMap,E=new Set;function $(){try{E.forEach((function(e){try{S.get(e)(),E.delete(e)}catch(n){throw E.delete(e),n}}))}catch(e){throw E.size&&$(),e}}function N(e){E.size||requestAnimationFrame($),E.add(e)}var k=new WeakMap;function _(e,n){var t=k.get(e);t||(t=new Map,k.set(e,t));var o=t.get(n);return o||(o={target:e,key:n,value:void 0,contexts:void 0,deps:void 0,state:0,checksum:0,observed:!1},t.set(n,o)),o}function O(e){var n=e.state;return e.deps&&e.deps.forEach((function(e){n+=e.state})),n}function I(e){e.observed&&N(e),e.contexts&&e.contexts.forEach(I)}function M(e,n){n&&n.forEach((function(n){e.deps.add(n),e.observed&&(n.contexts||(n.contexts=new Set),n.contexts.add(e)),M(e,n.deps)}))}var j=new Set;function T(e,n,t,o){var r=_(e,n);if(j.size&&j.has(r))throw Error("Circular get invocation is forbidden: '".concat(n,"'"));if(j.forEach((function(e){e.deps||(e.deps=new Set),e.deps.add(r),e.observed&&(r.contexts||(r.contexts=new Set),r.contexts.add(e))})),(o&&o(r.value)||!o)&&r.checksum&&r.checksum===O(r))return r.value;try{j.add(r),r.observed&&r.deps&&r.deps.size&&r.deps.forEach((function(e){e.contexts&&e.contexts.delete
|
||
|
<div class="box" style="text-align:center">
|
||
|
No MIDI output devices were found 😥<br /><br />Please attach a MIDI device and try again
|
||
|
</div>
|
||
|
<button onclick="window.location.reload()" id="start" class="enabled" style="background-color:darkgreen">Reload</button>
|
||
|
</div>`.style(gn);const e=Array.from(Array(16).keys()),n=window.location.pathname.substring(window.location.pathname.lastIndexOf("/")+1),t=localStorage.getItem(`touchmidi.${n}.config`);let o={};o=t?JSON.parse(t):yn;let r="disabled";return Qe.outputs.forEach((function(e,n){n==o.deviceId&&(r="enabled")})),Ze`
|
||
|
<div id="dialog">
|
||
|
<span id="title">Touch Midi v${"2.2.0"} <a href="https://code.benco.io/touchmidi/" target="_blank">[[ GitHub ]]</a></span>
|
||
|
<div id="container">
|
||
|
<div class="box">
|
||
|
Select MIDI Device
|
||
|
<select size="5" id="deviceList" onchange="${xn}">
|
||
|
${Array.from(Qe.outputs.entries()).map((e=>Ze`<option value="${e[0]}" selected="${e[0]==o.deviceId}">${e[1].name}</option>`))}
|
||
|
</select>
|
||
|
<br />
|
||
|
</div>
|
||
|
<div class="box">
|
||
|
MIDI Channels
|
||
|
<select id="channel">
|
||
|
<option value="0">Set By Layout</option>
|
||
|
${e.map((e=>Ze`<option value="${e+1}" selected="${e==o.globalChannel-1}">${e+1}</option>`))}
|
||
|
</select>
|
||
|
</div>
|
||
|
<div class="box">
|
||
|
<input type="checkbox" id="restoreValues" name="restoreValues" checked="${o.restoreValues}" />
|
||
|
<label for="restoreValues">Save & Restore at Startup</label>
|
||
|
<br />
|
||
|
<input type="checkbox" id="fullScreen" name="fullScreen" />
|
||
|
<label for="fullScreen">Start Fullscreen</label>
|
||
|
</div>
|
||
|
</div>
|
||
|
<button onclick="${wn}" id="start" class="${r}">Start</button>
|
||
|
</div>
|
||
|
`.style(gn)}}),te("midi-slider",{_previousPos:null,_width:30,_update:{observe:Sn},value:Number.MIN_SAFE_INTEGER,chan:1,cc:-1,nrpn:"",min:0,max:127,pitchBend:!1,colour:m("#ffffff"),label:"__unset__",horizontal:!1,labelScale:1,grow:1,render:({value:e,colour:n,label:t,min:o,max:r,cc:a,chan:i,horizontal:c,nrpn:l,pitchBend:d,_width:u,labelScale:s,grow:f})=>{const p=e;vn("midi-slider",`${a}${i}${l}`,e),e>r&&(e=r),e<o&&(e=o);const b=Math.round((e-o)/(r-o)*100);"__unset__"===t&&(t="%v");const v=`\n :host { \n flex-grow: ${f} \n }\n div {\n background: linear-gradient(to ${c?"right":"top"}, ${bn(n)} ${b}%, var(--bg) ${b}%);\n color: ${n};\n border-color: ${n};\n font-size: ${.2*u*s}px;\n }`;return a>0&&p>Number.MIN_SAFE_INTEGER&&an(a,i,e),l&&p>Number.MIN_SAFE_INTEGER&&cn(l,i,e,r>127),d&&function(e=1,n=0){if(!en)return;const t=nn>0?nn:e;dn(t);const o=Math.floor(n/128),r=Math.floor(n%128);console.debug(`MIDI pitchbend - val_msb:${o}, val_lsb:${r}, channel:${t}`),en.send([t-1+224,o,r])}(i,e),Ze`<div innerHTML="${pn(t,e,b,i,a)}"></div>`.style(":host {\n flex: 1 1;\n display: flex;\n margin: var(--spacing);\n}\n\ndiv {\n font-size: 4vw;\n display: flex;\n flex: 1 1;\n border: var(--b-width) solid;\n border-radius: var(--b-radius);\n justify-content: center;\n align-items: center;\n text-align: center;\n line-height: 0.9em;\n cursor: pointer;\n overflow: hidden;\n user-select: none;\n}\n",v)}}),te("midi-encoder",{_previousPos:null,_width:30,_update:{observe:Sn},value:Number.MIN_SAFE_INTEGER,chan:1,cc:-1,nrpn:"",min:0,max:127,colour:m("#ffffff"),label:"__unset__",horizontal:!1,labelScale:1,grow:1,render:({value:e,colour:n,label:t,min:o,max:r,chan:a,cc:i,nrpn:c,_width:l,labelScale:d,grow:u})=>{const s=e;vn("midi-encoder",`${i}${a}${c}`,e),e>r&&(e=r),e<o&&(e=o);const f=Math.round((e-o)/(r-o)*100),p=(e-o)/(r-o)*75;"__unset__"===t&&(t="%v"),i>0&&s>Number.MIN_SAFE_INTEGER&&an(i,a,e),c&&s>Number.MIN_SAFE_INTEGER&&cn(c,a,e,r>127);const b=`\n :host {\n flex-grow: ${u}\n }\n #label {\n color: ${n}; \n font-size:${.2*l*d}px\n }`;return Ze`<div>
|
||
|
<svg viewBox="0 0 36 36">
|
||
|
<path
|
||
|
d="M18 2.0
|
||
|
a 1 1 0 0 1 0 32
|
||
|
a 1 1 0 0 1 0 -32"
|
||
|
fill="none"
|
||
|
stroke="${n}"
|
||
|
stroke-opacity="0.3"
|
||
|
stroke-width="0.1rem"
|
||
|
stroke-dasharray="75, 100"
|
||
|
transform="rotate(226 18 18)"
|
||
|
stroke-linecap="round"
|
||
|
/>
|
||
|
<path
|
||
|
d="M18 2.0
|
||
|
a 1 1 0 0 1 0 32
|
||
|
a 1 1 0 0 1 0 -32"
|
||
|
fill="none"
|
||
|
stroke="${n}"
|
||
|
stroke-width="0.25rem"
|
||
|
stroke-dasharray="${p}, 100"
|
||
|
transform="rotate(226 18 18)"
|
||
|
stroke-linecap="round"
|
||
|
/>
|
||
|
</svg>
|
||
|
<div id="label" innerHTML="${pn(t,e,f,a,i)}"></div>
|
||
|
</div>`.style(":host {\n flex: 1 1;\n display: flex;\n margin: var(--spacing);\n}\n\nsvg {\n height: 100%;\n margin: 0 auto;\n}\n\ndiv {\n flex: auto;\n justify-content: center;\n display: flex;\n align-items: center;\n text-align: center;\n cursor: pointer;\n overflow: hidden;\n user-select: none;\n position: relative;\n}\n\n#label {\n font-size: 5vmin;\n position: absolute;\n z-index: 40;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n text-align: center;\n line-height: 0.9em;\n width: 100%;\n padding: 0.2rem;\n}\n",b)}}),te("midi-button",{_pressed:!1,_width:30,chan:1,cc:-1,nrpn:"",nrpnHires:!1,value:0,valueOff:0,velo:127,note:-1,prog:"",colour:m("#ffffff"),label:"__unset__",toggle:!1,labelScale:1,grow:1,render:({label:e,colour:n,_pressed:t,chan:o,cc:r,nrpn:a,prog:i,note:c,_width:l,labelScale:d,grow:u})=>{"__unset__"===e&&(c>0?e="%a":r>0?e="%t":a?e=a:i&&(e=i));const s=`\n :host {\n flex-grow: ${u}\n }\n button {\n background-color: ${t?`${bn(n)}`:"var(--bg)"};\n color: ${n};\n border-color: ${n};\n font-size: ${.3*l*d}px !important;\n }`;return Ze`<button
|
||
|
onmouseup="${En}"
|
||
|
ontouchend="${En}"
|
||
|
onmousedown="${$n}"
|
||
|
ontouchstart="${$n}"
|
||
|
onmouseleave="${En}"
|
||
|
innerHTML="${pn(e,"","",o,r,c)}"
|
||
|
></button>`.style(":host {\n flex: 1 1;\n display: flex;\n margin: var(--spacing);\n}\n\nbutton {\n font-family: var(--font);\n background-color: var(--bg);\n font-size: 5vw;\n display: flex;\n flex: 1 1;\n border: var(--b-width) solid;\n border-radius: var(--b-radius);\n justify-content: center;\n align-items: center;\n cursor: pointer;\n overflow: hidden;\n width: 1px;\n user-select: none;\n}\n",s)}}),te("midi-pad",{_previousPos:null,_width:30,_update:{observe:(e,n)=>{if(n.restoreValue)return void(e.value=n.restoreValue);e._previousPos={x:n.x,y:n.y};let t=e.valueX+n.dx,o=e.valueY-n.dy;t=fn(t,e.min,e.max),o=fn(o,e.min,e.max),e.valueX=Math.round(t),e.valueY=Math.round(o)}},valueX:Number.MIN_SAFE_INTEGER,valueY:Number.MIN_SAFE_INTEGER,chan:1,ccX:-1,ccY:-1,min:0,max:127,colour:m("#ffffff"),label:"__unset__",labelScale:1,grow:1,render:({valueX:e,valueY:n,colour:t,label:o,min:r,max:a,ccX:i,ccY:c,chan:l,nrpn:d,_width:u,labelScale:s,grow:f})=>{const p=e,b=n;vn("midi-pad",`${i}${l}${d}X`,e),vn("midi-pad",`${c}${l}${d}Y`,n),e=fn(e,r,a),n=fn(n,r,a);let v=Math.round((e-r)/(a-r)*100),h=Math.round((n-r)/(a-r)*100);"__unset__"===o&&(o="%v");const m=`\n :host {\n flex-grow: ${f}\n }\n div {\n color: ${t};\n border-color: ${t};\n }\n #label {\n font-size: ${.4*u*s}px;\n }\n #marker {\n background-color: ${bn(t)};\n border-color: ${t};\n bottom: calc(${h}% - ${.05*u}px);\n left: calc(${v}% - ${.05*u}px);\n width: ${.1*u}px;\n height: ${.1*u}px;\n }`;return i>0&&c>0&&p>Number.MIN_SAFE_INTEGER&&b>Number.MIN_SAFE_INTEGER&&(an(i,l,e),an(c,l,n)),Ze`<div>
|
||
|
<div id="label" innerHTML="${pn(o,`${e},${n}`,`${v},${h}`,l)}"></div>
|
||
|
<span id="marker"></span>
|
||
|
</div>`.style(":host {\n flex: 1 1;\n display: flex;\n margin: var(--spacing);\n}\n\ndiv {\n font-size: 4vw;\n display: flex;\n flex: 1 1;\n border: var(--b-width) solid;\n border-radius: var(--b-radius);\n justify-content: center;\n align-items: center;\n text-align: center;\n line-height: 0.9em;\n cursor: pointer;\n overflow: hidden;\n width: 1px;\n user-select: none;\n position: relative;\n}\n\n#marker {\n width: 3vmax;\n height: 3vmax;\n border-radius: 50%;\n position: absolute;\n background-color: white;\n display: block;\n z-index: 10;\n border: 0.3vmax solid white;\n}\n\n#label {\n border: none;\n padding: 1rem;\n}\n",m)}}),te("midi-counter",{_width:30,chan:1,cc:-1,value:0,min:0,max:127,colour:m("#ffffff"),label:"__unset__",labelScale:1,grow:1,render:({colour:e,chan:n,cc:t,_width:o,labelScale:r,grow:a,value:i})=>{vn("midi-counter",`${t}${n}0`,i);const c=`\n :host {\n flex-grow: ${a}\n }\n button:active {\n background-color: ${bn(e)};\n }\n #label {\n font-size: ${.2*o*r}px !important;\n border-color: ${e};\n color: ${e};\n background-color: var(--bg);\n }\n button {\n color: ${e};\n border-color: ${e};\n font-size: ${.3*o*r}px !important;\n }`;return Ze`<div>
|
||
|
<span id="label" innerHTML="${i}"></span>
|
||
|
<button id="dec" onmousedown="${Nn}" ontouchstart="${Nn}">-1</button>
|
||
|
<button id="inc" onmousedown="${Nn}" ontouchstart="${Nn}">+1</button>
|
||
|
</div>`.style(":host {\n flex: 1 1;\n display: flex;\n margin: var(--spacing);\n}\n\ndiv {\n display: flex;\n flex-direction: row;\n flex: 1 1;\n position: relative;\n}\n\nbutton {\n font-family: var(--font);\n background-color: var(--bg);\n font-size: 5vw;\n flex: 1 1;\n border: var(--b-width) solid;\n border-radius: var(--b-radius);\n justify-content: center;\n align-items: center;\n cursor: pointer;\n overflow: hidden;\n user-select: none;\n}\n\n#label {\n position: absolute;\n background-color: var(--bg);\n height: 50%;\n text-align: center;\n width: 25%;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n z-index: 4;\n font-size: 5vw;\n overflow: hidden;\n display: block;\n pointer-events: none;\n}\n",c)}}),te("midi-spacer",{grow:1,render:({grow:e})=>{const n=`\n :host{\n flex: ${e} 1;\n }\n div {\n flex ${e} 1;\n }`;return Ze`<div></div>`.style(n)}}),te("midi-label",{grow:1,render:({grow:e})=>{const n=`\n :host{\n flex: ${e} 1;\n }\n div {\n flex ${e} 1;\n font-size: 4vw;\n }`;return Ze`<div><slot></div>`.style(n)}});let kn=[],_n={};function On(e){for(let n of e.changedTouches)kn[n.identifier]=n.target}function In(e){for(let n of e.changedTouches)Cn(n.target,n.screenX,n.screenY)}function Mn(e){for(let n of e.changedTouches)kn.splice(n.identifier,1)}function jn(e){kn[20]=e.target}function Tn(e){Cn(kn[20],e.screenX,e.screenY)}function An(){kn.splice(20,1)}function Cn(e,n,t){if(!e)return;let o=0,r=0;e._previousPos&&(o=n-e._previousPos.x,r=t-e._previousPos.y,o=fn(o,-6,6)/1,r=fn(r,-6,6)/1),e._update={dx:o,dy:r,x:n,y:t}}function Dn(e){e.preventDefault()}function Pn(e){if(!e.deviceId)return void alert("No MIDI device id, MIDI output will fail!");let n=!1;for(let t of Qe.outputs.values())t.id===e.deviceId&&(n=!0);if(n){if(function(e="output-1",n=0){en=e,nn=n}(Qe.outputs.get(e.deviceId),e.globalChannel||0),console.log(`MIDI configured for device '${e.deviceId}' and channel: ${e.globalChannel}`),e.restoreValues){console.log("Restoring saved widget values...");for(let e of document.body.querySelectorAll("midi-slider,midi-encoder,midi-pad,midi-counter"))if("midi-pad"==e.tagName.toLowerCase()){let n=hn(e,`${e.ccX}${e.chan}${e.nrpn}X`),t=hn(e,`${e.ccY}${e.chan}${e.nrpn}Y`);n&&(e.valueX=n),t&&(e.valueY=t)}else{let n=hn(e);n&&(e.value=n)}}}else alert(`The provided MIDI device id '${e.deviceId}' is invalid, MIDI output will fail!`)}function Ln(){for(let e of document.body.querySelectorAll("midi-slider,midi-encoder,midi-pad,midi-button,midi-counter"))e._width=e.clientWidth}window.addEventListener("load",(async()=>{await async function(){const e=document.createElement("div");e.id="pageMask",document.body.append(e);const n=document.createElement("style");n.textContent="@import url('https://fonts.googleapis.com/css2?family=PT+Sans&display=swap');\n\n:root {\n /* these variables are used everywhere */\n --bg: black; /* background colour */\n --b-radius: min(1.9vmin, 15px); /* border radius */\n --b-width: 0.3rem; /* border thickness */\n --spacing: 0.3rem; /* widget spacing */\n\n --font: 'PT Sans', sans-serif; /* Consolas, 'Courier New', monospace; */\n}\n\nhtml,\nbody {\n height: 100%;\n margin: 0;\n padding: 0;\n overflow-y: hidden;\n color: white;\n background-color: var(--bg);\n font-family: var(--font);\n touch-action: none;\n}\n\nbody {\n display: flex;\n flex-direction: column;\n}\n\n/* Used to hide the page behind the config dialog */\n#pageMask {\n background: rgba(0, 0, 0, 0.8);\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n display: none;\n}\n";let t=document.createElement("meta");t.setAttribute("name","viewport"),t.setAttribute("content","width=device-width, user-scalable=no, initial-scale=1.0"),document.getElementsByTagName("head")[0].appendChild(t);let o=document.querySelector("link[rel~='icon']");o||(o=document.createElement("link"),o.rel="icon",o.href="https://raw.githubusercontent.com/benc-uk/touchmidi/main/src/assets/favicon.png",document.getElementsByTagName("head")[0].appendChild
|