taglib-wasm 2.2.1 → 2.2.2

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 (55) hide show
  1. package/dist/disc-folder.d.ts +3 -1
  2. package/dist/disc-folder.d.ts.map +1 -1
  3. package/dist/disc-folder.js +187 -152
  4. package/dist/index.browser.js +1 -1
  5. package/dist/simple.browser.js +1 -1
  6. package/dist/src/folder-api/album-corroborate.d.ts +13 -0
  7. package/dist/src/folder-api/album-corroborate.d.ts.map +1 -0
  8. package/dist/src/folder-api/album-corroborate.js +36 -0
  9. package/dist/src/folder-api/album-discs.d.ts +13 -0
  10. package/dist/src/folder-api/album-discs.d.ts.map +1 -0
  11. package/dist/src/folder-api/album-discs.js +122 -0
  12. package/dist/src/folder-api/album-grouping.d.ts +24 -0
  13. package/dist/src/folder-api/album-grouping.d.ts.map +1 -0
  14. package/dist/src/folder-api/album-grouping.js +118 -0
  15. package/dist/src/folder-api/album-identity.d.ts +27 -0
  16. package/dist/src/folder-api/album-identity.d.ts.map +1 -0
  17. package/dist/src/folder-api/album-identity.js +151 -0
  18. package/dist/src/folder-api/{group-albums.d.ts → album-types.d.ts} +55 -26
  19. package/dist/src/folder-api/album-types.d.ts.map +1 -0
  20. package/dist/src/folder-api/album-types.js +0 -0
  21. package/dist/src/folder-api/folder-disc.d.ts +24 -0
  22. package/dist/src/folder-api/folder-disc.d.ts.map +1 -0
  23. package/dist/src/folder-api/folder-disc.js +169 -0
  24. package/dist/src/folder-api/index.d.ts +3 -1
  25. package/dist/src/folder-api/index.d.ts.map +1 -1
  26. package/dist/src/folder-api/index.js +2 -4
  27. package/dist/src/folder-api/scan-for-albums.d.ts +1 -1
  28. package/dist/src/folder-api/scan-for-albums.d.ts.map +1 -1
  29. package/dist/src/folder-api/scan-for-albums.js +1 -3
  30. package/dist/src/runtime/wasi-adapter/audio-properties.d.ts +20 -0
  31. package/dist/src/runtime/wasi-adapter/audio-properties.d.ts.map +1 -0
  32. package/dist/src/runtime/wasi-adapter/audio-properties.js +84 -0
  33. package/dist/src/runtime/wasi-adapter/file-handle.d.ts +5 -19
  34. package/dist/src/runtime/wasi-adapter/file-handle.d.ts.map +1 -1
  35. package/dist/src/runtime/wasi-adapter/file-handle.js +67 -389
  36. package/dist/src/runtime/wasi-adapter/handle-state.d.ts +28 -0
  37. package/dist/src/runtime/wasi-adapter/handle-state.d.ts.map +1 -0
  38. package/dist/src/runtime/wasi-adapter/handle-state.js +58 -0
  39. package/dist/src/runtime/wasi-adapter/mp4-items.d.ts +34 -0
  40. package/dist/src/runtime/wasi-adapter/mp4-items.d.ts.map +1 -0
  41. package/dist/src/runtime/wasi-adapter/mp4-items.js +80 -0
  42. package/dist/src/runtime/wasi-adapter/property-surface.d.ts +25 -0
  43. package/dist/src/runtime/wasi-adapter/property-surface.d.ts.map +1 -0
  44. package/dist/src/runtime/wasi-adapter/property-surface.js +104 -0
  45. package/dist/src/runtime/wasi-adapter/structured-fields.d.ts +44 -0
  46. package/dist/src/runtime/wasi-adapter/structured-fields.d.ts.map +1 -0
  47. package/dist/src/runtime/wasi-adapter/structured-fields.js +139 -0
  48. package/dist/src/runtime/wasi-adapter/tag-keys.d.ts +28 -0
  49. package/dist/src/runtime/wasi-adapter/tag-keys.d.ts.map +1 -0
  50. package/dist/src/runtime/wasi-adapter/tag-keys.js +46 -0
  51. package/dist/src/version.d.ts +1 -1
  52. package/dist/src/version.js +1 -1
  53. package/package.json +2 -1
  54. package/dist/src/folder-api/group-albums.d.ts.map +0 -1
  55. package/dist/src/folder-api/group-albums.js +0 -544
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Audio metrics and format detection over the WASI tag-data snapshot.
3
+ *
4
+ * Pure functions over (tagData, fileData): the WasiFileHandle wrappers add
5
+ * destruction guards and pass their fields. Extracted from file-handle.ts in
6
+ * the taglib-1dfc split.
7
+ */
8
+ import type { AudioProperties } from "../../types.js";
9
+ /** The audio-properties block of the C++ snapshot, null when absent. */
10
+ export declare function getAudioProperties(tagData: Record<string, unknown> | null): AudioProperties | null;
11
+ /** OGG codec sniffing: "OpusHead" in the first page payload, else OGG. */
12
+ export declare function detectOggCodec(fileData: Uint8Array): string;
13
+ /**
14
+ * Format detection: container-based first (works for path and buffer modes),
15
+ * magic-byte fallback for buffers.
16
+ */
17
+ export declare function getFormat(tagData: Record<string, unknown> | null, fileData: Uint8Array | null): string;
18
+ /** MP4 detection: containerFormat (path mode) or ftyp box (buffer mode). */
19
+ export declare function isMP4(tagData: Record<string, unknown> | null, fileData: Uint8Array | null): boolean;
20
+ //# sourceMappingURL=audio-properties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-properties.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/audio-properties.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,gBAAgB,CAAC;AAexB,wEAAwE;AACxE,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACtC,eAAe,GAAG,IAAI,CA4BxB;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAe3D;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACvC,QAAQ,EAAE,UAAU,GAAG,IAAI,GAC1B,MAAM,CAuDR;AAED,4EAA4E;AAC5E,wBAAgB,KAAK,CACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EACvC,QAAQ,EAAE,UAAU,GAAG,IAAI,GAC1B,OAAO,CAYT"}
@@ -0,0 +1,84 @@
1
+ const CONTAINER_TO_FORMAT = {
2
+ MP3: "MP3",
3
+ MP4: "MP4",
4
+ FLAC: "FLAC",
5
+ OGG: "OGG",
6
+ WAV: "WAV",
7
+ AIFF: "AIFF",
8
+ WavPack: "WV",
9
+ TTA: "TTA",
10
+ ASF: "ASF",
11
+ Matroska: "MATROSKA"
12
+ };
13
+ function getAudioProperties(tagData) {
14
+ if (!tagData || !("sampleRate" in tagData)) return null;
15
+ const d = tagData;
16
+ const containerFormat = d.containerFormat || "unknown";
17
+ const mpegVersion = d.mpegVersion ?? 0;
18
+ const formatVersion = d.formatVersion ?? 0;
19
+ return {
20
+ duration: d.length ?? 0,
21
+ durationMs: d.lengthMs ?? 0,
22
+ bitrate: d.bitrate ?? 0,
23
+ sampleRate: d.sampleRate ?? 0,
24
+ channels: d.channels ?? 0,
25
+ bitsPerSample: d.bitsPerSample ?? 0,
26
+ codec: d.codec || "unknown",
27
+ containerFormat,
28
+ isLossless: d.isLossless ?? false,
29
+ ...mpegVersion > 0 ? { mpegVersion, mpegLayer: d.mpegLayer ?? 0 } : {},
30
+ ...containerFormat === "MP4" || containerFormat === "ASF" ? { isEncrypted: d.isEncrypted ?? false } : {},
31
+ ...formatVersion > 0 ? { formatVersion } : {},
32
+ ...d.outputGainDb !== void 0 ? { outputGainDb: d.outputGainDb } : {}
33
+ };
34
+ }
35
+ function detectOggCodec(fileData) {
36
+ if (fileData.length < 37) return "OGG";
37
+ const segCount = fileData[26];
38
+ if (segCount === void 0) return "OGG";
39
+ const payloadStart = 27 + segCount;
40
+ if (fileData.length < payloadStart + 8) return "OGG";
41
+ const sig = String.fromCharCode(
42
+ ...fileData.slice(payloadStart, payloadStart + 8)
43
+ );
44
+ if (sig === "OpusHead") return "OPUS";
45
+ return "OGG";
46
+ }
47
+ function getFormat(tagData, fileData) {
48
+ const container = tagData?.containerFormat;
49
+ if (container) {
50
+ const codec = tagData?.codec;
51
+ if (container === "OGG" && codec === "Opus") return "OPUS";
52
+ if (CONTAINER_TO_FORMAT[container]) return CONTAINER_TO_FORMAT[container];
53
+ }
54
+ if (!fileData || fileData.length < 8) return "unknown";
55
+ const magic = fileData.slice(0, 4);
56
+ if (magic[0] === 255 && (magic[1] & 224) === 224) return "MP3";
57
+ if (magic[0] === 73 && magic[1] === 68 && magic[2] === 51) {
58
+ return "MP3";
59
+ }
60
+ if (magic[0] === 102 && magic[1] === 76 && magic[2] === 97 && magic[3] === 67) return "FLAC";
61
+ if (magic[0] === 79 && magic[1] === 103 && magic[2] === 103 && magic[3] === 83) return detectOggCodec(fileData);
62
+ if (magic[0] === 82 && magic[1] === 73 && magic[2] === 70 && magic[3] === 70) return "WAV";
63
+ if (magic[0] === 119 && magic[1] === 118 && magic[2] === 112 && magic[3] === 107) return "WV";
64
+ if (magic[0] === 84 && magic[1] === 84 && magic[2] === 65 && magic[3] === 49) return "TTA";
65
+ if (fileData.length >= 16 && magic[0] === 48 && magic[1] === 38 && magic[2] === 178 && magic[3] === 117) return "ASF";
66
+ if (magic[0] === 26 && magic[1] === 69 && magic[2] === 223 && magic[3] === 163) return "MATROSKA";
67
+ const ftyp = fileData.slice(4, 8);
68
+ if (ftyp[0] === 102 && ftyp[1] === 116 && ftyp[2] === 121 && ftyp[3] === 112) return "MP4";
69
+ return "unknown";
70
+ }
71
+ function isMP4(tagData, fileData) {
72
+ if (!fileData) {
73
+ return tagData?.containerFormat === "MP4";
74
+ }
75
+ if (fileData.length < 8) return false;
76
+ const magic = fileData.slice(4, 8);
77
+ return magic[0] === 102 && magic[1] === 116 && magic[2] === 121 && magic[3] === 112;
78
+ }
79
+ export {
80
+ detectOggCodec,
81
+ getAudioProperties,
82
+ getFormat,
83
+ isMP4
84
+ };
@@ -1,15 +1,10 @@
1
- /**
2
- * @fileoverview WASI-based FileHandle implementation
3
- */
1
+ /** WASI-based FileHandle implementation (taglib-1dfc split). */
4
2
  import type { FileHandle, RawChapter, RawId3v2Frame, RawLyrics, RawPicture } from "../../wasm.js";
5
3
  import type { BasicTagData } from "../../types/tags.js";
6
4
  import type { AudioProperties } from "../../types.js";
7
5
  import type { WasiModule } from "../wasmer-sdk-loader/types.js";
8
6
  export declare class WasiFileHandle implements FileHandle {
9
- private readonly wasi;
10
- private fileData;
11
- private filePath;
12
- private tagData;
7
+ private readonly state;
13
8
  private destroyed;
14
9
  constructor(wasiModule: WasiModule);
15
10
  private checkNotDestroyed;
@@ -17,27 +12,18 @@ export declare class WasiFileHandle implements FileHandle {
17
12
  loadFromPath(path: string): boolean;
18
13
  isValid(): boolean;
19
14
  save(): boolean;
15
+ getBuffer(): Uint8Array;
20
16
  getTagData(): BasicTagData;
21
17
  setTagData(data: Partial<BasicTagData>): void;
22
18
  getAudioProperties(): AudioProperties | null;
23
19
  getFormat(): string;
24
- private detectOggCodec;
25
- getBuffer(): Uint8Array;
20
+ isMP4(): boolean;
26
21
  getProperties(): Record<string, string[]>;
27
- setProperties(props: Record<string, string[]>): void;
22
+ setProperties(properties: Record<string, string[]>): void;
28
23
  getProperty(key: string): string;
29
24
  setProperty(key: string, value: string): void;
30
- isMP4(): boolean;
31
25
  getMP4Item(key: string): string;
32
26
  setMP4Item(key: string, value: string): void;
33
- /** Record an exact atom name to be repaired after the PropertyMap write. */
34
- private registerMp4ItemName;
35
- /**
36
- * Record a foreign-mean freeform atom for deletion at save (taglib-65nm).
37
- * The PropertyMap erase pass cannot express foreign atoms, so the C++ shim
38
- * consumes this list and calls removeItem on each exact atom name.
39
- */
40
- private registerMp4ItemRemoval;
41
27
  getMp4ItemRemovals(): string[] | undefined;
42
28
  setMp4ItemRemovals(removals: string[]): void;
43
29
  removeMP4Item(key: string): void;
@@ -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,UAAU,EACV,UAAU,EACV,aAAa,EACb,SAAS,EACT,UAAU,EACX,MAAM,eAAe,CAAC;AACvB,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;AAuHhE,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;IAU3C,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAUnC,OAAO,IAAI,OAAO;IAMlB,IAAI,IAAI,OAAO;IAqBf,UAAU,IAAI,YAAY;IAc1B,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI;IAgB7C,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;IAyCzC,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI;IAmCpD,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAWhC,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAiB7C,KAAK,IAAI,OAAO;IAehB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAoB/B,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAkB5C,4EAA4E;IAC5E,OAAO,CAAC,mBAAmB;IAU3B;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IAU9B,kBAAkB,IAAI,MAAM,EAAE,GAAG,SAAS;IAK1C,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI;IAQ5C,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAqBhC,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;IAM1C,OAAO,IAAI,MAAM,GAAG,SAAS;IAM7B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAKlC,UAAU,IAAI;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE;IAQ1C,YAAY,CAAC,IAAI,EAAE;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI;IA+BtD,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,SAAS,IAAI,SAAS,EAAE;IAoBxB,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI;IAKpC,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,EAAE;IAsB3C,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,IAAI;IAUpD,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAInC,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,GAAG,SAAS;IAMhE,OAAO,IAAI,IAAI;CAKhB"}
1
+ {"version":3,"file":"file-handle.d.ts","sourceRoot":"","sources":["../../../../src/runtime/wasi-adapter/file-handle.ts"],"names":[],"mappings":"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"}