diff --git a/packages/react/dist/index.cjs.js b/packages/react/dist/index.cjs.js index d5899d1a..2acdb6b7 100644 --- a/packages/react/dist/index.cjs.js +++ b/packages/react/dist/index.cjs.js @@ -1,3 +1,3 @@ -"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var t=require("react"),te=require("@uiw/react-codemirror"),C=require("@codemirror/view"),A=require("@codemirror/state"),ae=require("@codemirror/lang-javascript"),l=require("@lezer/highlight"),re=require("@uiw/codemirror-themes"),oe=require("react-hook-inview"),se=require("@strudel.cycles/eval"),y=require("@strudel.cycles/tone"),j=require("@strudel.cycles/core"),ne=require("@strudel.cycles/webaudio"),E=require("@strudel.cycles/midi");function $(e){return e&&typeof e=="object"&&"default"in e?e:{default:e}}var g=$(t),ce=$(te),ie=re.createTheme({theme:"dark",settings:{background:"#222",foreground:"#75baff",caret:"#ffcc00",selection:"rgba(128, 203, 196, 0.5)",selectionMatch:"#036dd626",lineHighlight:"#8a91991a",gutterBackground:"transparent",gutterForeground:"#676e95"},styles:[{tag:l.tags.keyword,color:"#c792ea"},{tag:l.tags.operator,color:"#89ddff"},{tag:l.tags.special(l.tags.variableName),color:"#eeffff"},{tag:l.tags.typeName,color:"#f07178"},{tag:l.tags.atom,color:"#f78c6c"},{tag:l.tags.number,color:"#ff5370"},{tag:l.tags.definition(l.tags.variableName),color:"#82aaff"},{tag:l.tags.string,color:"#c3e88d"},{tag:l.tags.special(l.tags.string),color:"#f07178"},{tag:l.tags.comment,color:"#7d8799"},{tag:l.tags.variableName,color:"#f07178"},{tag:l.tags.tagName,color:"#ff5370"},{tag:l.tags.bracket,color:"#a2a1a4"},{tag:l.tags.meta,color:"#ffcb6b"},{tag:l.tags.attributeName,color:"#c792ea"},{tag:l.tags.propertyName,color:"#c792ea"},{tag:l.tags.className,color:"#decb6b"},{tag:l.tags.invalid,color:"#ffffff"}]});const P=A.StateEffect.define(),le=A.StateField.define({create(){return C.Decoration.none},update(e,o){try{for(let s of o.effects)if(s.is(P))if(s.value){const u=C.Decoration.mark({attributes:{style:"background-color: #FFCA2880"}});e=C.Decoration.set([u.range(0,o.newDoc.length)])}else e=C.Decoration.set([]);return e}catch(s){return console.warn("flash error",s),e}},provide:e=>C.EditorView.decorations.from(e)}),K=e=>{e.dispatch({effects:P.of(!0)}),setTimeout(()=>{e.dispatch({effects:P.of(!1)})},200)},L=A.StateEffect.define(),ue=A.StateField.define({create(){return C.Decoration.none},update(e,o){try{for(let s of o.effects)if(s.is(L)){const u=s.value.map(d=>(d.context.locations||[]).map(({start:i,end:c})=>{const f=d.context.color||"#FFCA28";let r=o.newDoc.line(i.line).from+i.column,a=o.newDoc.line(c.line).from+c.column;const w=o.newDoc.length;return r>w||a>w?void 0:C.Decoration.mark({attributes:{style:`outline: 1.5px solid ${f};`}}).range(r,a)})).flat().filter(Boolean)||[];e=C.Decoration.set(u,!0)}return e}catch{return C.Decoration.set([])}},provide:e=>C.EditorView.decorations.from(e)}),de=[ae.javascript(),ie,ue,le];function Q({value:e,onChange:o,onViewChanged:s,onSelectionChange:u,options:d,editorDidMount:i}){const c=t.useCallback(a=>{o?.(a)},[o]),f=t.useCallback(a=>{s?.(a)},[s]),r=t.useCallback(a=>{a.selectionSet&&u&&u?.(a.state.selection)},[u]);return g.default.createElement(g.default.Fragment,null,g.default.createElement(ce.default,{value:e,onChange:c,onCreateEditor:f,onUpdate:r,extensions:de}))}function J(e){const{onEvent:o,onQuery:s,onSchedule:u,ready:d=!0,onDraw:i}=e,[c,f]=t.useState(!1),r=1,a=()=>Math.floor(y.Tone.getTransport().seconds/r),w=(b=a())=>{const S=new j.TimeSpan(b,b+1),q=s?.(new j.State(S))||[];u?.(q,b);const R=S.begin.valueOf();y.Tone.getTransport().cancel(R);const M=(b+1)*r-.5,N=Math.max(y.Tone.getTransport().seconds,M)+.1;y.Tone.getTransport().schedule(()=>{w(b+1)},N),q?.filter(p=>p.part.begin.equals(p.whole?.begin)).forEach(p=>{y.Tone.getTransport().schedule(v=>{o(v,p,y.Tone.getContext().currentTime),y.Tone.Draw.schedule(()=>{i?.(v,p)},v)},p.part.begin.valueOf())})};t.useEffect(()=>{d&&w()},[o,u,s,i,d]);const k=async()=>{f(!0),await y.Tone.start(),y.Tone.getTransport().start("+0.1")},T=()=>{y.Tone.getTransport().pause(),f(!1)};return{start:k,stop:T,onEvent:o,started:c,setStarted:f,toggle:()=>c?T():k(),query:w,activeCycle:a}}function G(e){return t.useEffect(()=>(window.addEventListener("message",e),()=>window.removeEventListener("message",e)),[e]),t.useCallback(o=>window.postMessage(o,"*"),[])}let fe=()=>Math.floor((1+Math.random())*65536).toString(16).substring(1);const ge=e=>encodeURIComponent(btoa(e));function X({tune:e,defaultSynth:o,autolink:s=!0,onEvent:u,onDraw:d}){const i=t.useMemo(()=>fe(),[]),[c,f]=t.useState(e),[r,a]=t.useState(),[w,k]=t.useState(""),[T,_]=t.useState(),[b,S]=t.useState(!1),[q,R]=t.useState(""),[M,N]=t.useState(),p=t.useMemo(()=>c!==r||T,[c,r,T]),v=t.useCallback(m=>k(n=>n+`${n?` +"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var t=require("react"),ee=require("@uiw/react-codemirror"),E=require("@codemirror/view"),A=require("@codemirror/state"),te=require("@codemirror/lang-javascript"),l=require("@lezer/highlight"),ae=require("@uiw/codemirror-themes"),re=require("react-hook-inview"),oe=require("@strudel.cycles/eval"),p=require("@strudel.cycles/tone"),B=require("@strudel.cycles/core"),se=require("@strudel.cycles/webaudio"),M=require("@strudel.cycles/midi");function U(e){return e&&typeof e=="object"&&"default"in e?e:{default:e}}var d=U(t),ne=U(ee),ce=ae.createTheme({theme:"dark",settings:{background:"#222",foreground:"#75baff",caret:"#ffcc00",selection:"rgba(128, 203, 196, 0.5)",selectionMatch:"#036dd626",lineHighlight:"#8a91991a",gutterBackground:"transparent",gutterForeground:"#676e95"},styles:[{tag:l.tags.keyword,color:"#c792ea"},{tag:l.tags.operator,color:"#89ddff"},{tag:l.tags.special(l.tags.variableName),color:"#eeffff"},{tag:l.tags.typeName,color:"#f07178"},{tag:l.tags.atom,color:"#f78c6c"},{tag:l.tags.number,color:"#ff5370"},{tag:l.tags.definition(l.tags.variableName),color:"#82aaff"},{tag:l.tags.string,color:"#c3e88d"},{tag:l.tags.special(l.tags.string),color:"#f07178"},{tag:l.tags.comment,color:"#7d8799"},{tag:l.tags.variableName,color:"#f07178"},{tag:l.tags.tagName,color:"#ff5370"},{tag:l.tags.bracket,color:"#a2a1a4"},{tag:l.tags.meta,color:"#ffcb6b"},{tag:l.tags.attributeName,color:"#c792ea"},{tag:l.tags.propertyName,color:"#c792ea"},{tag:l.tags.className,color:"#decb6b"},{tag:l.tags.invalid,color:"#ffffff"}]});const O=A.StateEffect.define(),ie=A.StateField.define({create(){return E.Decoration.none},update(e,o){try{for(let s of o.effects)if(s.is(O))if(s.value){const i=E.Decoration.mark({attributes:{style:"background-color: #FFCA2880"}});e=E.Decoration.set([i.range(0,o.newDoc.length)])}else e=E.Decoration.set([]);return e}catch(s){return console.warn("flash error",s),e}},provide:e=>E.EditorView.decorations.from(e)}),$=e=>{e.dispatch({effects:O.of(!0)}),setTimeout(()=>{e.dispatch({effects:O.of(!1)})},200)},L=A.StateEffect.define(),le=A.StateField.define({create(){return E.Decoration.none},update(e,o){try{for(let s of o.effects)if(s.is(L)){const i=s.value.map(u=>(u.context.locations||[]).map(({start:n,end:m})=>{const a=u.context.color||"#FFCA28";let f=o.newDoc.line(n.line).from+n.column,r=o.newDoc.line(m.line).from+m.column;const v=o.newDoc.length;return f>v||r>v?void 0:E.Decoration.mark({attributes:{style:`outline: 1.5px solid ${a};`}}).range(f,r)})).flat().filter(Boolean)||[];e=E.Decoration.set(i,!0)}return e}catch{return E.Decoration.set([])}},provide:e=>E.EditorView.decorations.from(e)}),ue=[te.javascript(),ce,le,ie];function K({value:e,onChange:o,onViewChanged:s,onSelectionChange:i,options:u,editorDidMount:n}){const m=t.useCallback(r=>{o?.(r)},[o]),a=t.useCallback(r=>{s?.(r)},[s]),f=t.useCallback(r=>{r.selectionSet&&i&&i?.(r.state.selection)},[i]);return d.default.createElement(d.default.Fragment,null,d.default.createElement(ne.default,{value:e,onChange:m,onCreateEditor:a,onUpdate:f,extensions:ue}))}function Q(e){const{onEvent:o,onQuery:s,onSchedule:i,ready:u=!0,onDraw:n}=e,[m,a]=t.useState(!1),f=1,r=()=>Math.floor(p.Tone.getTransport().seconds/f),v=(w=r())=>{const R=new B.TimeSpan(w,w+1),k=s?.(new B.State(R))||[];i?.(k,w);const T=R.begin.valueOf();p.Tone.getTransport().cancel(T);const N=(w+1)*f-.5,C=Math.max(p.Tone.getTransport().seconds,N)+.1;p.Tone.getTransport().schedule(()=>{v(w+1)},C),k?.filter(h=>h.part.begin.equals(h.whole?.begin)).forEach(h=>{p.Tone.getTransport().schedule(S=>{o(S,h,p.Tone.getContext().currentTime),p.Tone.Draw.schedule(()=>{n?.(S,h)},S)},h.part.begin.valueOf())})};t.useEffect(()=>{u&&v()},[o,i,s,n,u]);const y=async()=>{a(!0),await p.Tone.start(),p.Tone.getTransport().start("+0.1")},b=()=>{p.Tone.getTransport().pause(),a(!1)};return{start:y,stop:b,onEvent:o,started:m,setStarted:a,toggle:()=>m?b():y(),query:v,activeCycle:r}}function J(e){return t.useEffect(()=>(window.addEventListener("message",e),()=>window.removeEventListener("message",e)),[e]),t.useCallback(o=>window.postMessage(o,"*"),[])}let de=()=>Math.floor((1+Math.random())*65536).toString(16).substring(1);const fe=e=>encodeURIComponent(btoa(e));function G({tune:e,autolink:o=!0,onEvent:s,onDraw:i}){const u=t.useMemo(()=>de(),[]),[n,m]=t.useState(e),[a,f]=t.useState(),[r,v]=t.useState(""),[y,b]=t.useState(),[W,w]=t.useState(!1),[R,k]=t.useState(""),[T,N]=t.useState(),C=t.useMemo(()=>n!==a||y,[n,a,y]),h=t.useCallback(g=>v(c=>c+`${c?` -`:""}${m}`),[]),W=t.useMemo(()=>{if(r&&!r.includes("strudel disable-highlighting"))return(m,n)=>d?.(m,n,r)},[r,d]),O=t.useMemo(()=>r&&r.includes("strudel hide-header"),[r]),H=t.useMemo(()=>r&&r.includes("strudel hide-console"),[r]),h=J({onDraw:W,onEvent:t.useCallback((m,n,ee)=>{try{u?.(n),n.context.logs?.length&&n.context.logs.forEach(v);const{onTrigger:x=ne.webaudioOutputTrigger}=n.context;x(m,n,ee,1)}catch(x){console.warn(x),x.message="unplayable event: "+x?.message,v(x.message)}},[u,v,o]),onQuery:t.useCallback(m=>{try{return M?.query(m)||[]}catch(n){return console.warn(n),n.message="query error: "+n.message,_(n),[]}},[M]),onSchedule:t.useCallback((m,n)=>Z(m),[]),ready:!!M&&!!r}),V=G(({data:{from:m,type:n}})=>{n==="start"&&m!==i&&(h.setStarted(!1),a(void 0))}),B=t.useCallback(async(m=c)=>{if(r&&!p){_(void 0),h.start();return}try{S(!0);const n=await se.evaluate(m);h.start(),V({type:"start",from:i}),N(()=>n.pattern),s&&(window.location.hash="#"+encodeURIComponent(btoa(c))),R(ge(c)),_(void 0),a(m),S(!1)}catch(n){n.message="evaluation error: "+n.message,console.warn(n),_(n)}},[r,p,c,h,s,i,V]),Z=(m,n)=>{m.length};return{hideHeader:O,hideConsole:H,pending:b,code:c,setCode:f,pattern:M,error:T,cycle:h,setPattern:N,dirty:p,log:w,togglePlay:()=>{h.started?h.stop():B()},setActiveCode:a,activateCode:B,activeCode:r,pushLog:v,hash:q}}function z(...e){return e.filter(Boolean).join(" ")}let F=[],I;function Y({view:e,pattern:o,active:s}){t.useEffect(()=>{if(e)if(o&&s){let d=function(){try{const i=y.Tone.getTransport().seconds,f=[Math.max(I||i,i-1/10),i+1/60];I=i+1/60,F=F.filter(a=>a.whole.end>i);const r=o.queryArc(...f).filter(a=>a.hasOnset());F=F.concat(r),e.dispatch({effects:L.of(F)})}catch{e.dispatch({effects:L.of([])})}u=requestAnimationFrame(d)},u=requestAnimationFrame(d);return()=>{cancelAnimationFrame(u)}}else F=[],e.dispatch({effects:L.of([])})},[o,s,e])}const me="_container_3i85k_1",he="_header_3i85k_5",be="_buttons_3i85k_9",pe="_button_3i85k_9",ve="_buttonDisabled_3i85k_17",ye="_error_3i85k_21",we="_body_3i85k_25";var D={container:me,header:he,buttons:be,button:pe,buttonDisabled:ve,error:ye,body:we};function U({type:e}){return g.default.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",className:"sc-h-5 sc-w-5",viewBox:"0 0 20 20",fill:"currentColor"},{refresh:g.default.createElement("path",{fillRule:"evenodd",d:"M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z",clipRule:"evenodd"}),play:g.default.createElement("path",{fillRule:"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z",clipRule:"evenodd"}),pause:g.default.createElement("path",{fillRule:"evenodd",d:"M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z",clipRule:"evenodd"})}[e])}function Me({tune:e,defaultSynth:o,hideOutsideView:s=!1,theme:u,init:d,onEvent:i,enableKeyboard:c}){const{code:f,setCode:r,pattern:a,activeCode:w,activateCode:k,evaluateOnly:T,error:_,cycle:b,dirty:S,togglePlay:q,stop:R}=X({tune:e,defaultSynth:o,autolink:!1,onEvent:i});t.useEffect(()=>{d&&T()},[e,d]);const[M,N]=t.useState(),[p,v]=oe.useInView({threshold:.01}),W=t.useRef(),O=t.useMemo(()=>((v||!s)&&(W.current=!0),v||W.current),[v,s]);return Y({view:M,pattern:a,active:b.started&&!w?.includes("strudel disable-highlighting")}),t.useLayoutEffect(()=>{if(c){const H=async h=>{(h.ctrlKey||h.altKey)&&(h.code==="Enter"?(h.preventDefault(),K(M),await k()):h.code==="Period"&&(b.stop(),h.preventDefault()))};return window.addEventListener("keydown",H,!0),()=>window.removeEventListener("keydown",H,!0)}},[c,a,f,k,b,M]),g.default.createElement("div",{className:D.container,ref:p},g.default.createElement("div",{className:D.header},g.default.createElement("div",{className:D.buttons},g.default.createElement("button",{className:z(D.button,b.started?"sc-animate-pulse":""),onClick:()=>q()},g.default.createElement(U,{type:b.started?"pause":"play"})),g.default.createElement("button",{className:z(S?D.button:D.buttonDisabled),onClick:()=>k()},g.default.createElement(U,{type:"refresh"}))),_&&g.default.createElement("div",{className:D.error},_.message)),g.default.createElement("div",{className:D.body},O&&g.default.createElement(Q,{value:f,onChange:r,onViewChanged:N})))}function Ee(e){const{ready:o,connected:s,disconnected:u}=e,[d,i]=t.useState(!0),[c,f]=t.useState(E.WebMidi?.outputs||[]);return t.useEffect(()=>{E.enableWebMidi().then(()=>{E.WebMidi.addListener("connected",a=>{f([...E.WebMidi.outputs]),s?.(E.WebMidi,a)}),E.WebMidi.addListener("disconnected",a=>{f([...E.WebMidi.outputs]),u?.(E.WebMidi,a)}),o?.(E.WebMidi),i(!1)}).catch(a=>{if(a){console.error(a),console.warn("Web Midi could not be enabled..");return}})},[o,s,u,c]),{loading:d,outputs:c,outputByName:a=>E.WebMidi.getOutputByName(a)}}exports.CodeMirror=Q;exports.MiniRepl=Me;exports.cx=z;exports.flash=K;exports.useCycle=J;exports.useHighlighting=Y;exports.usePostMessage=G;exports.useRepl=X;exports.useWebMidi=Ee; +`:""}${g}`),[]),S=t.useMemo(()=>{if(a&&!a.includes("strudel disable-highlighting"))return(g,c)=>i?.(g,c,a)},[a,i]),H=t.useMemo(()=>a&&a.includes("strudel hide-header"),[a]),_=t.useMemo(()=>a&&a.includes("strudel hide-console"),[a]),q=Q({onDraw:S,onEvent:t.useCallback((g,c,Z)=>{try{s?.(c),c.context.logs?.length&&c.context.logs.forEach(h);const{onTrigger:x=se.webaudioOutputTrigger}=c.context;x(g,c,Z,1)}catch(x){console.warn(x),x.message="unplayable event: "+x?.message,h(x.message)}},[s,h]),onQuery:t.useCallback(g=>{try{return T?.query(g)||[]}catch(c){return console.warn(c),c.message="query error: "+c.message,b(c),[]}},[T]),onSchedule:t.useCallback((g,c)=>Y(g),[]),ready:!!T&&!!a}),z=J(({data:{from:g,type:c}})=>{c==="start"&&g!==u&&(q.setStarted(!1),f(void 0))}),V=t.useCallback(async(g=n)=>{if(a&&!C){b(void 0),q.start();return}try{w(!0);const c=await oe.evaluate(g);q.start(),z({type:"start",from:u}),N(()=>c.pattern),o&&(window.location.hash="#"+encodeURIComponent(btoa(n))),k(fe(n)),b(void 0),f(g),w(!1)}catch(c){c.message="evaluation error: "+c.message,console.warn(c),b(c)}},[a,C,n,q,o,u,z]),Y=(g,c)=>{g.length};return{hideHeader:H,hideConsole:_,pending:W,code:n,setCode:m,pattern:T,error:y,cycle:q,setPattern:N,dirty:C,log:r,togglePlay:()=>{q.started?q.stop():V()},setActiveCode:f,activateCode:V,activeCode:a,pushLog:h,hash:R}}function P(...e){return e.filter(Boolean).join(" ")}let F=[],j;function X({view:e,pattern:o,active:s}){t.useEffect(()=>{if(e)if(o&&s){let u=function(){try{const n=p.Tone.getTransport().seconds,a=[Math.max(j||n,n-1/10),n+1/60];j=n+1/60,F=F.filter(r=>r.whole.end>n);const f=o.queryArc(...a).filter(r=>r.hasOnset());F=F.concat(f),e.dispatch({effects:L.of(F)})}catch{e.dispatch({effects:L.of([])})}i=requestAnimationFrame(u)},i=requestAnimationFrame(u);return()=>{cancelAnimationFrame(i)}}else F=[],e.dispatch({effects:L.of([])})},[o,s,e])}const ge="_container_3i85k_1",me="_header_3i85k_5",he="_buttons_3i85k_9",be="_button_3i85k_9",pe="_buttonDisabled_3i85k_17",ve="_error_3i85k_21",ye="_body_3i85k_25";var D={container:ge,header:me,buttons:he,button:be,buttonDisabled:pe,error:ve,body:ye};function I({type:e}){return d.default.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",className:"sc-h-5 sc-w-5",viewBox:"0 0 20 20",fill:"currentColor"},{refresh:d.default.createElement("path",{fillRule:"evenodd",d:"M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z",clipRule:"evenodd"}),play:d.default.createElement("path",{fillRule:"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z",clipRule:"evenodd"}),pause:d.default.createElement("path",{fillRule:"evenodd",d:"M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z",clipRule:"evenodd"})}[e])}function we({tune:e,hideOutsideView:o=!1,init:s,onEvent:i,enableKeyboard:u}){const{code:n,setCode:m,pattern:a,activeCode:f,activateCode:r,evaluateOnly:v,error:y,cycle:b,dirty:W,togglePlay:w,stop:R}=G({tune:e,autolink:!1,onEvent:i});t.useEffect(()=>{s&&v()},[e,s]);const[k,T]=t.useState(),[N,C]=re.useInView({threshold:.01}),h=t.useRef(),S=t.useMemo(()=>((C||!o)&&(h.current=!0),C||h.current),[C,o]);return X({view:k,pattern:a,active:b.started&&!f?.includes("strudel disable-highlighting")}),t.useLayoutEffect(()=>{if(u){const H=async _=>{(_.ctrlKey||_.altKey)&&(_.code==="Enter"?(_.preventDefault(),$(k),await r()):_.code==="Period"&&(b.stop(),_.preventDefault()))};return window.addEventListener("keydown",H,!0),()=>window.removeEventListener("keydown",H,!0)}},[u,a,n,r,b,k]),d.default.createElement("div",{className:D.container,ref:N},d.default.createElement("div",{className:D.header},d.default.createElement("div",{className:D.buttons},d.default.createElement("button",{className:P(D.button,b.started?"sc-animate-pulse":""),onClick:()=>w()},d.default.createElement(I,{type:b.started?"pause":"play"})),d.default.createElement("button",{className:P(W?D.button:D.buttonDisabled),onClick:()=>r()},d.default.createElement(I,{type:"refresh"}))),y&&d.default.createElement("div",{className:D.error},y.message)),d.default.createElement("div",{className:D.body},S&&d.default.createElement(K,{value:n,onChange:m,onViewChanged:T})))}function Me(e){const{ready:o,connected:s,disconnected:i}=e,[u,n]=t.useState(!0),[m,a]=t.useState(M.WebMidi?.outputs||[]);return t.useEffect(()=>{M.enableWebMidi().then(()=>{M.WebMidi.addListener("connected",r=>{a([...M.WebMidi.outputs]),s?.(M.WebMidi,r)}),M.WebMidi.addListener("disconnected",r=>{a([...M.WebMidi.outputs]),i?.(M.WebMidi,r)}),o?.(M.WebMidi),n(!1)}).catch(r=>{if(r){console.error(r),console.warn("Web Midi could not be enabled..");return}})},[o,s,i,m]),{loading:u,outputs:m,outputByName:r=>M.WebMidi.getOutputByName(r)}}exports.CodeMirror=K;exports.MiniRepl=we;exports.cx=P;exports.flash=$;exports.useCycle=Q;exports.useHighlighting=X;exports.usePostMessage=J;exports.useRepl=G;exports.useWebMidi=Me; diff --git a/packages/react/dist/index.es.js b/packages/react/dist/index.es.js index 66d2b2f8..143fe4dd 100644 --- a/packages/react/dist/index.es.js +++ b/packages/react/dist/index.es.js @@ -251,7 +251,7 @@ let s4 = () => { }; const generateHash = (code) => encodeURIComponent(btoa(code)); -function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw: onDrawProp }) { +function useRepl({ tune, autolink = true, onEvent, onDraw: onDrawProp }) { const id = useMemo(() => s4(), []); const [code, setCode] = useState(tune); const [activeCode, setActiveCode] = useState(); @@ -290,7 +290,7 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw: onDrawP pushLog(err.message); // not with setError, because then we would have to setError(undefined) on next playable event } }, - [onEvent, pushLog, defaultSynth], + [onEvent, pushLog], ), onQuery: useCallback( (state) => { @@ -473,10 +473,9 @@ function Icon({ type }) { }[type]); } -function MiniRepl({ tune, defaultSynth, hideOutsideView = false, theme, init, onEvent, enableKeyboard }) { +function MiniRepl({ tune, hideOutsideView = false, init, onEvent, enableKeyboard }) { const { code, setCode, pattern, activeCode, activateCode, evaluateOnly, error, cycle, dirty, togglePlay, stop } = useRepl({ tune, - defaultSynth, autolink: false, onEvent }); diff --git a/packages/react/src/App.jsx b/packages/react/src/App.jsx index 474010b3..61e81f2d 100644 --- a/packages/react/src/App.jsx +++ b/packages/react/src/App.jsx @@ -1,13 +1,9 @@ import React from 'react'; import { MiniRepl } from './components/MiniRepl'; import 'tailwindcss/tailwind.css'; -import { Tone, getDefaultSynth } from '@strudel.cycles/tone'; import { evalScope } from '@strudel.cycles/eval'; -const defaultSynth = getDefaultSynth(); - evalScope( - Tone, import('@strudel.cycles/core'), import('@strudel.cycles/tone'), import('@strudel.cycles/tonal'), @@ -20,7 +16,7 @@ evalScope( function App() { return (
- +
); } diff --git a/packages/react/src/components/MiniRepl.jsx b/packages/react/src/components/MiniRepl.jsx index d4807138..afe804af 100644 --- a/packages/react/src/components/MiniRepl.jsx +++ b/packages/react/src/components/MiniRepl.jsx @@ -9,11 +9,10 @@ import './style.css'; import styles from './MiniRepl.module.css'; import { Icon } from './Icon'; -export function MiniRepl({ tune, defaultSynth, hideOutsideView = false, theme, init, onEvent, enableKeyboard }) { +export function MiniRepl({ tune, hideOutsideView = false, init, onEvent, enableKeyboard }) { const { code, setCode, pattern, activeCode, activateCode, evaluateOnly, error, cycle, dirty, togglePlay, stop } = useRepl({ tune, - defaultSynth, autolink: false, onEvent, }); diff --git a/packages/react/src/hooks/useRepl.mjs b/packages/react/src/hooks/useRepl.mjs index 071b8ce0..6da1b887 100644 --- a/packages/react/src/hooks/useRepl.mjs +++ b/packages/react/src/hooks/useRepl.mjs @@ -17,7 +17,7 @@ let s4 = () => { }; const generateHash = (code) => encodeURIComponent(btoa(code)); -function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw: onDrawProp }) { +function useRepl({ tune, autolink = true, onEvent, onDraw: onDrawProp }) { const id = useMemo(() => s4(), []); const [code, setCode] = useState(tune); const [activeCode, setActiveCode] = useState(); @@ -56,7 +56,7 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw: onDrawP pushLog(err.message); // not with setError, because then we would have to setError(undefined) on next playable event } }, - [onEvent, pushLog, defaultSynth], + [onEvent, pushLog], ), onQuery: useCallback( (state) => { diff --git a/repl/src/App.jsx b/repl/src/App.jsx index 7f308771..a89c7a8f 100644 --- a/repl/src/App.jsx +++ b/repl/src/App.jsx @@ -7,7 +7,7 @@ This program is free software: you can redistribute it and/or modify it under th import controls from '@strudel.cycles/core/controls.mjs'; import { evalScope, evaluate } from '@strudel.cycles/eval'; import { CodeMirror, cx, flash, useHighlighting, useRepl, useWebMidi } from '@strudel.cycles/react'; -import { getDefaultSynth, cleanupDraw, cleanupUi, Tone } from '@strudel.cycles/tone'; +import { cleanupDraw, cleanupUi, Tone } from '@strudel.cycles/tone'; import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'; import './App.css'; import logo from './logo.svg'; @@ -80,7 +80,6 @@ function getRandomTune() { } const randomTune = getRandomTune(); -const defaultSynth = getDefaultSynth(); const isEmbedded = window.location !== window.parent.location; function App() { // const [editor, setEditor] = useState(); @@ -105,7 +104,6 @@ function App() { hideConsole, } = useRepl({ tune: '// LOADING...', - defaultSynth, }); useEffect(() => { initCode().then((decoded) => setCode(decoded || randomTune)); diff --git a/repl/src/static.mjs b/repl/src/static.mjs index db3de4f1..f0746477 100644 --- a/repl/src/static.mjs +++ b/repl/src/static.mjs @@ -6,11 +6,8 @@ This program is free software: you can redistribute it and/or modify it under th import { Tone } from '@strudel.cycles/tone'; import { State, TimeSpan } from '@strudel.cycles/core'; -import { getPlayableNoteValue } from '@strudel.cycles/core/util.mjs'; import { evaluate } from '@strudel.cycles/eval'; -import { getDefaultSynth } from '@strudel.cycles/tone'; - -const defaultSynth = getDefaultSynth(); +import { webaudioOutputTrigger } from '@strudel.cycles/webaudio'; // this is a test to play back events with as less runtime code as possible.. // the code asks for the number of seconds to prequery @@ -47,17 +44,8 @@ async function playStatic(code) { events.forEach((event) => { Tone.getTransport().schedule((time) => { try { - const { onTrigger, velocity } = event.context; - if (!onTrigger) { - if (defaultSynth) { - const note = getPlayableNoteValue(event); - defaultSynth.triggerAttackRelease(note, event.duration.valueOf(), time, velocity); - } else { - throw new Error('no defaultSynth passed to useRepl.'); - } - } else { - onTrigger(time, event); - } + const { onTrigger = webaudioOutputTrigger } = event.context; + onTrigger(time, event); } catch (err) { console.warn(err); err.message = 'unplayable event: ' + err?.message; diff --git a/tutorial/MiniRepl.jsx b/tutorial/MiniRepl.jsx index 295e2b99..840e6077 100644 --- a/tutorial/MiniRepl.jsx +++ b/tutorial/MiniRepl.jsx @@ -1,23 +1,14 @@ -import { Tone } from '@strudel.cycles/tone'; import { evalScope } from '@strudel.cycles/eval'; import { MiniRepl as _MiniRepl } from '@strudel.cycles/react'; import controls from '@strudel.cycles/core/controls.mjs'; import { samples } from '@strudel.cycles/webaudio'; - -export const defaultSynth = new Tone.PolySynth().chain(new Tone.Gain(0.5), Tone.Destination).set({ - oscillator: { type: 'triangle' }, - envelope: { - release: 0.01, - }, -}); +import { prebake } from '../repl/src/prebake.mjs'; fetch('https://strudel.tidalcycles.org/EmuSP12.json') .then((res) => res.json()) .then((json) => samples(json, 'https://strudel.tidalcycles.org/EmuSP12/')); - evalScope( - Tone, controls, import('@strudel.cycles/core'), import('@strudel.cycles/tone'), @@ -29,6 +20,8 @@ evalScope( import('@strudel.cycles/osc'), ); +prebake(); + export function MiniRepl({ tune }) { - return <_MiniRepl tune={tune} defaultSynth={defaultSynth} hideOutsideView={true} />; + return <_MiniRepl tune={tune} hideOutsideView={true} />; }