···11-{
22- "name": "diffuse/engine/audio",
33- "title": "Diffuse Audio",
44- "entrypoint": "index.html",
55- "actions": {
66- "pause": {
77- "title": "Pause",
88- "description": "Pause audio",
99- "params_schema": {
1010- "type": "object",
1111- "properties": {
1212- "audioId": {
1313- "type": "string"
1414- }
1515- },
1616- "required": ["audioId"]
1717- }
1818- },
1919- "play": {
2020- "title": "Play",
2121- "description": "Play audio",
2222- "params_schema": {
2323- "type": "object",
2424- "properties": {
2525- "audioId": {
2626- "type": "string"
2727- },
2828- "volume": {
2929- "type": "number",
3030- "default": 0.5
3131- }
3232- },
3333- "required": ["audioId"]
3434- }
3535- },
3636- "render": {
3737- "title": "Render",
3838- "description": "Determine the active set of audio elements.",
3939- "params_schema": {
4040- "type": "object",
4141- "properties": {
4242- "audio": {
4343- "type": "array",
4444- "description": "The audio items we want to render. These represent the audio elements that are in the DOM.",
4545- "items": {
4646- "type": "object",
4747- "properties": {
4848- "id": { "type": "string" },
4949- "isPreload": { "type": "boolean" },
5050- "mimeType": { "type": "string" },
5151- "progress": { "type": "number" },
5252- "url": { "type": "string" }
5353- },
5454- "required": ["id", "url"]
5555- }
5656- },
5757- "play": {
5858- "type": "object",
5959- "description": "Pass in this object to immediately start playing one of the rendered audio items.",
6060- "properties": {
6161- "audioId": {
6262- "type": "string",
6363- "description": "The id of the rendered audio item we want to play."
6464- },
6565- "volume": {
6666- "type": "number",
6767- "default": 0.5,
6868- "description": "A number equal to, or between, 0 and 1, that determines how loud the audio should play."
6969- }
7070- },
7171- "required": ["audioId"]
7272- }
7373- },
7474- "required": ["audio"]
7575- }
7676- },
7777- "reload": {
7878- "title": "Reload",
7979- "description": "Make sure the audio with the given id is loading properly. This should be used when for example, the internet connection comes back and the loading of the audio depended on said internet connection.",
8080- "params_schema": {
8181- "type": "object",
8282- "properties": {
8383- "audioId": {
8484- "type": "string"
8585- },
8686- "play": {
8787- "type": "boolean"
8888- },
8989- "progress": {
9090- "type": "number"
9191- }
9292- },
9393- "required": ["audioId", "percentage"]
9494- }
9595- },
9696- "seek": {
9797- "title": "Seek",
9898- "description": "Seek audio to a given position",
9999- "params_schema": {
100100- "type": "object",
101101- "properties": {
102102- "audioId": {
103103- "type": "string"
104104- },
105105- "percentage": {
106106- "type": "number",
107107- "description": "A number between 0 and 1 that determines the new current position in the audio"
108108- }
109109- },
110110- "required": ["audioId", "percentage"]
111111- }
112112- },
113113- "volume": {
114114- "title": "Volume",
115115- "description": "Set the volume of all audio and the default value, or a specific audio node.",
116116- "params_schema": {
117117- "type": "object",
118118- "properties": {
119119- "audioId": {
120120- "type": "string"
121121- },
122122- "volume": {
123123- "type": "number",
124124- "description": "A number between 0 and 1 that determines the new volume of all audio elements"
125125- }
126126- },
127127- "required": ["volume"]
128128- }
129129- }
130130- }
131131-}
-9
_backup/pages/engine/audio/index.astro
···11----
22-import Layout from "@layouts/applet.astro";
33-import Applet from "./_applet.astro";
44-import { title } from "./_manifest.json";
55----
66-77-<Layout title={title}>
88- <Applet />
99-</Layout>
-59
_backup/pages/engine/queue/_applet.astro
···11-<script>
22- import type { Tasks } from "@scripts/engine/queue/worker";
33- import type { Track } from "@applets/core/types";
44- import type { State } from "./types.d.ts";
55-66- import { register } from "@scripts/applet/common";
77- import { endpoint, SharedWorker, sync, transfer } from "@scripts/common";
88- import manifest from "./_manifest.json";
99-1010- ////////////////////////////////////////////
1111- // SETUP
1212- ////////////////////////////////////////////
1313- const port = new SharedWorker(new URL("../../../scripts/engine/queue/worker", import.meta.url), {
1414- type: "module",
1515- name: manifest.name,
1616- }).port;
1717-1818- const worker = endpoint<Tasks>(port);
1919-2020- // Register applet
2121- const context = register<State>({ mode: "shared-worker", worker });
2222- const groupId = context.groupId || "main";
2323-2424- // Initial state
2525- context.data = {
2626- future: [],
2727- now: null,
2828- past: [],
2929- };
3030-3131- context.data = await worker.data(groupId);
3232-3333- // Keep applet data with worker data in sync
3434- sync(context, port, { groupId });
3535-3636- ////////////////////////////////////////////
3737- // ACTIONS
3838- ////////////////////////////////////////////
3939- context.setActionHandler("add", add);
4040- context.setActionHandler("pool", pool);
4141- context.setActionHandler("shift", shift);
4242- context.setActionHandler("unshift", unshift);
4343-4444- async function add(items: Track[]) {
4545- await worker.add({ groupId, items });
4646- }
4747-4848- async function pool(tracks: Track[]) {
4949- await worker.pool({ groupId, tracks });
5050- }
5151-5252- async function shift() {
5353- await worker.shift({ groupId });
5454- }
5555-5656- async function unshift() {
5757- await worker.unshift({ groupId });
5858- }
5959-</script>
-47
_backup/pages/engine/queue/_manifest.json
···11-{
22- "name": "diffuse/engine/queue",
33- "title": "Diffuse Queue",
44- "entrypoint": "index.html",
55- "actions": {
66- "add": {
77- "title": "Add",
88- "description": "Add tracks to the queue.",
99- "params_schema": {
1010- "type": "array",
1111- "description": "Array of tracks",
1212- "items": {
1313- "type": "object",
1414- "properties": {
1515- "id": { "type": "string" },
1616- "uri": { "type": "string" }
1717- },
1818- "required": ["id", "uri"]
1919- }
2020- }
2121- },
2222- "pool": {
2323- "title": "Pool",
2424- "description": "Set the queue pool.",
2525- "params_schema": {
2626- "type": "array",
2727- "description": "Array of tracks",
2828- "items": {
2929- "type": "object",
3030- "properties": {
3131- "id": { "type": "string" },
3232- "uri": { "type": "string" }
3333- },
3434- "required": ["id", "uri"]
3535- }
3636- }
3737- },
3838- "shift": {
3939- "title": "Shift",
4040- "description": "Shift the queue, picking the first item from the up next array and putting the currently playing item into the history list."
4141- },
4242- "unshift": {
4343- "title": "Unshift",
4444- "description": "Unshift the queue, going backwards in time, picking the last item from the history array and putting the currently playing item into the up next list."
4545- }
4646- }
4747-}
-9
_backup/pages/engine/queue/index.astro
···11----
22-import Layout from "@layouts/applet.astro";
33-import Applet from "./_applet.astro";
44-import { title } from "./_manifest.json";
55----
66-77-<Layout title={title}>
88- <Applet />
99-</Layout>
-1
_backup/pages/engine/queue/types.d.ts
···11-export * from "@scripts/engine/queue/types.d.ts";
-265
_backup/pages/index.astro
···11----
22-import Applet from "../components/Applet.astro";
33-import List from "../components/List.astro";
44-import Page from "../layouts/page.astro";
55-66-import "../styles/page/index.css";
77-88-// Types
99-type Ref = {
1010- url: string;
1111- title: string;
1212-};
1313-1414-// Links
1515-const WEB_APPLETS_HREF = "https://unternet.co/docs/web-applets/introduction";
1616-1717-// Themes
1818-const themes = [
1919- { url: "theme/blur/", title: "(WIP) Blur" },
2020- { url: "theme/pilot/", title: "(WIP) Pilot" },
2121- { url: "theme/webamp/", title: "Webamp" },
2222-];
2323-2424-// Abstractions
2525-// TODO
2626-2727-// Constituents
2828-const constituents = [
2929- { url: "constituent/blur/artwork-controller/", title: "Blur ⦚ Artwork Controller" },
3030- { url: "constituent/blur/browser/", title: "(WIP) Blur ⦚ Browser" },
3131-];
3232-3333-// Applets
3434-const configurators = [
3535- { url: "configurator/input/", title: "Input" },
3636- { url: "configurator/output/", title: "Output" },
3737-];
3838-3939-const engines = [
4040- { url: "engine/audio/", title: "Audio" },
4141- { url: "engine/queue/", title: "Queue" },
4242-];
4343-4444-const input = [
4545- { url: "input/native-fs/", title: "Native File System" },
4646- { url: "input/opensubsonic/", title: "Opensubsonic" },
4747- { url: "input/s3/", title: "S3-Compatible API" },
4848-];
4949-5050-const orchestrators = [
5151- { url: "orchestrator/queue-audio/", title: "Queue ⭤ Audio" },
5252- { url: "orchestrator/queue-tracks/", title: "Queue ⭤ Tracks" },
5353- { url: "orchestrator/process-tracks/", title: "Process inputs into tracks" },
5454-];
5555-5656-const output = [
5757- { url: "output/indexed-db/", title: "IndexedDB" },
5858- { url: "output/native-fs/", title: "Native File System" },
5959- { url: "output/storacha-automerge/", title: "(WIP) Storacha Storage + Automerge CRDT" },
6060- { url: "output/todo/", title: "(TODO) Keyhive/Beelay" },
6161- { url: "output/todo/", title: "(TODO) Dialog DB" },
6262-];
6363-6464-const processors = [
6565- { url: "processor/artwork/", title: "Artwork retrieval" },
6666- { url: "processor/metadata/", title: "Metadata retrieval" },
6767- { url: "processor/search/", title: "Search" },
6868-];
6969-7070-// Demos
7171-const demos = [{ url: "demo/s3-tracks/", title: "Add sample S3 music" }];
7272----
7373-7474-<Page title="Diffuse">
7575- <header>
7676- <h1>
7777- <svg viewBox="0 0 902 134" width="160">
7878- <title>Diffuse</title>
7979- <use
8080- xlink:href="/images/diffuse-current.svg#diffuse"
8181- href="/images/diffuse-current.svg#diffuse"></use>
8282- </svg>
8383- </h1>
8484- <p>
8585- Diffuse is a collection of <a href={WEB_APPLETS_HREF}>web applets</a> that make it possible to
8686- listen to audio from various sources on your devices and the web, and to create the ideal digital
8787- listening experience for you.
8888- </p>
8989- <p>These applets can be used in various ways. The main ways so far are through:</p>
9090- <ul>
9191- <li><a href="#themes">Themes</a>, a traditional browser (web application) approach.</li>
9292- <li><a href="#abstractions">Abstractions</a>, for non-browser systems.</li>
9393- <li>
9494- Using <a href="#constituents">various parts</a> of themes and abstractions separately in different
9595- browser tabs.
9696- </li>
9797- </ul>
9898- <p>
9999- <strong>⚠️ Heavily experimental</strong>
100100- </p>
101101- </header>
102102- <main>
103103- <div class="columns">
104104- <!-- THEMES -->
105105- <section>
106106- <h2 id="themes">Themes</h2>
107107-108108- <p>
109109- Themes are “applet compositions” and provide a traditional browser web application way of
110110- using them. Each theme is unique, not just a skin (eg. not like winamp skins).
111111- </p>
112112-113113- <p>
114114- For example, most themes here will limit the currently playing audio tracks to one item,
115115- but you might as well create a DJ theme that can play multiple items at the same time.
116116- </p>
117117-118118- <List items={themes} />
119119- </section>
120120-121121- <!-- ABSTRACTIONS -->
122122- <section>
123123- <h2 id="abstractions">Abstractions</h2>
124124-125125- <p>
126126- These are applet configurations that enable certain use cases outside the traditional web
127127- app experience. Just like themes, these include various assumptions of how certain parts
128128- of the system should interact.
129129- </p>
130130-131131- <p><em>TODO: Enable intelligent user (ai) agent use-case.</em></p>
132132-133133- <List items={[]} />
134134- </section>
135135- </div>
136136-137137- <!-- CONSTITUENTS -->
138138- <section>
139139- <h2 id="constituents">Constituents</h2>
140140-141141- <p>
142142- Constituents are UI applets that are used in themes and abstractions. These are organised
143143- per theme or abstraction, but that doesn't mean they are restricted to that theme or
144144- abstraction, you can mix and match as you like. You can even use them on their own.
145145- </p>
146146-147147- <p>
148148- Some themes may be constructed out of various applets that are not listed here. The reason
149149- for that is those applets cannot be used solely on their own, they require an external
150150- context to coordinate them.
151151- </p>
152152-153153- <p>
154154- There's tradeoffs to both approaches. A particular tradeoff to keep in mind for constituents
155155- is that they'll have nested dependencies. So when overriding applets dependencies, the
156156- overrides need to be passed down the tree.
157157- </p>
158158-159159- <List items={constituents} />
160160- </section>
161161-162162- <!-- APPLETS -->
163163- <section>
164164- <h2 id="applets">Applets</h2>
165165-166166- <p>
167167- Applets are <a href={WEB_APPLETS_HREF}>web applets</a>, the components of the system. These
168168- are then recombined into an entire music player experience, or whatever you want to build.
169169- </p>
170170-171171- <div class="columns">
172172- <Applet title="Configurators" list={configurators}>
173173- Applets that serve as an intermediate in order to make a particular kind of applet
174174- configurable. In other words, these allow for an applet to be swapped out with another
175175- that takes the same, or a subset of the actions and data output.
176176- </Applet>
177177-178178- <Applet title="Engines" list={engines}>
179179- Applets with each a singular purpose and don't have any UI. There are specialised UI and
180180- orchestrators applets that control these.
181181- </Applet>
182182-183183- <Applet title="Input" list={input}>
184184- Inputs are sources of audio tracks. Each track is an entry in the list of possible items
185185- to play. These can be files or streams, static or dynamic.
186186- </Applet>
187187-188188- <Applet title="Orchestrators" list={orchestrators}>
189189- These too are applet compositions. However, unlike themes, these are purely logical.
190190- Mostly exist in order to construct sensible defaults to use across themes and
191191- abstractions.
192192- </Applet>
193193-194194- <Applet title="Output" list={output}>
195195- Output is application-derived data such as playlists. These applets can receive such data
196196- and keep it around.
197197- </Applet>
198198-199199- <Applet title="Processors" list={processors}>
200200- These applets work with the tracks generated by the input applets to add more data to
201201- them, or process them in some other way.
202202- </Applet>
203203-204204- <Applet title="Supplements" list={[]}>Additional applets, such as scrobblers.</Applet>
205205- </div>
206206- </section>
207207-208208- <!-- DEMOS -->
209209- <section>
210210- <h2 id="demos">Demos</h2>
211211-212212- <p>Just some utility web pages to help demo the system.</p>
213213-214214- <List items={demos} />
215215- </section>
216216-217217- <!-- CROSS-ORIGIN -->
218218- <section>
219219- <h2 id="cross-origin">Cross-Origin</h2>
220220-221221- <p>
222222- You can use applets from different origins. However, one important caveat to remember is <a
223223- href="https://developer.mozilla.org/en-US/docs/Web/Privacy/Guides/State_Partitioning#state_partitioning"
224224- >state partitioning</a
225225- >. This causes local state (eg. IndexedDB) to be different when the applet is used on a
226226- different domain versus using the applet directly. There might be ways around state
227227- partitioning, but I haven't found a user-friendly way of doing so.
228228- </p>
229229-230230- <p>
231231- <strong
232232- >That said, there isn't that much local state that needs to be shared cross origin.</strong
233233- > Much of it is associated with the input applets and that configuration is saved in your chosen
234234- output applet. So essentially, state partitioning behaves as if the two domains are on different
235235- devices; so using an output applet to sync data between devices works nicely. It does mean you
236236- have to somehow configure the same output applet in both contexts.
237237- </p>
238238- </section>
239239-240240- <!-- BUILD YOUR OWN -->
241241- <section>
242242- <h2 id="yours">Build your own</h2>
243243-244244- <p>
245245- Ideally you'd be able to mix and match these applets to build your own music player. There
246246- are still a few todos and unknowns here:
247247- </p>
248248-249249- <ul>
250250- <li>
251251- This is currently using a fork of the web applets SDK that adds a few features (waiting on
252252- PRs). Meaning that it won't be as easy to write your own applets in the same way as done
253253- here.
254254- </li>
255255- <li>
256256- I wrote some custom code on top of the web applets SDK that makes the applets talk to each
257257- other over a broadcast channel. This should ideally become a JS library or added to the
258258- web applets SDK. Though you can just copy-paste from the Diffuse repo if you want (it's
259259- not that much code).
260260- </li>
261261- <li><em>... Probably a bunch of stuff I'm forgetting, teaching materials, etc ...</em></li>
262262- </ul>
263263- </section>
264264- </main>
265265-</Page>
···11+---
22+layout: layouts/diffuse.vto
33+44+engines:
55+ - url: "engine/audio/"
66+ title: "Audio"
77+ - url: "engine/queue/"
88+ title: "Queue"
99+1010+---
1111+<link rel="stylesheet" href="./styles/page/index.css" />
1212+1313+<header>
1414+ <h1>
1515+ <svg viewBox="0 0 902 134" width="160">
1616+ <title>Diffuse</title>
1717+ <use
1818+ xlink:href="/images/diffuse-current.svg#diffuse"
1919+ href="/images/diffuse-current.svg#diffuse"></use>
2020+ </svg>
2121+ </h1>
2222+ <p>
2323+ Diffuse is a collection of custom elements that make it possible to
2424+ listen to audio from various sources on your devices and the web, and to create the ideal digital
2525+ listening experience for you.
2626+ </p>
2727+ <p>
2828+ <strong>⚠️ Heavily experimental</strong>
2929+ </p>
3030+</header>
3131+<main>
3232+ <div class="columns">
3333+ <!-- THEMES -->
3434+ <section>
3535+ <h2 id="themes">Themes</h2>
3636+3737+ <p>
3838+ Themes are compositions and provide a traditional browser web application way of
3939+ using them. Each theme is unique, not just a skin (ie. not like winamp skins).
4040+ </p>
4141+4242+ <p>
4343+ For example, most themes here will limit the currently playing audio tracks to one item,
4444+ but you might as well create a DJ theme that can play multiple items at the same time.
4545+ </p>
4646+ </section>
4747+4848+ <!-- ABSTRACTIONS -->
4949+ <!--<section></section>-->
5050+ </div>
5151+5252+ <!-- CONSTITUENTS -->
5353+ <!--<section></section>-->
5454+5555+ <!-- ELEMENTS -->
5656+ <section>
5757+ <h2 id="elements">Elements</h2>
5858+5959+ <p>
6060+ The (web) components of the system. These
6161+ are then recombined into an entire music player experience, or whatever you want to build.
6262+ </p>
6363+6464+ <div class="columns">
6565+ {{ await comp.element({
6666+ title: "Engines",
6767+ items: engines,
6868+ content: `
6969+ Elements with each a singular purpose and don't have any UI. There are specialised UI and
7070+ orchestrator elements that control these.
7171+ `
7272+ }) }}
7373+7474+ <!--<Applet title="Configurators" list={configurators}>
7575+ Applets that serve as an intermediate in order to make a particular kind of applet
7676+ configurable. In other words, these allow for an applet to be swapped out with another
7777+ that takes the same, or a subset of the actions and data output.
7878+ </Applet>
7979+8080+ <Applet title="Input" list={input}>
8181+ Inputs are sources of audio tracks. Each track is an entry in the list of possible items
8282+ to play. These can be files or streams, static or dynamic.
8383+ </Applet>
8484+8585+ <Applet title="Orchestrators" list={orchestrators}>
8686+ These too are applet compositions. However, unlike themes, these are purely logical.
8787+ Mostly exist in order to construct sensible defaults to use across themes and
8888+ abstractions.
8989+ </Applet>
9090+9191+ <Applet title="Output" list={output}>
9292+ Output is application-derived data such as playlists. These applets can receive such data
9393+ and keep it around.
9494+ </Applet>
9595+9696+ <Applet title="Processors" list={processors}>
9797+ These applets work with the tracks generated by the input applets to add more data to
9898+ them, or process them in some other way.
9999+ </Applet>
100100+101101+ <Applet title="Supplements" list={[]}>Additional applets, such as scrobblers.</Applet>-->
102102+ </div>
103103+ </section>
104104+105105+ <!-- DEMOS -->
106106+ <!--<section>
107107+ <h2 id="demos">Demos</h2>
108108+109109+ <p>Just some utility web pages to help demo the system.</p>
110110+111111+ <List items={demos} />
112112+ </section>-->
113113+114114+ <!-- BUILD YOUR OWN -->
115115+ <!--<section></section>-->
116116+</main>