taglib-wasm 1.1.1 → 1.2.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.
Files changed (60) hide show
  1. package/README.md +512 -38
  2. package/dist/index.browser.js +366 -56
  3. package/dist/index.d.ts +2 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +2 -0
  6. package/dist/simple.browser.js +366 -56
  7. package/dist/src/bwf/bext.d.ts +28 -0
  8. package/dist/src/bwf/bext.d.ts.map +1 -0
  9. package/dist/src/bwf/bext.js +126 -0
  10. package/dist/src/msgpack/encoder.d.ts.map +1 -1
  11. package/dist/src/msgpack/encoder.js +9 -1
  12. package/dist/src/runtime/unified-loader/module-loading.js +1 -1
  13. package/dist/src/runtime/wasi-adapter/adapter.d.ts +0 -2
  14. package/dist/src/runtime/wasi-adapter/adapter.d.ts.map +1 -1
  15. package/dist/src/runtime/wasi-adapter/adapter.js +0 -12
  16. package/dist/src/runtime/wasi-adapter/file-handle.d.ts +12 -4
  17. package/dist/src/runtime/wasi-adapter/file-handle.d.ts.map +1 -1
  18. package/dist/src/runtime/wasi-adapter/file-handle.js +73 -54
  19. package/dist/src/runtime/wasi-host-loader.d.ts +1 -1
  20. package/dist/src/runtime/wasi-host-loader.js +1 -1
  21. package/dist/src/taglib/audio-file-base.d.ts.map +1 -1
  22. package/dist/src/taglib/audio-file-base.js +25 -42
  23. package/dist/src/taglib/audio-file-bwf.d.ts +14 -0
  24. package/dist/src/taglib/audio-file-bwf.d.ts.map +1 -0
  25. package/dist/src/taglib/audio-file-bwf.js +41 -0
  26. package/dist/src/taglib/audio-file-impl.d.ts +10 -0
  27. package/dist/src/taglib/audio-file-impl.d.ts.map +1 -1
  28. package/dist/src/taglib/audio-file-impl.js +69 -13
  29. package/dist/src/taglib/audio-file-interface.d.ts +27 -0
  30. package/dist/src/taglib/audio-file-interface.d.ts.map +1 -1
  31. package/dist/src/taglib/embind-adapter.d.ts +53 -0
  32. package/dist/src/taglib/embind-adapter.d.ts.map +1 -0
  33. package/dist/src/taglib/embind-adapter.js +82 -0
  34. package/dist/src/taglib/taglib-class.d.ts.map +1 -1
  35. package/dist/src/taglib/taglib-class.js +3 -1
  36. package/dist/src/types/audio-formats.d.ts +20 -0
  37. package/dist/src/types/audio-formats.d.ts.map +1 -1
  38. package/dist/src/types/bwf.d.ts +43 -0
  39. package/dist/src/types/bwf.d.ts.map +1 -0
  40. package/dist/src/types/bwf.js +0 -0
  41. package/dist/src/types/chapters.d.ts +47 -0
  42. package/dist/src/types/chapters.d.ts.map +1 -0
  43. package/dist/src/types/chapters.js +0 -0
  44. package/dist/src/types/index.d.ts +2 -0
  45. package/dist/src/types/index.d.ts.map +1 -1
  46. package/dist/src/types/index.js +2 -0
  47. package/dist/src/types/metadata-mappings.d.ts +1 -1
  48. package/dist/src/types/metadata-mappings.d.ts.map +1 -1
  49. package/dist/src/types/tags.d.ts +25 -7
  50. package/dist/src/types/tags.d.ts.map +1 -1
  51. package/dist/src/version.d.ts +1 -1
  52. package/dist/src/version.js +1 -1
  53. package/dist/src/wasm.d.ts +17 -39
  54. package/dist/src/wasm.d.ts.map +1 -1
  55. package/dist/taglib-wasi.wasm +0 -0
  56. package/dist/taglib-web.wasm +0 -0
  57. package/dist/taglib-wrapper.d.ts +0 -2
  58. package/dist/taglib-wrapper.js +1 -1
  59. package/package.json +5 -5
  60. package/dist/taglib_wasi.wasm +0 -0
@@ -0,0 +1,126 @@
1
+ const FIXED_PREFIX_LEN = 602;
2
+ const VERSION_OFFSET = 346;
3
+ const UMID_OFFSET = 348;
4
+ const UMID_LEN = 64;
5
+ const LOUDNESS_OFFSET = 412;
6
+ const LOUDNESS_UNSET = 32767;
7
+ function readFixedString(bytes, offset, len) {
8
+ let end = offset;
9
+ const max = Math.min(offset + len, bytes.length);
10
+ while (end < max && bytes[end] !== 0) end++;
11
+ let s = "";
12
+ for (let i = offset; i < end; i++) s += String.fromCharCode(bytes[i]);
13
+ return s;
14
+ }
15
+ function writeFixedString(bytes, offset, len, value) {
16
+ for (let i = 0; i < len; i++) {
17
+ bytes[offset + i] = i < value.length ? value.charCodeAt(i) & 255 : 0;
18
+ }
19
+ }
20
+ function clampInt16(n) {
21
+ return Math.max(-32768, Math.min(32767, Math.round(n)));
22
+ }
23
+ function loudnessRaw(v) {
24
+ return v === void 0 ? LOUDNESS_UNSET : clampInt16(v * 100);
25
+ }
26
+ function loudnessFromRaw(raw) {
27
+ return raw === LOUDNESS_UNSET ? void 0 : raw / 100;
28
+ }
29
+ function bytesToHex(bytes) {
30
+ let s = "";
31
+ for (const b of bytes) s += b.toString(16).padStart(2, "0");
32
+ return s;
33
+ }
34
+ function hexToBytes(hex, outLen) {
35
+ const clean = hex.replace(/[^0-9a-fA-F]/g, "");
36
+ const out = new Uint8Array(outLen);
37
+ for (let i = 0; i + 1 < clean.length + 1 && i / 2 < outLen; i += 2) {
38
+ const pair = clean.slice(i, i + 2);
39
+ if (pair.length === 2) out[i / 2] = parseInt(pair, 16);
40
+ }
41
+ return out;
42
+ }
43
+ function decodeBext(bytes) {
44
+ if (bytes.length < VERSION_OFFSET + 2) return void 0;
45
+ const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
46
+ const timeRefLow = dv.getUint32(338, true);
47
+ const timeRefHigh = dv.getUint32(342, true);
48
+ const version = dv.getUint16(VERSION_OFFSET, true);
49
+ const result = {
50
+ description: readFixedString(bytes, 0, 256),
51
+ originator: readFixedString(bytes, 256, 32),
52
+ originatorReference: readFixedString(bytes, 288, 32),
53
+ originationDate: readFixedString(bytes, 320, 10),
54
+ originationTime: readFixedString(bytes, 330, 8),
55
+ timeReferenceSamples: BigInt(timeRefHigh) << 32n | BigInt(timeRefLow),
56
+ version,
57
+ codingHistory: bytes.length > FIXED_PREFIX_LEN ? readFixedString(
58
+ bytes,
59
+ FIXED_PREFIX_LEN,
60
+ bytes.length - FIXED_PREFIX_LEN
61
+ ) : ""
62
+ };
63
+ if (version >= 1 && bytes.length >= UMID_OFFSET + UMID_LEN) {
64
+ result.umid = bytesToHex(
65
+ bytes.subarray(UMID_OFFSET, UMID_OFFSET + UMID_LEN)
66
+ );
67
+ }
68
+ if (version >= 2 && bytes.length >= LOUDNESS_OFFSET + 10) {
69
+ const lv = loudnessFromRaw(dv.getInt16(LOUDNESS_OFFSET, true));
70
+ const lr = loudnessFromRaw(dv.getInt16(LOUDNESS_OFFSET + 2, true));
71
+ const mtp = loudnessFromRaw(dv.getInt16(LOUDNESS_OFFSET + 4, true));
72
+ const mml = loudnessFromRaw(dv.getInt16(LOUDNESS_OFFSET + 6, true));
73
+ const msl = loudnessFromRaw(dv.getInt16(LOUDNESS_OFFSET + 8, true));
74
+ if (lv !== void 0) result.loudnessValueDb = lv;
75
+ if (lr !== void 0) result.loudnessRangeDb = lr;
76
+ if (mtp !== void 0) result.maxTruePeakLevelDbtp = mtp;
77
+ if (mml !== void 0) result.maxMomentaryLoudnessDb = mml;
78
+ if (msl !== void 0) result.maxShortTermLoudnessDb = msl;
79
+ }
80
+ return result;
81
+ }
82
+ function encodeBext(b) {
83
+ const codingHistory = b.codingHistory ?? "";
84
+ const bytes = new Uint8Array(FIXED_PREFIX_LEN + codingHistory.length);
85
+ const dv = new DataView(bytes.buffer);
86
+ const hasLoudness = b.loudnessValueDb !== void 0 || b.loudnessRangeDb !== void 0 || b.maxTruePeakLevelDbtp !== void 0 || b.maxMomentaryLoudnessDb !== void 0 || b.maxShortTermLoudnessDb !== void 0;
87
+ const version = Number.isInteger(b.version) ? b.version : hasLoudness ? 2 : b.umid ? 1 : 0;
88
+ writeFixedString(bytes, 0, 256, b.description ?? "");
89
+ writeFixedString(bytes, 256, 32, b.originator ?? "");
90
+ writeFixedString(bytes, 288, 32, b.originatorReference ?? "");
91
+ writeFixedString(bytes, 320, 10, b.originationDate ?? "");
92
+ writeFixedString(bytes, 330, 8, b.originationTime ?? "");
93
+ const tr = b.timeReferenceSamples ?? 0n;
94
+ dv.setUint32(338, Number(tr & 0xffffffffn), true);
95
+ dv.setUint32(342, Number(tr >> 32n & 0xffffffffn), true);
96
+ dv.setUint16(VERSION_OFFSET, version, true);
97
+ if (version >= 1 && b.umid) {
98
+ bytes.set(hexToBytes(b.umid, UMID_LEN), UMID_OFFSET);
99
+ }
100
+ if (version >= 2) {
101
+ dv.setInt16(LOUDNESS_OFFSET, loudnessRaw(b.loudnessValueDb), true);
102
+ dv.setInt16(LOUDNESS_OFFSET + 2, loudnessRaw(b.loudnessRangeDb), true);
103
+ dv.setInt16(LOUDNESS_OFFSET + 4, loudnessRaw(b.maxTruePeakLevelDbtp), true);
104
+ dv.setInt16(
105
+ LOUDNESS_OFFSET + 6,
106
+ loudnessRaw(b.maxMomentaryLoudnessDb),
107
+ true
108
+ );
109
+ dv.setInt16(
110
+ LOUDNESS_OFFSET + 8,
111
+ loudnessRaw(b.maxShortTermLoudnessDb),
112
+ true
113
+ );
114
+ }
115
+ writeFixedString(
116
+ bytes,
117
+ FIXED_PREFIX_LEN,
118
+ codingHistory.length,
119
+ codingHistory
120
+ );
121
+ return bytes;
122
+ }
123
+ export {
124
+ decodeBext,
125
+ encodeBext
126
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/msgpack/encoder.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAErF,OAAO,EAAU,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE/D,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,OAAO,EACP,WAAW,EACZ,MAAM,aAAa,CAAC;AAcrB,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,CAiB9D;AAED,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,eAAe,GAAG,UAAU,CAS7E;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,WAAW,GAAG,UAAU,CAStE;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAe1D;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,UAAU,CAelE;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,IAAI,EAAE,CAAC,EACP,OAAO,GAAE,OAAO,CAAC,cAAc,CAAM,GACpC,UAAU,CAUZ;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,UAAU,CAe/D;AAqBD,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,UAAU,CAc1E;AAED,wBAAiB,uBAAuB,CAAC,CAAC,EACxC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,GACxB,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CActC;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAS7D;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,GAC1E,UAAU,CAeZ;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAW7D;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG;IACxD,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAaA"}
1
+ {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/msgpack/encoder.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAErF,OAAO,EAAU,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAE/D,OAAO,KAAK,EACV,eAAe,EACf,WAAW,EACX,OAAO,EACP,WAAW,EACZ,MAAM,aAAa,CAAC;AAsBrB,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,UAAU,CAiB9D;AAED,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,eAAe,GAAG,UAAU,CAS7E;AAED,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,WAAW,GAAG,UAAU,CAStE;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,CAe1D;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,UAAU,CAelE;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,IAAI,EAAE,CAAC,EACP,OAAO,GAAE,OAAO,CAAC,cAAc,CAAM,GACpC,UAAU,CAUZ;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,UAAU,CAe/D;AAqBD,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,WAAW,EAAE,GAAG,UAAU,CAc1E;AAED,wBAAiB,uBAAuB,CAAC,CAAC,EACxC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,GACxB,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CActC;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAS7D;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,GAC1E,UAAU,CAeZ;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAW7D;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,OAAO,GAAG;IACxD,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAaA"}
@@ -1,7 +1,15 @@
1
1
  import { encode } from "@msgpack/msgpack";
2
2
  import { errorMessage, MetadataError } from "../errors/classes.js";
3
3
  import { toTagLibKey } from "../constants/properties.js";
4
- const PASSTHROUGH_KEYS = /* @__PURE__ */ new Set(["pictures", "ratings", "lyrics", "chapters"]);
4
+ const PASSTHROUGH_KEYS = /* @__PURE__ */ new Set([
5
+ "pictures",
6
+ "ratings",
7
+ "lyrics",
8
+ "chapters",
9
+ "_mp4ChapterStyle",
10
+ "bextData",
11
+ "ixml"
12
+ ]);
5
13
  const MSGPACK_ENCODE_OPTIONS = {
6
14
  sortKeys: false,
7
15
  forceFloat32: false,
@@ -38,7 +38,7 @@ async function loadModule(wasmType, runtime, options) {
38
38
  }
39
39
  }
40
40
  async function loadWasiModuleWithFallback(runtime, options) {
41
- const defaultWasmPath = resolveWasmPath("../../../taglib_wasi.wasm");
41
+ const defaultWasmPath = resolveWasmPath("../../../taglib-wasi.wasm");
42
42
  try {
43
43
  const { loadWasiHost } = await import("../wasi-host-loader.js");
44
44
  const wasiModule = await loadWasiHost({
@@ -11,8 +11,6 @@ export declare class WasiToTagLibAdapter implements TagLibModule {
11
11
  private readonly heap;
12
12
  constructor(wasiModule: WasiModule);
13
13
  FileHandle: new () => FileHandle;
14
- TagWrapper: new () => import("../../wasm.js").TagWrapper;
15
- AudioPropertiesWrapper: new () => import("../../wasm.js").AudioPropertiesWrapper;
16
14
  get ready(): Promise<this>;
17
15
  get HEAP8(): Int8Array;
18
16
  get HEAP16(): Int16Array;
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAKhE,qBAAa,mBAAoB,YAAW,YAAY;IACtD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,UAAU,EAAE,UAAU;IAKlC,UAAU,EAMM,UAAU,UAAU,CAAC;IAErC,UAAU,EAIM,UAAU,OAAO,eAAe,EAAE,UAAU,CAAC;IAE7D,sBAAsB,EAMN,UAAU,OAAO,eAAe,EAAE,sBAAsB,CAAC;IAEzE,IAAI,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAEzB;IAED,IAAI,KAAK,IAAI,SAAS,CAErB;IAED,IAAI,MAAM,IAAI,UAAU,CAEvB;IAED,IAAI,MAAM,IAAI,UAAU,CAEvB;IAED,IAAI,MAAM,IAAI,UAAU,CAEvB;IAED,IAAI,OAAO,IAAI,WAAW,CAEzB;IAED,IAAI,OAAO,IAAI,WAAW,CAEzB;IAED,IAAI,OAAO,IAAI,YAAY,CAE1B;IAED,IAAI,OAAO,IAAI,YAAY,CAE1B;IAED,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAI7B,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIxB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAe9C,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAOjC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAQhE,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAIpC,gBAAgB,IAAI,UAAU;IAI9B,OAAO,IAAI,MAAM;IAIjB,WAAW,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM;IAM/B,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMlC,KAAK,CACH,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,SAAS,EAAE,MAAM,EAAE,GAClB,GAAG;IAMN,KAAK,CACH,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,SAAS,EAAE,MAAM,EAAE,EACnB,KAAK,EAAE,GAAG,EAAE,GACX,GAAG;CAKP"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAKhE,qBAAa,mBAAoB,YAAW,YAAY;IACtD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;gBAEtB,UAAU,EAAE,UAAU;IAKlC,UAAU,EAMM,UAAU,UAAU,CAAC;IAErC,IAAI,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAEzB;IAED,IAAI,KAAK,IAAI,SAAS,CAErB;IAED,IAAI,MAAM,IAAI,UAAU,CAEvB;IAED,IAAI,MAAM,IAAI,UAAU,CAEvB;IAED,IAAI,MAAM,IAAI,UAAU,CAEvB;IAED,IAAI,OAAO,IAAI,WAAW,CAEzB;IAED,IAAI,OAAO,IAAI,WAAW,CAEzB;IAED,IAAI,OAAO,IAAI,YAAY,CAE1B;IAED,IAAI,OAAO,IAAI,YAAY,CAE1B;IAED,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAI7B,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIxB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAe9C,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAOjC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAQhE,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAIpC,gBAAgB,IAAI,UAAU;IAI9B,OAAO,IAAI,MAAM;IAIjB,WAAW,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM;IAM/B,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMlC,KAAK,CACH,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,SAAS,EAAE,MAAM,EAAE,GAClB,GAAG;IAMN,KAAK,CACH,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,SAAS,EAAE,MAAM,EAAE,EACnB,KAAK,EAAE,GAAG,EAAE,GACX,GAAG;CAKP"}
@@ -15,18 +15,6 @@ class WasiToTagLibAdapter {
15
15
  );
16
16
  }
17
17
  });
18
- __publicField(this, "TagWrapper", class {
19
- constructor() {
20
- throw new WasmerExecutionError("TagWrapper not directly constructable");
21
- }
22
- });
23
- __publicField(this, "AudioPropertiesWrapper", class {
24
- constructor() {
25
- throw new WasmerExecutionError(
26
- "AudioPropertiesWrapper not directly constructable"
27
- );
28
- }
29
- });
30
18
  this.wasi = wasiModule;
31
19
  this.heap = new Uint8Array(wasiModule.memory.buffer);
32
20
  }
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * @fileoverview WASI-based FileHandle implementation
3
3
  */
4
- import type { AudioPropertiesWrapper, FileHandle, RawPicture, TagWrapper } from "../../wasm.js";
4
+ import type { FileHandle, RawChapter, RawPicture } from "../../wasm.js";
5
+ import type { BasicTagData } from "../../types/tags.js";
6
+ import type { AudioProperties } from "../../types.js";
5
7
  import type { WasiModule } from "../wasmer-sdk-loader/types.js";
6
8
  export declare class WasiFileHandle implements FileHandle {
7
9
  private readonly wasi;
@@ -15,9 +17,9 @@ export declare class WasiFileHandle implements FileHandle {
15
17
  loadFromPath(path: string): boolean;
16
18
  isValid(): boolean;
17
19
  save(): boolean;
18
- getTag(): TagWrapper;
19
- private createTagWrapper;
20
- getAudioProperties(): AudioPropertiesWrapper | null;
20
+ getTagData(): BasicTagData;
21
+ setTagData(data: Partial<BasicTagData>): void;
22
+ getAudioProperties(): AudioProperties | null;
21
23
  getFormat(): string;
22
24
  private detectOggCodec;
23
25
  getBuffer(): Uint8Array;
@@ -33,6 +35,12 @@ export declare class WasiFileHandle implements FileHandle {
33
35
  setPictures(pictures: RawPicture[]): void;
34
36
  addPicture(picture: RawPicture): void;
35
37
  removePictures(): void;
38
+ getChapters(): RawChapter[];
39
+ setChapters(chapters: RawChapter[], mp4ChapterStyle: string): void;
40
+ getBextData(): Uint8Array | undefined;
41
+ setBextData(data: Uint8Array | null): void;
42
+ getIxml(): string | undefined;
43
+ setIxml(data: string | null): void;
36
44
  getRatings(): {
37
45
  rating: number;
38
46
  email: string;
@@ -1 +1 @@
1
- {"version":3,"file":"file-handle.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/file-handle.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,sBAAsB,EACtB,UAAU,EACV,UAAU,EACV,UAAU,EACX,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAgDhE,qBAAa,cAAe,YAAW,UAAU;IAC/C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,OAAO,CAAwC;IACvD,OAAO,CAAC,SAAS,CAAS;gBAEd,UAAU,EAAE,UAAU;IAIlC,OAAO,CAAC,iBAAiB;IAQzB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO;IAW3C,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAWnC,OAAO,IAAI,OAAO;IAMlB,IAAI,IAAI,OAAO;IAqBf,MAAM,IAAI,UAAU;IASpB,OAAO,CAAC,gBAAgB;IAsCxB,kBAAkB,IAAI,sBAAsB,GAAG,IAAI;IAqBnD,SAAS,IAAI,MAAM;IA2DnB,OAAO,CAAC,cAAc;IAiBtB,SAAS,IAAI,UAAU;IAKvB,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAuBzC,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI;IAgBpD,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAOhC,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAc7C,KAAK,IAAI,OAAO;IAehB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAK/B,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAK5C,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAShC,WAAW,IAAI,UAAU,EAAE;IAK3B,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI;IAKzC,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAOrC,cAAc,IAAI,IAAI;IAKtB,UAAU,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE;IAOlE,UAAU,CACR,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,GAC9D,IAAI;IAaP,OAAO,IAAI,IAAI;CAKhB"}
1
+ {"version":3,"file":"file-handle.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/file-handle.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AA8DhE,qBAAa,cAAe,YAAW,UAAU;IAC/C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,OAAO,CAAwC;IACvD,OAAO,CAAC,SAAS,CAAS;gBAEd,UAAU,EAAE,UAAU;IAIlC,OAAO,CAAC,iBAAiB;IAQzB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO;IAW3C,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAWnC,OAAO,IAAI,OAAO;IAMlB,IAAI,IAAI,OAAO;IAqBf,UAAU,IAAI,YAAY;IAc1B,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI;IAK7C,kBAAkB,IAAI,eAAe,GAAG,IAAI;IA+B5C,SAAS,IAAI,MAAM;IA2DnB,OAAO,CAAC,cAAc;IAiBtB,SAAS,IAAI,UAAU;IAKvB,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAuBzC,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI;IAgBpD,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAOhC,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAc7C,KAAK,IAAI,OAAO;IAehB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAK/B,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAK5C,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAShC,WAAW,IAAI,UAAU,EAAE;IAK3B,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI;IAKzC,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI;IAOrC,cAAc,IAAI,IAAI;IAKtB,WAAW,IAAI,UAAU,EAAE;IAK3B,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI;IASlE,WAAW,IAAI,UAAU,GAAG,SAAS;IAKrC,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI;IAS1C,OAAO,IAAI,MAAM,GAAG,SAAS;IAM7B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAKlC,UAAU,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE;IAOlE,UAAU,CACR,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,GAC9D,IAAI;IAaP,OAAO,IAAI,IAAI;CAKhB"}
@@ -24,9 +24,18 @@ const AUDIO_KEYS = /* @__PURE__ */ new Set([
24
24
  "lengthMs",
25
25
  "mpegLayer",
26
26
  "mpegVersion",
27
+ "outputGainDb",
27
28
  "sampleRate"
28
29
  ]);
29
- const INTERNAL_KEYS = /* @__PURE__ */ new Set(["pictures", "ratings"]);
30
+ const INTERNAL_KEYS = /* @__PURE__ */ new Set([
31
+ "pictures",
32
+ "ratings",
33
+ "lyrics",
34
+ "chapters",
35
+ "_mp4ChapterStyle",
36
+ "bextData",
37
+ "ixml"
38
+ ]);
30
39
  const CONTAINER_TO_FORMAT = {
31
40
  MP3: "MP3",
32
41
  MP4: "MP4",
@@ -43,6 +52,10 @@ const NUMERIC_FIELD_ALIASES = {
43
52
  date: "year",
44
53
  trackNumber: "track"
45
54
  };
55
+ function firstString(v) {
56
+ if (Array.isArray(v)) return v[0] ?? "";
57
+ return v || "";
58
+ }
46
59
  class WasiFileHandle {
47
60
  constructor(wasiModule) {
48
61
  __publicField(this, "wasi");
@@ -95,67 +108,44 @@ class WasiFileHandle {
95
108
  }
96
109
  return false;
97
110
  }
98
- getTag() {
111
+ getTagData() {
99
112
  this.checkNotDestroyed();
100
- if (!this.tagData) {
101
- return this.createTagWrapper({});
102
- }
103
- return this.createTagWrapper(this.tagData);
104
- }
105
- createTagWrapper(data) {
106
- const firstString = (v) => {
107
- if (Array.isArray(v)) return v[0] ?? "";
108
- return v || "";
109
- };
113
+ const d = this.tagData ?? {};
110
114
  return {
111
- title: () => firstString(data.title),
112
- artist: () => firstString(data.artist),
113
- album: () => firstString(data.album),
114
- comment: () => firstString(data.comment),
115
- genre: () => firstString(data.genre),
116
- year: () => data.year || 0,
117
- track: () => data.track || 0,
118
- setTitle: (value) => {
119
- this.tagData = { ...this.tagData, title: value };
120
- },
121
- setArtist: (value) => {
122
- this.tagData = { ...this.tagData, artist: value };
123
- },
124
- setAlbum: (value) => {
125
- this.tagData = { ...this.tagData, album: value };
126
- },
127
- setComment: (value) => {
128
- this.tagData = { ...this.tagData, comment: value };
129
- },
130
- setGenre: (value) => {
131
- this.tagData = { ...this.tagData, genre: value };
132
- },
133
- setYear: (value) => {
134
- this.tagData = { ...this.tagData, year: value };
135
- },
136
- setTrack: (value) => {
137
- this.tagData = { ...this.tagData, track: value };
138
- }
115
+ title: firstString(d.title),
116
+ artist: firstString(d.artist),
117
+ album: firstString(d.album),
118
+ comment: firstString(d.comment),
119
+ genre: firstString(d.genre),
120
+ year: d.year || 0,
121
+ track: d.track || 0
139
122
  };
140
123
  }
124
+ setTagData(data) {
125
+ this.checkNotDestroyed();
126
+ this.tagData = { ...this.tagData, ...data };
127
+ }
141
128
  getAudioProperties() {
142
129
  this.checkNotDestroyed();
143
130
  if (!this.tagData || !("sampleRate" in this.tagData)) return null;
144
- const data = this.tagData;
131
+ const d = this.tagData;
132
+ const containerFormat = d.containerFormat || "unknown";
133
+ const mpegVersion = d.mpegVersion ?? 0;
134
+ const formatVersion = d.formatVersion ?? 0;
145
135
  return {
146
- lengthInSeconds: () => data.length ?? 0,
147
- lengthInMilliseconds: () => data.lengthMs ?? 0,
148
- bitrate: () => data.bitrate ?? 0,
149
- sampleRate: () => data.sampleRate ?? 0,
150
- channels: () => data.channels ?? 0,
151
- bitsPerSample: () => data.bitsPerSample ?? 0,
152
- codec: () => data.codec ?? "",
153
- containerFormat: () => data.containerFormat ?? "",
154
- isLossless: () => data.isLossless ?? false,
155
- mpegVersion: () => data.mpegVersion ?? 0,
156
- mpegLayer: () => data.mpegLayer ?? 0,
157
- isEncrypted: () => data.isEncrypted ?? false,
158
- formatVersion: () => data.formatVersion ?? 0
136
+ duration: d.length ?? 0,
137
+ durationMs: d.lengthMs ?? 0,
138
+ bitrate: d.bitrate ?? 0,
139
+ sampleRate: d.sampleRate ?? 0,
140
+ channels: d.channels ?? 0,
141
+ bitsPerSample: d.bitsPerSample ?? 0,
142
+ codec: d.codec || "unknown",
143
+ containerFormat,
144
+ isLossless: d.isLossless ?? false,
145
+ ...mpegVersion > 0 ? { mpegVersion, mpegLayer: d.mpegLayer ?? 0 } : {},
146
+ ...containerFormat === "MP4" || containerFormat === "ASF" ? { isEncrypted: d.isEncrypted ?? false } : {},
147
+ ...formatVersion > 0 ? { formatVersion } : {},
148
+ ...d.outputGainDb !== void 0 ? { outputGainDb: d.outputGainDb } : {}
159
149
  };
160
150
  }
161
151
  getFormat() {
@@ -295,6 +285,35 @@ class WasiFileHandle {
295
285
  this.checkNotDestroyed();
296
286
  this.tagData = { ...this.tagData, pictures: [] };
297
287
  }
288
+ getChapters() {
289
+ this.checkNotDestroyed();
290
+ return this.tagData?.chapters ?? [];
291
+ }
292
+ setChapters(chapters, mp4ChapterStyle) {
293
+ this.checkNotDestroyed();
294
+ this.tagData = {
295
+ ...this.tagData,
296
+ _mp4ChapterStyle: mp4ChapterStyle,
297
+ chapters
298
+ };
299
+ }
300
+ getBextData() {
301
+ this.checkNotDestroyed();
302
+ return this.tagData?.bextData ?? void 0;
303
+ }
304
+ setBextData(data) {
305
+ this.checkNotDestroyed();
306
+ this.tagData = { ...this.tagData, bextData: data };
307
+ }
308
+ getIxml() {
309
+ this.checkNotDestroyed();
310
+ const v = this.tagData?.ixml;
311
+ return typeof v === "string" && v.length > 0 ? v : void 0;
312
+ }
313
+ setIxml(data) {
314
+ this.checkNotDestroyed();
315
+ this.tagData = { ...this.tagData, ixml: data };
316
+ }
298
317
  getRatings() {
299
318
  this.checkNotDestroyed();
300
319
  return this.tagData?.ratings ?? [];
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @fileoverview WASI host loader for in-process filesystem access
3
3
  *
4
- * Loads the taglib_wasi.wasm binary with real WASI filesystem
4
+ * Loads the taglib-wasi.wasm binary with real WASI filesystem
5
5
  * implementations, enabling efficient seek-based file I/O.
6
6
  */
7
7
  import type { FileSystemProvider } from "./wasi-fs-provider.js";
@@ -22,7 +22,7 @@ async function resolveFs(provided) {
22
22
  }
23
23
  async function loadWasiHost(config) {
24
24
  const defaultPath = (() => {
25
- const url = new URL("../../taglib_wasi.wasm", import.meta.url);
25
+ const url = new URL("../../taglib-wasi.wasm", import.meta.url);
26
26
  return url.protocol === "file:" ? fileUrlToPath(url) : url.href;
27
27
  })();
28
28
  const wasmPath = config.wasmPath ?? defaultPath;
@@ -1 +1 @@
1
- {"version":3,"file":"audio-file-base.d.ts","sourceRoot":"","sources":["../../../src/taglib/audio-file-base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,KAAK,EAEV,eAAe,EAEf,QAAQ,EACR,WAAW,EACX,WAAW,EACZ,MAAM,aAAa,CAAC;AAGrB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEhE;;;;;GAKG;AACH,8BAAsB,iBAAiB;IASnC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY;IARzC,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IACxC,SAAS,CAAC,qBAAqB,EAAE,eAAe,GAAG,IAAI,CAAQ;IAC/D,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IACvC,SAAS,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,IAAI,CAAC;IACpE,SAAS,CAAC,iBAAiB,EAAE,OAAO,CAAS;IAC7C,SAAS,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,WAAW,CAAC;gBAG/B,MAAM,EAAE,YAAY,EACvC,UAAU,EAAE,UAAU,EACtB,UAAU,CAAC,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,IAAI,EACzD,iBAAiB,GAAE,OAAe,EAClC,kBAAkB,CAAC,EAAE,WAAW;IASlC,SAAS,KAAK,MAAM,IAAI,UAAU,CAKjC;IAED,SAAS,IAAI,QAAQ;IAIrB,QAAQ,CAAC,CAAC,SAAS,QAAQ,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,IAAI,cAAc,CAAC,CAAC,CAAC;IAIlE,GAAG,IAAI,UAAU;IA+DjB,eAAe,IAAI,eAAe,GAAG,SAAS;IAkC9C,UAAU,IAAI,WAAW;IAIzB,aAAa,CAAC,UAAU,EAAE,WAAW,GAAG,IAAI;IAQ5C,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK5C,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7C,KAAK,IAAI,OAAO;IAIhB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAQ3C,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAO5C,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAOhC,OAAO,IAAI,OAAO;IAIlB,OAAO,IAAI,IAAI;IAQf,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI;CAGzB"}
1
+ {"version":3,"file":"audio-file-base.d.ts","sourceRoot":"","sources":["../../../src/taglib/audio-file-base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,KAAK,EACV,eAAe,EACf,QAAQ,EACR,WAAW,EACX,WAAW,EACZ,MAAM,aAAa,CAAC;AAGrB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEhE;;;;;GAKG;AACH,8BAAsB,iBAAiB;IASnC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY;IARzC,SAAS,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IACxC,SAAS,CAAC,qBAAqB,EAAE,eAAe,GAAG,IAAI,CAAQ;IAC/D,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IACvC,SAAS,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,IAAI,CAAC;IACpE,SAAS,CAAC,iBAAiB,EAAE,OAAO,CAAS;IAC7C,SAAS,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,WAAW,CAAC;gBAG/B,MAAM,EAAE,YAAY,EACvC,UAAU,EAAE,UAAU,EACtB,UAAU,CAAC,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,IAAI,EACzD,iBAAiB,GAAE,OAAe,EAClC,kBAAkB,CAAC,EAAE,WAAW;IASlC,SAAS,KAAK,MAAM,IAAI,UAAU,CAKjC;IAED,SAAS,IAAI,QAAQ;IAIrB,QAAQ,CAAC,CAAC,SAAS,QAAQ,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,IAAI,cAAc,CAAC,CAAC,CAAC;IAIlE,GAAG,IAAI,UAAU;IAgEjB,eAAe,IAAI,eAAe,GAAG,SAAS;IAO9C,UAAU,IAAI,WAAW;IAIzB,aAAa,CAAC,UAAU,EAAE,WAAW,GAAG,IAAI;IAQ5C,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAK5C,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7C,KAAK,IAAI,OAAO;IAIhB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAQ3C,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAO5C,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAOhC,OAAO,IAAI,OAAO;IAIlB,OAAO,IAAI,IAAI;IAQf,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI;CAGzB"}
@@ -31,61 +31,63 @@ class BaseAudioFileImpl {
31
31
  return this.getFormat() === format;
32
32
  }
33
33
  tag() {
34
- const tagWrapper = this.handle.getTag();
35
- if (!tagWrapper) {
36
- throw new MetadataError(
37
- "read",
38
- "Tag may be corrupted or format not fully supported"
39
- );
40
- }
34
+ const handle = this.handle;
35
+ let data = handle.getTagData();
41
36
  const tag = {
42
37
  get title() {
43
- return tagWrapper.title();
38
+ return data.title;
44
39
  },
45
40
  get artist() {
46
- return tagWrapper.artist();
41
+ return data.artist;
47
42
  },
48
43
  get album() {
49
- return tagWrapper.album();
44
+ return data.album;
50
45
  },
51
46
  get comment() {
52
- return tagWrapper.comment();
47
+ return data.comment;
53
48
  },
54
49
  get genre() {
55
- return tagWrapper.genre();
50
+ return data.genre;
56
51
  },
57
52
  get year() {
58
- return tagWrapper.year();
53
+ return data.year;
59
54
  },
60
55
  get track() {
61
- return tagWrapper.track();
56
+ return data.track;
62
57
  },
63
58
  setTitle: (value) => {
64
- tagWrapper.setTitle(value);
59
+ handle.setTagData({ title: value });
60
+ data = handle.getTagData();
65
61
  return tag;
66
62
  },
67
63
  setArtist: (value) => {
68
- tagWrapper.setArtist(value);
64
+ handle.setTagData({ artist: value });
65
+ data = handle.getTagData();
69
66
  return tag;
70
67
  },
71
68
  setAlbum: (value) => {
72
- tagWrapper.setAlbum(value);
69
+ handle.setTagData({ album: value });
70
+ data = handle.getTagData();
73
71
  return tag;
74
72
  },
75
73
  setComment: (value) => {
76
- tagWrapper.setComment(value);
74
+ handle.setTagData({ comment: value });
75
+ data = handle.getTagData();
77
76
  return tag;
78
77
  },
79
78
  setGenre: (value) => {
80
- tagWrapper.setGenre(value);
79
+ handle.setTagData({ genre: value });
80
+ data = handle.getTagData();
81
81
  return tag;
82
82
  },
83
83
  setYear: (value) => {
84
- tagWrapper.setYear(value);
84
+ handle.setTagData({ year: value });
85
+ data = handle.getTagData();
85
86
  return tag;
86
87
  },
87
88
  setTrack: (value) => {
88
- tagWrapper.setTrack(value);
89
+ handle.setTagData({ track: value });
90
+ data = handle.getTagData();
89
91
  return tag;
90
92
  }
91
93
  };
@@ -93,28 +95,9 @@ class BaseAudioFileImpl {
93
95
  }
94
96
  audioProperties() {
95
97
  if (!this.cachedAudioProperties) {
96
- const propsWrapper = this.handle.getAudioProperties();
97
- if (!propsWrapper) {
98
- return void 0;
99
- }
100
- const containerFormat = propsWrapper.containerFormat() || "unknown";
101
- const mpegVersion = propsWrapper.mpegVersion();
102
- const formatVersion = propsWrapper.formatVersion();
103
- this.cachedAudioProperties = {
104
- duration: propsWrapper.lengthInSeconds(),
105
- bitrate: propsWrapper.bitrate(),
106
- sampleRate: propsWrapper.sampleRate(),
107
- channels: propsWrapper.channels(),
108
- bitsPerSample: propsWrapper.bitsPerSample(),
109
- codec: propsWrapper.codec() || "unknown",
110
- containerFormat,
111
- isLossless: propsWrapper.isLossless(),
112
- ...mpegVersion > 0 ? { mpegVersion, mpegLayer: propsWrapper.mpegLayer() } : {},
113
- ...containerFormat === "MP4" || containerFormat === "ASF" ? { isEncrypted: propsWrapper.isEncrypted() } : {},
114
- ...formatVersion > 0 ? { formatVersion } : {}
115
- };
98
+ this.cachedAudioProperties = this.handle.getAudioProperties() ?? null;
116
99
  }
117
- return this.cachedAudioProperties;
100
+ return this.cachedAudioProperties ?? void 0;
118
101
  }
119
102
  properties() {
120
103
  return remapKeysFromTagLib(this.handle.getProperties());
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @fileoverview BWF (`bext` + iXML) operations, factored out of AudioFileImpl
3
+ * to keep that file under the size limit. Each function takes the raw FileHandle
4
+ * plus the already-resolved format string (for the unsupported-format guard).
5
+ */
6
+ import type { FileHandle } from "../wasm.js";
7
+ import type { BroadcastAudioExtension } from "../types/bwf.js";
8
+ export declare function getBextData(handle: FileHandle): Uint8Array | undefined;
9
+ export declare function setBextData(handle: FileHandle, format: string, data: Uint8Array | null): void;
10
+ export declare function getBext(handle: FileHandle): BroadcastAudioExtension | undefined;
11
+ export declare function setBext(handle: FileHandle, format: string, bext: BroadcastAudioExtension): void;
12
+ export declare function getIxml(handle: FileHandle): string | undefined;
13
+ export declare function setIxml(handle: FileHandle, format: string, data: string | null): void;
14
+ //# sourceMappingURL=audio-file-bwf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-file-bwf.d.ts","sourceRoot":"","sources":["../../../src/taglib/audio-file-bwf.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAc/D,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS,CAGtE;AAED,wBAAgB,WAAW,CACzB,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,UAAU,GAAG,IAAI,GACtB,IAAI,CAGN;AAED,wBAAgB,OAAO,CACrB,MAAM,EAAE,UAAU,GACjB,uBAAuB,GAAG,SAAS,CAGrC;AAED,wBAAgB,OAAO,CACrB,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,uBAAuB,GAC5B,IAAI,CAGN;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAE9D;AAED,wBAAgB,OAAO,CACrB,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GAAG,IAAI,GAClB,IAAI,CAGN"}
@@ -0,0 +1,41 @@
1
+ import { decodeBext, encodeBext } from "../bwf/bext.js";
2
+ import { UnsupportedFormatError } from "../errors.js";
3
+ const BWF_FORMATS = /* @__PURE__ */ new Set(["WAV", "FLAC"]);
4
+ function requireBwf(format) {
5
+ if (!BWF_FORMATS.has(format)) {
6
+ throw new UnsupportedFormatError(format, ["WAV", "FLAC"], {
7
+ operation: "BWF metadata"
8
+ });
9
+ }
10
+ }
11
+ function getBextData(handle) {
12
+ const raw = handle.getBextData();
13
+ return raw && raw.length > 0 ? raw : void 0;
14
+ }
15
+ function setBextData(handle, format, data) {
16
+ requireBwf(format);
17
+ handle.setBextData(data);
18
+ }
19
+ function getBext(handle) {
20
+ const raw = handle.getBextData();
21
+ return raw && raw.length > 0 ? decodeBext(raw) : void 0;
22
+ }
23
+ function setBext(handle, format, bext) {
24
+ requireBwf(format);
25
+ handle.setBextData(encodeBext(bext));
26
+ }
27
+ function getIxml(handle) {
28
+ return handle.getIxml();
29
+ }
30
+ function setIxml(handle, format, data) {
31
+ requireBwf(format);
32
+ handle.setIxml(data);
33
+ }
34
+ export {
35
+ getBext,
36
+ getBextData,
37
+ getIxml,
38
+ setBext,
39
+ setBextData,
40
+ setIxml
41
+ };
@@ -1,5 +1,7 @@
1
1
  import type { FileHandle, TagLibModule } from "../wasm.js";
2
2
  import type { OpenOptions, Picture } from "../types.js";
3
+ import type { Chapter, SetChaptersOptions } from "../types/chapters.js";
4
+ import type { BroadcastAudioExtension } from "../types/bwf.js";
3
5
  import type { Rating } from "../constants/complex-properties.js";
4
6
  import type { AudioFile } from "./audio-file-interface.js";
5
7
  import { BaseAudioFileImpl } from "./audio-file-base.js";
@@ -19,6 +21,14 @@ export declare class AudioFileImpl extends BaseAudioFileImpl implements AudioFil
19
21
  setPictures(pictures: Picture[]): void;
20
22
  addPicture(picture: Picture): void;
21
23
  removePictures(): void;
24
+ getChapters(): Chapter[];
25
+ setChapters(chapters: Chapter[], options?: SetChaptersOptions): void;
26
+ getBext(): BroadcastAudioExtension | undefined;
27
+ setBext(bext: BroadcastAudioExtension): void;
28
+ getBextData(): Uint8Array | undefined;
29
+ setBextData(data: Uint8Array | null): void;
30
+ getIxml(): string | undefined;
31
+ setIxml(data: string | null): void;
22
32
  getRatings(): Rating[];
23
33
  setRatings(ratings: Rating[]): void;
24
34
  getRating(): number | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"audio-file-impl.d.ts","sourceRoot":"","sources":["../../../src/taglib/audio-file-impl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAIjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAmBzD;;;;;GAKG;AACH,qBAAa,aAAc,SAAQ,iBAAkB,YAAW,SAAS;IACvE,OAAO,CAAC,cAAc,CAA2B;gBAG/C,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,UAAU,EACtB,UAAU,CAAC,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,IAAI,EACzD,iBAAiB,GAAE,OAAe,EAClC,kBAAkB,CAAC,EAAE,WAAW;IAYlC,IAAI,IAAI,OAAO;IAYf,aAAa,IAAI,UAAU;IAgBrB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsE9C,WAAW,IAAI,OAAO,EAAE;IAUxB,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI;IAStC,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IASlC,cAAc,IAAI,IAAI;IAItB,UAAU,IAAI,MAAM,EAAE;IAUtB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI;IAQnC,SAAS,IAAI,MAAM,GAAG,SAAS;IAK/B,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;CAGhD"}
1
+ {"version":3,"file":"audio-file-impl.d.ts","sourceRoot":"","sources":["../../../src/taglib/audio-file-impl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAc,YAAY,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oCAAoC,CAAC;AAQjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAqCzD;;;;;GAKG;AACH,qBAAa,aAAc,SAAQ,iBAAkB,YAAW,SAAS;IACvE,OAAO,CAAC,cAAc,CAA2B;gBAG/C,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,UAAU,EACtB,UAAU,CAAC,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,IAAI,EACzD,iBAAiB,GAAE,OAAe,EAClC,kBAAkB,CAAC,EAAE,WAAW;IAYlC,IAAI,IAAI,OAAO;IAYf,aAAa,IAAI,UAAU;IAgBrB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmE9C,WAAW,IAAI,OAAO,EAAE;IAUxB,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI;IAStC,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IASlC,cAAc,IAAI,IAAI;IAItB,WAAW,IAAI,OAAO,EAAE;IAYxB,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,IAAI;IAkBpE,OAAO,IAAI,uBAAuB,GAAG,SAAS;IAI9C,OAAO,CAAC,IAAI,EAAE,uBAAuB,GAAG,IAAI;IAI5C,WAAW,IAAI,UAAU,GAAG,SAAS;IAIrC,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI;IAI1C,OAAO,IAAI,MAAM,GAAG,SAAS;IAI7B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIlC,UAAU,IAAI,MAAM,EAAE;IAUtB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI;IAQnC,SAAS,IAAI,MAAM,GAAG,SAAS;IAK/B,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;CAGhD"}