agdi 3.3.5 → 3.3.7

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.
Files changed (36) hide show
  1. package/README.md +13 -0
  2. package/dist/APEv2Parser-EU45AV6X.js +14 -0
  3. package/dist/AiffParser-FOX7GQ42.js +189 -0
  4. package/dist/AsfParser-HD5CSGIO.js +610 -0
  5. package/dist/DsdiffParser-OJREDMBI.js +188 -0
  6. package/dist/DsfParser-2YL4ARJ7.js +110 -0
  7. package/dist/FlacParser-IVV4RYF6.js +15 -0
  8. package/dist/MP4Parser-NLX4A2YN.js +1140 -0
  9. package/dist/MatroskaParser-4OEK43GF.js +654 -0
  10. package/dist/MpegParser-PXKEUF2B.js +642 -0
  11. package/dist/MusepackParser-54QGYRLY.js +322 -0
  12. package/dist/OggParser-KRV5QCGZ.js +435 -0
  13. package/dist/WavPackParser-XPZSQFVS.js +203 -0
  14. package/dist/WaveParser-27IS2RAI.js +294 -0
  15. package/dist/chunk-2B4QMSZW.js +311 -0
  16. package/dist/chunk-3JKZUGPJ.js +70 -0
  17. package/dist/chunk-4VNS5WPM.js +42 -0
  18. package/dist/chunk-65JVFJ3X.js +729 -0
  19. package/dist/chunk-6OKLAJRQ.js +0 -0
  20. package/dist/chunk-AGSFUVRG.js +439 -0
  21. package/dist/chunk-GD35BJSH.js +177 -0
  22. package/dist/chunk-HNLU36CC.js +702 -0
  23. package/dist/{chunk-M2FF7ETI.js → chunk-J6OLLWVT.js} +1 -1
  24. package/dist/chunk-LREP5CZP.js +146 -0
  25. package/dist/chunk-M54HVABG.js +34 -0
  26. package/dist/{chunk-S45VXJEO.js → chunk-OPFFFAQC.js} +19 -1
  27. package/dist/chunk-VGOIHW7D.js +1529 -0
  28. package/dist/chunk-YIHDW7JC.js +314 -0
  29. package/dist/config-D3QBUN2Y.js +13 -0
  30. package/dist/{config-ZFU7TSU2.js → config-K2XM6D4Z.js} +3 -2
  31. package/dist/{event-bus-Q3WCETQQ.js → event-bus-MO5SFUME.js} +1 -0
  32. package/dist/index.js +3273 -1274
  33. package/dist/lib-2XISBYT3.js +144950 -0
  34. package/dist/lib-HCGLI2GJ.js +4161 -0
  35. package/dist/{telemetry-service-OHU5NKON.js → telemetry-service-76YPOPDM.js} +8 -4
  36. package/package.json +6 -3
@@ -0,0 +1,729 @@
1
+ import {
2
+ Genres
3
+ } from "./chunk-2B4QMSZW.js";
4
+ import {
5
+ AttachedPictureType,
6
+ ExtendedHeader,
7
+ ID3v2Header,
8
+ SyncTextHeader,
9
+ TextEncodingToken,
10
+ TextHeader,
11
+ UINT32SYNCSAFE
12
+ } from "./chunk-LREP5CZP.js";
13
+ import {
14
+ decodeString,
15
+ decodeUintBE,
16
+ findZero,
17
+ getBit
18
+ } from "./chunk-GD35BJSH.js";
19
+ import {
20
+ UINT24_BE,
21
+ UINT32_BE,
22
+ UINT8,
23
+ Uint8ArrayType,
24
+ makeUnexpectedFileContentError,
25
+ require_src,
26
+ textDecode
27
+ } from "./chunk-VGOIHW7D.js";
28
+ import {
29
+ __toESM
30
+ } from "./chunk-4VNS5WPM.js";
31
+
32
+ // ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/id3v2/FrameParser.js
33
+ var import_debug = __toESM(require_src(), 1);
34
+
35
+ // ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/id3v2/ID3v2ChapterToken.js
36
+ var ChapterInfo = {
37
+ len: 16,
38
+ get: (buf, off) => {
39
+ const startOffset = UINT32_BE.get(buf, off + 8);
40
+ const endOffset = UINT32_BE.get(buf, off + 12);
41
+ return {
42
+ startTime: UINT32_BE.get(buf, off),
43
+ endTime: UINT32_BE.get(buf, off + 4),
44
+ startOffset: startOffset === 4294967295 ? void 0 : startOffset,
45
+ endOffset: endOffset === 4294967295 ? void 0 : endOffset
46
+ };
47
+ }
48
+ };
49
+
50
+ // ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/id3v2/FrameHeader.js
51
+ function getFrameHeaderLength(majorVer) {
52
+ switch (majorVer) {
53
+ case 2:
54
+ return 6;
55
+ case 3:
56
+ case 4:
57
+ return 10;
58
+ default:
59
+ throw makeUnexpectedMajorVersionError(majorVer);
60
+ }
61
+ }
62
+ function readFrameFlags(b) {
63
+ return {
64
+ status: {
65
+ tag_alter_preservation: getBit(b, 0, 6),
66
+ file_alter_preservation: getBit(b, 0, 5),
67
+ read_only: getBit(b, 0, 4)
68
+ },
69
+ format: {
70
+ grouping_identity: getBit(b, 1, 7),
71
+ compression: getBit(b, 1, 3),
72
+ encryption: getBit(b, 1, 2),
73
+ unsynchronisation: getBit(b, 1, 1),
74
+ data_length_indicator: getBit(b, 1, 0)
75
+ }
76
+ };
77
+ }
78
+ function readFrameHeader(uint8Array, majorVer, warningCollector) {
79
+ switch (majorVer) {
80
+ case 2:
81
+ return parseFrameHeaderV22(uint8Array, majorVer, warningCollector);
82
+ case 3:
83
+ case 4:
84
+ return parseFrameHeaderV23V24(uint8Array, majorVer, warningCollector);
85
+ default:
86
+ throw makeUnexpectedMajorVersionError(majorVer);
87
+ }
88
+ }
89
+ function parseFrameHeaderV22(uint8Array, majorVer, warningCollector) {
90
+ const header = {
91
+ id: textDecode(uint8Array.subarray(0, 3), "ascii"),
92
+ length: UINT24_BE.get(uint8Array, 3)
93
+ };
94
+ if (!header.id.match(/^[A-Z0-9]{3}$/)) {
95
+ warningCollector.addWarning(`Invalid ID3v2.${majorVer} frame-header-ID: ${header.id}`);
96
+ }
97
+ return header;
98
+ }
99
+ function parseFrameHeaderV23V24(uint8Array, majorVer, warningCollector) {
100
+ const header = {
101
+ id: textDecode(uint8Array.subarray(0, 4), "ascii"),
102
+ length: (majorVer === 4 ? UINT32SYNCSAFE : UINT32_BE).get(uint8Array, 4),
103
+ flags: readFrameFlags(uint8Array.subarray(8, 10))
104
+ };
105
+ if (!header.id.match(/^[A-Z0-9]{4}$/)) {
106
+ warningCollector.addWarning(`Invalid ID3v2.${majorVer} frame-header-ID: ${header.id}`);
107
+ }
108
+ return header;
109
+ }
110
+ function makeUnexpectedMajorVersionError(majorVer) {
111
+ throw new Id3v2ContentError(`Unexpected majorVer: ${majorVer}`);
112
+ }
113
+
114
+ // ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/id3v2/FrameParser.js
115
+ var debug = (0, import_debug.default)("music-metadata:id3v2:frame-parser");
116
+ var defaultEnc = "latin1";
117
+ var urlEnc = { encoding: defaultEnc, bom: false };
118
+ function parseGenre(origVal) {
119
+ const genres = [];
120
+ let code;
121
+ let word = "";
122
+ for (const c of origVal) {
123
+ if (typeof code === "string") {
124
+ if (c === "(" && code === "") {
125
+ word += "(";
126
+ code = void 0;
127
+ } else if (c === ")") {
128
+ if (word !== "") {
129
+ genres.push(word);
130
+ word = "";
131
+ }
132
+ const genre = parseGenreCode(code);
133
+ if (genre) {
134
+ genres.push(genre);
135
+ }
136
+ code = void 0;
137
+ } else
138
+ code += c;
139
+ } else if (c === "(") {
140
+ code = "";
141
+ } else {
142
+ word += c;
143
+ }
144
+ }
145
+ if (word) {
146
+ if (genres.length === 0 && word.match(/^\d*$/)) {
147
+ word = parseGenreCode(word);
148
+ }
149
+ if (word) {
150
+ genres.push(word);
151
+ }
152
+ }
153
+ return genres;
154
+ }
155
+ function parseGenreCode(code) {
156
+ if (code === "RX")
157
+ return "Remix";
158
+ if (code === "CR")
159
+ return "Cover";
160
+ if (code.match(/^\d*$/)) {
161
+ return Genres[Number.parseInt(code, 10)];
162
+ }
163
+ }
164
+ var FrameParser = class _FrameParser {
165
+ /**
166
+ * Create id3v2 frame parser
167
+ * @param major - Major version, e.g. (4) for id3v2.4
168
+ * @param warningCollector - Used to collect decode issue
169
+ */
170
+ constructor(major, warningCollector) {
171
+ this.major = major;
172
+ this.warningCollector = warningCollector;
173
+ }
174
+ readData(uint8Array, type, includeCovers) {
175
+ if (uint8Array.length === 0) {
176
+ this.warningCollector.addWarning(`id3v2.${this.major} header has empty tag type=${type}`);
177
+ return;
178
+ }
179
+ const { encoding, bom } = TextEncodingToken.get(uint8Array, 0);
180
+ const length = uint8Array.length;
181
+ let offset = 0;
182
+ let output = [];
183
+ const nullTerminatorLength = _FrameParser.getNullTerminatorLength(encoding);
184
+ let fzero;
185
+ debug(`Parsing tag type=${type}, encoding=${encoding}, bom=${bom}`);
186
+ switch (type !== "TXXX" && type[0] === "T" ? "T*" : type) {
187
+ case "T*":
188
+ // 4.2.1. Text information frames - details
189
+ case "GRP1":
190
+ // iTunes-specific ID3v2 grouping field
191
+ case "GP1":
192
+ // iTunes-specific ID3v2.2 grouping field
193
+ case "IPLS":
194
+ // v2.3: Involved people list
195
+ case "MVIN":
196
+ case "MVNM":
197
+ case "PCS":
198
+ case "PCST": {
199
+ let text;
200
+ try {
201
+ text = _FrameParser.trimNullPadding(decodeString(uint8Array.subarray(1), encoding));
202
+ } catch (error) {
203
+ if (error instanceof Error) {
204
+ this.warningCollector.addWarning(`id3v2.${this.major} type=${type} header has invalid string value: ${error.message}`);
205
+ break;
206
+ }
207
+ throw error;
208
+ }
209
+ switch (type) {
210
+ case "TMCL":
211
+ // Musician credits list
212
+ case "TIPL":
213
+ // Involved people list
214
+ case "IPLS":
215
+ output = _FrameParser.functionList(this.splitValue(type, text));
216
+ break;
217
+ case "TRK":
218
+ case "TRCK":
219
+ case "TPOS":
220
+ case "TIT1":
221
+ case "TIT2":
222
+ case "TIT3":
223
+ output = text;
224
+ break;
225
+ case "TCOM":
226
+ case "TEXT":
227
+ case "TOLY":
228
+ case "TOPE":
229
+ case "TPE1":
230
+ case "TSRC":
231
+ output = this.splitValue(type, text);
232
+ break;
233
+ case "TCO":
234
+ case "TCON":
235
+ output = this.splitValue(type, text).map((v) => parseGenre(v)).reduce((acc, val) => acc.concat(val), []);
236
+ break;
237
+ case "PCS":
238
+ case "PCST":
239
+ output = this.major >= 4 ? this.splitValue(type, text) : [text];
240
+ output = Array.isArray(output) && output[0] === "" ? 1 : 0;
241
+ break;
242
+ default:
243
+ output = this.major >= 4 ? this.splitValue(type, text) : [text];
244
+ }
245
+ break;
246
+ }
247
+ case "TXXX": {
248
+ const idAndData = _FrameParser.readIdentifierAndData(uint8Array.subarray(1), encoding);
249
+ output = {
250
+ description: idAndData.id,
251
+ text: this.splitValue(type, decodeString(idAndData.data, encoding).replace(/\x00+$/, ""))
252
+ };
253
+ break;
254
+ }
255
+ case "PIC":
256
+ case "APIC":
257
+ if (includeCovers) {
258
+ const pic = {};
259
+ uint8Array = uint8Array.subarray(1);
260
+ switch (this.major) {
261
+ case 2:
262
+ pic.format = decodeString(uint8Array.subarray(0, 3), "latin1");
263
+ uint8Array = uint8Array.subarray(3);
264
+ break;
265
+ case 3:
266
+ case 4:
267
+ fzero = findZero(uint8Array, defaultEnc);
268
+ pic.format = decodeString(uint8Array.subarray(0, fzero), defaultEnc);
269
+ uint8Array = uint8Array.subarray(fzero + 1);
270
+ break;
271
+ default:
272
+ throw makeUnexpectedMajorVersionError2(this.major);
273
+ }
274
+ pic.format = _FrameParser.fixPictureMimeType(pic.format);
275
+ pic.type = AttachedPictureType[uint8Array[0]];
276
+ uint8Array = uint8Array.subarray(1);
277
+ fzero = findZero(uint8Array, encoding);
278
+ pic.description = decodeString(uint8Array.subarray(0, fzero), encoding);
279
+ uint8Array = uint8Array.subarray(fzero + nullTerminatorLength);
280
+ pic.data = uint8Array;
281
+ output = pic;
282
+ }
283
+ break;
284
+ case "CNT":
285
+ case "PCNT":
286
+ output = decodeUintBE(uint8Array);
287
+ break;
288
+ case "SYLT": {
289
+ const syltHeader = SyncTextHeader.get(uint8Array, 0);
290
+ uint8Array = uint8Array.subarray(SyncTextHeader.len);
291
+ const result = {
292
+ descriptor: "",
293
+ language: syltHeader.language,
294
+ contentType: syltHeader.contentType,
295
+ timeStampFormat: syltHeader.timeStampFormat,
296
+ syncText: []
297
+ };
298
+ let readSyllables = false;
299
+ while (uint8Array.length > 0) {
300
+ const nullStr = _FrameParser.readNullTerminatedString(uint8Array, syltHeader.encoding);
301
+ uint8Array = uint8Array.subarray(nullStr.len);
302
+ if (readSyllables) {
303
+ const timestamp = UINT32_BE.get(uint8Array, 0);
304
+ uint8Array = uint8Array.subarray(UINT32_BE.len);
305
+ result.syncText.push({
306
+ text: nullStr.text,
307
+ timestamp
308
+ });
309
+ } else {
310
+ result.descriptor = nullStr.text;
311
+ readSyllables = true;
312
+ }
313
+ }
314
+ output = result;
315
+ break;
316
+ }
317
+ case "ULT":
318
+ case "USLT":
319
+ case "COM":
320
+ case "COMM": {
321
+ const textHeader = TextHeader.get(uint8Array, offset);
322
+ offset += TextHeader.len;
323
+ const descriptorStr = _FrameParser.readNullTerminatedString(uint8Array.subarray(offset), textHeader.encoding);
324
+ offset += descriptorStr.len;
325
+ const textStr = _FrameParser.readNullTerminatedString(uint8Array.subarray(offset), textHeader.encoding);
326
+ const comment = {
327
+ language: textHeader.language,
328
+ descriptor: descriptorStr.text,
329
+ text: textStr.text
330
+ };
331
+ output = comment;
332
+ break;
333
+ }
334
+ case "UFID": {
335
+ const ufid = _FrameParser.readIdentifierAndData(uint8Array, defaultEnc);
336
+ output = { owner_identifier: ufid.id, identifier: ufid.data };
337
+ break;
338
+ }
339
+ case "PRIV": {
340
+ const priv = _FrameParser.readIdentifierAndData(uint8Array, defaultEnc);
341
+ output = { owner_identifier: priv.id, data: priv.data };
342
+ break;
343
+ }
344
+ case "POPM": {
345
+ uint8Array = uint8Array.subarray(offset);
346
+ const emailStr = _FrameParser.readNullTerminatedString(uint8Array, urlEnc);
347
+ const email = emailStr.text;
348
+ uint8Array = uint8Array.subarray(emailStr.len);
349
+ if (uint8Array.length === 0) {
350
+ this.warningCollector.addWarning(`id3v2.${this.major} type=${type} POPM frame missing rating byte`);
351
+ output = { email, rating: 0, counter: void 0 };
352
+ break;
353
+ }
354
+ const rating = UINT8.get(uint8Array, 0);
355
+ const counterBytes = uint8Array.subarray(UINT8.len);
356
+ output = {
357
+ email,
358
+ rating,
359
+ counter: counterBytes.length > 0 ? decodeUintBE(counterBytes) : void 0
360
+ };
361
+ break;
362
+ }
363
+ case "GEOB": {
364
+ const encoding2 = TextEncodingToken.get(uint8Array, 0);
365
+ uint8Array = uint8Array.subarray(1);
366
+ const mimeTypeStr = _FrameParser.readNullTerminatedString(uint8Array, urlEnc);
367
+ const mimeType = mimeTypeStr.text;
368
+ uint8Array = uint8Array.subarray(mimeTypeStr.len);
369
+ const filenameStr = _FrameParser.readNullTerminatedString(uint8Array, encoding2);
370
+ const filename = filenameStr.text;
371
+ uint8Array = uint8Array.subarray(filenameStr.len);
372
+ const descriptionStr = _FrameParser.readNullTerminatedString(uint8Array, encoding2);
373
+ const description = descriptionStr.text;
374
+ uint8Array = uint8Array.subarray(descriptionStr.len);
375
+ const geob = {
376
+ type: mimeType,
377
+ filename,
378
+ description,
379
+ data: uint8Array
380
+ };
381
+ output = geob;
382
+ break;
383
+ }
384
+ // W-Frames:
385
+ case "WCOM":
386
+ case "WCOP":
387
+ case "WOAF":
388
+ case "WOAR":
389
+ case "WOAS":
390
+ case "WORS":
391
+ case "WPAY":
392
+ case "WPUB":
393
+ output = _FrameParser.readNullTerminatedString(uint8Array, urlEnc).text;
394
+ break;
395
+ case "WXXX": {
396
+ const encoding2 = TextEncodingToken.get(uint8Array, 0);
397
+ uint8Array = uint8Array.subarray(1);
398
+ const descriptionStr = _FrameParser.readNullTerminatedString(uint8Array, encoding2);
399
+ const description = descriptionStr.text;
400
+ uint8Array = uint8Array.subarray(descriptionStr.len);
401
+ output = { description, url: _FrameParser.trimNullPadding(decodeString(uint8Array, defaultEnc)) };
402
+ break;
403
+ }
404
+ case "WFD":
405
+ case "WFED": {
406
+ const encoding2 = TextEncodingToken.get(uint8Array, 0);
407
+ uint8Array = uint8Array.subarray(1);
408
+ output = _FrameParser.readNullTerminatedString(uint8Array, encoding2).text;
409
+ break;
410
+ }
411
+ case "MCDI": {
412
+ output = uint8Array.subarray(0, length);
413
+ break;
414
+ }
415
+ // ID3v2 Chapters 1.0
416
+ // https://mutagen-specs.readthedocs.io/en/latest/id3/id3v2-chapters-1.0.html#chapter-frame
417
+ case "CHAP": {
418
+ debug("Reading CHAP");
419
+ fzero = findZero(uint8Array, defaultEnc);
420
+ const chapter = {
421
+ label: decodeString(uint8Array.subarray(0, fzero), defaultEnc),
422
+ info: ChapterInfo.get(uint8Array, fzero + 1),
423
+ frames: /* @__PURE__ */ new Map()
424
+ };
425
+ offset += fzero + 1 + ChapterInfo.len;
426
+ while (offset < length) {
427
+ const subFrame = readFrameHeader(uint8Array.subarray(offset), this.major, this.warningCollector);
428
+ const headerSize = getFrameHeaderLength(this.major);
429
+ offset += headerSize;
430
+ const subOutput = this.readData(uint8Array.subarray(offset, offset + subFrame.length), subFrame.id, includeCovers);
431
+ offset += subFrame.length;
432
+ chapter.frames.set(subFrame.id, subOutput);
433
+ }
434
+ output = chapter;
435
+ break;
436
+ }
437
+ // ID3v2 Chapters 1.0
438
+ // https://mutagen-specs.readthedocs.io/en/latest/id3/id3v2-chapters-1.0.html#table-of-contents-frame
439
+ case "CTOC": {
440
+ debug("Reading CTOC");
441
+ const idEnd = findZero(uint8Array, defaultEnc);
442
+ const label = decodeString(uint8Array.subarray(0, idEnd), defaultEnc);
443
+ offset = idEnd + 1;
444
+ const flags = uint8Array[offset++];
445
+ const topLevel = (flags & 2) !== 0;
446
+ const ordered = (flags & 1) !== 0;
447
+ const entryCount = uint8Array[offset++];
448
+ const childElementIds = [];
449
+ for (let i = 0; i < entryCount && offset < length; i++) {
450
+ const end = findZero(uint8Array.subarray(offset), defaultEnc);
451
+ const childId = decodeString(uint8Array.subarray(offset, offset + end), defaultEnc);
452
+ childElementIds.push(childId);
453
+ offset += end + 1;
454
+ }
455
+ const toc = {
456
+ label,
457
+ flags: { topLevel, ordered },
458
+ childElementIds,
459
+ frames: /* @__PURE__ */ new Map()
460
+ };
461
+ while (offset < length) {
462
+ const subFrame = readFrameHeader(uint8Array.subarray(offset), this.major, this.warningCollector);
463
+ const headerSize = getFrameHeaderLength(this.major);
464
+ offset += headerSize;
465
+ const subOutput = this.readData(uint8Array.subarray(offset, offset + subFrame.length), subFrame.id, includeCovers);
466
+ offset += subFrame.length;
467
+ toc.frames.set(subFrame.id, subOutput);
468
+ }
469
+ output = toc;
470
+ break;
471
+ }
472
+ default:
473
+ debug(`Warning: unsupported id3v2-tag-type: ${type}`);
474
+ break;
475
+ }
476
+ return output;
477
+ }
478
+ static readNullTerminatedString(uint8Array, encoding) {
479
+ const bomSize = encoding.bom ? 2 : 0;
480
+ const originalLen = uint8Array.length;
481
+ const valueArray = uint8Array.subarray(bomSize);
482
+ const zeroIndex = findZero(valueArray, encoding.encoding);
483
+ if (zeroIndex >= valueArray.length) {
484
+ return {
485
+ text: decodeString(valueArray, encoding.encoding),
486
+ len: originalLen
487
+ };
488
+ }
489
+ const txt = valueArray.subarray(0, zeroIndex);
490
+ return {
491
+ text: decodeString(txt, encoding.encoding),
492
+ len: bomSize + zeroIndex + _FrameParser.getNullTerminatorLength(encoding.encoding)
493
+ };
494
+ }
495
+ static fixPictureMimeType(pictureType) {
496
+ pictureType = pictureType.toLocaleLowerCase();
497
+ switch (pictureType) {
498
+ case "jpg":
499
+ return "image/jpeg";
500
+ case "png":
501
+ return "image/png";
502
+ }
503
+ return pictureType;
504
+ }
505
+ /**
506
+ * Converts TMCL (Musician credits list) or TIPL (Involved people list)
507
+ * @param entries
508
+ */
509
+ static functionList(entries) {
510
+ const res = {};
511
+ for (let i = 0; i + 1 < entries.length; i += 2) {
512
+ const names = entries[i + 1].split(",");
513
+ res[entries[i]] = res[entries[i]] ? res[entries[i]].concat(names) : names;
514
+ }
515
+ return res;
516
+ }
517
+ /**
518
+ * id3v2.4 defines that multiple T* values are separated by 0x00
519
+ * id3v2.3 defines that TCOM, TEXT, TOLY, TOPE & TPE1 values are separated by /
520
+ * @param tag - Tag name
521
+ * @param text - Concatenated tag value
522
+ * @returns Split tag value
523
+ */
524
+ splitValue(tag, text) {
525
+ let values;
526
+ if (this.major < 4) {
527
+ values = text.split(/\x00/g);
528
+ if (values.length > 1) {
529
+ this.warningCollector.addWarning(`ID3v2.${this.major} ${tag} uses non standard null-separator.`);
530
+ } else {
531
+ values = text.split(/\//g);
532
+ }
533
+ } else {
534
+ values = text.split(/\x00/g);
535
+ }
536
+ return _FrameParser.trimArray(values);
537
+ }
538
+ static trimArray(values) {
539
+ return values.map((value) => _FrameParser.trimNullPadding(value).trim());
540
+ }
541
+ static trimNullPadding(value) {
542
+ let end = value.length;
543
+ while (end > 0 && value.charCodeAt(end - 1) === 0) {
544
+ end--;
545
+ }
546
+ return end === value.length ? value : value.slice(0, end);
547
+ }
548
+ static readIdentifierAndData(uint8Array, encoding) {
549
+ const idStr = _FrameParser.readNullTerminatedString(uint8Array, { encoding, bom: false });
550
+ return { id: idStr.text, data: uint8Array.subarray(idStr.len) };
551
+ }
552
+ static getNullTerminatorLength(enc) {
553
+ return enc.startsWith("utf-16") ? 2 : 1;
554
+ }
555
+ };
556
+ var Id3v2ContentError = class extends makeUnexpectedFileContentError("id3v2") {
557
+ };
558
+ function makeUnexpectedMajorVersionError2(majorVer) {
559
+ throw new Id3v2ContentError(`Unexpected majorVer: ${majorVer}`);
560
+ }
561
+
562
+ // ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/id3v2/ID3v2Parser.js
563
+ var ID3v2Parser = class _ID3v2Parser {
564
+ constructor() {
565
+ this.tokenizer = void 0;
566
+ this.id3Header = void 0;
567
+ this.metadata = void 0;
568
+ this.headerType = void 0;
569
+ this.options = void 0;
570
+ }
571
+ static removeUnsyncBytes(buffer) {
572
+ let readI = 0;
573
+ let writeI = 0;
574
+ while (readI < buffer.length - 1) {
575
+ if (readI !== writeI) {
576
+ buffer[writeI] = buffer[readI];
577
+ }
578
+ readI += buffer[readI] === 255 && buffer[readI + 1] === 0 ? 2 : 1;
579
+ writeI++;
580
+ }
581
+ if (readI < buffer.length) {
582
+ buffer[writeI++] = buffer[readI];
583
+ }
584
+ return buffer.subarray(0, writeI);
585
+ }
586
+ static readFrameData(uint8Array, frameHeader, majorVer, includeCovers, warningCollector) {
587
+ const frameParser = new FrameParser(majorVer, warningCollector);
588
+ switch (majorVer) {
589
+ case 2:
590
+ return frameParser.readData(uint8Array, frameHeader.id, includeCovers);
591
+ case 3:
592
+ case 4:
593
+ if (frameHeader.flags?.format.unsynchronisation) {
594
+ uint8Array = _ID3v2Parser.removeUnsyncBytes(uint8Array);
595
+ }
596
+ if (frameHeader.flags?.format.data_length_indicator) {
597
+ uint8Array = uint8Array.subarray(4, uint8Array.length);
598
+ }
599
+ return frameParser.readData(uint8Array, frameHeader.id, includeCovers);
600
+ default:
601
+ throw makeUnexpectedMajorVersionError3(majorVer);
602
+ }
603
+ }
604
+ /**
605
+ * Create a combined tag key, of tag & description
606
+ * @param tag e.g.: COM
607
+ * @param description e.g. iTunPGAP
608
+ * @returns string e.g. COM:iTunPGAP
609
+ */
610
+ static makeDescriptionTagName(tag, description) {
611
+ return tag + (description ? `:${description}` : "");
612
+ }
613
+ async parse(metadata, tokenizer, options) {
614
+ this.tokenizer = tokenizer;
615
+ this.metadata = metadata;
616
+ this.options = options;
617
+ const id3Header = await this.tokenizer.readToken(ID3v2Header);
618
+ if (id3Header.fileIdentifier !== "ID3") {
619
+ throw new Id3v2ContentError("expected ID3-header file-identifier 'ID3' was not found");
620
+ }
621
+ this.id3Header = id3Header;
622
+ this.headerType = `ID3v2.${id3Header.version.major}`;
623
+ await (id3Header.flags.isExtendedHeader ? this.parseExtendedHeader() : this.parseId3Data(id3Header.size));
624
+ const chapters = _ID3v2Parser.mapId3v2Chapters(this.metadata.native[this.headerType]);
625
+ this.metadata.setFormat("chapters", chapters);
626
+ }
627
+ async parseExtendedHeader() {
628
+ const extendedHeader = await this.tokenizer.readToken(ExtendedHeader);
629
+ const dataRemaining = extendedHeader.size - ExtendedHeader.len;
630
+ return dataRemaining > 0 ? this.parseExtendedHeaderData(dataRemaining, extendedHeader.size) : this.parseId3Data(this.id3Header.size - extendedHeader.size);
631
+ }
632
+ async parseExtendedHeaderData(dataRemaining, extendedHeaderSize) {
633
+ await this.tokenizer.ignore(dataRemaining);
634
+ return this.parseId3Data(this.id3Header.size - extendedHeaderSize);
635
+ }
636
+ async parseId3Data(dataLen) {
637
+ const uint8Array = await this.tokenizer.readToken(new Uint8ArrayType(dataLen));
638
+ for (const tag of this.parseMetadata(uint8Array)) {
639
+ switch (tag.id) {
640
+ case "TXXX":
641
+ if (tag.value) {
642
+ await this.handleTag(tag, tag.value.text, () => tag.value.description);
643
+ }
644
+ break;
645
+ default:
646
+ await (Array.isArray(tag.value) ? Promise.all(tag.value.map((value) => this.addTag(tag.id, value))) : this.addTag(tag.id, tag.value));
647
+ }
648
+ }
649
+ }
650
+ async handleTag(tag, values, descriptor, resolveValue = (value) => value) {
651
+ await Promise.all(values.map((value) => this.addTag(_ID3v2Parser.makeDescriptionTagName(tag.id, descriptor(value)), resolveValue(value))));
652
+ }
653
+ async addTag(id, value) {
654
+ await this.metadata.addTag(this.headerType, id, value);
655
+ }
656
+ parseMetadata(data) {
657
+ let offset = 0;
658
+ const tags = [];
659
+ while (true) {
660
+ if (offset === data.length)
661
+ break;
662
+ const frameHeaderLength = getFrameHeaderLength(this.id3Header.version.major);
663
+ if (offset + frameHeaderLength > data.length) {
664
+ this.metadata.addWarning("Illegal ID3v2 tag length");
665
+ break;
666
+ }
667
+ const frameHeaderBytes = data.subarray(offset, offset + frameHeaderLength);
668
+ offset += frameHeaderLength;
669
+ const frameHeader = readFrameHeader(frameHeaderBytes, this.id3Header.version.major, this.metadata);
670
+ const frameDataBytes = data.subarray(offset, offset + frameHeader.length);
671
+ offset += frameHeader.length;
672
+ const values = _ID3v2Parser.readFrameData(frameDataBytes, frameHeader, this.id3Header.version.major, !this.options.skipCovers, this.metadata);
673
+ if (values) {
674
+ tags.push({ id: frameHeader.id, value: values });
675
+ }
676
+ }
677
+ return tags;
678
+ }
679
+ /**
680
+ * Convert parsed ID3v2 chapter frames (CHAP / CTOC) to generic `format.chapters`.
681
+ *
682
+ * This function expects the `native` tags already to contain parsed `CHAP` and `CTOC` frame values,
683
+ * as produced by `FrameParser.readData`.
684
+ */
685
+ static mapId3v2Chapters(id3Tags) {
686
+ if (!id3Tags)
687
+ return;
688
+ const chapFrames = id3Tags.filter((t) => t.id === "CHAP");
689
+ if (!chapFrames?.length)
690
+ return;
691
+ const tocFrames = id3Tags.filter((t) => t.id === "CTOC");
692
+ const topLevelToc = tocFrames?.find((t) => t.value.flags?.topLevel);
693
+ const chapterById = /* @__PURE__ */ new Map();
694
+ for (const chap of chapFrames) {
695
+ chapterById.set(chap.value.label, chap.value);
696
+ }
697
+ const orderedIds = topLevelToc?.value.childElementIds;
698
+ const chapters = [];
699
+ const source = orderedIds ?? [...chapterById.keys()];
700
+ for (const id of source) {
701
+ const chap = chapterById.get(id);
702
+ if (!chap)
703
+ continue;
704
+ const frames = chap.frames;
705
+ const title = frames.get("TIT2");
706
+ if (!title)
707
+ continue;
708
+ chapters.push({
709
+ id,
710
+ title,
711
+ url: frames.get("WXXX"),
712
+ start: chap.info.startTime / 1e3,
713
+ end: chap.info.endTime / 1e3,
714
+ image: frames.get("APIC")
715
+ });
716
+ }
717
+ if (!orderedIds) {
718
+ chapters.sort((a, b) => a.start - b.start);
719
+ }
720
+ return chapters.length ? chapters : void 0;
721
+ }
722
+ };
723
+ function makeUnexpectedMajorVersionError3(majorVer) {
724
+ throw new Id3v2ContentError(`Unexpected majorVer: ${majorVer}`);
725
+ }
726
+
727
+ export {
728
+ ID3v2Parser
729
+ };