Experiment to rebuild Diffuse using web applets.
1import Webamp from "webamp";
2import { URLTrack } from "webamp";
3
4import type { Output, Track } from "@applets/core/types.d.ts";
5import { applet, waitUntilAppletIsReady } from "../../theme.ts";
6
7////////////////////////////////////////////
8// 🎨 Styles
9////////////////////////////////////////////
10import "@styles/themes/webamp/index.css";
11
12////////////////////////////////////////////
13// 🗂️ Applets
14////////////////////////////////////////////
15
16const configurator = {
17 input: await applet("../../configurator/input"),
18};
19
20const orchestrator = {
21 output: await applet<Output>("../../orchestrator/output-management"),
22
23 // TODO: Should this be explicitely be ran after the output orchestrator is loaded?
24 input: await applet("../../orchestrator/input-cache"),
25};
26
27////////////////////////////////////////////
28// ⚡
29////////////////////////////////////////////
30const amp = new Webamp({
31 initialTracks: [],
32});
33
34const ampNode = document.createElement("div");
35ampNode.style = "height: 100vh; left: 0; position: absolute; top: 0; width: 100%; z-index: -1000;";
36document.body.appendChild(ampNode);
37amp.renderWhenReady(ampNode);
38
39orchestrator.output.ondata = async () => {
40 const tracks = await loadTracks();
41 amp.setTracksToPlay([]);
42 amp.appendTracks(tracks);
43 amp.nextTrack();
44};
45
46////////////////////////////////////////////
47// 🛠️
48////////////////////////////////////////////
49async function loadTracks(): Promise<URLTrack[]> {
50 return await orchestrator.output.data.tracks.reduce(
51 async (promise: Promise<URLTrack[]>, track: Track) => {
52 const acc = await promise;
53
54 // TODO: Ideally the URL should only be resolved when needed,
55 // but webamp doesn't allow for that.
56 // Maybe you could work around it with a service worker.
57 const url = await configurator.input.sendAction<string | undefined>(
58 "resolve",
59 { method: "GET", uri: track.uri },
60 {
61 timeoutDuration: 60000,
62 },
63 );
64
65 if (!url) return acc;
66
67 const urlTrack: URLTrack = {
68 url,
69 metaData: {
70 title: track.tags?.title || "",
71 artist: track.tags?.artist || "",
72 album: track.tags?.album,
73 },
74 duration: track.stats?.duration,
75 };
76
77 return [...acc, urlTrack];
78 },
79 Promise.resolve([]),
80 );
81}