Experiment to rebuild Diffuse using web applets.
1import { applet, reactive } from "@scripts/applet/common";
2
3////////////////////////////////////////////
4// 🗂️ Applets
5////////////////////////////////////////////
6import type * as AudioEngine from "@applets/engine/audio/types.d.ts";
7import type * as QueueEngine from "@applets/engine/queue/types.d.ts";
8
9import type * as AudioUI from "@applets/theme/pilot/audio/types";
10
11const engine = {
12 audio: await applet<AudioEngine.State>("/engine/audio"),
13 queue: await applet<QueueEngine.State>("/engine/queue"),
14};
15
16const orchestrator = {
17 queueAudio: applet("/orchestrator/queue-audio"),
18 queueTracks: applet("/orchestrator/queue-tracks"),
19 processTracks: applet("/orchestrator/process-tracks"),
20};
21
22const ui = {
23 audio: await applet<AudioUI.State>("/theme/pilot/audio/", { setHeight: true }),
24};
25
26////////////////////////////////////////////
27// ⚙️ [Connections → Engines]
28// 🔉 AUDIO
29////////////////////////////////////////////
30
31// NOTE:
32// These could probably be optimised, but it works.
33
34reactive(
35 engine.audio,
36 (data) =>
37 data.isPlaying && (data.items[engine.queue.data.now?.id ?? Infinity]?.isPlaying ?? false),
38 (isPlaying) => ui.audio.sendAction("modifyIsPlaying", isPlaying),
39);
40
41reactive(
42 engine.audio,
43 (data) => data.items[engine.queue.data.now?.id ?? Infinity]?.progress ?? 0,
44 (progress: number) => ui.audio.sendAction("modifyProgress", progress),
45);
46
47////////////////////////////////////////////
48// 🌅 [Connections → UI]
49// 🔉 AUDIO
50////////////////////////////////////////////
51
52let initialAudioChecked = false;
53
54reactive(
55 ui.audio,
56 (data) => data.isPlaying,
57 async (isPlaying) => {
58 const audioId = engine.queue.data.now?.id;
59
60 // Sync audio state and ui state
61 // TODO: Figure out a better way to do this
62 if (!initialAudioChecked) {
63 if (engine.audio.data.isPlaying && !isPlaying) {
64 ui.audio.sendAction("modifyIsPlaying", true);
65 initialAudioChecked = true;
66 return;
67 }
68 }
69
70 // Otherwise just control the audio
71 if (isPlaying) {
72 engine.audio.sendAction("play", { audioId });
73 } else {
74 engine.audio.sendAction("pause", { audioId });
75 }
76 },
77);
78
79reactive(
80 ui.audio,
81 (data: AudioUI.State) => data.seekPosition,
82 (seekPosition) => {
83 if (seekPosition !== undefined && engine.queue.data.now?.id) {
84 engine.audio.sendAction("seek", {
85 percentage: seekPosition,
86 audioId: engine.queue.data.now.id,
87 });
88 }
89 },
90);