MCPcopy Create free account
hub / github.com/stemdeckapp/stemdeck / openTrack

Function openTrack

static/mobile/app.js:207–284  ·  view source on GitHub ↗
(card, { autoplay = false } = {})

Source from the content-addressed store, hash-verified

205
206// Load a track: fetch detail, build lanes, spin up the Web Audio engine.
207async function openTrack(card, { autoplay = false } = {}) {
208 state.tab = "mixer";
209 state.current = { ...card, detail: null, loading: true, error: null };
210 state.playing = false;
211 state.progress = 0;
212 state.speed = 1.0;
213 render();
214
215 if (engine) { engine.destroy(); engine = null; engineTrackId = null; }
216 engineReady = false;
217 const token = ++engineToken;
218 pendingPlay = autoplay;
219
220 let detail;
221 try {
222 const res = await fetch(`/api/jobs/${card.id}`, { cache: "no-store" });
223 if (!res.ok) throw new Error(`GET /api/jobs/${card.id} -> ${res.status}`);
224 detail = await res.json();
225 } catch (e) {
226 if (token !== engineToken) return;
227 console.warn("[mobile] track detail failed:", e);
228 state.current.loading = false;
229 state.current.error = "Couldn't load this track.";
230 render();
231 return;
232 }
233 if (token !== engineToken) return;
234
235 // Use WAV stems with range-request chunking (chunkedAudioEngine.js): fetches
236 // 10-second windows at a time, so the first audio starts after ~7 MB instead
237 // of the full file, and peak RAM stays around 28 MB regardless of track length.
238 const laneList = (detail.stems || [])
239 .filter((s) => s && s.name !== "original" && s.url)
240 .map((s, i) => ({ name: s.name, url: s.url, ...stemMeta(s.name, i) }));
241
242 state.vols = {};
243 state.muted = {};
244 state.solo = {};
245 for (const l of laneList) state.vols[l.name] = 1;
246
247 state.current.detail = {
248 duration: detail.duration || 0,
249 lanes: laneList,
250 hasVideo: !!detail.has_video,
251 analysis: extractAnalysis(detail, laneList),
252 };
253 state.current.loading = false;
254 state.current.stemCount = laneList.length;
255
256 if (!laneList.length) {
257 state.current.error = "This track has no playable stems yet.";
258 render();
259 return;
260 }
261
262 const engineOpts = {
263 onTime: onEngineTime,
264 onEnded: () => { state.playing = false; render(); },

Callers 4

prevTrackFunction · 0.85
nextTrackFunction · 0.85
togglePlayFunction · 0.85
app.jsFile · 0.85

Calls 7

createChunkedAudioEngineFunction · 0.90
stemMetaFunction · 0.85
extractAnalysisFunction · 0.85
ensureAudioCtxFunction · 0.85
toastFunction · 0.85
renderFunction · 0.70
applyMixFunction · 0.70

Tested by

no test coverage detected