Something went wrong. Try again.
Experiment to rebuild Diffuse using web applets.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118import type { URLTrack } from "webamp";import Webamp from "webamp";
import type { GroupConsult, ManagedOutput, ResolvedUri, Track } from "@applets/core/types.d.ts";import { applet, inputUrl, wait } from "@scripts/applet/common";
////////////////////////////////////////////// 🗂️ Applets////////////////////////////////////////////const configurator = { input: applet("/configurator/input"), output: applet<ManagedOutput>("/configurator/output"),};
const orchestrator = { queueAudio: applet("/orchestrator/queue-audio"), queueTracks: applet("/orchestrator/queue-tracks"), processTracks: applet("/orchestrator/process-tracks"),};
////////////////////////////////////////////// ⚡////////////////////////////////////////////const amp = new Webamp({ initialTracks: [],});
// Overrideconst loadFromUrl = amp.media.loadFromUrl.bind(amp.media);
async function loadOverride(uri: string, autoPlay: boolean) { const resp = await inputUrl(await configurator.input, uri); if (!resp) throw new Error("Failed to resolve URI"); return await loadFromUrl(resp.url, autoPlay);}
amp.media.loadFromUrl = loadOverride.bind(amp.media);
// Renderconst ampNode = document.createElement("div");ampNode.style = "height: 100vh; left: 0; position: absolute; top: 0; width: 100%; z-index: -1000;";document.body.appendChild(ampNode);amp.renderWhenReady(ampNode);
// Wait for tracks to loadconfigurator.output .then((output) => { output.ondata = loadAndInsert; return wait(output, (d) => d?.tracks.state === "loaded"); }) .then(async () => { await loadAndInsert(); });
// Load & insertlet inserting = false;let tracksCacheId: string | undefined = undefined;
async function loadAndInsert() { const output = await configurator.output;
if (output.data.tracks.state !== "loaded") return; if (output.data.tracks.cacheId === tracksCacheId) return; if (inserting) return;
inserting = true; tracksCacheId = output.data.tracks.cacheId; const tracks = await loadTracks();
// TODO: This kinda messes up the UI, // but at least the active audio doesn't stop playing. amp.store.dispatch({ type: "REMOVE_ALL_TRACKS" });
// TODO: Webamp blows up if you add too much tracks amp.appendTracks(tracks.slice(0, 1000));
const status = amp.getMediaStatus(); if (status !== "PLAYING") amp.nextTrack();
inserting = false;}
////////////////////////////////////////////// 🛠️////////////////////////////////////////////async function loadTracks(): Promise<URLTrack[]> { const input = await configurator.input; const output = await configurator.output;
const groups = await input.sendAction<GroupConsult>( "groupConsult", output.data.tracks.collection, { timeoutDuration: 60000 * 5, worker: true }, );
// Available tracks let tracks: Track[] = [];
Object.values(groups).forEach((value) => { if (value.available === false) return; tracks = tracks.concat(value.tracks); }, []);
return tracks.map((track) => { const urlTrack: URLTrack = { url: track.uri, metaData: { title: track.tags?.title || "", artist: track.tags?.artist || "", album: track.tags?.album, }, duration: track.stats?.duration, };
return urlTrack; });}