@music-lyric-player/base 0.9.0 → 0.10.0
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 +8 -8
- package/dist/index.comm.js +1 -1
- package/dist/index.comm.js.map +1 -1
- package/dist/index.ecma.d.ts +52 -6
- package/dist/index.ecma.js +64 -39
- package/dist/index.ecma.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -14,12 +14,12 @@ npm install @music-lyric-player/base music-lyric-kit
|
|
|
14
14
|
|
|
15
15
|
## Events
|
|
16
16
|
|
|
17
|
-
| Event
|
|
18
|
-
|
|
|
19
|
-
| `play`
|
|
20
|
-
| `pause`
|
|
21
|
-
| `lyricUpdate` | `(info: Info)`
|
|
22
|
-
| `linesUpdate` | `(lines, indexes, firstIndex, isSeek)` | Active lines change
|
|
17
|
+
| Event | Payload | Fires when |
|
|
18
|
+
| ------------- | -------------------------------------- | -------------------------- |
|
|
19
|
+
| `play` | `(currentTime: number)` | Playback starts or resumes |
|
|
20
|
+
| `pause` | `(currentTime: number)` | Playback pauses |
|
|
21
|
+
| `lyricUpdate` | `(info: Info)` | A new lyric is loaded |
|
|
22
|
+
| `linesUpdate` | `(lines, indexes, firstIndex, isSeek)` | Active lines change |
|
|
23
23
|
|
|
24
24
|
## Usage
|
|
25
25
|
|
|
@@ -50,8 +50,8 @@ base.play(0)
|
|
|
50
50
|
|
|
51
51
|
## Options
|
|
52
52
|
|
|
53
|
-
| Field
|
|
54
|
-
|
|
|
53
|
+
| Field | Type | Default | Description |
|
|
54
|
+
| -------- | ------------------------ | --------- | ------------------------------------------------------------------------------------ |
|
|
55
55
|
| `driver` | `'animation' \| 'timer'` | `'timer'` | Tick source. `animation` uses `requestAnimationFrame`; `timer` uses `setTimeout(16)` |
|
|
56
56
|
|
|
57
57
|
```js
|
package/dist/index.comm.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("@music-lyric-player/utils");require("lodash-es");const o=l.freezeObjectDeep({driver:"animation",bridgeActive:!0}),f=Object.freeze(Object.defineProperty({__proto__:null,DEFAULT:o},Symbol.toStringTag,{value:"Module"})),m="0.5.1";class d{get version(){return m}type="Incorrect";metas=[];lines=[];agents=[];toJSON(){return{version:this.version,type:this.type,metas:this.metas,lines:this.lines,agents:this.agents}}}class g{config=new l.ConfigManager(o);event=new l.Event;state;active;time;info;constructor(){this.state={playing:!1,frameId:null,timerId:null,scanIndex:0},this.active={lines:[],index:[]},this.time={start:0,seek:0},this.info=new d}handleGetCurrentTime(){return this.state.playing?this.time.seek+(performance.now()-this.time.start):this.time.seek}handleGetLineTime(e){if(e<0||e>=this.info.lines.length)return 0;if(e===this.info.lines.length-1)return 1/0;const t=this.info.lines[e],s=this.info.lines[e+1];return Math.max(t.time.end,s.time.start)}handleGetActiveIndex(){return this.active.index.length>0?this.active.index[0]:-1}handleBridgeActive(e,t){if(!this.config.current.bridgeActive||t.length<2)return{lines:e,index:t};const s=t[0],n=t[t.length-1];if(n-s+1===t.length)return{lines:e,index:t};const i=new Map;for(let a=0;a<t.length;a++)i.set(t[a],e[a]);const r=[],h=[];for(let a=s;a<=n;a++){const c=i.get(a)??this.info.lines[a];c&&(r.push(c),h.push(a))}return{lines:r,index:h}}handleEmitLinesUpdate(e){const t=this.handleBridgeActive(this.active.lines,this.active.index);this.event.emit("linesUpdate",t.lines,t.index,this.handleGetActiveIndex(),e)}handleSyncTime(e){const t=[],s=[];let n=this.info.lines.length;for(let i=0;i<this.info.lines.length;i++){const r=this.info.lines[i];if(r.time.start>e){n=i;break}this.handleGetLineTime(i)>e&&(t.push(r),s.push(i))}this.state.scanIndex=n,this.active.lines=t,this.active.index=s,this.handleEmitLinesUpdate(!0)}handleUpdateActiveLines(e){let t=!1;const s=[],n=[];for(let i=0;i<this.active.lines.length;i++){const r=this.active.lines[i],h=this.active.index[i];e>=this.handleGetLineTime(h)?t=!0:(s.push(r),n.push(h))}for(;this.state.scanIndex<this.info.lines.length;){const i=this.info.lines[this.state.scanIndex];if(e>=i.time.start)e<this.handleGetLineTime(this.state.scanIndex)&&(s.push(i),n.push(this.state.scanIndex),t=!0),this.state.scanIndex++;else break}t&&(this.active.lines=s,this.active.index=n,this.handleEmitLinesUpdate(!1))}onTick=()=>{if(!this.state.playing)return;const e=this.handleGetCurrentTime();switch(this.handleUpdateActiveLines(e),this.config.current.driver){case"animation":this.state.frameId=window.requestAnimationFrame(this.onTick);break;case"timer":this.state.timerId=window.setTimeout(this.onTick,16);break}};updateLyric(e){e&&(this.pause(),this.info=e,this.active.lines=[],this.active.index=[],this.state.scanIndex=0,this.time.seek=0,this.event.emit("lyricUpdate",e),this.event.emit("linesUpdate",[],[],-1,!1))}play(e){this.pause(),typeof e=="number"&&!Number.isNaN(e)&&(this.time.seek=e,this.handleSyncTime(e)),this.time.start=performance.now(),this.state.playing=!0,this.onTick(),this.event.emit("play",this.handleGetCurrentTime())}pause(){this.state.playing&&(this.time.seek=this.handleGetCurrentTime(),this.state.playing=!1),this.state.frameId!==null&&(cancelAnimationFrame(this.state.frameId),this.state.frameId=null),this.state.timerId!==null&&(clearTimeout(this.state.timerId),this.state.timerId=null),this.event.emit("pause",this.handleGetCurrentTime())}dispose(){this.pause(),this.event.clear(),this.active.lines=[],this.active.index=[],this.info=new d}matchLinesWithTime(e){const t=[],s=[];for(let n=0;n<this.info.lines.length;n++){const i=this.info.lines[n];if(i.time.start>e)break;this.handleGetLineTime(n)>e&&(t.push(i),s.push(n))}return this.handleBridgeActive(t,s)}get currentPlaying(){return this.state.playing}get currentLines(){return this.handleBridgeActive(this.active.lines,this.active.index).lines}get currentIndex(){return this.handleBridgeActive(this.active.lines,this.active.index).index}get currentActive(){return this.handleGetActiveIndex()}get currentInfo(){return this.info}get currentTime(){return this.handleGetCurrentTime()}}exports.BaseLyricPlayer=g;exports.BaseLyricPlayerConfig=f;
|
|
2
2
|
//# sourceMappingURL=index.comm.js.map
|
package/dist/index.comm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.comm.js","sources":["../src/options.ts","../../../node_modules/.pnpm/@music-lyric-kit+lyric@0.4.0/node_modules/@music-lyric-kit/lyric/dist/index.ecma.js","../src/index.ts"],"sourcesContent":["export interface Options {\n /**\n * Driver type for playback scheduling.\n * - `animation`: use requestAnimationFrame\n * - `timer`: use setTimeout\n * @default animation\n */\n driver: 'timer' | 'animation'\n}\n\nexport const DEFAULT_OPTIONS: Options = {\n driver: 'timer',\n}\n","import { createRandomHex as r } from \"@music-lyric-kit/utils\";\nclass s {\n start = 0;\n end = 0;\n get duration() {\n return this.end - this.start;\n }\n toJSON() {\n return {\n start: this.start,\n end: this.end,\n duration: this.duration\n };\n }\n}\nvar o = /* @__PURE__ */ ((t) => (t.Normal = \"Normal\", t.Space = \"Space\", t))(o || {});\nclass i {\n stress = !1;\n toJSON() {\n return {\n stress: this.stress\n };\n }\n}\nclass p {\n get type() {\n return \"Normal\";\n }\n time = new s();\n content = \"\";\n extended = [];\n config = new i();\n toJSON() {\n return {\n type: this.type,\n time: this.time,\n content: this.content,\n extended: this.extended,\n config: this.config\n };\n }\n}\nclass N {\n get type() {\n return \"Space\";\n }\n count = 1;\n toJSON() {\n return {\n type: this.type,\n count: this.count\n };\n }\n}\nvar a = /* @__PURE__ */ ((t) => (t.UnKnown = \"UnKnown\", t.Translate = \"Translate\", t.Roman = \"Roman\", t))(a || {});\nclass S {\n type = \"UnKnown\";\n content = \"\";\n toJSON() {\n return {\n type: this.type,\n content: this.content\n };\n }\n}\nvar l = /* @__PURE__ */ ((t) => (t.Normal = \"Normal\", t.Interlude = \"Interlude\", t))(l || {});\nclass x {\n get type() {\n return \"Interlude\";\n }\n id = r(4).toUpperCase();\n time = new s();\n toJSON() {\n return {\n id: this.id,\n type: this.type,\n time: this.time\n };\n }\n}\nclass c {\n words = [];\n extended = [];\n get original() {\n return this.words.map((n) => n.type === o.Normal ? n.content : new Array(n.count).fill(\" \").join(\"\")).join(\"\");\n }\n toJSON() {\n return {\n words: this.words,\n extended: this.extended,\n original: this.original\n };\n }\n}\nclass y {\n get type() {\n return \"Normal\";\n }\n id = r(4).toUpperCase();\n time = new s();\n content = new c();\n agent;\n background;\n toJSON() {\n return {\n id: this.id,\n type: this.type,\n time: this.time,\n content: this.content,\n agent: this.agent,\n background: this.background\n };\n }\n}\nvar u = /* @__PURE__ */ ((t) => (t.Offset = \"Offset\", t.Duration = \"Duration\", t.Title = \"Title\", t.Singer = \"Singer\", t.Album = \"Album\", t.Creator = \"Creator\", t.UnKnown = \"UnKnown\", t))(u || {});\nclass e {\n id = r(4).toUpperCase();\n toJSON() {\n return {\n id: this.id,\n type: this.type,\n content: this.content\n };\n }\n}\nclass f extends e {\n get type() {\n return \"Offset\";\n }\n content = 0;\n}\nclass w extends e {\n get type() {\n return \"Duration\";\n }\n content = 0;\n}\nclass O extends e {\n get type() {\n return \"Title\";\n }\n content = \"\";\n}\nclass b extends e {\n get type() {\n return \"Singer\";\n }\n content = \"\";\n}\nclass J extends e {\n get type() {\n return \"Album\";\n }\n content = \"\";\n}\nclass U extends e {\n get type() {\n return \"Creator\";\n }\n content = {\n role: \"\",\n name: []\n };\n}\nclass C extends e {\n get type() {\n return \"UnKnown\";\n }\n content = \"\";\n}\nclass I {\n id = \"\";\n name = \"\";\n count = 0;\n}\nclass d {\n // index in global\n global = 0;\n // index in block\n block = 0;\n toJSON() {\n return {\n global: this.global,\n block: this.block\n };\n }\n}\nclass v {\n id = \"\";\n index = new d();\n toJSON() {\n return {\n id: this.id,\n index: this.index\n };\n }\n}\nconst m = \"0.5.1\";\nvar g = /* @__PURE__ */ ((t) => (t.Incorrect = \"Incorrect\", t.Normal = \"Normal\", t.Syllable = \"Syllable\", t.Pure = \"Pure\", t.Empty = \"Empty\", t.NoTime = \"NoTime\", t))(g || {});\nclass A {\n get version() {\n return m;\n }\n type = \"Incorrect\";\n metas = [];\n lines = [];\n agents = [];\n toJSON() {\n return {\n version: this.version,\n type: this.type,\n metas: this.metas,\n lines: this.lines,\n agents: this.agents\n };\n }\n}\nexport {\n I as Agent,\n v as AgentLine,\n d as AgentLineIndex,\n S as Extended,\n a as ExtendedType,\n A as Info,\n x as LineInterlude,\n y as LineNormal,\n c as LineNormalContent,\n l as LineType,\n J as MetaAlbum,\n U as MetaCreator,\n w as MetaDuration,\n f as MetaOffset,\n b as MetaSinger,\n O as MetaTitle,\n u as MetaType,\n C as MetaUnKnown,\n s as Time,\n g as Type,\n m as Version,\n p as WordNormal,\n N as WordSpace,\n o as WordType\n};\n//# sourceMappingURL=index.ecma.js.map\n","import type { Line } from '@music-lyric-kit/lyric'\nimport type { DeepPartial } from '@music-lyric-player/utils'\nimport type { Options } from './options'\n\nimport { DEFAULT_OPTIONS } from './options'\n\nimport { Info } from '@music-lyric-kit/lyric'\nimport { ConfigManager, Event } from '@music-lyric-player/utils'\n\nexport interface BaseLyricPlayerEventMap {\n /**\n * When the player starts or resumes playback.\n * @param currentTime The current playback time.\n */\n play: (currentTime: number) => void\n\n /**\n * When the player pauses playback.\n * @param currentTime The current playback time.\n */\n pause: (currentTime: number) => void\n\n /**\n * When the entire lyric information is updated (e.g., loading a new lyric/song).\n * @param info The newly loaded lyric information object.\n */\n lyricUpdate: (info: Info) => void\n\n /**\n * When the currently active lyric lines change during playback.\n * @param lines An array of the currently active lyric lines.\n * @param indexs An array of the currently active lyric lines' indexes.\n * @param firstIndex The index of the first currently active lyric line (-1 if none).\n * @param isSeek Is seek.\n */\n linesUpdate: (lines: Line[], indexs: number[], index: number, isSeek: boolean) => void\n}\n\nexport class BaseLyricPlayer {\n readonly config = new ConfigManager<Options, DeepPartial<Options>>(DEFAULT_OPTIONS)\n\n readonly event: Event<BaseLyricPlayerEventMap> = new Event()\n\n private state: {\n playing: boolean\n frameId: number | null\n timerId: number | null\n scanIndex: number\n }\n private active: {\n lines: Line[]\n index: number[]\n }\n private time: {\n start: number\n seek: number\n }\n private info: Info\n\n constructor() {\n this.state = {\n playing: false,\n frameId: null,\n timerId: null,\n scanIndex: 0,\n }\n this.active = {\n lines: [],\n index: [],\n }\n this.time = {\n start: 0,\n seek: 0,\n }\n this.info = new Info()\n }\n\n private handleGetCurrentTime() {\n if (!this.state.playing) {\n return this.time.seek\n }\n return this.time.seek + (performance.now() - this.time.start)\n }\n\n private handleGetLineTime(index: number): number {\n if (index < 0 || index >= this.info.lines.length) {\n return 0\n }\n\n if (index === this.info.lines.length - 1) {\n return Infinity\n }\n\n const line = this.info.lines[index]\n const nextLine = this.info.lines[index + 1]\n return Math.max(line.time.end, nextLine.time.start)\n }\n\n private handleGetActiveIndex() {\n return this.active.index.length > 0 ? this.active.index[0] : -1\n }\n\n private handleSyncTime(time: number) {\n const lines: Line[] = []\n const index: number[] = []\n\n let firstIndex = this.info.lines.length\n for (let i = 0; i < this.info.lines.length; i++) {\n const line = this.info.lines[i]\n if (line.time.start > time) {\n firstIndex = i\n break\n }\n\n if (this.handleGetLineTime(i) > time) {\n lines.push(line)\n index.push(i)\n }\n }\n\n this.state.scanIndex = firstIndex\n\n this.active.lines = lines\n this.active.index = index\n\n this.event.emit('linesUpdate', [...this.active.lines], [...this.active.index], this.handleGetActiveIndex(), true)\n }\n\n private handleUpdateActiveLines(now: number) {\n let hasChanged = false\n\n const newActiveLines: Line[] = []\n const newActiveIndex: number[] = []\n\n for (let i = 0; i < this.active.lines.length; i++) {\n const line = this.active.lines[i]\n const infoIndex = this.active.index[i]\n\n if (now >= this.handleGetLineTime(infoIndex)) {\n hasChanged = true\n } else {\n newActiveLines.push(line)\n newActiveIndex.push(infoIndex)\n }\n }\n\n while (this.state.scanIndex < this.info.lines.length) {\n const nextLine = this.info.lines[this.state.scanIndex]\n if (now >= nextLine.time.start) {\n if (now < this.handleGetLineTime(this.state.scanIndex)) {\n newActiveLines.push(nextLine)\n newActiveIndex.push(this.state.scanIndex)\n hasChanged = true\n }\n this.state.scanIndex++\n } else {\n break\n }\n }\n\n if (!hasChanged) {\n return\n }\n\n this.active.lines = newActiveLines\n this.active.index = newActiveIndex\n this.event.emit('linesUpdate', [...this.active.lines], [...this.active.index], this.handleGetActiveIndex(), false)\n }\n\n private onTick = () => {\n if (!this.state.playing) {\n return\n }\n\n const now = this.handleGetCurrentTime()\n this.handleUpdateActiveLines(now)\n\n switch (this.config.current.driver) {\n case 'animation':\n this.state.frameId = window.requestAnimationFrame(this.onTick)\n break\n case 'timer':\n this.state.timerId = window.setTimeout(this.onTick, 16)\n break\n }\n }\n\n updateLyric(info: Info) {\n if (!info) {\n return\n }\n\n this.pause()\n this.info = info\n\n this.active.lines = []\n this.active.index = []\n\n this.state.scanIndex = 0\n this.time.seek = 0\n\n this.event.emit('lyricUpdate', info)\n this.event.emit('linesUpdate', [], [], -1, false)\n }\n\n /**\n * Start playback\n * @param time Optional time in ms to seek to before starting playback. If not provided, playback will start from the current position.\n */\n play(time?: number) {\n this.pause()\n\n if (typeof time === 'number' && !Number.isNaN(time)) {\n this.time.seek = time\n this.handleSyncTime(time)\n }\n\n this.time.start = performance.now()\n this.state.playing = true\n this.onTick()\n\n this.event.emit('play', this.handleGetCurrentTime())\n }\n\n /**\n * Pause playback\n */\n pause() {\n if (this.state.playing) {\n this.time.seek = this.handleGetCurrentTime()\n this.state.playing = false\n }\n if (this.state.frameId !== null) {\n cancelAnimationFrame(this.state.frameId)\n this.state.frameId = null\n }\n if (this.state.timerId !== null) {\n clearTimeout(this.state.timerId)\n this.state.timerId = null\n }\n\n this.event.emit('pause', this.handleGetCurrentTime())\n }\n\n /**\n * Stop playback\n */\n dispose() {\n this.pause()\n this.event.clear()\n\n this.active.lines = []\n this.active.index = []\n\n this.info = new Info()\n }\n\n /**\n * Find all active lines at the given time (ms). Does not mutate internal state.\n * @param time time in ms to find active lines for.\n */\n matchLinesWithTime(time: number): { lines: Line[]; index: number[] } {\n const lines: Line[] = []\n const index: number[] = []\n for (let i = 0; i < this.info.lines.length; i++) {\n const line = this.info.lines[i]\n if (line.time.start > time) {\n break\n }\n if (this.handleGetLineTime(i) > time) {\n lines.push(line)\n index.push(i)\n }\n }\n return { lines, index }\n }\n\n /**\n * Whether the player is currently playing.\n */\n get currentPlaying() {\n return this.state.playing\n }\n\n /**\n * Current active lines.\n */\n get currentLines() {\n return [...this.active.lines]\n }\n\n /**\n * Indices of currently active lines.\n */\n get currentIndex() {\n return [...this.active.index]\n }\n\n /**\n * The index of the primary active line, or -1 if none.\n */\n get currentActive() {\n return this.handleGetActiveIndex()\n }\n\n /**\n * The current lyric info object.\n */\n get currentInfo() {\n return this.info\n }\n\n /**\n * The current playback time in ms.\n */\n get currentTime() {\n return this.handleGetCurrentTime()\n }\n}\n"],"names":["DEFAULT_OPTIONS","m","A","BaseLyricPlayer","ConfigManager","Event","Info","index","line","nextLine","time","lines","firstIndex","i","now","hasChanged","newActiveLines","newActiveIndex","infoIndex","info"],"mappings":"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","x_google_ignoreList":[1]}
|
|
1
|
+
{"version":3,"file":"index.comm.js","sources":["../src/config/root.ts","../../../node_modules/.pnpm/@music-lyric-kit+lyric@0.4.0/node_modules/@music-lyric-kit/lyric/dist/index.ecma.js","../src/core.ts"],"sourcesContent":["import type { ConfigManager, DeepRequired, NestedKeys } from '@music-lyric-player/utils'\n\nimport { freezeObjectDeep } from '@music-lyric-player/utils'\n\nexport interface Root {\n /**\n * Driver type for playback scheduling.\n * - `animation`: use requestAnimationFrame\n * - `timer`: use setTimeout\n *\n * @default 'animation'\n */\n driver?: 'timer' | 'animation'\n /**\n * Whether to bridge gaps between simultaneously active lines.\n *\n * Active lines may not be consecutive — a line in the middle could have already ended (`played`) while its neighbors are still active, producing a `[active, played, active]` pattern.\n *\n * Enabling this promotes the sandwiched lines back to active so the visual reads as one continuous `[active, active, active]` block.\n *\n * @default true\n */\n bridgeActive?: boolean\n}\n\n/**\n * Fully‑resolved config in which every field is required, produced by deep‑requiring the user‑facing {@link Config}.\n */\nexport type RootRequired = DeepRequired<Root>\n\n/**\n * All config keys\n */\nexport type RootKeys = NestedKeys<Root>\n\n/**\n * Set of config key paths that changed since the previous value, as emitted by `ConfigManager.event['update']`.\n */\nexport type RootKeySet = Set<RootKeys>\n\n/**\n * Runtime config manager bound to this module's {@link Config} shape.\n */\nexport type RootManager = ConfigManager<RootRequired, Root>\n\nexport const DEFAULT: Root = freezeObjectDeep({\n driver: 'animation',\n bridgeActive: true,\n})\n","import { createRandomHex as r } from \"@music-lyric-kit/utils\";\nclass s {\n start = 0;\n end = 0;\n get duration() {\n return this.end - this.start;\n }\n toJSON() {\n return {\n start: this.start,\n end: this.end,\n duration: this.duration\n };\n }\n}\nvar o = /* @__PURE__ */ ((t) => (t.Normal = \"Normal\", t.Space = \"Space\", t))(o || {});\nclass i {\n stress = !1;\n toJSON() {\n return {\n stress: this.stress\n };\n }\n}\nclass p {\n get type() {\n return \"Normal\";\n }\n time = new s();\n content = \"\";\n extended = [];\n config = new i();\n toJSON() {\n return {\n type: this.type,\n time: this.time,\n content: this.content,\n extended: this.extended,\n config: this.config\n };\n }\n}\nclass N {\n get type() {\n return \"Space\";\n }\n count = 1;\n toJSON() {\n return {\n type: this.type,\n count: this.count\n };\n }\n}\nvar a = /* @__PURE__ */ ((t) => (t.UnKnown = \"UnKnown\", t.Translate = \"Translate\", t.Roman = \"Roman\", t))(a || {});\nclass S {\n type = \"UnKnown\";\n content = \"\";\n toJSON() {\n return {\n type: this.type,\n content: this.content\n };\n }\n}\nvar l = /* @__PURE__ */ ((t) => (t.Normal = \"Normal\", t.Interlude = \"Interlude\", t))(l || {});\nclass x {\n get type() {\n return \"Interlude\";\n }\n id = r(4).toUpperCase();\n time = new s();\n toJSON() {\n return {\n id: this.id,\n type: this.type,\n time: this.time\n };\n }\n}\nclass c {\n words = [];\n extended = [];\n get original() {\n return this.words.map((n) => n.type === o.Normal ? n.content : new Array(n.count).fill(\" \").join(\"\")).join(\"\");\n }\n toJSON() {\n return {\n words: this.words,\n extended: this.extended,\n original: this.original\n };\n }\n}\nclass y {\n get type() {\n return \"Normal\";\n }\n id = r(4).toUpperCase();\n time = new s();\n content = new c();\n agent;\n background;\n toJSON() {\n return {\n id: this.id,\n type: this.type,\n time: this.time,\n content: this.content,\n agent: this.agent,\n background: this.background\n };\n }\n}\nvar u = /* @__PURE__ */ ((t) => (t.Offset = \"Offset\", t.Duration = \"Duration\", t.Title = \"Title\", t.Singer = \"Singer\", t.Album = \"Album\", t.Creator = \"Creator\", t.UnKnown = \"UnKnown\", t))(u || {});\nclass e {\n id = r(4).toUpperCase();\n toJSON() {\n return {\n id: this.id,\n type: this.type,\n content: this.content\n };\n }\n}\nclass f extends e {\n get type() {\n return \"Offset\";\n }\n content = 0;\n}\nclass w extends e {\n get type() {\n return \"Duration\";\n }\n content = 0;\n}\nclass O extends e {\n get type() {\n return \"Title\";\n }\n content = \"\";\n}\nclass b extends e {\n get type() {\n return \"Singer\";\n }\n content = \"\";\n}\nclass J extends e {\n get type() {\n return \"Album\";\n }\n content = \"\";\n}\nclass U extends e {\n get type() {\n return \"Creator\";\n }\n content = {\n role: \"\",\n name: []\n };\n}\nclass C extends e {\n get type() {\n return \"UnKnown\";\n }\n content = \"\";\n}\nclass I {\n id = \"\";\n name = \"\";\n count = 0;\n}\nclass d {\n // index in global\n global = 0;\n // index in block\n block = 0;\n toJSON() {\n return {\n global: this.global,\n block: this.block\n };\n }\n}\nclass v {\n id = \"\";\n index = new d();\n toJSON() {\n return {\n id: this.id,\n index: this.index\n };\n }\n}\nconst m = \"0.5.1\";\nvar g = /* @__PURE__ */ ((t) => (t.Incorrect = \"Incorrect\", t.Normal = \"Normal\", t.Syllable = \"Syllable\", t.Pure = \"Pure\", t.Empty = \"Empty\", t.NoTime = \"NoTime\", t))(g || {});\nclass A {\n get version() {\n return m;\n }\n type = \"Incorrect\";\n metas = [];\n lines = [];\n agents = [];\n toJSON() {\n return {\n version: this.version,\n type: this.type,\n metas: this.metas,\n lines: this.lines,\n agents: this.agents\n };\n }\n}\nexport {\n I as Agent,\n v as AgentLine,\n d as AgentLineIndex,\n S as Extended,\n a as ExtendedType,\n A as Info,\n x as LineInterlude,\n y as LineNormal,\n c as LineNormalContent,\n l as LineType,\n J as MetaAlbum,\n U as MetaCreator,\n w as MetaDuration,\n f as MetaOffset,\n b as MetaSinger,\n O as MetaTitle,\n u as MetaType,\n C as MetaUnKnown,\n s as Time,\n g as Type,\n m as Version,\n p as WordNormal,\n N as WordSpace,\n o as WordType\n};\n//# sourceMappingURL=index.ecma.js.map\n","import type { Line } from '@music-lyric-kit/lyric'\nimport type { BaseLyricPlayerEventMap } from './interface'\n\nimport { Info } from '@music-lyric-kit/lyric'\nimport { ConfigManager, Event } from '@music-lyric-player/utils'\nimport { BaseLyricPlayerConfig } from './config'\n\nexport class BaseLyricPlayer {\n readonly config: BaseLyricPlayerConfig.RootManager = new ConfigManager(BaseLyricPlayerConfig.DEFAULT as BaseLyricPlayerConfig.RootRequired)\n\n readonly event: Event<BaseLyricPlayerEventMap> = new Event()\n\n private state: {\n playing: boolean\n frameId: number | null\n timerId: number | null\n scanIndex: number\n }\n private active: {\n lines: Line[]\n index: number[]\n }\n private time: {\n start: number\n seek: number\n }\n private info: Info\n\n constructor() {\n this.state = {\n playing: false,\n frameId: null,\n timerId: null,\n scanIndex: 0,\n }\n this.active = {\n lines: [],\n index: [],\n }\n this.time = {\n start: 0,\n seek: 0,\n }\n this.info = new Info()\n }\n\n private handleGetCurrentTime() {\n if (!this.state.playing) {\n return this.time.seek\n }\n return this.time.seek + (performance.now() - this.time.start)\n }\n\n private handleGetLineTime(index: number): number {\n if (index < 0 || index >= this.info.lines.length) {\n return 0\n }\n\n if (index === this.info.lines.length - 1) {\n return Infinity\n }\n\n const line = this.info.lines[index]\n const nextLine = this.info.lines[index + 1]\n return Math.max(line.time.end, nextLine.time.start)\n }\n\n private handleGetActiveIndex() {\n return this.active.index.length > 0 ? this.active.index[0] : -1\n }\n\n private handleBridgeActive(lines: Line[], index: number[]): { lines: Line[]; index: number[] } {\n if (!this.config.current.bridgeActive || index.length < 2) {\n return { lines, index }\n }\n const min = index[0]\n const max = index[index.length - 1]\n if (max - min + 1 === index.length) {\n return { lines, index }\n }\n const existing = new Map<number, Line>()\n for (let i = 0; i < index.length; i++) {\n existing.set(index[i], lines[i])\n }\n const bridgedLines: Line[] = []\n const bridgedIndex: number[] = []\n for (let i = min; i <= max; i++) {\n const line = existing.get(i) ?? this.info.lines[i]\n if (!line) continue\n bridgedLines.push(line)\n bridgedIndex.push(i)\n }\n return { lines: bridgedLines, index: bridgedIndex }\n }\n\n private handleEmitLinesUpdate(isSeek: boolean) {\n const bridged = this.handleBridgeActive(this.active.lines, this.active.index)\n this.event.emit('linesUpdate', bridged.lines, bridged.index, this.handleGetActiveIndex(), isSeek)\n }\n\n private handleSyncTime(time: number) {\n const lines: Line[] = []\n const index: number[] = []\n\n let firstIndex = this.info.lines.length\n for (let i = 0; i < this.info.lines.length; i++) {\n const line = this.info.lines[i]\n if (line.time.start > time) {\n firstIndex = i\n break\n }\n\n if (this.handleGetLineTime(i) > time) {\n lines.push(line)\n index.push(i)\n }\n }\n\n this.state.scanIndex = firstIndex\n\n this.active.lines = lines\n this.active.index = index\n\n this.handleEmitLinesUpdate(true)\n }\n\n private handleUpdateActiveLines(now: number) {\n let hasChanged = false\n\n const newActiveLines: Line[] = []\n const newActiveIndex: number[] = []\n\n for (let i = 0; i < this.active.lines.length; i++) {\n const line = this.active.lines[i]\n const infoIndex = this.active.index[i]\n\n if (now >= this.handleGetLineTime(infoIndex)) {\n hasChanged = true\n } else {\n newActiveLines.push(line)\n newActiveIndex.push(infoIndex)\n }\n }\n\n while (this.state.scanIndex < this.info.lines.length) {\n const nextLine = this.info.lines[this.state.scanIndex]\n if (now >= nextLine.time.start) {\n if (now < this.handleGetLineTime(this.state.scanIndex)) {\n newActiveLines.push(nextLine)\n newActiveIndex.push(this.state.scanIndex)\n hasChanged = true\n }\n this.state.scanIndex++\n } else {\n break\n }\n }\n\n if (!hasChanged) {\n return\n }\n\n this.active.lines = newActiveLines\n this.active.index = newActiveIndex\n this.handleEmitLinesUpdate(false)\n }\n\n private onTick = () => {\n if (!this.state.playing) {\n return\n }\n\n const now = this.handleGetCurrentTime()\n this.handleUpdateActiveLines(now)\n\n switch (this.config.current.driver) {\n case 'animation':\n this.state.frameId = window.requestAnimationFrame(this.onTick)\n break\n case 'timer':\n this.state.timerId = window.setTimeout(this.onTick, 16)\n break\n }\n }\n\n updateLyric(info: Info) {\n if (!info) {\n return\n }\n\n this.pause()\n this.info = info\n\n this.active.lines = []\n this.active.index = []\n\n this.state.scanIndex = 0\n this.time.seek = 0\n\n this.event.emit('lyricUpdate', info)\n this.event.emit('linesUpdate', [], [], -1, false)\n }\n\n /**\n * Start playback\n * @param time Optional time in ms to seek to before starting playback. If not provided, playback will start from the current position.\n */\n play(time?: number) {\n this.pause()\n\n if (typeof time === 'number' && !Number.isNaN(time)) {\n this.time.seek = time\n this.handleSyncTime(time)\n }\n\n this.time.start = performance.now()\n this.state.playing = true\n this.onTick()\n\n this.event.emit('play', this.handleGetCurrentTime())\n }\n\n /**\n * Pause playback\n */\n pause() {\n if (this.state.playing) {\n this.time.seek = this.handleGetCurrentTime()\n this.state.playing = false\n }\n if (this.state.frameId !== null) {\n cancelAnimationFrame(this.state.frameId)\n this.state.frameId = null\n }\n if (this.state.timerId !== null) {\n clearTimeout(this.state.timerId)\n this.state.timerId = null\n }\n\n this.event.emit('pause', this.handleGetCurrentTime())\n }\n\n /**\n * Stop playback\n */\n dispose() {\n this.pause()\n this.event.clear()\n\n this.active.lines = []\n this.active.index = []\n\n this.info = new Info()\n }\n\n /**\n * Find all active lines at the given time (ms). Does not mutate internal state.\n * @param time time in ms to find active lines for.\n */\n matchLinesWithTime(time: number): { lines: Line[]; index: number[] } {\n const lines: Line[] = []\n const index: number[] = []\n for (let i = 0; i < this.info.lines.length; i++) {\n const line = this.info.lines[i]\n if (line.time.start > time) {\n break\n }\n if (this.handleGetLineTime(i) > time) {\n lines.push(line)\n index.push(i)\n }\n }\n return this.handleBridgeActive(lines, index)\n }\n\n /**\n * Whether the player is currently playing.\n */\n get currentPlaying() {\n return this.state.playing\n }\n\n /**\n * Current active lines.\n */\n get currentLines() {\n return this.handleBridgeActive(this.active.lines, this.active.index).lines\n }\n\n /**\n * Indices of currently active lines.\n */\n get currentIndex() {\n return this.handleBridgeActive(this.active.lines, this.active.index).index\n }\n\n /**\n * The index of the primary active line, or -1 if none.\n */\n get currentActive() {\n return this.handleGetActiveIndex()\n }\n\n /**\n * The current lyric info object.\n */\n get currentInfo() {\n return this.info\n }\n\n /**\n * The current playback time in ms.\n */\n get currentTime() {\n return this.handleGetCurrentTime()\n }\n}\n"],"names":["DEFAULT","freezeObjectDeep","A","BaseLyricPlayer","ConfigManager","BaseLyricPlayerConfig.DEFAULT","Event","Info","index","line","nextLine","lines","min","max","existing","i","bridgedLines","bridgedIndex","isSeek","bridged","time","firstIndex","now","hasChanged","newActiveLines","newActiveIndex","infoIndex","info"],"mappings":"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","x_google_ignoreList":[1]}
|
package/dist/index.ecma.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { ConfigManager } from '@music-lyric-player/utils';
|
|
2
|
+
import { DeepRequired } from '@music-lyric-player/utils';
|
|
2
3
|
import { Event as Event_2 } from '@music-lyric-player/utils';
|
|
3
4
|
import { Info } from '@music-lyric-kit/lyric';
|
|
4
5
|
import { Line } from '@music-lyric-kit/lyric';
|
|
6
|
+
import { NestedKeys } from '@music-lyric-player/utils';
|
|
5
7
|
|
|
6
8
|
export declare class BaseLyricPlayer {
|
|
7
|
-
readonly config:
|
|
8
|
-
driver?: "timer" | "animation" | undefined;
|
|
9
|
-
}, "driver">;
|
|
9
|
+
readonly config: BaseLyricPlayerConfig.RootManager;
|
|
10
10
|
readonly event: Event_2<BaseLyricPlayerEventMap>;
|
|
11
11
|
private state;
|
|
12
12
|
private active;
|
|
@@ -16,6 +16,8 @@ export declare class BaseLyricPlayer {
|
|
|
16
16
|
private handleGetCurrentTime;
|
|
17
17
|
private handleGetLineTime;
|
|
18
18
|
private handleGetActiveIndex;
|
|
19
|
+
private handleBridgeActive;
|
|
20
|
+
private handleEmitLinesUpdate;
|
|
19
21
|
private handleSyncTime;
|
|
20
22
|
private handleUpdateActiveLines;
|
|
21
23
|
private onTick;
|
|
@@ -67,6 +69,17 @@ export declare class BaseLyricPlayer {
|
|
|
67
69
|
get currentTime(): number;
|
|
68
70
|
}
|
|
69
71
|
|
|
72
|
+
export declare namespace BaseLyricPlayerConfig {
|
|
73
|
+
export {
|
|
74
|
+
Root,
|
|
75
|
+
RootRequired,
|
|
76
|
+
RootKeys,
|
|
77
|
+
RootKeySet,
|
|
78
|
+
RootManager,
|
|
79
|
+
DEFAULT
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
70
83
|
export declare interface BaseLyricPlayerEventMap {
|
|
71
84
|
/**
|
|
72
85
|
* When the player starts or resumes playback.
|
|
@@ -93,14 +106,47 @@ export declare interface BaseLyricPlayerEventMap {
|
|
|
93
106
|
linesUpdate: (lines: Line[], indexs: number[], index: number, isSeek: boolean) => void;
|
|
94
107
|
}
|
|
95
108
|
|
|
96
|
-
declare
|
|
109
|
+
declare const DEFAULT: Root;
|
|
110
|
+
|
|
111
|
+
declare interface Root {
|
|
97
112
|
/**
|
|
98
113
|
* Driver type for playback scheduling.
|
|
99
114
|
* - `animation`: use requestAnimationFrame
|
|
100
115
|
* - `timer`: use setTimeout
|
|
101
|
-
*
|
|
116
|
+
*
|
|
117
|
+
* @default 'animation'
|
|
118
|
+
*/
|
|
119
|
+
driver?: 'timer' | 'animation';
|
|
120
|
+
/**
|
|
121
|
+
* Whether to bridge gaps between simultaneously active lines.
|
|
122
|
+
*
|
|
123
|
+
* Active lines may not be consecutive — a line in the middle could have already ended (`played`) while its neighbors are still active, producing a `[active, played, active]` pattern.
|
|
124
|
+
*
|
|
125
|
+
* Enabling this promotes the sandwiched lines back to active so the visual reads as one continuous `[active, active, active]` block.
|
|
126
|
+
*
|
|
127
|
+
* @default true
|
|
102
128
|
*/
|
|
103
|
-
|
|
129
|
+
bridgeActive?: boolean;
|
|
104
130
|
}
|
|
105
131
|
|
|
132
|
+
/**
|
|
133
|
+
* All config keys
|
|
134
|
+
*/
|
|
135
|
+
declare type RootKeys = NestedKeys<Root>;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Set of config key paths that changed since the previous value, as emitted by `ConfigManager.event['update']`.
|
|
139
|
+
*/
|
|
140
|
+
declare type RootKeySet = Set<RootKeys>;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Runtime config manager bound to this module's {@link Config} shape.
|
|
144
|
+
*/
|
|
145
|
+
declare type RootManager = ConfigManager<RootRequired, Root>;
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Fully‑resolved config in which every field is required, produced by deep‑requiring the user‑facing {@link Config}.
|
|
149
|
+
*/
|
|
150
|
+
declare type RootRequired = DeepRequired<Root>;
|
|
151
|
+
|
|
106
152
|
export { }
|
package/dist/index.ecma.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
import { freezeObjectDeep as u, ConfigManager as m, Event as f } from "@music-lyric-player/utils";
|
|
1
2
|
import "lodash-es";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
},
|
|
6
|
-
|
|
3
|
+
const o = u({
|
|
4
|
+
driver: "animation",
|
|
5
|
+
bridgeActive: !0
|
|
6
|
+
}), I = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
7
|
+
__proto__: null,
|
|
8
|
+
DEFAULT: o
|
|
9
|
+
}, Symbol.toStringTag, { value: "Module" })), g = "0.5.1";
|
|
10
|
+
class c {
|
|
7
11
|
get version() {
|
|
8
|
-
return
|
|
12
|
+
return g;
|
|
9
13
|
}
|
|
10
14
|
type = "Incorrect";
|
|
11
15
|
metas = [];
|
|
@@ -21,9 +25,9 @@ class r {
|
|
|
21
25
|
};
|
|
22
26
|
}
|
|
23
27
|
}
|
|
24
|
-
class
|
|
25
|
-
config = new
|
|
26
|
-
event = new
|
|
28
|
+
class x {
|
|
29
|
+
config = new m(o);
|
|
30
|
+
event = new f();
|
|
27
31
|
state;
|
|
28
32
|
active;
|
|
29
33
|
time;
|
|
@@ -40,7 +44,7 @@ class v {
|
|
|
40
44
|
}, this.time = {
|
|
41
45
|
start: 0,
|
|
42
46
|
seek: 0
|
|
43
|
-
}, this.info = new
|
|
47
|
+
}, this.info = new c();
|
|
44
48
|
}
|
|
45
49
|
handleGetCurrentTime() {
|
|
46
50
|
return this.state.playing ? this.time.seek + (performance.now() - this.time.start) : this.time.seek;
|
|
@@ -50,40 +54,60 @@ class v {
|
|
|
50
54
|
return 0;
|
|
51
55
|
if (e === this.info.lines.length - 1)
|
|
52
56
|
return 1 / 0;
|
|
53
|
-
const
|
|
54
|
-
return Math.max(
|
|
57
|
+
const t = this.info.lines[e], s = this.info.lines[e + 1];
|
|
58
|
+
return Math.max(t.time.end, s.time.start);
|
|
55
59
|
}
|
|
56
60
|
handleGetActiveIndex() {
|
|
57
61
|
return this.active.index.length > 0 ? this.active.index[0] : -1;
|
|
58
62
|
}
|
|
63
|
+
handleBridgeActive(e, t) {
|
|
64
|
+
if (!this.config.current.bridgeActive || t.length < 2)
|
|
65
|
+
return { lines: e, index: t };
|
|
66
|
+
const s = t[0], n = t[t.length - 1];
|
|
67
|
+
if (n - s + 1 === t.length)
|
|
68
|
+
return { lines: e, index: t };
|
|
69
|
+
const i = /* @__PURE__ */ new Map();
|
|
70
|
+
for (let a = 0; a < t.length; a++)
|
|
71
|
+
i.set(t[a], e[a]);
|
|
72
|
+
const h = [], r = [];
|
|
73
|
+
for (let a = s; a <= n; a++) {
|
|
74
|
+
const l = i.get(a) ?? this.info.lines[a];
|
|
75
|
+
l && (h.push(l), r.push(a));
|
|
76
|
+
}
|
|
77
|
+
return { lines: h, index: r };
|
|
78
|
+
}
|
|
79
|
+
handleEmitLinesUpdate(e) {
|
|
80
|
+
const t = this.handleBridgeActive(this.active.lines, this.active.index);
|
|
81
|
+
this.event.emit("linesUpdate", t.lines, t.index, this.handleGetActiveIndex(), e);
|
|
82
|
+
}
|
|
59
83
|
handleSyncTime(e) {
|
|
60
|
-
const
|
|
61
|
-
let
|
|
62
|
-
for (let
|
|
63
|
-
const
|
|
64
|
-
if (
|
|
65
|
-
|
|
84
|
+
const t = [], s = [];
|
|
85
|
+
let n = this.info.lines.length;
|
|
86
|
+
for (let i = 0; i < this.info.lines.length; i++) {
|
|
87
|
+
const h = this.info.lines[i];
|
|
88
|
+
if (h.time.start > e) {
|
|
89
|
+
n = i;
|
|
66
90
|
break;
|
|
67
91
|
}
|
|
68
|
-
this.handleGetLineTime(
|
|
92
|
+
this.handleGetLineTime(i) > e && (t.push(h), s.push(i));
|
|
69
93
|
}
|
|
70
|
-
this.state.scanIndex =
|
|
94
|
+
this.state.scanIndex = n, this.active.lines = t, this.active.index = s, this.handleEmitLinesUpdate(!0);
|
|
71
95
|
}
|
|
72
96
|
handleUpdateActiveLines(e) {
|
|
73
|
-
let
|
|
74
|
-
const
|
|
75
|
-
for (let
|
|
76
|
-
const
|
|
77
|
-
e >= this.handleGetLineTime(
|
|
97
|
+
let t = !1;
|
|
98
|
+
const s = [], n = [];
|
|
99
|
+
for (let i = 0; i < this.active.lines.length; i++) {
|
|
100
|
+
const h = this.active.lines[i], r = this.active.index[i];
|
|
101
|
+
e >= this.handleGetLineTime(r) ? t = !0 : (s.push(h), n.push(r));
|
|
78
102
|
}
|
|
79
103
|
for (; this.state.scanIndex < this.info.lines.length; ) {
|
|
80
|
-
const
|
|
81
|
-
if (e >=
|
|
82
|
-
e < this.handleGetLineTime(this.state.scanIndex) && (
|
|
104
|
+
const i = this.info.lines[this.state.scanIndex];
|
|
105
|
+
if (e >= i.time.start)
|
|
106
|
+
e < this.handleGetLineTime(this.state.scanIndex) && (s.push(i), n.push(this.state.scanIndex), t = !0), this.state.scanIndex++;
|
|
83
107
|
else
|
|
84
108
|
break;
|
|
85
109
|
}
|
|
86
|
-
|
|
110
|
+
t && (this.active.lines = s, this.active.index = n, this.handleEmitLinesUpdate(!1));
|
|
87
111
|
}
|
|
88
112
|
onTick = () => {
|
|
89
113
|
if (!this.state.playing)
|
|
@@ -118,21 +142,21 @@ class v {
|
|
|
118
142
|
* Stop playback
|
|
119
143
|
*/
|
|
120
144
|
dispose() {
|
|
121
|
-
this.pause(), this.event.clear(), this.active.lines = [], this.active.index = [], this.info = new
|
|
145
|
+
this.pause(), this.event.clear(), this.active.lines = [], this.active.index = [], this.info = new c();
|
|
122
146
|
}
|
|
123
147
|
/**
|
|
124
148
|
* Find all active lines at the given time (ms). Does not mutate internal state.
|
|
125
149
|
* @param time time in ms to find active lines for.
|
|
126
150
|
*/
|
|
127
151
|
matchLinesWithTime(e) {
|
|
128
|
-
const
|
|
129
|
-
for (let
|
|
130
|
-
const
|
|
131
|
-
if (
|
|
152
|
+
const t = [], s = [];
|
|
153
|
+
for (let n = 0; n < this.info.lines.length; n++) {
|
|
154
|
+
const i = this.info.lines[n];
|
|
155
|
+
if (i.time.start > e)
|
|
132
156
|
break;
|
|
133
|
-
this.handleGetLineTime(
|
|
157
|
+
this.handleGetLineTime(n) > e && (t.push(i), s.push(n));
|
|
134
158
|
}
|
|
135
|
-
return
|
|
159
|
+
return this.handleBridgeActive(t, s);
|
|
136
160
|
}
|
|
137
161
|
/**
|
|
138
162
|
* Whether the player is currently playing.
|
|
@@ -144,13 +168,13 @@ class v {
|
|
|
144
168
|
* Current active lines.
|
|
145
169
|
*/
|
|
146
170
|
get currentLines() {
|
|
147
|
-
return
|
|
171
|
+
return this.handleBridgeActive(this.active.lines, this.active.index).lines;
|
|
148
172
|
}
|
|
149
173
|
/**
|
|
150
174
|
* Indices of currently active lines.
|
|
151
175
|
*/
|
|
152
176
|
get currentIndex() {
|
|
153
|
-
return
|
|
177
|
+
return this.handleBridgeActive(this.active.lines, this.active.index).index;
|
|
154
178
|
}
|
|
155
179
|
/**
|
|
156
180
|
* The index of the primary active line, or -1 if none.
|
|
@@ -172,6 +196,7 @@ class v {
|
|
|
172
196
|
}
|
|
173
197
|
}
|
|
174
198
|
export {
|
|
175
|
-
|
|
199
|
+
x as BaseLyricPlayer,
|
|
200
|
+
I as BaseLyricPlayerConfig
|
|
176
201
|
};
|
|
177
202
|
//# sourceMappingURL=index.ecma.js.map
|
package/dist/index.ecma.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.ecma.js","sources":["../src/options.ts","../../../node_modules/.pnpm/@music-lyric-kit+lyric@0.4.0/node_modules/@music-lyric-kit/lyric/dist/index.ecma.js","../src/index.ts"],"sourcesContent":["export interface Options {\n /**\n * Driver type for playback scheduling.\n * - `animation`: use requestAnimationFrame\n * - `timer`: use setTimeout\n * @default animation\n */\n driver: 'timer' | 'animation'\n}\n\nexport const DEFAULT_OPTIONS: Options = {\n driver: 'timer',\n}\n","import { createRandomHex as r } from \"@music-lyric-kit/utils\";\nclass s {\n start = 0;\n end = 0;\n get duration() {\n return this.end - this.start;\n }\n toJSON() {\n return {\n start: this.start,\n end: this.end,\n duration: this.duration\n };\n }\n}\nvar o = /* @__PURE__ */ ((t) => (t.Normal = \"Normal\", t.Space = \"Space\", t))(o || {});\nclass i {\n stress = !1;\n toJSON() {\n return {\n stress: this.stress\n };\n }\n}\nclass p {\n get type() {\n return \"Normal\";\n }\n time = new s();\n content = \"\";\n extended = [];\n config = new i();\n toJSON() {\n return {\n type: this.type,\n time: this.time,\n content: this.content,\n extended: this.extended,\n config: this.config\n };\n }\n}\nclass N {\n get type() {\n return \"Space\";\n }\n count = 1;\n toJSON() {\n return {\n type: this.type,\n count: this.count\n };\n }\n}\nvar a = /* @__PURE__ */ ((t) => (t.UnKnown = \"UnKnown\", t.Translate = \"Translate\", t.Roman = \"Roman\", t))(a || {});\nclass S {\n type = \"UnKnown\";\n content = \"\";\n toJSON() {\n return {\n type: this.type,\n content: this.content\n };\n }\n}\nvar l = /* @__PURE__ */ ((t) => (t.Normal = \"Normal\", t.Interlude = \"Interlude\", t))(l || {});\nclass x {\n get type() {\n return \"Interlude\";\n }\n id = r(4).toUpperCase();\n time = new s();\n toJSON() {\n return {\n id: this.id,\n type: this.type,\n time: this.time\n };\n }\n}\nclass c {\n words = [];\n extended = [];\n get original() {\n return this.words.map((n) => n.type === o.Normal ? n.content : new Array(n.count).fill(\" \").join(\"\")).join(\"\");\n }\n toJSON() {\n return {\n words: this.words,\n extended: this.extended,\n original: this.original\n };\n }\n}\nclass y {\n get type() {\n return \"Normal\";\n }\n id = r(4).toUpperCase();\n time = new s();\n content = new c();\n agent;\n background;\n toJSON() {\n return {\n id: this.id,\n type: this.type,\n time: this.time,\n content: this.content,\n agent: this.agent,\n background: this.background\n };\n }\n}\nvar u = /* @__PURE__ */ ((t) => (t.Offset = \"Offset\", t.Duration = \"Duration\", t.Title = \"Title\", t.Singer = \"Singer\", t.Album = \"Album\", t.Creator = \"Creator\", t.UnKnown = \"UnKnown\", t))(u || {});\nclass e {\n id = r(4).toUpperCase();\n toJSON() {\n return {\n id: this.id,\n type: this.type,\n content: this.content\n };\n }\n}\nclass f extends e {\n get type() {\n return \"Offset\";\n }\n content = 0;\n}\nclass w extends e {\n get type() {\n return \"Duration\";\n }\n content = 0;\n}\nclass O extends e {\n get type() {\n return \"Title\";\n }\n content = \"\";\n}\nclass b extends e {\n get type() {\n return \"Singer\";\n }\n content = \"\";\n}\nclass J extends e {\n get type() {\n return \"Album\";\n }\n content = \"\";\n}\nclass U extends e {\n get type() {\n return \"Creator\";\n }\n content = {\n role: \"\",\n name: []\n };\n}\nclass C extends e {\n get type() {\n return \"UnKnown\";\n }\n content = \"\";\n}\nclass I {\n id = \"\";\n name = \"\";\n count = 0;\n}\nclass d {\n // index in global\n global = 0;\n // index in block\n block = 0;\n toJSON() {\n return {\n global: this.global,\n block: this.block\n };\n }\n}\nclass v {\n id = \"\";\n index = new d();\n toJSON() {\n return {\n id: this.id,\n index: this.index\n };\n }\n}\nconst m = \"0.5.1\";\nvar g = /* @__PURE__ */ ((t) => (t.Incorrect = \"Incorrect\", t.Normal = \"Normal\", t.Syllable = \"Syllable\", t.Pure = \"Pure\", t.Empty = \"Empty\", t.NoTime = \"NoTime\", t))(g || {});\nclass A {\n get version() {\n return m;\n }\n type = \"Incorrect\";\n metas = [];\n lines = [];\n agents = [];\n toJSON() {\n return {\n version: this.version,\n type: this.type,\n metas: this.metas,\n lines: this.lines,\n agents: this.agents\n };\n }\n}\nexport {\n I as Agent,\n v as AgentLine,\n d as AgentLineIndex,\n S as Extended,\n a as ExtendedType,\n A as Info,\n x as LineInterlude,\n y as LineNormal,\n c as LineNormalContent,\n l as LineType,\n J as MetaAlbum,\n U as MetaCreator,\n w as MetaDuration,\n f as MetaOffset,\n b as MetaSinger,\n O as MetaTitle,\n u as MetaType,\n C as MetaUnKnown,\n s as Time,\n g as Type,\n m as Version,\n p as WordNormal,\n N as WordSpace,\n o as WordType\n};\n//# sourceMappingURL=index.ecma.js.map\n","import type { Line } from '@music-lyric-kit/lyric'\nimport type { DeepPartial } from '@music-lyric-player/utils'\nimport type { Options } from './options'\n\nimport { DEFAULT_OPTIONS } from './options'\n\nimport { Info } from '@music-lyric-kit/lyric'\nimport { ConfigManager, Event } from '@music-lyric-player/utils'\n\nexport interface BaseLyricPlayerEventMap {\n /**\n * When the player starts or resumes playback.\n * @param currentTime The current playback time.\n */\n play: (currentTime: number) => void\n\n /**\n * When the player pauses playback.\n * @param currentTime The current playback time.\n */\n pause: (currentTime: number) => void\n\n /**\n * When the entire lyric information is updated (e.g., loading a new lyric/song).\n * @param info The newly loaded lyric information object.\n */\n lyricUpdate: (info: Info) => void\n\n /**\n * When the currently active lyric lines change during playback.\n * @param lines An array of the currently active lyric lines.\n * @param indexs An array of the currently active lyric lines' indexes.\n * @param firstIndex The index of the first currently active lyric line (-1 if none).\n * @param isSeek Is seek.\n */\n linesUpdate: (lines: Line[], indexs: number[], index: number, isSeek: boolean) => void\n}\n\nexport class BaseLyricPlayer {\n readonly config = new ConfigManager<Options, DeepPartial<Options>>(DEFAULT_OPTIONS)\n\n readonly event: Event<BaseLyricPlayerEventMap> = new Event()\n\n private state: {\n playing: boolean\n frameId: number | null\n timerId: number | null\n scanIndex: number\n }\n private active: {\n lines: Line[]\n index: number[]\n }\n private time: {\n start: number\n seek: number\n }\n private info: Info\n\n constructor() {\n this.state = {\n playing: false,\n frameId: null,\n timerId: null,\n scanIndex: 0,\n }\n this.active = {\n lines: [],\n index: [],\n }\n this.time = {\n start: 0,\n seek: 0,\n }\n this.info = new Info()\n }\n\n private handleGetCurrentTime() {\n if (!this.state.playing) {\n return this.time.seek\n }\n return this.time.seek + (performance.now() - this.time.start)\n }\n\n private handleGetLineTime(index: number): number {\n if (index < 0 || index >= this.info.lines.length) {\n return 0\n }\n\n if (index === this.info.lines.length - 1) {\n return Infinity\n }\n\n const line = this.info.lines[index]\n const nextLine = this.info.lines[index + 1]\n return Math.max(line.time.end, nextLine.time.start)\n }\n\n private handleGetActiveIndex() {\n return this.active.index.length > 0 ? this.active.index[0] : -1\n }\n\n private handleSyncTime(time: number) {\n const lines: Line[] = []\n const index: number[] = []\n\n let firstIndex = this.info.lines.length\n for (let i = 0; i < this.info.lines.length; i++) {\n const line = this.info.lines[i]\n if (line.time.start > time) {\n firstIndex = i\n break\n }\n\n if (this.handleGetLineTime(i) > time) {\n lines.push(line)\n index.push(i)\n }\n }\n\n this.state.scanIndex = firstIndex\n\n this.active.lines = lines\n this.active.index = index\n\n this.event.emit('linesUpdate', [...this.active.lines], [...this.active.index], this.handleGetActiveIndex(), true)\n }\n\n private handleUpdateActiveLines(now: number) {\n let hasChanged = false\n\n const newActiveLines: Line[] = []\n const newActiveIndex: number[] = []\n\n for (let i = 0; i < this.active.lines.length; i++) {\n const line = this.active.lines[i]\n const infoIndex = this.active.index[i]\n\n if (now >= this.handleGetLineTime(infoIndex)) {\n hasChanged = true\n } else {\n newActiveLines.push(line)\n newActiveIndex.push(infoIndex)\n }\n }\n\n while (this.state.scanIndex < this.info.lines.length) {\n const nextLine = this.info.lines[this.state.scanIndex]\n if (now >= nextLine.time.start) {\n if (now < this.handleGetLineTime(this.state.scanIndex)) {\n newActiveLines.push(nextLine)\n newActiveIndex.push(this.state.scanIndex)\n hasChanged = true\n }\n this.state.scanIndex++\n } else {\n break\n }\n }\n\n if (!hasChanged) {\n return\n }\n\n this.active.lines = newActiveLines\n this.active.index = newActiveIndex\n this.event.emit('linesUpdate', [...this.active.lines], [...this.active.index], this.handleGetActiveIndex(), false)\n }\n\n private onTick = () => {\n if (!this.state.playing) {\n return\n }\n\n const now = this.handleGetCurrentTime()\n this.handleUpdateActiveLines(now)\n\n switch (this.config.current.driver) {\n case 'animation':\n this.state.frameId = window.requestAnimationFrame(this.onTick)\n break\n case 'timer':\n this.state.timerId = window.setTimeout(this.onTick, 16)\n break\n }\n }\n\n updateLyric(info: Info) {\n if (!info) {\n return\n }\n\n this.pause()\n this.info = info\n\n this.active.lines = []\n this.active.index = []\n\n this.state.scanIndex = 0\n this.time.seek = 0\n\n this.event.emit('lyricUpdate', info)\n this.event.emit('linesUpdate', [], [], -1, false)\n }\n\n /**\n * Start playback\n * @param time Optional time in ms to seek to before starting playback. If not provided, playback will start from the current position.\n */\n play(time?: number) {\n this.pause()\n\n if (typeof time === 'number' && !Number.isNaN(time)) {\n this.time.seek = time\n this.handleSyncTime(time)\n }\n\n this.time.start = performance.now()\n this.state.playing = true\n this.onTick()\n\n this.event.emit('play', this.handleGetCurrentTime())\n }\n\n /**\n * Pause playback\n */\n pause() {\n if (this.state.playing) {\n this.time.seek = this.handleGetCurrentTime()\n this.state.playing = false\n }\n if (this.state.frameId !== null) {\n cancelAnimationFrame(this.state.frameId)\n this.state.frameId = null\n }\n if (this.state.timerId !== null) {\n clearTimeout(this.state.timerId)\n this.state.timerId = null\n }\n\n this.event.emit('pause', this.handleGetCurrentTime())\n }\n\n /**\n * Stop playback\n */\n dispose() {\n this.pause()\n this.event.clear()\n\n this.active.lines = []\n this.active.index = []\n\n this.info = new Info()\n }\n\n /**\n * Find all active lines at the given time (ms). Does not mutate internal state.\n * @param time time in ms to find active lines for.\n */\n matchLinesWithTime(time: number): { lines: Line[]; index: number[] } {\n const lines: Line[] = []\n const index: number[] = []\n for (let i = 0; i < this.info.lines.length; i++) {\n const line = this.info.lines[i]\n if (line.time.start > time) {\n break\n }\n if (this.handleGetLineTime(i) > time) {\n lines.push(line)\n index.push(i)\n }\n }\n return { lines, index }\n }\n\n /**\n * Whether the player is currently playing.\n */\n get currentPlaying() {\n return this.state.playing\n }\n\n /**\n * Current active lines.\n */\n get currentLines() {\n return [...this.active.lines]\n }\n\n /**\n * Indices of currently active lines.\n */\n get currentIndex() {\n return [...this.active.index]\n }\n\n /**\n * The index of the primary active line, or -1 if none.\n */\n get currentActive() {\n return this.handleGetActiveIndex()\n }\n\n /**\n * The current lyric info object.\n */\n get currentInfo() {\n return this.info\n }\n\n /**\n * The current playback time in ms.\n */\n get currentTime() {\n return this.handleGetCurrentTime()\n }\n}\n"],"names":["DEFAULT_OPTIONS","A","BaseLyricPlayer","ConfigManager","Event","Info","index","line","nextLine","time","lines","firstIndex","i","now","hasChanged","newActiveLines","newActiveIndex","infoIndex","info"],"mappings":"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","x_google_ignoreList":[1]}
|
|
1
|
+
{"version":3,"file":"index.ecma.js","sources":["../src/config/root.ts","../../../node_modules/.pnpm/@music-lyric-kit+lyric@0.4.0/node_modules/@music-lyric-kit/lyric/dist/index.ecma.js","../src/core.ts"],"sourcesContent":["import type { ConfigManager, DeepRequired, NestedKeys } from '@music-lyric-player/utils'\n\nimport { freezeObjectDeep } from '@music-lyric-player/utils'\n\nexport interface Root {\n /**\n * Driver type for playback scheduling.\n * - `animation`: use requestAnimationFrame\n * - `timer`: use setTimeout\n *\n * @default 'animation'\n */\n driver?: 'timer' | 'animation'\n /**\n * Whether to bridge gaps between simultaneously active lines.\n *\n * Active lines may not be consecutive — a line in the middle could have already ended (`played`) while its neighbors are still active, producing a `[active, played, active]` pattern.\n *\n * Enabling this promotes the sandwiched lines back to active so the visual reads as one continuous `[active, active, active]` block.\n *\n * @default true\n */\n bridgeActive?: boolean\n}\n\n/**\n * Fully‑resolved config in which every field is required, produced by deep‑requiring the user‑facing {@link Config}.\n */\nexport type RootRequired = DeepRequired<Root>\n\n/**\n * All config keys\n */\nexport type RootKeys = NestedKeys<Root>\n\n/**\n * Set of config key paths that changed since the previous value, as emitted by `ConfigManager.event['update']`.\n */\nexport type RootKeySet = Set<RootKeys>\n\n/**\n * Runtime config manager bound to this module's {@link Config} shape.\n */\nexport type RootManager = ConfigManager<RootRequired, Root>\n\nexport const DEFAULT: Root = freezeObjectDeep({\n driver: 'animation',\n bridgeActive: true,\n})\n","import { createRandomHex as r } from \"@music-lyric-kit/utils\";\nclass s {\n start = 0;\n end = 0;\n get duration() {\n return this.end - this.start;\n }\n toJSON() {\n return {\n start: this.start,\n end: this.end,\n duration: this.duration\n };\n }\n}\nvar o = /* @__PURE__ */ ((t) => (t.Normal = \"Normal\", t.Space = \"Space\", t))(o || {});\nclass i {\n stress = !1;\n toJSON() {\n return {\n stress: this.stress\n };\n }\n}\nclass p {\n get type() {\n return \"Normal\";\n }\n time = new s();\n content = \"\";\n extended = [];\n config = new i();\n toJSON() {\n return {\n type: this.type,\n time: this.time,\n content: this.content,\n extended: this.extended,\n config: this.config\n };\n }\n}\nclass N {\n get type() {\n return \"Space\";\n }\n count = 1;\n toJSON() {\n return {\n type: this.type,\n count: this.count\n };\n }\n}\nvar a = /* @__PURE__ */ ((t) => (t.UnKnown = \"UnKnown\", t.Translate = \"Translate\", t.Roman = \"Roman\", t))(a || {});\nclass S {\n type = \"UnKnown\";\n content = \"\";\n toJSON() {\n return {\n type: this.type,\n content: this.content\n };\n }\n}\nvar l = /* @__PURE__ */ ((t) => (t.Normal = \"Normal\", t.Interlude = \"Interlude\", t))(l || {});\nclass x {\n get type() {\n return \"Interlude\";\n }\n id = r(4).toUpperCase();\n time = new s();\n toJSON() {\n return {\n id: this.id,\n type: this.type,\n time: this.time\n };\n }\n}\nclass c {\n words = [];\n extended = [];\n get original() {\n return this.words.map((n) => n.type === o.Normal ? n.content : new Array(n.count).fill(\" \").join(\"\")).join(\"\");\n }\n toJSON() {\n return {\n words: this.words,\n extended: this.extended,\n original: this.original\n };\n }\n}\nclass y {\n get type() {\n return \"Normal\";\n }\n id = r(4).toUpperCase();\n time = new s();\n content = new c();\n agent;\n background;\n toJSON() {\n return {\n id: this.id,\n type: this.type,\n time: this.time,\n content: this.content,\n agent: this.agent,\n background: this.background\n };\n }\n}\nvar u = /* @__PURE__ */ ((t) => (t.Offset = \"Offset\", t.Duration = \"Duration\", t.Title = \"Title\", t.Singer = \"Singer\", t.Album = \"Album\", t.Creator = \"Creator\", t.UnKnown = \"UnKnown\", t))(u || {});\nclass e {\n id = r(4).toUpperCase();\n toJSON() {\n return {\n id: this.id,\n type: this.type,\n content: this.content\n };\n }\n}\nclass f extends e {\n get type() {\n return \"Offset\";\n }\n content = 0;\n}\nclass w extends e {\n get type() {\n return \"Duration\";\n }\n content = 0;\n}\nclass O extends e {\n get type() {\n return \"Title\";\n }\n content = \"\";\n}\nclass b extends e {\n get type() {\n return \"Singer\";\n }\n content = \"\";\n}\nclass J extends e {\n get type() {\n return \"Album\";\n }\n content = \"\";\n}\nclass U extends e {\n get type() {\n return \"Creator\";\n }\n content = {\n role: \"\",\n name: []\n };\n}\nclass C extends e {\n get type() {\n return \"UnKnown\";\n }\n content = \"\";\n}\nclass I {\n id = \"\";\n name = \"\";\n count = 0;\n}\nclass d {\n // index in global\n global = 0;\n // index in block\n block = 0;\n toJSON() {\n return {\n global: this.global,\n block: this.block\n };\n }\n}\nclass v {\n id = \"\";\n index = new d();\n toJSON() {\n return {\n id: this.id,\n index: this.index\n };\n }\n}\nconst m = \"0.5.1\";\nvar g = /* @__PURE__ */ ((t) => (t.Incorrect = \"Incorrect\", t.Normal = \"Normal\", t.Syllable = \"Syllable\", t.Pure = \"Pure\", t.Empty = \"Empty\", t.NoTime = \"NoTime\", t))(g || {});\nclass A {\n get version() {\n return m;\n }\n type = \"Incorrect\";\n metas = [];\n lines = [];\n agents = [];\n toJSON() {\n return {\n version: this.version,\n type: this.type,\n metas: this.metas,\n lines: this.lines,\n agents: this.agents\n };\n }\n}\nexport {\n I as Agent,\n v as AgentLine,\n d as AgentLineIndex,\n S as Extended,\n a as ExtendedType,\n A as Info,\n x as LineInterlude,\n y as LineNormal,\n c as LineNormalContent,\n l as LineType,\n J as MetaAlbum,\n U as MetaCreator,\n w as MetaDuration,\n f as MetaOffset,\n b as MetaSinger,\n O as MetaTitle,\n u as MetaType,\n C as MetaUnKnown,\n s as Time,\n g as Type,\n m as Version,\n p as WordNormal,\n N as WordSpace,\n o as WordType\n};\n//# sourceMappingURL=index.ecma.js.map\n","import type { Line } from '@music-lyric-kit/lyric'\nimport type { BaseLyricPlayerEventMap } from './interface'\n\nimport { Info } from '@music-lyric-kit/lyric'\nimport { ConfigManager, Event } from '@music-lyric-player/utils'\nimport { BaseLyricPlayerConfig } from './config'\n\nexport class BaseLyricPlayer {\n readonly config: BaseLyricPlayerConfig.RootManager = new ConfigManager(BaseLyricPlayerConfig.DEFAULT as BaseLyricPlayerConfig.RootRequired)\n\n readonly event: Event<BaseLyricPlayerEventMap> = new Event()\n\n private state: {\n playing: boolean\n frameId: number | null\n timerId: number | null\n scanIndex: number\n }\n private active: {\n lines: Line[]\n index: number[]\n }\n private time: {\n start: number\n seek: number\n }\n private info: Info\n\n constructor() {\n this.state = {\n playing: false,\n frameId: null,\n timerId: null,\n scanIndex: 0,\n }\n this.active = {\n lines: [],\n index: [],\n }\n this.time = {\n start: 0,\n seek: 0,\n }\n this.info = new Info()\n }\n\n private handleGetCurrentTime() {\n if (!this.state.playing) {\n return this.time.seek\n }\n return this.time.seek + (performance.now() - this.time.start)\n }\n\n private handleGetLineTime(index: number): number {\n if (index < 0 || index >= this.info.lines.length) {\n return 0\n }\n\n if (index === this.info.lines.length - 1) {\n return Infinity\n }\n\n const line = this.info.lines[index]\n const nextLine = this.info.lines[index + 1]\n return Math.max(line.time.end, nextLine.time.start)\n }\n\n private handleGetActiveIndex() {\n return this.active.index.length > 0 ? this.active.index[0] : -1\n }\n\n private handleBridgeActive(lines: Line[], index: number[]): { lines: Line[]; index: number[] } {\n if (!this.config.current.bridgeActive || index.length < 2) {\n return { lines, index }\n }\n const min = index[0]\n const max = index[index.length - 1]\n if (max - min + 1 === index.length) {\n return { lines, index }\n }\n const existing = new Map<number, Line>()\n for (let i = 0; i < index.length; i++) {\n existing.set(index[i], lines[i])\n }\n const bridgedLines: Line[] = []\n const bridgedIndex: number[] = []\n for (let i = min; i <= max; i++) {\n const line = existing.get(i) ?? this.info.lines[i]\n if (!line) continue\n bridgedLines.push(line)\n bridgedIndex.push(i)\n }\n return { lines: bridgedLines, index: bridgedIndex }\n }\n\n private handleEmitLinesUpdate(isSeek: boolean) {\n const bridged = this.handleBridgeActive(this.active.lines, this.active.index)\n this.event.emit('linesUpdate', bridged.lines, bridged.index, this.handleGetActiveIndex(), isSeek)\n }\n\n private handleSyncTime(time: number) {\n const lines: Line[] = []\n const index: number[] = []\n\n let firstIndex = this.info.lines.length\n for (let i = 0; i < this.info.lines.length; i++) {\n const line = this.info.lines[i]\n if (line.time.start > time) {\n firstIndex = i\n break\n }\n\n if (this.handleGetLineTime(i) > time) {\n lines.push(line)\n index.push(i)\n }\n }\n\n this.state.scanIndex = firstIndex\n\n this.active.lines = lines\n this.active.index = index\n\n this.handleEmitLinesUpdate(true)\n }\n\n private handleUpdateActiveLines(now: number) {\n let hasChanged = false\n\n const newActiveLines: Line[] = []\n const newActiveIndex: number[] = []\n\n for (let i = 0; i < this.active.lines.length; i++) {\n const line = this.active.lines[i]\n const infoIndex = this.active.index[i]\n\n if (now >= this.handleGetLineTime(infoIndex)) {\n hasChanged = true\n } else {\n newActiveLines.push(line)\n newActiveIndex.push(infoIndex)\n }\n }\n\n while (this.state.scanIndex < this.info.lines.length) {\n const nextLine = this.info.lines[this.state.scanIndex]\n if (now >= nextLine.time.start) {\n if (now < this.handleGetLineTime(this.state.scanIndex)) {\n newActiveLines.push(nextLine)\n newActiveIndex.push(this.state.scanIndex)\n hasChanged = true\n }\n this.state.scanIndex++\n } else {\n break\n }\n }\n\n if (!hasChanged) {\n return\n }\n\n this.active.lines = newActiveLines\n this.active.index = newActiveIndex\n this.handleEmitLinesUpdate(false)\n }\n\n private onTick = () => {\n if (!this.state.playing) {\n return\n }\n\n const now = this.handleGetCurrentTime()\n this.handleUpdateActiveLines(now)\n\n switch (this.config.current.driver) {\n case 'animation':\n this.state.frameId = window.requestAnimationFrame(this.onTick)\n break\n case 'timer':\n this.state.timerId = window.setTimeout(this.onTick, 16)\n break\n }\n }\n\n updateLyric(info: Info) {\n if (!info) {\n return\n }\n\n this.pause()\n this.info = info\n\n this.active.lines = []\n this.active.index = []\n\n this.state.scanIndex = 0\n this.time.seek = 0\n\n this.event.emit('lyricUpdate', info)\n this.event.emit('linesUpdate', [], [], -1, false)\n }\n\n /**\n * Start playback\n * @param time Optional time in ms to seek to before starting playback. If not provided, playback will start from the current position.\n */\n play(time?: number) {\n this.pause()\n\n if (typeof time === 'number' && !Number.isNaN(time)) {\n this.time.seek = time\n this.handleSyncTime(time)\n }\n\n this.time.start = performance.now()\n this.state.playing = true\n this.onTick()\n\n this.event.emit('play', this.handleGetCurrentTime())\n }\n\n /**\n * Pause playback\n */\n pause() {\n if (this.state.playing) {\n this.time.seek = this.handleGetCurrentTime()\n this.state.playing = false\n }\n if (this.state.frameId !== null) {\n cancelAnimationFrame(this.state.frameId)\n this.state.frameId = null\n }\n if (this.state.timerId !== null) {\n clearTimeout(this.state.timerId)\n this.state.timerId = null\n }\n\n this.event.emit('pause', this.handleGetCurrentTime())\n }\n\n /**\n * Stop playback\n */\n dispose() {\n this.pause()\n this.event.clear()\n\n this.active.lines = []\n this.active.index = []\n\n this.info = new Info()\n }\n\n /**\n * Find all active lines at the given time (ms). Does not mutate internal state.\n * @param time time in ms to find active lines for.\n */\n matchLinesWithTime(time: number): { lines: Line[]; index: number[] } {\n const lines: Line[] = []\n const index: number[] = []\n for (let i = 0; i < this.info.lines.length; i++) {\n const line = this.info.lines[i]\n if (line.time.start > time) {\n break\n }\n if (this.handleGetLineTime(i) > time) {\n lines.push(line)\n index.push(i)\n }\n }\n return this.handleBridgeActive(lines, index)\n }\n\n /**\n * Whether the player is currently playing.\n */\n get currentPlaying() {\n return this.state.playing\n }\n\n /**\n * Current active lines.\n */\n get currentLines() {\n return this.handleBridgeActive(this.active.lines, this.active.index).lines\n }\n\n /**\n * Indices of currently active lines.\n */\n get currentIndex() {\n return this.handleBridgeActive(this.active.lines, this.active.index).index\n }\n\n /**\n * The index of the primary active line, or -1 if none.\n */\n get currentActive() {\n return this.handleGetActiveIndex()\n }\n\n /**\n * The current lyric info object.\n */\n get currentInfo() {\n return this.info\n }\n\n /**\n * The current playback time in ms.\n */\n get currentTime() {\n return this.handleGetCurrentTime()\n }\n}\n"],"names":["DEFAULT","freezeObjectDeep","m","A","BaseLyricPlayer","ConfigManager","BaseLyricPlayerConfig.DEFAULT","Event","Info","index","line","nextLine","lines","min","max","existing","i","bridgedLines","bridgedIndex","isSeek","bridged","time","firstIndex","now","hasChanged","newActiveLines","newActiveIndex","infoIndex","info"],"mappings":"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","x_google_ignoreList":[1]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@music-lyric-player/base",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"author": "folltoshe",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Music Lyric Player - Base Player",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@music-lyric-kit/lyric": "^0.4.0"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@music-lyric-player/utils": "^0.
|
|
35
|
+
"@music-lyric-player/utils": "^0.10.0"
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
38
|
"build": "vite build"
|