@lucaismyname/ginger 0.0.13 → 0.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -2
- package/dist/{GingerSplitContexts-4YZ-OJ9V.js → GingerSplitContexts-BzBExb95.js} +22 -21
- package/dist/GingerSplitContexts-BzBExb95.js.map +1 -0
- package/dist/GingerSplitContexts-C7puo0M7.cjs +2 -0
- package/dist/GingerSplitContexts-C7puo0M7.cjs.map +1 -0
- package/dist/analyzer/liveAudioGraph.d.ts +14 -0
- package/dist/analyzer/liveAudioGraph.d.ts.map +1 -0
- package/dist/analyzer/useGingerLiveAnalyzer.d.ts +21 -0
- package/dist/analyzer/useGingerLiveAnalyzer.d.ts.map +1 -0
- package/dist/audio/GingerPlayer.d.ts.map +1 -1
- package/dist/audio/GingerPlayer.test.d.ts +2 -0
- package/dist/audio/GingerPlayer.test.d.ts.map +1 -0
- package/dist/client.cjs +1 -1
- package/dist/client.js +21 -18
- package/dist/context/GingerContext.d.ts +2 -1
- package/dist/context/GingerContext.d.ts.map +1 -1
- package/dist/context/GingerProvider.d.ts.map +1 -1
- package/dist/context/GingerSplitContexts.d.ts +2 -1
- package/dist/context/GingerSplitContexts.d.ts.map +1 -1
- package/dist/core/playbackReducer.d.ts.map +1 -1
- package/dist/core/queue.d.ts.map +1 -1
- package/dist/experimental-gapless/index.cjs +1 -1
- package/dist/experimental-gapless/index.js +1 -1
- package/dist/ginger-BTPRqWHs.js +1621 -0
- package/dist/ginger-BTPRqWHs.js.map +1 -0
- package/dist/ginger-BiI69vrn.cjs +2 -0
- package/dist/ginger-BiI69vrn.cjs.map +1 -0
- package/dist/hooks/hooks.test.d.ts +2 -0
- package/dist/hooks/hooks.test.d.ts.map +1 -0
- package/dist/hooks/useGinger.d.ts +1 -0
- package/dist/hooks/useGinger.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -18
- package/dist/internal/fft.d.ts +7 -0
- package/dist/internal/fft.d.ts.map +1 -0
- package/dist/internal/fft.test.d.ts +2 -0
- package/dist/internal/fft.test.d.ts.map +1 -0
- package/dist/media/useMediaSession.d.ts.map +1 -1
- package/dist/media/useMediaSession.test.d.ts +2 -0
- package/dist/media/useMediaSession.test.d.ts.map +1 -0
- package/dist/testing/helpers.d.ts +21 -0
- package/dist/testing/helpers.d.ts.map +1 -0
- package/dist/testing/index.cjs +19 -19
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.ts +2 -7
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +33 -4
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/renderGinger.d.ts +8 -0
- package/dist/testing/renderGinger.d.ts.map +1 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/useSeekDrag-Br1V0Vao.js +290 -0
- package/dist/useSeekDrag-Br1V0Vao.js.map +1 -0
- package/dist/useSeekDrag-aS7uk26h.cjs +2 -0
- package/dist/useSeekDrag-aS7uk26h.cjs.map +1 -0
- package/dist/waveform/analyzeAudioFile.d.ts +31 -0
- package/dist/waveform/analyzeAudioFile.d.ts.map +1 -0
- package/dist/waveform/analyzeAudioFile.test.d.ts +2 -0
- package/dist/waveform/analyzeAudioFile.test.d.ts.map +1 -0
- package/dist/waveform/index.cjs +1 -1
- package/dist/waveform/index.cjs.map +1 -1
- package/dist/waveform/index.d.ts +4 -0
- package/dist/waveform/index.d.ts.map +1 -1
- package/dist/waveform/index.js +207 -23
- package/dist/waveform/index.js.map +1 -1
- package/dist/waveform/useAudioFileAnalysis.d.ts +8 -0
- package/dist/waveform/useAudioFileAnalysis.d.ts.map +1 -0
- package/package.json +4 -1
- package/dist/GingerSplitContexts-4YZ-OJ9V.js.map +0 -1
- package/dist/GingerSplitContexts-Bze1Bqe2.cjs +0 -2
- package/dist/GingerSplitContexts-Bze1Bqe2.cjs.map +0 -1
- package/dist/ginger-DYoHDn8T.cjs +0 -2
- package/dist/ginger-DYoHDn8T.cjs.map +0 -1
- package/dist/ginger-Dntdd6zH.js +0 -1599
- package/dist/ginger-Dntdd6zH.js.map +0 -1
- package/dist/useSeekDrag-DBzoym0-.cjs +0 -2
- package/dist/useSeekDrag-DBzoym0-.cjs.map +0 -1
- package/dist/useSeekDrag-jLsYA-uG.js +0 -174
- package/dist/useSeekDrag-jLsYA-uG.js.map +0 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { Track } from '../types';
|
|
3
|
+
import { RenderGingerProviderOptions } from './helpers';
|
|
4
|
+
export type RenderGingerOptions = RenderGingerProviderOptions & {
|
|
5
|
+
tracks?: Track[];
|
|
6
|
+
};
|
|
7
|
+
export declare function renderGinger(ui: ReactNode, options?: RenderGingerOptions): import('@testing-library/react').RenderResult<typeof import("@testing-library/dom/types/queries"), HTMLElement, HTMLElement>;
|
|
8
|
+
//# sourceMappingURL=renderGinger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderGinger.d.ts","sourceRoot":"","sources":["../../src/testing/renderGinger.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,WAAW,CAAC;AAE7D,MAAM,MAAM,mBAAmB,GAAG,2BAA2B,GAAG;IAC9D,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;CAClB,CAAC;AAEF,wBAAgB,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,GAAE,mBAAwB,gIAQ5E"}
|
package/dist/types.d.ts
CHANGED
|
@@ -164,6 +164,11 @@ export type GingerAction = {
|
|
|
164
164
|
} | {
|
|
165
165
|
type: "SET_PLAYLIST_META";
|
|
166
166
|
payload: PlaylistMeta | null;
|
|
167
|
+
} | {
|
|
168
|
+
type: "SET_PLAYBACK_MODE";
|
|
169
|
+
payload: PlaybackMode;
|
|
170
|
+
} | {
|
|
171
|
+
type: "MEDIA_SOURCE_CLEARED";
|
|
167
172
|
} | {
|
|
168
173
|
type: "MEDIA_ERROR";
|
|
169
174
|
payload: {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { useMemo as M, useState as P, useRef as L, useCallback as Q, useLayoutEffect as Y, useEffect as I } from "react";
|
|
2
|
+
import { b as R, u as q, g as W, c as Z } from "./GingerSplitContexts-BzBExb95.js";
|
|
3
|
+
import { r as _, h as $, p as j, i as ee, j as te, b as ne, k as re } from "./ginger-BTPRqWHs.js";
|
|
4
|
+
function se() {
|
|
5
|
+
const n = R(), t = q();
|
|
6
|
+
return M(
|
|
7
|
+
() => {
|
|
8
|
+
const e = W(n, t);
|
|
9
|
+
return {
|
|
10
|
+
state: e,
|
|
11
|
+
currentTrack: re(e),
|
|
12
|
+
playbackUi: ne(e),
|
|
13
|
+
duration: te(e),
|
|
14
|
+
remaining: ee(e),
|
|
15
|
+
progress: j(e),
|
|
16
|
+
artworkUrl: $(e),
|
|
17
|
+
albumLine: _(e),
|
|
18
|
+
play: n.play,
|
|
19
|
+
pause: n.pause,
|
|
20
|
+
togglePlayPause: n.togglePlayPause,
|
|
21
|
+
seek: t.seek,
|
|
22
|
+
setVolume: t.setVolume,
|
|
23
|
+
setMuted: t.setMuted,
|
|
24
|
+
toggleMute: t.toggleMute,
|
|
25
|
+
setPlaybackRate: t.setPlaybackRate,
|
|
26
|
+
next: n.next,
|
|
27
|
+
prev: n.prev,
|
|
28
|
+
setRepeatMode: n.setRepeatMode,
|
|
29
|
+
cycleRepeat: n.cycleRepeat,
|
|
30
|
+
toggleShuffle: n.toggleShuffle,
|
|
31
|
+
setQueue: n.setQueue,
|
|
32
|
+
insertTrackAt: n.insertTrackAt,
|
|
33
|
+
removeTrackAt: n.removeTrackAt,
|
|
34
|
+
moveTrack: n.moveTrack,
|
|
35
|
+
enqueueNext: n.enqueueNext,
|
|
36
|
+
playTrackAt: n.playTrackAt,
|
|
37
|
+
selectTrackAt: n.selectTrackAt,
|
|
38
|
+
setPlaylistMeta: n.setPlaylistMeta,
|
|
39
|
+
setPlaybackMode: n.setPlaybackMode,
|
|
40
|
+
init: n.init,
|
|
41
|
+
audioRef: t.audioRef,
|
|
42
|
+
dispatch: n.dispatch
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
[n, t]
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
const B = /* @__PURE__ */ new WeakMap();
|
|
49
|
+
function ce(n) {
|
|
50
|
+
const t = 2 ** Math.round(Math.log2(n));
|
|
51
|
+
return Math.min(32768, Math.max(32, t));
|
|
52
|
+
}
|
|
53
|
+
function oe(n, t) {
|
|
54
|
+
let e = B.get(n);
|
|
55
|
+
if (!e) {
|
|
56
|
+
const i = window.AudioContext ?? window.webkitAudioContext;
|
|
57
|
+
if (!i)
|
|
58
|
+
throw new Error("Web Audio API is not available");
|
|
59
|
+
const l = new i(), y = l.createMediaElementSource(n);
|
|
60
|
+
e = { context: l, source: y, consumers: /* @__PURE__ */ new Map(), nextId: 0 }, B.set(n, e);
|
|
61
|
+
}
|
|
62
|
+
const { context: s, source: o } = e, c = s.createAnalyser();
|
|
63
|
+
c.fftSize = ce(t.fftSize), c.smoothingTimeConstant = t.smoothingTimeConstant, c.minDecibels = t.minDecibels, c.maxDecibels = t.maxDecibels, o.connect(c);
|
|
64
|
+
const r = e.consumers.size === 0;
|
|
65
|
+
r && c.connect(s.destination);
|
|
66
|
+
const a = e.nextId;
|
|
67
|
+
return e.nextId += 1, e.consumers.set(a, { analyser: c, isPlaybackSink: r }), { id: a, context: s, analyser: c };
|
|
68
|
+
}
|
|
69
|
+
function V(n, t) {
|
|
70
|
+
const e = B.get(n);
|
|
71
|
+
if (!e) return;
|
|
72
|
+
const s = e.consumers.get(t);
|
|
73
|
+
if (!s) return;
|
|
74
|
+
const { analyser: o, isPlaybackSink: c } = s;
|
|
75
|
+
if (o.disconnect(), e.consumers.delete(t), e.consumers.size === 0) {
|
|
76
|
+
try {
|
|
77
|
+
e.source.disconnect();
|
|
78
|
+
} catch {
|
|
79
|
+
}
|
|
80
|
+
e.context.close(), B.delete(n);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (c) {
|
|
84
|
+
const r = e.consumers.values().next().value;
|
|
85
|
+
r && (r.analyser.connect(e.context.destination), r.isPlaybackSink = !0);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const G = new Uint8Array(0), N = new Uint8Array(0);
|
|
89
|
+
function me(n = {}) {
|
|
90
|
+
const {
|
|
91
|
+
enabled: t = !0,
|
|
92
|
+
fftSize: e = 2048,
|
|
93
|
+
smoothingTimeConstant: s = 0.8,
|
|
94
|
+
minDecibels: o = -100,
|
|
95
|
+
maxDecibels: c = -30
|
|
96
|
+
} = n, { audioRef: r, state: a } = se(), i = M(
|
|
97
|
+
() => ({
|
|
98
|
+
fftSize: e,
|
|
99
|
+
smoothingTimeConstant: s,
|
|
100
|
+
minDecibels: o,
|
|
101
|
+
maxDecibels: c
|
|
102
|
+
}),
|
|
103
|
+
[e, s, o, c]
|
|
104
|
+
), [l, y] = P(0), [m, u] = P(null), [x, g] = P(!1), [S, T] = P({ frequencyBinCount: 0, sampleRate: 0 }), d = L(G), k = L(N), J = Q(async () => {
|
|
105
|
+
const v = w.current;
|
|
106
|
+
v && v.state === "suspended" && await v.resume();
|
|
107
|
+
}, []), w = L(null), C = L(null);
|
|
108
|
+
return Y(() => {
|
|
109
|
+
if (!t || typeof window > "u")
|
|
110
|
+
return;
|
|
111
|
+
let v = !1, D = null, E = null, F = 0;
|
|
112
|
+
const U = () => {
|
|
113
|
+
const f = w.current;
|
|
114
|
+
f && g(f.state === "suspended");
|
|
115
|
+
}, z = () => {
|
|
116
|
+
if (v) return;
|
|
117
|
+
const f = C.current, h = d.current, p = k.current;
|
|
118
|
+
f && h.length > 0 && p.length > 0 && (f.getByteFrequencyData(h), f.getByteTimeDomainData(p), y((A) => A + 1)), F = requestAnimationFrame(z);
|
|
119
|
+
}, K = () => {
|
|
120
|
+
const f = r.current;
|
|
121
|
+
if (!f || v) return "no-element";
|
|
122
|
+
try {
|
|
123
|
+
const { id: h, context: p, analyser: A } = oe(f, i);
|
|
124
|
+
D = h, E = f, w.current = p, C.current = A, g(p.state === "suspended"), u(null), p.addEventListener("statechange", U);
|
|
125
|
+
const b = A.frequencyBinCount, O = A.fftSize;
|
|
126
|
+
return d.current = new Uint8Array(b), k.current = new Uint8Array(O), T({ frequencyBinCount: b, sampleRate: p.sampleRate }), F = requestAnimationFrame(z), "ok";
|
|
127
|
+
} catch (h) {
|
|
128
|
+
const p = h instanceof Error ? h.message : "Failed to attach live analyser";
|
|
129
|
+
return u(p), w.current = null, C.current = null, d.current = G, k.current = N, T({ frequencyBinCount: 0, sampleRate: 0 }), "error";
|
|
130
|
+
}
|
|
131
|
+
}, X = K();
|
|
132
|
+
if (X !== "ok") {
|
|
133
|
+
let f = 0;
|
|
134
|
+
const h = 120;
|
|
135
|
+
let p = 0;
|
|
136
|
+
const A = () => {
|
|
137
|
+
if (v) return;
|
|
138
|
+
const b = K();
|
|
139
|
+
b === "ok" || b === "error" || (p += 1, !(p >= h) && (f = requestAnimationFrame(A)));
|
|
140
|
+
};
|
|
141
|
+
return X === "no-element" && (f = requestAnimationFrame(A)), () => {
|
|
142
|
+
var b;
|
|
143
|
+
v = !0, cancelAnimationFrame(f), cancelAnimationFrame(F), D != null && E && V(E, D), (b = w.current) == null || b.removeEventListener("statechange", U), w.current = null, C.current = null, d.current = G, k.current = N;
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
return () => {
|
|
147
|
+
var f;
|
|
148
|
+
v = !0, cancelAnimationFrame(F), D != null && E && V(E, D), (f = w.current) == null || f.removeEventListener("statechange", U), w.current = null, C.current = null, d.current = G, k.current = N, T({ frequencyBinCount: 0, sampleRate: 0 });
|
|
149
|
+
};
|
|
150
|
+
}, [t, r, i, a.currentIndex]), {
|
|
151
|
+
frequencyData: d.current,
|
|
152
|
+
timeDomainData: k.current,
|
|
153
|
+
frequencyBinCount: S.frequencyBinCount,
|
|
154
|
+
sampleRate: S.sampleRate,
|
|
155
|
+
isSuspended: x,
|
|
156
|
+
error: m,
|
|
157
|
+
resume: J
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function de(n = !0, t = {}) {
|
|
161
|
+
const { togglePlayPause: e, next: s, prev: o } = R(), { toggleMute: c } = q(), r = t.mute;
|
|
162
|
+
I(() => {
|
|
163
|
+
if (!n || typeof window > "u") return;
|
|
164
|
+
const a = (t.playPause ?? " ").toLowerCase(), i = (t.next ?? "ArrowRight").toLowerCase(), l = (t.previous ?? "ArrowLeft").toLowerCase(), y = r == null ? void 0 : r.toLowerCase(), m = (u) => {
|
|
165
|
+
const x = u.target;
|
|
166
|
+
if (x && (["INPUT", "TEXTAREA", "SELECT"].includes(x.tagName) || x.isContentEditable)) return;
|
|
167
|
+
const g = u.key.toLowerCase();
|
|
168
|
+
g === a ? (u.preventDefault(), e()) : g === i ? (u.preventDefault(), s()) : g === l ? (u.preventDefault(), o()) : y && g === y && (u.preventDefault(), c());
|
|
169
|
+
};
|
|
170
|
+
return window.addEventListener("keydown", m), () => window.removeEventListener("keydown", m);
|
|
171
|
+
}, [t.next, t.playPause, t.previous, n, r, s, o, c, e]);
|
|
172
|
+
}
|
|
173
|
+
function pe() {
|
|
174
|
+
const { tracks: n, currentIndex: t } = R(), { currentTime: e, seek: s } = q(), o = M(() => {
|
|
175
|
+
var a;
|
|
176
|
+
return [...((a = n[t]) == null ? void 0 : a.chapters) ?? []].filter((i) => i && Number.isFinite(i.startSeconds) && i.startSeconds >= 0).sort((i, l) => i.startSeconds - l.startSeconds);
|
|
177
|
+
}, [t, n]), c = M(() => {
|
|
178
|
+
if (o.length === 0) return -1;
|
|
179
|
+
for (let r = o.length - 1; r >= 0; r -= 1)
|
|
180
|
+
if (e >= o[r].startSeconds) return r;
|
|
181
|
+
return -1;
|
|
182
|
+
}, [e, o]);
|
|
183
|
+
return {
|
|
184
|
+
list: o,
|
|
185
|
+
activeIndex: c,
|
|
186
|
+
active: c >= 0 ? o[c] ?? null : null,
|
|
187
|
+
seekTo: (r) => {
|
|
188
|
+
const a = o[r];
|
|
189
|
+
a && s(a.startSeconds);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
const H = /\[(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?\]/g;
|
|
194
|
+
function ae(n) {
|
|
195
|
+
const t = [];
|
|
196
|
+
for (const e of n.split(/\r?\n/)) {
|
|
197
|
+
const s = [...e.matchAll(H)];
|
|
198
|
+
if (s.length === 0) continue;
|
|
199
|
+
const o = e.replace(H, "").trim();
|
|
200
|
+
for (const c of s) {
|
|
201
|
+
const r = Number(c[1] ?? 0), a = Number(c[2] ?? 0), i = Number((c[3] ?? "0").padEnd(3, "0")), l = r * 60 + a + i / 1e3;
|
|
202
|
+
Number.isFinite(l) && l >= 0 && t.push({ time: l, text: o });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return t.sort((e, s) => e.time - s.time);
|
|
206
|
+
}
|
|
207
|
+
function ye() {
|
|
208
|
+
const { tracks: n, currentIndex: t } = R(), { currentTime: e } = q(), s = n[t], o = M(() => s ? Array.isArray(s.lyricsTimed) && s.lyricsTimed.length > 0 ? [...s.lyricsTimed].filter((r) => Number.isFinite(r.time) && r.time >= 0).sort((r, a) => r.time - a.time) : typeof s.lyrics == "string" ? ae(s.lyrics) : [] : [], [s]), c = M(() => {
|
|
209
|
+
for (let r = o.length - 1; r >= 0; r -= 1)
|
|
210
|
+
if (e >= o[r].time) return r;
|
|
211
|
+
return -1;
|
|
212
|
+
}, [e, o]);
|
|
213
|
+
return {
|
|
214
|
+
lines: o,
|
|
215
|
+
activeIndex: c,
|
|
216
|
+
activeLine: c >= 0 ? o[c] ?? null : null
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
function ge(n) {
|
|
220
|
+
const { durationMs: t, stopAfterTracks: e, respectPause: s = !0, enabled: o = !0, onFire: c } = n, { currentIndex: r, pause: a, isPaused: i } = R(), l = L(e ?? 0), y = L(r);
|
|
221
|
+
I(() => {
|
|
222
|
+
l.current = e ?? 0;
|
|
223
|
+
}, [e]), I(() => {
|
|
224
|
+
if (!o || !t || t <= 0 || s && i) return;
|
|
225
|
+
const m = setTimeout(() => {
|
|
226
|
+
a(), c == null || c();
|
|
227
|
+
}, t);
|
|
228
|
+
return () => clearTimeout(m);
|
|
229
|
+
}, [t, o, i, c, a, s]), I(() => {
|
|
230
|
+
if (!o || !e || e <= 0) return;
|
|
231
|
+
const m = y.current;
|
|
232
|
+
y.current = r, r !== m && (l.current -= 1, l.current <= 0 && (a(), c == null || c()));
|
|
233
|
+
}, [r, o, c, a, e]);
|
|
234
|
+
}
|
|
235
|
+
function ke(n = !1) {
|
|
236
|
+
const t = Z(), e = L(t);
|
|
237
|
+
I(() => {
|
|
238
|
+
if (!n || typeof console > "u") return;
|
|
239
|
+
const s = e.current;
|
|
240
|
+
s !== t && console.debug("[ginger]", {
|
|
241
|
+
from: {
|
|
242
|
+
currentIndex: s.currentIndex,
|
|
243
|
+
isPaused: s.isPaused,
|
|
244
|
+
currentTime: s.currentTime,
|
|
245
|
+
repeatMode: s.repeatMode
|
|
246
|
+
},
|
|
247
|
+
to: {
|
|
248
|
+
currentIndex: t.currentIndex,
|
|
249
|
+
isPaused: t.isPaused,
|
|
250
|
+
currentTime: t.currentTime,
|
|
251
|
+
repeatMode: t.repeatMode
|
|
252
|
+
}
|
|
253
|
+
}), e.current = t;
|
|
254
|
+
}, [n, t]);
|
|
255
|
+
}
|
|
256
|
+
function ie(n) {
|
|
257
|
+
return Math.max(0, Math.min(1, n));
|
|
258
|
+
}
|
|
259
|
+
function ve(n) {
|
|
260
|
+
const t = q(), e = R(), { seek: s } = t, [o, c] = P(0), [r, a] = P(!1), i = j(W(e, t)), l = r ? o : i, y = Q(
|
|
261
|
+
(m) => {
|
|
262
|
+
if (!(n > 0)) return;
|
|
263
|
+
const u = m.currentTarget, x = u.getBoundingClientRect(), g = (d) => {
|
|
264
|
+
const k = ie((d - x.left) / x.width);
|
|
265
|
+
c(k), s(k * n);
|
|
266
|
+
};
|
|
267
|
+
a(!0), u.setPointerCapture(m.pointerId), g(m.clientX);
|
|
268
|
+
const S = (d) => g(d.clientX), T = (d) => {
|
|
269
|
+
g(d.clientX), a(!1), u.releasePointerCapture(m.pointerId), u.removeEventListener("pointermove", S), u.removeEventListener("pointerup", T), u.removeEventListener("pointercancel", T);
|
|
270
|
+
};
|
|
271
|
+
u.addEventListener("pointermove", S), u.addEventListener("pointerup", T), u.addEventListener("pointercancel", T);
|
|
272
|
+
},
|
|
273
|
+
[n, s]
|
|
274
|
+
);
|
|
275
|
+
return { fraction: o, displayFraction: l, isDragging: r, onPointerDown: y };
|
|
276
|
+
}
|
|
277
|
+
export {
|
|
278
|
+
oe as a,
|
|
279
|
+
pe as b,
|
|
280
|
+
ke as c,
|
|
281
|
+
V as d,
|
|
282
|
+
de as e,
|
|
283
|
+
me as f,
|
|
284
|
+
ye as g,
|
|
285
|
+
ge as h,
|
|
286
|
+
ve as i,
|
|
287
|
+
ae as p,
|
|
288
|
+
se as u
|
|
289
|
+
};
|
|
290
|
+
//# sourceMappingURL=useSeekDrag-Br1V0Vao.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSeekDrag-Br1V0Vao.js","sources":["../src/hooks/useGinger.ts","../src/analyzer/liveAudioGraph.ts","../src/analyzer/useGingerLiveAnalyzer.ts","../src/hooks/useGingerKeyboardShortcuts.ts","../src/hooks/useGingerChapters.ts","../src/internal/lyrics.ts","../src/hooks/useGingerLyricsSync.ts","../src/hooks/useGingerSleepTimer.ts","../src/hooks/useGingerDebugLog.ts","../src/hooks/useSeekDrag.ts"],"sourcesContent":["import { useMemo } from \"react\";\nimport { gingerStateFromContextValues, useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\nimport {\n derivePlaybackUiState,\n effectiveDuration,\n effectiveRemaining,\n getCurrentTrack,\n progressFraction,\n resolvedAlbumLine,\n resolvedArtwork,\n} from \"../internal/selectors\";\n\nexport function useGinger() {\n const pb = useGingerPlayback();\n const md = useGingerMedia();\n\n return useMemo(\n () => {\n const state = gingerStateFromContextValues(pb, md);\n return {\n state,\n currentTrack: getCurrentTrack(state),\n playbackUi: derivePlaybackUiState(state),\n duration: effectiveDuration(state),\n remaining: effectiveRemaining(state),\n progress: progressFraction(state),\n artworkUrl: resolvedArtwork(state),\n albumLine: resolvedAlbumLine(state),\n play: pb.play,\n pause: pb.pause,\n togglePlayPause: pb.togglePlayPause,\n seek: md.seek,\n setVolume: md.setVolume,\n setMuted: md.setMuted,\n toggleMute: md.toggleMute,\n setPlaybackRate: md.setPlaybackRate,\n next: pb.next,\n prev: pb.prev,\n setRepeatMode: pb.setRepeatMode,\n cycleRepeat: pb.cycleRepeat,\n toggleShuffle: pb.toggleShuffle,\n setQueue: pb.setQueue,\n insertTrackAt: pb.insertTrackAt,\n removeTrackAt: pb.removeTrackAt,\n moveTrack: pb.moveTrack,\n enqueueNext: pb.enqueueNext,\n playTrackAt: pb.playTrackAt,\n selectTrackAt: pb.selectTrackAt,\n setPlaylistMeta: pb.setPlaylistMeta,\n setPlaybackMode: pb.setPlaybackMode,\n init: pb.init,\n audioRef: md.audioRef,\n dispatch: pb.dispatch,\n };\n },\n [pb, md],\n );\n}\n","/** One MediaElementAudioSourceNode per HTMLAudioElement; multiple AnalyserNodes may tap the source. */\n\nexport type LiveAnalyserOptions = {\n fftSize: number;\n smoothingTimeConstant: number;\n minDecibels: number;\n maxDecibels: number;\n};\n\ntype Consumer = {\n analyser: AnalyserNode;\n /** This analyser is wired to `audioContext.destination` so the graph is audible. */\n isPlaybackSink: boolean;\n};\n\ntype ElementEntry = {\n context: AudioContext;\n source: MediaElementAudioSourceNode;\n consumers: Map<number, Consumer>;\n nextId: number;\n};\n\nconst entries = new WeakMap<HTMLAudioElement, ElementEntry>();\n\nfunction clampFftSize(n: number): number {\n const p = 2 ** Math.round(Math.log2(n));\n return Math.min(32768, Math.max(32, p));\n}\n\nexport function attachLiveAnalyser(\n element: HTMLAudioElement,\n options: LiveAnalyserOptions,\n): { id: number; context: AudioContext; analyser: AnalyserNode } {\n let entry = entries.get(element);\n if (!entry) {\n const Context = window.AudioContext ?? (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!Context) {\n throw new Error(\"Web Audio API is not available\");\n }\n const context = new Context();\n const source = context.createMediaElementSource(element);\n entry = { context, source, consumers: new Map(), nextId: 0 };\n entries.set(element, entry);\n }\n\n const { context, source } = entry;\n const analyser = context.createAnalyser();\n analyser.fftSize = clampFftSize(options.fftSize);\n analyser.smoothingTimeConstant = options.smoothingTimeConstant;\n analyser.minDecibels = options.minDecibels;\n analyser.maxDecibels = options.maxDecibels;\n\n source.connect(analyser);\n\n const isFirst = entry.consumers.size === 0;\n if (isFirst) {\n analyser.connect(context.destination);\n }\n\n const id = entry.nextId;\n entry.nextId += 1;\n entry.consumers.set(id, { analyser, isPlaybackSink: isFirst });\n\n return { id, context, analyser };\n}\n\nexport function detachLiveAnalyser(element: HTMLAudioElement, id: number): void {\n const entry = entries.get(element);\n if (!entry) return;\n\n const consumer = entry.consumers.get(id);\n if (!consumer) return;\n\n const { analyser, isPlaybackSink } = consumer;\n analyser.disconnect();\n entry.consumers.delete(id);\n\n if (entry.consumers.size === 0) {\n try {\n entry.source.disconnect();\n } catch {\n // ignore\n }\n void entry.context.close();\n entries.delete(element);\n return;\n }\n\n if (isPlaybackSink) {\n const first = entry.consumers.values().next().value as Consumer | undefined;\n if (first) {\n first.analyser.connect(entry.context.destination);\n first.isPlaybackSink = true;\n }\n }\n}\n","import { useCallback, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { useGinger } from \"../hooks/useGinger\";\nimport { attachLiveAnalyser, detachLiveAnalyser, type LiveAnalyserOptions } from \"./liveAudioGraph\";\n\nexport type UseGingerLiveAnalyzerOptions = {\n /** When false, the analyser is detached and no frames are read. Default true. */\n enabled?: boolean;\n fftSize?: number;\n smoothingTimeConstant?: number;\n minDecibels?: number;\n maxDecibels?: number;\n};\n\nexport type UseGingerLiveAnalyzerResult = {\n /** Byte frequency data (0–255); length equals `frequencyBinCount`. Updated each animation frame while enabled. */\n frequencyData: Uint8Array;\n /** Byte time-domain data (0–255); length equals `fftSize`. */\n timeDomainData: Uint8Array;\n frequencyBinCount: number;\n sampleRate: number;\n isSuspended: boolean;\n error: string | null;\n resume: () => Promise<void>;\n};\n\nconst emptyFreq = new Uint8Array(0);\nconst emptyTime = new Uint8Array(0);\n\nexport function useGingerLiveAnalyzer(options: UseGingerLiveAnalyzerOptions = {}): UseGingerLiveAnalyzerResult {\n const {\n enabled = true,\n fftSize = 2048,\n smoothingTimeConstant = 0.8,\n minDecibels = -100,\n maxDecibels = -30,\n } = options;\n\n const { audioRef, state } = useGinger();\n const opts = useMemo<LiveAnalyserOptions>(\n () => ({\n fftSize,\n smoothingTimeConstant,\n minDecibels,\n maxDecibels,\n }),\n [fftSize, smoothingTimeConstant, minDecibels, maxDecibels],\n );\n\n const [frame, setFrame] = useState(0);\n const [error, setError] = useState<string | null>(null);\n const [isSuspended, setIsSuspended] = useState(false);\n const [meta, setMeta] = useState({ frequencyBinCount: 0, sampleRate: 0 });\n\n const freqRef = useRef<Uint8Array>(emptyFreq);\n const timeRef = useRef<Uint8Array>(emptyTime);\n\n const resume = useCallback(async () => {\n const ctx = contextHolderRef.current;\n if (ctx && ctx.state === \"suspended\") {\n await ctx.resume();\n }\n }, []);\n\n const contextHolderRef = useRef<AudioContext | null>(null);\n const analyserHolderRef = useRef<AnalyserNode | null>(null);\n\n useLayoutEffect(() => {\n if (!enabled || typeof window === \"undefined\") {\n return;\n }\n\n let cancelled = false;\n let consumerId: number | null = null;\n let element: HTMLAudioElement | null = null;\n let rafId = 0;\n\n const onStateChange = () => {\n const ctx = contextHolderRef.current;\n if (ctx) setIsSuspended(ctx.state === \"suspended\");\n };\n\n const runLoop = () => {\n if (cancelled) return;\n const a = analyserHolderRef.current;\n const fq = freqRef.current;\n const td = timeRef.current;\n if (a && fq.length > 0 && td.length > 0) {\n a.getByteFrequencyData(fq as Uint8Array<ArrayBuffer>);\n a.getByteTimeDomainData(td as Uint8Array<ArrayBuffer>);\n setFrame((n) => n + 1);\n }\n rafId = requestAnimationFrame(runLoop);\n };\n\n type AttachOutcome = \"ok\" | \"no-element\" | \"error\";\n\n const attach = (): AttachOutcome => {\n const el = audioRef.current;\n if (!el || cancelled) return \"no-element\";\n try {\n const { id, context, analyser } = attachLiveAnalyser(el, opts);\n consumerId = id;\n element = el;\n contextHolderRef.current = context;\n analyserHolderRef.current = analyser;\n setIsSuspended(context.state === \"suspended\");\n setError(null);\n\n context.addEventListener(\"statechange\", onStateChange);\n\n const n = analyser.frequencyBinCount;\n const fft = analyser.fftSize;\n freqRef.current = new Uint8Array(n);\n timeRef.current = new Uint8Array(fft);\n setMeta({ frequencyBinCount: n, sampleRate: context.sampleRate });\n\n rafId = requestAnimationFrame(runLoop);\n return \"ok\";\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"Failed to attach live analyser\";\n setError(msg);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n setMeta({ frequencyBinCount: 0, sampleRate: 0 });\n return \"error\";\n }\n };\n\n const first = attach();\n if (first !== \"ok\") {\n let retryRaf = 0;\n const maxAttempts = 120;\n let attempts = 0;\n\n const retryLoop = () => {\n if (cancelled) return;\n const out = attach();\n if (out === \"ok\" || out === \"error\") return;\n attempts += 1;\n if (attempts >= maxAttempts) return;\n retryRaf = requestAnimationFrame(retryLoop);\n };\n\n if (first === \"no-element\") {\n retryRaf = requestAnimationFrame(retryLoop);\n }\n\n return () => {\n cancelled = true;\n cancelAnimationFrame(retryRaf);\n cancelAnimationFrame(rafId);\n if (consumerId != null && element) {\n detachLiveAnalyser(element, consumerId);\n }\n contextHolderRef.current?.removeEventListener(\"statechange\", onStateChange);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n };\n }\n\n return () => {\n cancelled = true;\n cancelAnimationFrame(rafId);\n if (consumerId != null && element) {\n detachLiveAnalyser(element, consumerId);\n }\n contextHolderRef.current?.removeEventListener(\"statechange\", onStateChange);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n setMeta({ frequencyBinCount: 0, sampleRate: 0 });\n };\n }, [enabled, audioRef, opts, state.currentIndex]);\n\n void frame;\n\n return {\n frequencyData: freqRef.current,\n timeDomainData: timeRef.current,\n frequencyBinCount: meta.frequencyBinCount,\n sampleRate: meta.sampleRate,\n isSuspended,\n error,\n resume,\n };\n}\n","import { useEffect } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerKeyboardShortcutBindings = {\n playPause?: string;\n next?: string;\n previous?: string;\n mute?: string;\n};\n\nexport function useGingerKeyboardShortcuts(\n enabled = true,\n bindings: GingerKeyboardShortcutBindings = {},\n): void {\n const { togglePlayPause, next, prev } = useGingerPlayback();\n const { toggleMute } = useGingerMedia();\n\n const muteBinding = bindings.mute;\n\n useEffect(() => {\n if (!enabled || typeof window === \"undefined\") return;\n const playPause = (bindings.playPause ?? \" \").toLowerCase();\n const nextKey = (bindings.next ?? \"ArrowRight\").toLowerCase();\n const prevKey = (bindings.previous ?? \"ArrowLeft\").toLowerCase();\n const muteKey = muteBinding?.toLowerCase();\n\n const onKeyDown = (event: KeyboardEvent) => {\n const target = event.target as HTMLElement | null;\n if (target && ([\"INPUT\", \"TEXTAREA\", \"SELECT\"].includes(target.tagName) || target.isContentEditable)) return;\n const key = event.key.toLowerCase();\n if (key === playPause) {\n event.preventDefault();\n togglePlayPause();\n } else if (key === nextKey) {\n event.preventDefault();\n next();\n } else if (key === prevKey) {\n event.preventDefault();\n prev();\n } else if (muteKey && key === muteKey) {\n event.preventDefault();\n toggleMute();\n }\n };\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, [bindings.next, bindings.playPause, bindings.previous, enabled, muteBinding, next, prev, toggleMute, togglePlayPause]);\n}\n","import { useMemo } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerChapter = {\n title: string;\n startSeconds: number;\n};\n\nexport type GingerChapterState = {\n list: GingerChapter[];\n activeIndex: number;\n active: GingerChapter | null;\n seekTo: (index: number) => void;\n};\n\nexport function useGingerChapters(): GingerChapterState {\n const { tracks, currentIndex } = useGingerPlayback();\n const { currentTime, seek } = useGingerMedia();\n\n const list = useMemo(() => {\n const chapters = tracks[currentIndex]?.chapters ?? [];\n return [...chapters]\n .filter((item) => item && Number.isFinite(item.startSeconds) && item.startSeconds >= 0)\n .sort((a, b) => a.startSeconds - b.startSeconds);\n }, [currentIndex, tracks]);\n\n const activeIndex = useMemo(() => {\n if (list.length === 0) return -1;\n for (let i = list.length - 1; i >= 0; i -= 1) {\n if (currentTime >= list[i]!.startSeconds) return i;\n }\n return -1;\n }, [currentTime, list]);\n\n return {\n list,\n activeIndex,\n active: activeIndex >= 0 ? list[activeIndex] ?? null : null,\n seekTo: (index: number) => {\n const chapter = list[index];\n if (chapter) seek(chapter.startSeconds);\n },\n };\n}\n","export type TimedLyricLine = {\n time: number;\n text: string;\n};\n\nconst lrcTag = /\\[(\\d{1,2}):(\\d{2})(?:\\.(\\d{1,3}))?\\]/g;\n\nexport function parseLrc(lrc: string): TimedLyricLine[] {\n const lines: TimedLyricLine[] = [];\n for (const rawLine of lrc.split(/\\r?\\n/)) {\n const matches = [...rawLine.matchAll(lrcTag)];\n if (matches.length === 0) continue;\n const text = rawLine.replace(lrcTag, \"\").trim();\n for (const m of matches) {\n const minutes = Number(m[1] ?? 0);\n const seconds = Number(m[2] ?? 0);\n const millis = Number((m[3] ?? \"0\").padEnd(3, \"0\"));\n const time = minutes * 60 + seconds + millis / 1000;\n if (Number.isFinite(time) && time >= 0) {\n lines.push({ time, text });\n }\n }\n }\n return lines.sort((a, b) => a.time - b.time);\n}\n","import { useMemo } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\nimport { parseLrc, type TimedLyricLine } from \"../internal/lyrics\";\n\nexport type GingerLyricsSyncState = {\n lines: TimedLyricLine[];\n activeIndex: number;\n activeLine: TimedLyricLine | null;\n};\n\nexport function useGingerLyricsSync(): GingerLyricsSyncState {\n const { tracks, currentIndex } = useGingerPlayback();\n const { currentTime } = useGingerMedia();\n const currentTrack = tracks[currentIndex];\n\n const lines = useMemo(() => {\n if (!currentTrack) return [];\n if (Array.isArray(currentTrack.lyricsTimed) && currentTrack.lyricsTimed.length > 0) {\n return [...currentTrack.lyricsTimed]\n .filter((line) => Number.isFinite(line.time) && line.time >= 0)\n .sort((a, b) => a.time - b.time);\n }\n if (typeof currentTrack.lyrics === \"string\") {\n return parseLrc(currentTrack.lyrics);\n }\n return [];\n }, [currentTrack]);\n\n const activeIndex = useMemo(() => {\n for (let i = lines.length - 1; i >= 0; i -= 1) {\n if (currentTime >= lines[i]!.time) return i;\n }\n return -1;\n }, [currentTime, lines]);\n\n return {\n lines,\n activeIndex,\n activeLine: activeIndex >= 0 ? lines[activeIndex] ?? null : null,\n };\n}\n","import { useEffect, useRef } from \"react\";\nimport { useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerSleepTimerOptions = {\n durationMs?: number;\n stopAfterTracks?: number;\n respectPause?: boolean;\n enabled?: boolean;\n onFire?: () => void;\n};\n\nexport function useGingerSleepTimer(options: GingerSleepTimerOptions): void {\n const { durationMs, stopAfterTracks, respectPause = true, enabled = true, onFire } = options;\n const { currentIndex, pause, isPaused } = useGingerPlayback();\n const remainingTracksRef = useRef(stopAfterTracks ?? 0);\n const prevIndexRef = useRef(currentIndex);\n\n useEffect(() => {\n remainingTracksRef.current = stopAfterTracks ?? 0;\n }, [stopAfterTracks]);\n\n useEffect(() => {\n if (!enabled || !durationMs || durationMs <= 0) return;\n if (respectPause && isPaused) return;\n const id = setTimeout(() => {\n pause();\n onFire?.();\n }, durationMs);\n return () => clearTimeout(id);\n }, [durationMs, enabled, isPaused, onFire, pause, respectPause]);\n\n useEffect(() => {\n if (!enabled || !stopAfterTracks || stopAfterTracks <= 0) return;\n const prev = prevIndexRef.current;\n prevIndexRef.current = currentIndex;\n if (currentIndex === prev) return;\n remainingTracksRef.current -= 1;\n if (remainingTracksRef.current <= 0) {\n pause();\n onFire?.();\n }\n }, [currentIndex, enabled, onFire, pause, stopAfterTracks]);\n}\n","import { useEffect, useRef } from \"react\";\nimport { useGingerState } from \"../context/GingerSplitContexts\";\n\nexport function useGingerDebugLog(enabled = false): void {\n const state = useGingerState();\n const prevRef = useRef(state);\n\n useEffect(() => {\n if (!enabled || typeof console === \"undefined\") return;\n const prev = prevRef.current;\n if (prev !== state) {\n console.debug(\"[ginger]\", {\n from: {\n currentIndex: prev.currentIndex,\n isPaused: prev.isPaused,\n currentTime: prev.currentTime,\n repeatMode: prev.repeatMode,\n },\n to: {\n currentIndex: state.currentIndex,\n isPaused: state.isPaused,\n currentTime: state.currentTime,\n repeatMode: state.repeatMode,\n },\n });\n }\n prevRef.current = state;\n }, [enabled, state]);\n}\n","import { useCallback, useState } from \"react\";\nimport type { PointerEvent as ReactPointerEvent } from \"react\";\nimport { useGingerMedia, useGingerPlayback, gingerStateFromContextValues } from \"../context/GingerSplitContexts\";\nimport { progressFraction } from \"../internal/selectors\";\n\nexport type SeekDragState = {\n /** Raw drag fraction — only updated during an active drag gesture. */\n fraction: number;\n /** Blended fraction: follows live playback when idle, drag position when dragging. */\n displayFraction: number;\n isDragging: boolean;\n onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n};\n\nfunction clamp01(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nexport function useSeekDrag(duration: number): SeekDragState {\n const media = useGingerMedia();\n const playback = useGingerPlayback();\n const { seek } = media;\n const [fraction, setFraction] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n\n const liveFraction = progressFraction(gingerStateFromContextValues(playback, media));\n const displayFraction = isDragging ? fraction : liveFraction;\n\n const onPointerDown = useCallback(\n (event: ReactPointerEvent<HTMLElement>) => {\n if (!(duration > 0)) return;\n const target = event.currentTarget;\n const rect = target.getBoundingClientRect();\n const update = (clientX: number) => {\n const ratio = clamp01((clientX - rect.left) / rect.width);\n setFraction(ratio);\n seek(ratio * duration);\n };\n setIsDragging(true);\n target.setPointerCapture(event.pointerId);\n update(event.clientX);\n const onMove = (moveEvent: PointerEvent) => update(moveEvent.clientX);\n const onUp = (upEvent: PointerEvent) => {\n update(upEvent.clientX);\n setIsDragging(false);\n target.releasePointerCapture(event.pointerId);\n target.removeEventListener(\"pointermove\", onMove);\n target.removeEventListener(\"pointerup\", onUp);\n target.removeEventListener(\"pointercancel\", onUp);\n };\n target.addEventListener(\"pointermove\", onMove);\n target.addEventListener(\"pointerup\", onUp);\n target.addEventListener(\"pointercancel\", onUp);\n },\n [duration, seek],\n );\n\n return { fraction, displayFraction, isDragging, onPointerDown };\n}\n"],"names":["useGinger","pb","useGingerPlayback","md","useGingerMedia","useMemo","state","gingerStateFromContextValues","getCurrentTrack","derivePlaybackUiState","effectiveDuration","effectiveRemaining","progressFraction","resolvedArtwork","resolvedAlbumLine","entries","clampFftSize","p","attachLiveAnalyser","element","options","entry","Context","context","source","analyser","isFirst","id","detachLiveAnalyser","consumer","isPlaybackSink","first","emptyFreq","emptyTime","useGingerLiveAnalyzer","enabled","fftSize","smoothingTimeConstant","minDecibels","maxDecibels","audioRef","opts","frame","setFrame","useState","error","setError","isSuspended","setIsSuspended","meta","setMeta","freqRef","useRef","timeRef","resume","useCallback","ctx","contextHolderRef","analyserHolderRef","useLayoutEffect","cancelled","consumerId","rafId","onStateChange","runLoop","a","fq","td","n","attach","el","fft","e","msg","retryRaf","maxAttempts","attempts","retryLoop","out","_a","useGingerKeyboardShortcuts","bindings","togglePlayPause","next","prev","toggleMute","muteBinding","useEffect","playPause","nextKey","prevKey","muteKey","onKeyDown","event","target","key","useGingerChapters","tracks","currentIndex","currentTime","seek","list","item","b","activeIndex","i","index","chapter","lrcTag","parseLrc","lrc","lines","rawLine","matches","text","m","minutes","seconds","millis","time","useGingerLyricsSync","currentTrack","line","useGingerSleepTimer","durationMs","stopAfterTracks","respectPause","onFire","pause","isPaused","remainingTracksRef","prevIndexRef","useGingerDebugLog","useGingerState","prevRef","clamp01","value","useSeekDrag","duration","media","playback","fraction","setFraction","isDragging","setIsDragging","liveFraction","displayFraction","onPointerDown","rect","update","clientX","ratio","onMove","moveEvent","onUp","upEvent"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const a=require("react"),d=require("./GingerSplitContexts-C7puo0M7.cjs"),b=require("./ginger-BiI69vrn.cjs");function V(){const n=d.useGingerPlayback(),t=d.useGingerMedia();return a.useMemo(()=>{const e=d.gingerStateFromContextValues(n,t);return{state:e,currentTrack:b.getCurrentTrack(e),playbackUi:b.derivePlaybackUiState(e),duration:b.effectiveDuration(e),remaining:b.effectiveRemaining(e),progress:b.progressFraction(e),artworkUrl:b.resolvedArtwork(e),albumLine:b.resolvedAlbumLine(e),play:n.play,pause:n.pause,togglePlayPause:n.togglePlayPause,seek:t.seek,setVolume:t.setVolume,setMuted:t.setMuted,toggleMute:t.toggleMute,setPlaybackRate:t.setPlaybackRate,next:n.next,prev:n.prev,setRepeatMode:n.setRepeatMode,cycleRepeat:n.cycleRepeat,toggleShuffle:n.toggleShuffle,setQueue:n.setQueue,insertTrackAt:n.insertTrackAt,removeTrackAt:n.removeTrackAt,moveTrack:n.moveTrack,enqueueNext:n.enqueueNext,playTrackAt:n.playTrackAt,selectTrackAt:n.selectTrackAt,setPlaylistMeta:n.setPlaylistMeta,setPlaybackMode:n.setPlaybackMode,init:n.init,audioRef:t.audioRef,dispatch:n.dispatch}},[n,t])}const q=new WeakMap;function j(n){const t=2**Math.round(Math.log2(n));return Math.min(32768,Math.max(32,t))}function X(n,t){let e=q.get(n);if(!e){const i=window.AudioContext??window.webkitAudioContext;if(!i)throw new Error("Web Audio API is not available");const f=new i,k=f.createMediaElementSource(n);e={context:f,source:k,consumers:new Map,nextId:0},q.set(n,e)}const{context:s,source:o}=e,c=s.createAnalyser();c.fftSize=j(t.fftSize),c.smoothingTimeConstant=t.smoothingTimeConstant,c.minDecibels=t.minDecibels,c.maxDecibels=t.maxDecibels,o.connect(c);const r=e.consumers.size===0;r&&c.connect(s.destination);const u=e.nextId;return e.nextId+=1,e.consumers.set(u,{analyser:c,isPlaybackSink:r}),{id:u,context:s,analyser:c}}function N(n,t){const e=q.get(n);if(!e)return;const s=e.consumers.get(t);if(!s)return;const{analyser:o,isPlaybackSink:c}=s;if(o.disconnect(),e.consumers.delete(t),e.consumers.size===0){try{e.source.disconnect()}catch{}e.context.close(),q.delete(n);return}if(c){const r=e.consumers.values().next().value;r&&(r.analyser.connect(e.context.destination),r.isPlaybackSink=!0)}}const D=new Uint8Array(0),I=new Uint8Array(0);function J(n={}){const{enabled:t=!0,fftSize:e=2048,smoothingTimeConstant:s=.8,minDecibels:o=-100,maxDecibels:c=-30}=n,{audioRef:r,state:u}=V(),i=a.useMemo(()=>({fftSize:e,smoothingTimeConstant:s,minDecibels:o,maxDecibels:c}),[e,s,o,c]),[f,k]=a.useState(0),[g,l]=a.useState(null),[S,v]=a.useState(!1),[P,T]=a.useState({frequencyBinCount:0,sampleRate:0}),p=a.useRef(D),h=a.useRef(I),Q=a.useCallback(async()=>{const x=w.current;x&&x.state==="suspended"&&await x.resume()},[]),w=a.useRef(null),R=a.useRef(null);return a.useLayoutEffect(()=>{if(!t||typeof window>"u")return;let x=!1,C=null,E=null,G=0;const F=()=>{const m=w.current;m&&v(m.state==="suspended")},z=()=>{if(x)return;const m=R.current,A=p.current,y=h.current;m&&A.length>0&&y.length>0&&(m.getByteFrequencyData(A),m.getByteTimeDomainData(y),k(M=>M+1)),G=requestAnimationFrame(z)},B=()=>{const m=r.current;if(!m||x)return"no-element";try{const{id:A,context:y,analyser:M}=X(m,i);C=A,E=m,w.current=y,R.current=M,v(y.state==="suspended"),l(null),y.addEventListener("statechange",F);const L=M.frequencyBinCount,W=M.fftSize;return p.current=new Uint8Array(L),h.current=new Uint8Array(W),T({frequencyBinCount:L,sampleRate:y.sampleRate}),G=requestAnimationFrame(z),"ok"}catch(A){const y=A instanceof Error?A.message:"Failed to attach live analyser";return l(y),w.current=null,R.current=null,p.current=D,h.current=I,T({frequencyBinCount:0,sampleRate:0}),"error"}},U=B();if(U!=="ok"){let m=0;const A=120;let y=0;const M=()=>{if(x)return;const L=B();L==="ok"||L==="error"||(y+=1,!(y>=A)&&(m=requestAnimationFrame(M)))};return U==="no-element"&&(m=requestAnimationFrame(M)),()=>{var L;x=!0,cancelAnimationFrame(m),cancelAnimationFrame(G),C!=null&&E&&N(E,C),(L=w.current)==null||L.removeEventListener("statechange",F),w.current=null,R.current=null,p.current=D,h.current=I}}return()=>{var m;x=!0,cancelAnimationFrame(G),C!=null&&E&&N(E,C),(m=w.current)==null||m.removeEventListener("statechange",F),w.current=null,R.current=null,p.current=D,h.current=I,T({frequencyBinCount:0,sampleRate:0})}},[t,r,i,u.currentIndex]),{frequencyData:p.current,timeDomainData:h.current,frequencyBinCount:P.frequencyBinCount,sampleRate:P.sampleRate,isSuspended:S,error:g,resume:Q}}function O(n=!0,t={}){const{togglePlayPause:e,next:s,prev:o}=d.useGingerPlayback(),{toggleMute:c}=d.useGingerMedia(),r=t.mute;a.useEffect(()=>{if(!n||typeof window>"u")return;const u=(t.playPause??" ").toLowerCase(),i=(t.next??"ArrowRight").toLowerCase(),f=(t.previous??"ArrowLeft").toLowerCase(),k=r==null?void 0:r.toLowerCase(),g=l=>{const S=l.target;if(S&&(["INPUT","TEXTAREA","SELECT"].includes(S.tagName)||S.isContentEditable))return;const v=l.key.toLowerCase();v===u?(l.preventDefault(),e()):v===i?(l.preventDefault(),s()):v===f?(l.preventDefault(),o()):k&&v===k&&(l.preventDefault(),c())};return window.addEventListener("keydown",g),()=>window.removeEventListener("keydown",g)},[t.next,t.playPause,t.previous,n,r,s,o,c,e])}function Y(){const{tracks:n,currentIndex:t}=d.useGingerPlayback(),{currentTime:e,seek:s}=d.useGingerMedia(),o=a.useMemo(()=>{var u;return[...((u=n[t])==null?void 0:u.chapters)??[]].filter(i=>i&&Number.isFinite(i.startSeconds)&&i.startSeconds>=0).sort((i,f)=>i.startSeconds-f.startSeconds)},[t,n]),c=a.useMemo(()=>{if(o.length===0)return-1;for(let r=o.length-1;r>=0;r-=1)if(e>=o[r].startSeconds)return r;return-1},[e,o]);return{list:o,activeIndex:c,active:c>=0?o[c]??null:null,seekTo:r=>{const u=o[r];u&&s(u.startSeconds)}}}const K=/\[(\d{1,2}):(\d{2})(?:\.(\d{1,3}))?\]/g;function H(n){const t=[];for(const e of n.split(/\r?\n/)){const s=[...e.matchAll(K)];if(s.length===0)continue;const o=e.replace(K,"").trim();for(const c of s){const r=Number(c[1]??0),u=Number(c[2]??0),i=Number((c[3]??"0").padEnd(3,"0")),f=r*60+u+i/1e3;Number.isFinite(f)&&f>=0&&t.push({time:f,text:o})}}return t.sort((e,s)=>e.time-s.time)}function Z(){const{tracks:n,currentIndex:t}=d.useGingerPlayback(),{currentTime:e}=d.useGingerMedia(),s=n[t],o=a.useMemo(()=>s?Array.isArray(s.lyricsTimed)&&s.lyricsTimed.length>0?[...s.lyricsTimed].filter(r=>Number.isFinite(r.time)&&r.time>=0).sort((r,u)=>r.time-u.time):typeof s.lyrics=="string"?H(s.lyrics):[]:[],[s]),c=a.useMemo(()=>{for(let r=o.length-1;r>=0;r-=1)if(e>=o[r].time)return r;return-1},[e,o]);return{lines:o,activeIndex:c,activeLine:c>=0?o[c]??null:null}}function _(n){const{durationMs:t,stopAfterTracks:e,respectPause:s=!0,enabled:o=!0,onFire:c}=n,{currentIndex:r,pause:u,isPaused:i}=d.useGingerPlayback(),f=a.useRef(e??0),k=a.useRef(r);a.useEffect(()=>{f.current=e??0},[e]),a.useEffect(()=>{if(!o||!t||t<=0||s&&i)return;const g=setTimeout(()=>{u(),c==null||c()},t);return()=>clearTimeout(g)},[t,o,i,c,u,s]),a.useEffect(()=>{if(!o||!e||e<=0)return;const g=k.current;k.current=r,r!==g&&(f.current-=1,f.current<=0&&(u(),c==null||c()))},[r,o,c,u,e])}function $(n=!1){const t=d.useGingerState(),e=a.useRef(t);a.useEffect(()=>{if(!n||typeof console>"u")return;const s=e.current;s!==t&&console.debug("[ginger]",{from:{currentIndex:s.currentIndex,isPaused:s.isPaused,currentTime:s.currentTime,repeatMode:s.repeatMode},to:{currentIndex:t.currentIndex,isPaused:t.isPaused,currentTime:t.currentTime,repeatMode:t.repeatMode}}),e.current=t},[n,t])}function ee(n){return Math.max(0,Math.min(1,n))}function te(n){const t=d.useGingerMedia(),e=d.useGingerPlayback(),{seek:s}=t,[o,c]=a.useState(0),[r,u]=a.useState(!1),i=b.progressFraction(d.gingerStateFromContextValues(e,t)),f=r?o:i,k=a.useCallback(g=>{if(!(n>0))return;const l=g.currentTarget,S=l.getBoundingClientRect(),v=p=>{const h=ee((p-S.left)/S.width);c(h),s(h*n)};u(!0),l.setPointerCapture(g.pointerId),v(g.clientX);const P=p=>v(p.clientX),T=p=>{v(p.clientX),u(!1),l.releasePointerCapture(g.pointerId),l.removeEventListener("pointermove",P),l.removeEventListener("pointerup",T),l.removeEventListener("pointercancel",T)};l.addEventListener("pointermove",P),l.addEventListener("pointerup",T),l.addEventListener("pointercancel",T)},[n,s]);return{fraction:o,displayFraction:f,isDragging:r,onPointerDown:k}}exports.attachLiveAnalyser=X;exports.detachLiveAnalyser=N;exports.parseLrc=H;exports.useGinger=V;exports.useGingerChapters=Y;exports.useGingerDebugLog=$;exports.useGingerKeyboardShortcuts=O;exports.useGingerLiveAnalyzer=J;exports.useGingerLyricsSync=Z;exports.useGingerSleepTimer=_;exports.useSeekDrag=te;
|
|
2
|
+
//# sourceMappingURL=useSeekDrag-aS7uk26h.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSeekDrag-aS7uk26h.cjs","sources":["../src/hooks/useGinger.ts","../src/analyzer/liveAudioGraph.ts","../src/analyzer/useGingerLiveAnalyzer.ts","../src/hooks/useGingerKeyboardShortcuts.ts","../src/hooks/useGingerChapters.ts","../src/internal/lyrics.ts","../src/hooks/useGingerLyricsSync.ts","../src/hooks/useGingerSleepTimer.ts","../src/hooks/useGingerDebugLog.ts","../src/hooks/useSeekDrag.ts"],"sourcesContent":["import { useMemo } from \"react\";\nimport { gingerStateFromContextValues, useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\nimport {\n derivePlaybackUiState,\n effectiveDuration,\n effectiveRemaining,\n getCurrentTrack,\n progressFraction,\n resolvedAlbumLine,\n resolvedArtwork,\n} from \"../internal/selectors\";\n\nexport function useGinger() {\n const pb = useGingerPlayback();\n const md = useGingerMedia();\n\n return useMemo(\n () => {\n const state = gingerStateFromContextValues(pb, md);\n return {\n state,\n currentTrack: getCurrentTrack(state),\n playbackUi: derivePlaybackUiState(state),\n duration: effectiveDuration(state),\n remaining: effectiveRemaining(state),\n progress: progressFraction(state),\n artworkUrl: resolvedArtwork(state),\n albumLine: resolvedAlbumLine(state),\n play: pb.play,\n pause: pb.pause,\n togglePlayPause: pb.togglePlayPause,\n seek: md.seek,\n setVolume: md.setVolume,\n setMuted: md.setMuted,\n toggleMute: md.toggleMute,\n setPlaybackRate: md.setPlaybackRate,\n next: pb.next,\n prev: pb.prev,\n setRepeatMode: pb.setRepeatMode,\n cycleRepeat: pb.cycleRepeat,\n toggleShuffle: pb.toggleShuffle,\n setQueue: pb.setQueue,\n insertTrackAt: pb.insertTrackAt,\n removeTrackAt: pb.removeTrackAt,\n moveTrack: pb.moveTrack,\n enqueueNext: pb.enqueueNext,\n playTrackAt: pb.playTrackAt,\n selectTrackAt: pb.selectTrackAt,\n setPlaylistMeta: pb.setPlaylistMeta,\n setPlaybackMode: pb.setPlaybackMode,\n init: pb.init,\n audioRef: md.audioRef,\n dispatch: pb.dispatch,\n };\n },\n [pb, md],\n );\n}\n","/** One MediaElementAudioSourceNode per HTMLAudioElement; multiple AnalyserNodes may tap the source. */\n\nexport type LiveAnalyserOptions = {\n fftSize: number;\n smoothingTimeConstant: number;\n minDecibels: number;\n maxDecibels: number;\n};\n\ntype Consumer = {\n analyser: AnalyserNode;\n /** This analyser is wired to `audioContext.destination` so the graph is audible. */\n isPlaybackSink: boolean;\n};\n\ntype ElementEntry = {\n context: AudioContext;\n source: MediaElementAudioSourceNode;\n consumers: Map<number, Consumer>;\n nextId: number;\n};\n\nconst entries = new WeakMap<HTMLAudioElement, ElementEntry>();\n\nfunction clampFftSize(n: number): number {\n const p = 2 ** Math.round(Math.log2(n));\n return Math.min(32768, Math.max(32, p));\n}\n\nexport function attachLiveAnalyser(\n element: HTMLAudioElement,\n options: LiveAnalyserOptions,\n): { id: number; context: AudioContext; analyser: AnalyserNode } {\n let entry = entries.get(element);\n if (!entry) {\n const Context = window.AudioContext ?? (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!Context) {\n throw new Error(\"Web Audio API is not available\");\n }\n const context = new Context();\n const source = context.createMediaElementSource(element);\n entry = { context, source, consumers: new Map(), nextId: 0 };\n entries.set(element, entry);\n }\n\n const { context, source } = entry;\n const analyser = context.createAnalyser();\n analyser.fftSize = clampFftSize(options.fftSize);\n analyser.smoothingTimeConstant = options.smoothingTimeConstant;\n analyser.minDecibels = options.minDecibels;\n analyser.maxDecibels = options.maxDecibels;\n\n source.connect(analyser);\n\n const isFirst = entry.consumers.size === 0;\n if (isFirst) {\n analyser.connect(context.destination);\n }\n\n const id = entry.nextId;\n entry.nextId += 1;\n entry.consumers.set(id, { analyser, isPlaybackSink: isFirst });\n\n return { id, context, analyser };\n}\n\nexport function detachLiveAnalyser(element: HTMLAudioElement, id: number): void {\n const entry = entries.get(element);\n if (!entry) return;\n\n const consumer = entry.consumers.get(id);\n if (!consumer) return;\n\n const { analyser, isPlaybackSink } = consumer;\n analyser.disconnect();\n entry.consumers.delete(id);\n\n if (entry.consumers.size === 0) {\n try {\n entry.source.disconnect();\n } catch {\n // ignore\n }\n void entry.context.close();\n entries.delete(element);\n return;\n }\n\n if (isPlaybackSink) {\n const first = entry.consumers.values().next().value as Consumer | undefined;\n if (first) {\n first.analyser.connect(entry.context.destination);\n first.isPlaybackSink = true;\n }\n }\n}\n","import { useCallback, useLayoutEffect, useMemo, useRef, useState } from \"react\";\nimport { useGinger } from \"../hooks/useGinger\";\nimport { attachLiveAnalyser, detachLiveAnalyser, type LiveAnalyserOptions } from \"./liveAudioGraph\";\n\nexport type UseGingerLiveAnalyzerOptions = {\n /** When false, the analyser is detached and no frames are read. Default true. */\n enabled?: boolean;\n fftSize?: number;\n smoothingTimeConstant?: number;\n minDecibels?: number;\n maxDecibels?: number;\n};\n\nexport type UseGingerLiveAnalyzerResult = {\n /** Byte frequency data (0–255); length equals `frequencyBinCount`. Updated each animation frame while enabled. */\n frequencyData: Uint8Array;\n /** Byte time-domain data (0–255); length equals `fftSize`. */\n timeDomainData: Uint8Array;\n frequencyBinCount: number;\n sampleRate: number;\n isSuspended: boolean;\n error: string | null;\n resume: () => Promise<void>;\n};\n\nconst emptyFreq = new Uint8Array(0);\nconst emptyTime = new Uint8Array(0);\n\nexport function useGingerLiveAnalyzer(options: UseGingerLiveAnalyzerOptions = {}): UseGingerLiveAnalyzerResult {\n const {\n enabled = true,\n fftSize = 2048,\n smoothingTimeConstant = 0.8,\n minDecibels = -100,\n maxDecibels = -30,\n } = options;\n\n const { audioRef, state } = useGinger();\n const opts = useMemo<LiveAnalyserOptions>(\n () => ({\n fftSize,\n smoothingTimeConstant,\n minDecibels,\n maxDecibels,\n }),\n [fftSize, smoothingTimeConstant, minDecibels, maxDecibels],\n );\n\n const [frame, setFrame] = useState(0);\n const [error, setError] = useState<string | null>(null);\n const [isSuspended, setIsSuspended] = useState(false);\n const [meta, setMeta] = useState({ frequencyBinCount: 0, sampleRate: 0 });\n\n const freqRef = useRef<Uint8Array>(emptyFreq);\n const timeRef = useRef<Uint8Array>(emptyTime);\n\n const resume = useCallback(async () => {\n const ctx = contextHolderRef.current;\n if (ctx && ctx.state === \"suspended\") {\n await ctx.resume();\n }\n }, []);\n\n const contextHolderRef = useRef<AudioContext | null>(null);\n const analyserHolderRef = useRef<AnalyserNode | null>(null);\n\n useLayoutEffect(() => {\n if (!enabled || typeof window === \"undefined\") {\n return;\n }\n\n let cancelled = false;\n let consumerId: number | null = null;\n let element: HTMLAudioElement | null = null;\n let rafId = 0;\n\n const onStateChange = () => {\n const ctx = contextHolderRef.current;\n if (ctx) setIsSuspended(ctx.state === \"suspended\");\n };\n\n const runLoop = () => {\n if (cancelled) return;\n const a = analyserHolderRef.current;\n const fq = freqRef.current;\n const td = timeRef.current;\n if (a && fq.length > 0 && td.length > 0) {\n a.getByteFrequencyData(fq as Uint8Array<ArrayBuffer>);\n a.getByteTimeDomainData(td as Uint8Array<ArrayBuffer>);\n setFrame((n) => n + 1);\n }\n rafId = requestAnimationFrame(runLoop);\n };\n\n type AttachOutcome = \"ok\" | \"no-element\" | \"error\";\n\n const attach = (): AttachOutcome => {\n const el = audioRef.current;\n if (!el || cancelled) return \"no-element\";\n try {\n const { id, context, analyser } = attachLiveAnalyser(el, opts);\n consumerId = id;\n element = el;\n contextHolderRef.current = context;\n analyserHolderRef.current = analyser;\n setIsSuspended(context.state === \"suspended\");\n setError(null);\n\n context.addEventListener(\"statechange\", onStateChange);\n\n const n = analyser.frequencyBinCount;\n const fft = analyser.fftSize;\n freqRef.current = new Uint8Array(n);\n timeRef.current = new Uint8Array(fft);\n setMeta({ frequencyBinCount: n, sampleRate: context.sampleRate });\n\n rafId = requestAnimationFrame(runLoop);\n return \"ok\";\n } catch (e) {\n const msg = e instanceof Error ? e.message : \"Failed to attach live analyser\";\n setError(msg);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n setMeta({ frequencyBinCount: 0, sampleRate: 0 });\n return \"error\";\n }\n };\n\n const first = attach();\n if (first !== \"ok\") {\n let retryRaf = 0;\n const maxAttempts = 120;\n let attempts = 0;\n\n const retryLoop = () => {\n if (cancelled) return;\n const out = attach();\n if (out === \"ok\" || out === \"error\") return;\n attempts += 1;\n if (attempts >= maxAttempts) return;\n retryRaf = requestAnimationFrame(retryLoop);\n };\n\n if (first === \"no-element\") {\n retryRaf = requestAnimationFrame(retryLoop);\n }\n\n return () => {\n cancelled = true;\n cancelAnimationFrame(retryRaf);\n cancelAnimationFrame(rafId);\n if (consumerId != null && element) {\n detachLiveAnalyser(element, consumerId);\n }\n contextHolderRef.current?.removeEventListener(\"statechange\", onStateChange);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n };\n }\n\n return () => {\n cancelled = true;\n cancelAnimationFrame(rafId);\n if (consumerId != null && element) {\n detachLiveAnalyser(element, consumerId);\n }\n contextHolderRef.current?.removeEventListener(\"statechange\", onStateChange);\n contextHolderRef.current = null;\n analyserHolderRef.current = null;\n freqRef.current = emptyFreq;\n timeRef.current = emptyTime;\n setMeta({ frequencyBinCount: 0, sampleRate: 0 });\n };\n }, [enabled, audioRef, opts, state.currentIndex]);\n\n void frame;\n\n return {\n frequencyData: freqRef.current,\n timeDomainData: timeRef.current,\n frequencyBinCount: meta.frequencyBinCount,\n sampleRate: meta.sampleRate,\n isSuspended,\n error,\n resume,\n };\n}\n","import { useEffect } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerKeyboardShortcutBindings = {\n playPause?: string;\n next?: string;\n previous?: string;\n mute?: string;\n};\n\nexport function useGingerKeyboardShortcuts(\n enabled = true,\n bindings: GingerKeyboardShortcutBindings = {},\n): void {\n const { togglePlayPause, next, prev } = useGingerPlayback();\n const { toggleMute } = useGingerMedia();\n\n const muteBinding = bindings.mute;\n\n useEffect(() => {\n if (!enabled || typeof window === \"undefined\") return;\n const playPause = (bindings.playPause ?? \" \").toLowerCase();\n const nextKey = (bindings.next ?? \"ArrowRight\").toLowerCase();\n const prevKey = (bindings.previous ?? \"ArrowLeft\").toLowerCase();\n const muteKey = muteBinding?.toLowerCase();\n\n const onKeyDown = (event: KeyboardEvent) => {\n const target = event.target as HTMLElement | null;\n if (target && ([\"INPUT\", \"TEXTAREA\", \"SELECT\"].includes(target.tagName) || target.isContentEditable)) return;\n const key = event.key.toLowerCase();\n if (key === playPause) {\n event.preventDefault();\n togglePlayPause();\n } else if (key === nextKey) {\n event.preventDefault();\n next();\n } else if (key === prevKey) {\n event.preventDefault();\n prev();\n } else if (muteKey && key === muteKey) {\n event.preventDefault();\n toggleMute();\n }\n };\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, [bindings.next, bindings.playPause, bindings.previous, enabled, muteBinding, next, prev, toggleMute, togglePlayPause]);\n}\n","import { useMemo } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerChapter = {\n title: string;\n startSeconds: number;\n};\n\nexport type GingerChapterState = {\n list: GingerChapter[];\n activeIndex: number;\n active: GingerChapter | null;\n seekTo: (index: number) => void;\n};\n\nexport function useGingerChapters(): GingerChapterState {\n const { tracks, currentIndex } = useGingerPlayback();\n const { currentTime, seek } = useGingerMedia();\n\n const list = useMemo(() => {\n const chapters = tracks[currentIndex]?.chapters ?? [];\n return [...chapters]\n .filter((item) => item && Number.isFinite(item.startSeconds) && item.startSeconds >= 0)\n .sort((a, b) => a.startSeconds - b.startSeconds);\n }, [currentIndex, tracks]);\n\n const activeIndex = useMemo(() => {\n if (list.length === 0) return -1;\n for (let i = list.length - 1; i >= 0; i -= 1) {\n if (currentTime >= list[i]!.startSeconds) return i;\n }\n return -1;\n }, [currentTime, list]);\n\n return {\n list,\n activeIndex,\n active: activeIndex >= 0 ? list[activeIndex] ?? null : null,\n seekTo: (index: number) => {\n const chapter = list[index];\n if (chapter) seek(chapter.startSeconds);\n },\n };\n}\n","export type TimedLyricLine = {\n time: number;\n text: string;\n};\n\nconst lrcTag = /\\[(\\d{1,2}):(\\d{2})(?:\\.(\\d{1,3}))?\\]/g;\n\nexport function parseLrc(lrc: string): TimedLyricLine[] {\n const lines: TimedLyricLine[] = [];\n for (const rawLine of lrc.split(/\\r?\\n/)) {\n const matches = [...rawLine.matchAll(lrcTag)];\n if (matches.length === 0) continue;\n const text = rawLine.replace(lrcTag, \"\").trim();\n for (const m of matches) {\n const minutes = Number(m[1] ?? 0);\n const seconds = Number(m[2] ?? 0);\n const millis = Number((m[3] ?? \"0\").padEnd(3, \"0\"));\n const time = minutes * 60 + seconds + millis / 1000;\n if (Number.isFinite(time) && time >= 0) {\n lines.push({ time, text });\n }\n }\n }\n return lines.sort((a, b) => a.time - b.time);\n}\n","import { useMemo } from \"react\";\nimport { useGingerMedia, useGingerPlayback } from \"../context/GingerSplitContexts\";\nimport { parseLrc, type TimedLyricLine } from \"../internal/lyrics\";\n\nexport type GingerLyricsSyncState = {\n lines: TimedLyricLine[];\n activeIndex: number;\n activeLine: TimedLyricLine | null;\n};\n\nexport function useGingerLyricsSync(): GingerLyricsSyncState {\n const { tracks, currentIndex } = useGingerPlayback();\n const { currentTime } = useGingerMedia();\n const currentTrack = tracks[currentIndex];\n\n const lines = useMemo(() => {\n if (!currentTrack) return [];\n if (Array.isArray(currentTrack.lyricsTimed) && currentTrack.lyricsTimed.length > 0) {\n return [...currentTrack.lyricsTimed]\n .filter((line) => Number.isFinite(line.time) && line.time >= 0)\n .sort((a, b) => a.time - b.time);\n }\n if (typeof currentTrack.lyrics === \"string\") {\n return parseLrc(currentTrack.lyrics);\n }\n return [];\n }, [currentTrack]);\n\n const activeIndex = useMemo(() => {\n for (let i = lines.length - 1; i >= 0; i -= 1) {\n if (currentTime >= lines[i]!.time) return i;\n }\n return -1;\n }, [currentTime, lines]);\n\n return {\n lines,\n activeIndex,\n activeLine: activeIndex >= 0 ? lines[activeIndex] ?? null : null,\n };\n}\n","import { useEffect, useRef } from \"react\";\nimport { useGingerPlayback } from \"../context/GingerSplitContexts\";\n\nexport type GingerSleepTimerOptions = {\n durationMs?: number;\n stopAfterTracks?: number;\n respectPause?: boolean;\n enabled?: boolean;\n onFire?: () => void;\n};\n\nexport function useGingerSleepTimer(options: GingerSleepTimerOptions): void {\n const { durationMs, stopAfterTracks, respectPause = true, enabled = true, onFire } = options;\n const { currentIndex, pause, isPaused } = useGingerPlayback();\n const remainingTracksRef = useRef(stopAfterTracks ?? 0);\n const prevIndexRef = useRef(currentIndex);\n\n useEffect(() => {\n remainingTracksRef.current = stopAfterTracks ?? 0;\n }, [stopAfterTracks]);\n\n useEffect(() => {\n if (!enabled || !durationMs || durationMs <= 0) return;\n if (respectPause && isPaused) return;\n const id = setTimeout(() => {\n pause();\n onFire?.();\n }, durationMs);\n return () => clearTimeout(id);\n }, [durationMs, enabled, isPaused, onFire, pause, respectPause]);\n\n useEffect(() => {\n if (!enabled || !stopAfterTracks || stopAfterTracks <= 0) return;\n const prev = prevIndexRef.current;\n prevIndexRef.current = currentIndex;\n if (currentIndex === prev) return;\n remainingTracksRef.current -= 1;\n if (remainingTracksRef.current <= 0) {\n pause();\n onFire?.();\n }\n }, [currentIndex, enabled, onFire, pause, stopAfterTracks]);\n}\n","import { useEffect, useRef } from \"react\";\nimport { useGingerState } from \"../context/GingerSplitContexts\";\n\nexport function useGingerDebugLog(enabled = false): void {\n const state = useGingerState();\n const prevRef = useRef(state);\n\n useEffect(() => {\n if (!enabled || typeof console === \"undefined\") return;\n const prev = prevRef.current;\n if (prev !== state) {\n console.debug(\"[ginger]\", {\n from: {\n currentIndex: prev.currentIndex,\n isPaused: prev.isPaused,\n currentTime: prev.currentTime,\n repeatMode: prev.repeatMode,\n },\n to: {\n currentIndex: state.currentIndex,\n isPaused: state.isPaused,\n currentTime: state.currentTime,\n repeatMode: state.repeatMode,\n },\n });\n }\n prevRef.current = state;\n }, [enabled, state]);\n}\n","import { useCallback, useState } from \"react\";\nimport type { PointerEvent as ReactPointerEvent } from \"react\";\nimport { useGingerMedia, useGingerPlayback, gingerStateFromContextValues } from \"../context/GingerSplitContexts\";\nimport { progressFraction } from \"../internal/selectors\";\n\nexport type SeekDragState = {\n /** Raw drag fraction — only updated during an active drag gesture. */\n fraction: number;\n /** Blended fraction: follows live playback when idle, drag position when dragging. */\n displayFraction: number;\n isDragging: boolean;\n onPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n};\n\nfunction clamp01(value: number): number {\n return Math.max(0, Math.min(1, value));\n}\n\nexport function useSeekDrag(duration: number): SeekDragState {\n const media = useGingerMedia();\n const playback = useGingerPlayback();\n const { seek } = media;\n const [fraction, setFraction] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n\n const liveFraction = progressFraction(gingerStateFromContextValues(playback, media));\n const displayFraction = isDragging ? fraction : liveFraction;\n\n const onPointerDown = useCallback(\n (event: ReactPointerEvent<HTMLElement>) => {\n if (!(duration > 0)) return;\n const target = event.currentTarget;\n const rect = target.getBoundingClientRect();\n const update = (clientX: number) => {\n const ratio = clamp01((clientX - rect.left) / rect.width);\n setFraction(ratio);\n seek(ratio * duration);\n };\n setIsDragging(true);\n target.setPointerCapture(event.pointerId);\n update(event.clientX);\n const onMove = (moveEvent: PointerEvent) => update(moveEvent.clientX);\n const onUp = (upEvent: PointerEvent) => {\n update(upEvent.clientX);\n setIsDragging(false);\n target.releasePointerCapture(event.pointerId);\n target.removeEventListener(\"pointermove\", onMove);\n target.removeEventListener(\"pointerup\", onUp);\n target.removeEventListener(\"pointercancel\", onUp);\n };\n target.addEventListener(\"pointermove\", onMove);\n target.addEventListener(\"pointerup\", onUp);\n target.addEventListener(\"pointercancel\", onUp);\n },\n [duration, seek],\n );\n\n return { fraction, displayFraction, isDragging, onPointerDown };\n}\n"],"names":["useGinger","pb","useGingerPlayback","md","useGingerMedia","useMemo","state","gingerStateFromContextValues","getCurrentTrack","derivePlaybackUiState","effectiveDuration","effectiveRemaining","progressFraction","resolvedArtwork","resolvedAlbumLine","entries","clampFftSize","p","attachLiveAnalyser","element","options","entry","Context","context","source","analyser","isFirst","id","detachLiveAnalyser","consumer","isPlaybackSink","first","emptyFreq","emptyTime","useGingerLiveAnalyzer","enabled","fftSize","smoothingTimeConstant","minDecibels","maxDecibels","audioRef","opts","frame","setFrame","useState","error","setError","isSuspended","setIsSuspended","meta","setMeta","freqRef","useRef","timeRef","resume","useCallback","ctx","contextHolderRef","analyserHolderRef","useLayoutEffect","cancelled","consumerId","rafId","onStateChange","runLoop","a","fq","td","n","attach","el","fft","e","msg","retryRaf","maxAttempts","attempts","retryLoop","out","_a","useGingerKeyboardShortcuts","bindings","togglePlayPause","next","prev","toggleMute","muteBinding","useEffect","playPause","nextKey","prevKey","muteKey","onKeyDown","event","target","key","useGingerChapters","tracks","currentIndex","currentTime","seek","list","item","b","activeIndex","i","index","chapter","lrcTag","parseLrc","lrc","lines","rawLine","matches","text","m","minutes","seconds","millis","time","useGingerLyricsSync","currentTrack","line","useGingerSleepTimer","durationMs","stopAfterTracks","respectPause","onFire","pause","isPaused","remainingTracksRef","prevIndexRef","useGingerDebugLog","useGingerState","prevRef","clamp01","value","useSeekDrag","duration","media","playback","fraction","setFraction","isDragging","setIsDragging","liveFraction","displayFraction","onPointerDown","rect","update","clientX","ratio","onMove","moveEvent","onUp","upEvent"],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type AnalyzeAudioFileOptions = {
|
|
2
|
+
/** Number of time rows in the amplitude grid (and spectrogram if enabled). Default 128. */
|
|
3
|
+
timeSlices?: number;
|
|
4
|
+
/** Sub-buckets per time slice for the amplitude grid. Default 8. */
|
|
5
|
+
samplesPerSlice?: number;
|
|
6
|
+
/** When true, include `spectrogram` using windowed FFT per time slice. Default false. */
|
|
7
|
+
spectrogram?: boolean;
|
|
8
|
+
/** FFT length for spectrogram (power of 2). Default 1024. */
|
|
9
|
+
fftSize?: number;
|
|
10
|
+
/** Number of frequency bins to keep per row (first bins; capped by fftSize/2). Default 256. */
|
|
11
|
+
frequencyBins?: number;
|
|
12
|
+
/** Channel index, or `"mix"` for equal mix of all channels. Default 0. */
|
|
13
|
+
channel?: number | "mix";
|
|
14
|
+
};
|
|
15
|
+
export type AudioFileAnalysis = {
|
|
16
|
+
duration: number;
|
|
17
|
+
sampleRate: number;
|
|
18
|
+
/** Peak amplitudes in [0, 1]: `timeSlices` rows × `samplesPerSlice` columns. */
|
|
19
|
+
amplitudeGrid: number[][];
|
|
20
|
+
/** Optional magnitude spectrogram rows, each length `frequencyBins`, normalized to [0, 1] globally. */
|
|
21
|
+
spectrogram?: number[][];
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Decodes an `AudioBuffer` into visualization-friendly grids (no network).
|
|
25
|
+
*/
|
|
26
|
+
export declare function analyzeAudioBuffer(buffer: AudioBuffer, options?: AnalyzeAudioFileOptions): AudioFileAnalysis;
|
|
27
|
+
/**
|
|
28
|
+
* Fetches a URL, decodes audio to an `AudioBuffer`, runs {@link analyzeAudioBuffer}, then closes the temporary `AudioContext`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function analyzeAudioFile(fileUrl: string, options?: AnalyzeAudioFileOptions): Promise<AudioFileAnalysis>;
|
|
31
|
+
//# sourceMappingURL=analyzeAudioFile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzeAudioFile.d.ts","sourceRoot":"","sources":["../../src/waveform/analyzeAudioFile.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,uBAAuB,GAAG;IACpC,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yFAAyF;IACzF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+FAA+F;IAC/F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,aAAa,EAAE,MAAM,EAAE,EAAE,CAAC;IAC1B,uGAAuG;IACvG,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;CAC1B,CAAC;AAwGF;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,GAAE,uBAA4B,GAAG,iBAAiB,CAwBhH;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,iBAAiB,CAAC,CAiB5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzeAudioFile.test.d.ts","sourceRoot":"","sources":["../../src/waveform/analyzeAudioFile.test.ts"],"names":[],"mappings":""}
|
package/dist/waveform/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("react");function F(e,t=64){const[r,a]=y.useState({peaks:[],isLoading:!1,error:null});return y.useEffect(()=>{if(!e){a({peaks:[],isLoading:!1,error:null});return}let o=!1;return a(n=>({...n,isLoading:!0,error:null})),(async()=>{try{const n=await fetch(e);if(!n.ok)throw new Error(`Fetch failed: ${n.status} ${n.statusText}`);const l=await n.arrayBuffer(),s=new AudioContext,u=(await s.decodeAudioData(l)).getChannelData(0),w=Math.max(1,Math.floor(u.length/t)),f=[];for(let d=0;d<t;d+=1){let i=0;const h=d*w,M=Math.min(u.length,h+w);for(let c=h;c<M;c+=1)i=Math.max(i,Math.abs(u[c]??0));f.push(i)}await s.close(),o||a({peaks:f,isLoading:!1,error:null})}catch(n){o||a({peaks:[],isLoading:!1,error:n instanceof Error?n.message:"Failed to decode peaks"})}})(),()=>{o=!0}},[t,e]),r}function L(e,t){const r=e.length;if(r!==t.length||r<2||r&r-1)throw new Error("fftInPlace: length must be equal powers of 2 >= 2");let a=0;for(let o=0;o<r-1;o+=1){if(o<a){const l=e[o],s=t[o];e[o]=e[a],t[o]=t[a],e[a]=l,t[a]=s}let n=r>>1;for(;n<=a;)a-=n,n>>=1;a+=n}for(let o=2;o<=r;o<<=1){const n=-2*Math.PI/o,l=Math.cos(n),s=Math.sin(n);for(let g=0;g<r;g+=o){let u=1,w=0;const f=o>>1;for(let d=0;d<f;d+=1){const i=g+d,h=i+f,M=u*e[h]-w*t[h],c=u*t[h]+w*e[h];e[h]=e[i]-M,t[h]=t[i]-c,e[i]=e[i]+M,t[i]=t[i]+c;const m=u*l-w*s,p=u*s+w*l;u=m,w=p}}}}function C(e){const t=e.length;if(t<2||t&t-1)throw new Error("realFftMagnitudes: length must be a power of 2 >= 2");const r=new Float64Array(t),a=new Float64Array(t);for(let n=0;n<t;n+=1)r[n]=e[n];L(r,a);const o=new Float64Array(t>>1);for(let n=0;n<t>>1;n+=1)o[n]=Math.hypot(r[n],a[n]);return o}function k(e){const t=new Float64Array(e);if(e===1)return t[0]=1,t;const r=e-1;for(let a=0;a<e;a+=1)t[a]=.5*(1-Math.cos(2*Math.PI*a/r));return t}function S(e){const t=2**Math.round(Math.log2(e));return Math.min(8192,Math.max(32,t))}function b(e){const{numberOfChannels:t,length:r}=e;if(t===1)return e.getChannelData(0);const a=new Float32Array(r),o=1/t;for(let n=0;n<t;n+=1){const l=e.getChannelData(n);for(let s=0;s<r;s+=1)a[s]+=l[s]*o}return a}function B(e,t){if(t==="mix")return b(e);const r=Math.max(0,Math.min(e.numberOfChannels-1,t));return e.getChannelData(r)}function E(e,t,r){const a=[],o=e.length;if(o===0){for(let l=0;l<t;l+=1)a.push(Array.from({length:r},()=>0));return a}const n=o/t;for(let l=0;l<t;l+=1){const s=[],g=Math.floor(l*n),u=Math.floor((l+1)*n),f=Math.max(1,u-g)/r;for(let d=0;d<r;d+=1){const i=Math.floor(g+d*f),h=Math.min(u,Math.floor(g+(d+1)*f));let M=0;for(let c=i;c<h;c+=1)M=Math.max(M,Math.abs(e[c]??0));s.push(M)}a.push(s)}return a}function z(e,t,r,a){const o=[];let n=1e-12;const l=e.length,s=S(r),g=s>>1,u=Math.min(a,g),w=k(s);if(l<s){for(let f=0;f<t;f+=1)o.push(Array.from({length:u},()=>0));return{rows:o,maxMag:1}}for(let f=0;f<t;f+=1){const d=t<=1?0:Math.min(Math.floor(f*(l-s)/(t-1)),l-s),i=new Float64Array(s);for(let c=0;c<s;c+=1)i[c]=(e[d+c]??0)*(w[c]??0);const h=C(i),M=[];for(let c=0;c<u;c+=1){const m=h[c]??0;M.push(m),n=Math.max(n,m)}o.push(M)}return{rows:o,maxMag:n}}function A(e,t={}){const r=Math.max(1,t.timeSlices??128),a=Math.max(1,t.samplesPerSlice??8),o=!!t.spectrogram,n=t.fftSize??1024,l=Math.max(1,t.frequencyBins??256),s=t.channel??0,g=B(e,s),u=E(g,r,a),w={duration:e.duration,sampleRate:e.sampleRate,amplitudeGrid:u};if(o){const{rows:f,maxMag:d}=z(g,r,n,l),i=d>0?1/d:1;w.spectrogram=f.map(h=>h.map(M=>M*i))}return w}async function x(e,t={}){const r=await fetch(e);if(!r.ok)throw new Error(`Fetch failed: ${r.status} ${r.statusText}`);const a=await r.arrayBuffer(),o=window.AudioContext??window.webkitAudioContext;if(!o)throw new Error("Web Audio API is not available");const n=new o;try{const l=await n.decodeAudioData(a.slice(0));return A(l,t)}finally{await n.close()}}function P(e,t={}){const[r,a]=y.useState({data:null,isLoading:!1,error:null});return y.useEffect(()=>{if(!e){a({data:null,isLoading:!1,error:null});return}if(typeof window>"u"){a({data:null,isLoading:!1,error:null});return}let o=!1;return a(n=>({...n,isLoading:!0,error:null})),(async()=>{try{const n=await x(e,t);o||a({data:n,isLoading:!1,error:null})}catch(n){o||a({data:null,isLoading:!1,error:n instanceof Error?n.message:"Failed to analyze audio file"})}})(),()=>{o=!0}},[e,t.timeSlices,t.samplesPerSlice,t.spectrogram,t.fftSize,t.frequencyBins,t.channel]),r}exports.analyzeAudioBuffer=A;exports.analyzeAudioFile=x;exports.useAudioFileAnalysis=P;exports.useAudioPeaks=F;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|