Skip to content

Commit

Permalink
add learn page
Browse files Browse the repository at this point in the history
  • Loading branch information
felixroos committed Jun 27, 2024
1 parent 4e2b516 commit ac9824d
Show file tree
Hide file tree
Showing 11 changed files with 458 additions and 31 deletions.
5 changes: 4 additions & 1 deletion packages/core/src/repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { AudioView } from "./audioview.js";
import * as api from "./node.js";

export class SalatRepl {
constructor() {
constructor({ onToggle } = {}) {
this.audio = new AudioView();
this.onToggle = onToggle;
Object.assign(globalThis, api);
}
evaluate(code) {
Expand All @@ -14,8 +15,10 @@ export class SalatRepl {
await this.audio.init();
}
this.audio.updateGraph(node);
this.onToggle?.(true);
}
stop() {
this.audio.stop();
this.onToggle?.(false);
}
}
17 changes: 16 additions & 1 deletion packages/graphviz/src/graphviz.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import { Graphviz } from "@hpcc-js/wasm";
const graphvizLoaded = Graphviz.load();

Node.prototype.render = async function (container, options = {}) {
const { dagify = false, resolveModules = false } = options;
const {
dagify = false,
resolveModules = false,
rankdir = "TB",
size = 0,
} = options;
let node = this;
resolveModules && node.resolveModules();
if (dagify) {
Expand All @@ -18,12 +23,16 @@ Node.prototype.render = async function (container, options = {}) {
let edges = [];
const color = "teal";
const fontcolor = "teal";
const fontsize = 10;
const fontname = "monospace";

for (let id in nodes) {
nodes[id].ins.forEach((parent, i) => {
edges.push({
source: parent,
target: id,
fontsize,
fontname,
color,
fontcolor,
directed: true,
Expand All @@ -37,8 +46,12 @@ Node.prototype.render = async function (container, options = {}) {
id,
color,
fontcolor,
fontsize,
fontname,
label: node.value ?? node.type,
ordering: "in",
width: 0.5,
height: 0.4,
}));

const graphviz = await graphvizLoaded;
Expand All @@ -50,6 +63,8 @@ Node.prototype.render = async function (container, options = {}) {
},
});
dot = dot.split("\n");
dot.splice(1, 0, `rankdir="${rankdir}"`);
size && dot.splice(1, 0, `size="${size}"`);
dot.splice(1, 0, 'bgcolor="transparent"');
dot.splice(1, 0, 'color="white"');
dot = dot.join("\n");
Expand Down
41 changes: 41 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
"dependencies": {
"@astrojs/solid-js": "^4.4.0",
"@astrojs/tailwind": "^5.1.0",
"@kabelsalat/core": "workspace:*",
"@kabelsalat/graphviz": "workspace:*",
"astro": "^4.11.3",
"solid-js": "^1.8.17",
"tailwindcss": "^3.4.4",
"@kabelsalat/core": "workspace:*",
"@kabelsalat/graphviz": "workspace:*"
"tailwindcss": "^3.4.4"
},
"devDependencies": {
"@tailwindcss/typography": "^0.5.13"
}
}
3 changes: 3 additions & 0 deletions website/src/components/Box.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="py-1 px-6 pr-10 bg-stone-800 relative mb-4">
<div><slot /></div>
</div>
50 changes: 50 additions & 0 deletions website/src/components/Icon.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
export function Icon({ type }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5 inline"
view-box="0 0 20 20"
fill="currentColor"
>
{
{
refresh: (
<path
fill-rule="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"
clip-rule="evenodd"
/>
),
play: (
<path
fill-rule="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"
clip-rule="evenodd"
/>
),
pause: (
<path
fill-rule="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"
clip-rule="evenodd"
/>
),
stop: (
<path
fill-rule="evenodd"
d="M2 10a8 8 0 1116 0 8 8 0 01-16 0zm5-2.25A.75.75 0 017.75 7h4.5a.75.75 0 01.75.75v4.5a.75.75 0 01-.75.75h-4.5a.75.75 0 01-.75-.75v-4.5z"
clip-rule="evenodd"
/>
),
skip: (
<path
fill-rule="evenodd"
d="M52.5 440.6c-9.5 7.9-22.8 9.7-34.1 4.4S0 428.4 0 416V96C0 83.6 7.2 72.3 18.4 67s24.5-3.6 34.1 4.4l192 160L256 241V96c0-17.7 14.3-32 32-32s32 14.3 32 32V416c0 17.7-14.3 32-32 32s-32-14.3-32-32V271l-11.5 9.6-192 160z"
clip-rule="evenodd"
/>
),
}[type]
}
</svg>
);
}
69 changes: 69 additions & 0 deletions website/src/components/MiniRepl.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { createSignal } from "solid-js";
import "@kabelsalat/graphviz";
import { SalatRepl } from "@kabelsalat/core";
import { Icon } from "./Icon";

let vizSettings = {
resolveModules: false,
dagify: false,
rankdir: "LR",
size: 12,
};

export function MiniRepl(props) {
const initialCode = props.code;
let [code, setCode] = createSignal(initialCode);
let [started, setStarted] = createSignal(false);
const repl = new SalatRepl({ onToggle: (_started) => setStarted(_started) });
let container;
async function run() {
const node = repl.evaluate(code());
node.render(container, vizSettings); // update viz
repl.play(node);
}
let handleKeydown = (e) => {
// console.log("key", e.code);
if (e.key === "Enter" && (e.ctrlKey || e.altKey)) {
run();
} else if (e.code === "Period" && (e.ctrlKey || e.altKey)) {
repl.stop();
e.preventDefault();
}
};

return (
<div class="flex flex-col overflow-hidden rounded-md my-4 border border-teal-500 text-teal-600 font-mono">
<div class="flex bg-teal-600 text-white">
<button
class="w-14 hover:bg-teal-700 flex justify-center p-1 border-r border-teal-500 "
onClick={() => (started() ? repl.stop() : run())}
>
{!started() ? <Icon type="play" /> : <Icon type="stop" />}
</button>
<button
class="w-14 hover:bg-teal-700 flex justify-center py-1"
onClick={() => run()}
>
<Icon type="refresh" />
</button>
</div>
<div class="flex border-b border-teal-500 overflow-hidden">
<textarea
rows={Math.min(code().split("\n").length, 10)}
class="bg-stone-900 shrink-0 p-4 focus:ring-0 outline-0 grow"
spellcheck="false"
value={code()}
onInput={(e) => setCode(e.target.value)}
onKeyDown={handleKeydown}
></textarea>
</div>
<div
class={`bg-stone-900 overflow-auto text-gray-500 p-4 grow-0 text-center max-h-[400px]`}
ref={(el) => {
container = el;
repl.evaluate(code()).render(container, vizSettings);
}}
></div>
</div>
);
}
24 changes: 6 additions & 18 deletions website/src/components/Repl.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export function Repl() {
let [hideCode, setHideCode] = createSignal(false);
let container;
async function run() {
setInited(true);
const node = repl.evaluate(code());
node.render(container, vizSettings); // update viz
window.location.hash = "#" + btoa(code());
Expand Down Expand Up @@ -84,18 +85,18 @@ export function Repl() {
return (
<div
class="flex flex-col h-full max-h-full justify-stretch text-teal-600 font-mono"
onClick={() => {
!inited() && run();
setInited(true);
onClick={(e) => {
e.target.tagName !== "A" && !inited() && run();
}}
>
<div class="px-4 py-2 space-x-8 font-bold border-b border-teal-500 flex">
<div class="px-4 py-2 space-x-8 font-bold border-b border-teal-500 flex justify-between">
<marquee class="text-teal-100 w-32">
KABƎL.SALAT.KABƎL.SALAT.KABƎL.SALAT.KABƎL.SALAT.KABƎL.SALAT
</marquee>
<div class="text-yellow-400">
{!inited() && "click somewhere to play"}
</div>
<a href="/kabelsalat/learn">learn more</a>
</div>
<div class="grid grid-cols-2 flex-auto shrink grow overflow-hidden">
{!hideCode() && (
Expand Down Expand Up @@ -126,20 +127,7 @@ export function Repl() {
welcome to kabelsalat. this is a very experimental audio graph live
coding prototype.
</p>
<pre>keyboard: ctrl+enter: start, ctrl+dot: stop</pre>
<code>
utility functions:{" "}
{`n(number) .mul(n) .add(n) .range(min,max) .apply(fn)`}
</code>
<br />
<code>
audio functions:{" "}
{`adsr(gate, att, dec, sus, rel) clock(bpm) clockdiv(clock, divisor) distort(in, amt) noise() pulse(freq, pw) saw(freq) sine(freq, sync) tri(freq) slide(in, rate) filter(in, cutoff, reso) fold(in, rate) seq(clock, ...steps) delay(in, time) hold(in, trig)`}
</code>
{/* clockout(clock) */}
{/* midiin() */}
{/* monoseq(clock, gateT) */}
{/* gateseq(clock, gateT) */}
<pre>keyboard: ctrl+enter: run, ctrl+dot: stop</pre>
<pre></pre>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions website/src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import { Repl } from "../components/Repl";
---

<html lang="en" class="h-full bg-stone-800">
<html lang="en" class="h-full bg-stone-900">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/png" href="/favicon.png" />
<link rel="icon" type="image/png" href="/kabelsalat/favicon.png" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>kabelsalat</title>
Expand Down
Loading

0 comments on commit ac9824d

Please sign in to comment.