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
@@ -100,6 +100,20 @@ var init_pictures = __esm({
100
100
  }
101
101
  });
102
102
 
103
+ // src/types/chapters.ts
104
+ var init_chapters = __esm({
105
+ "src/types/chapters.ts"() {
106
+ "use strict";
107
+ }
108
+ });
109
+
110
+ // src/types/bwf.ts
111
+ var init_bwf = __esm({
112
+ "src/types/bwf.ts"() {
113
+ "use strict";
114
+ }
115
+ });
116
+
103
117
  // src/types/config.ts
104
118
  var init_config = __esm({
105
119
  "src/types/config.ts"() {
@@ -122,6 +136,8 @@ var init_types = __esm({
122
136
  init_tags();
123
137
  init_metadata_mappings();
124
138
  init_pictures();
139
+ init_chapters();
140
+ init_bwf();
125
141
  init_config();
126
142
  init_format_property_keys();
127
143
  }
@@ -135,6 +151,136 @@ var init_types2 = __esm({
135
151
  }
136
152
  });
137
153
 
154
+ // src/bwf/bext.ts
155
+ function readFixedString(bytes, offset, len) {
156
+ let end = offset;
157
+ const max = Math.min(offset + len, bytes.length);
158
+ while (end < max && bytes[end] !== 0) end++;
159
+ let s = "";
160
+ for (let i = offset; i < end; i++) s += String.fromCharCode(bytes[i]);
161
+ return s;
162
+ }
163
+ function writeFixedString(bytes, offset, len, value) {
164
+ for (let i = 0; i < len; i++) {
165
+ bytes[offset + i] = i < value.length ? value.charCodeAt(i) & 255 : 0;
166
+ }
167
+ }
168
+ function clampInt16(n) {
169
+ return Math.max(-32768, Math.min(32767, Math.round(n)));
170
+ }
171
+ function loudnessRaw(v) {
172
+ return v === void 0 ? LOUDNESS_UNSET : clampInt16(v * 100);
173
+ }
174
+ function loudnessFromRaw(raw) {
175
+ return raw === LOUDNESS_UNSET ? void 0 : raw / 100;
176
+ }
177
+ function bytesToHex(bytes) {
178
+ let s = "";
179
+ for (const b of bytes) s += b.toString(16).padStart(2, "0");
180
+ return s;
181
+ }
182
+ function hexToBytes(hex, outLen) {
183
+ const clean = hex.replace(/[^0-9a-fA-F]/g, "");
184
+ const out = new Uint8Array(outLen);
185
+ for (let i = 0; i + 1 < clean.length + 1 && i / 2 < outLen; i += 2) {
186
+ const pair = clean.slice(i, i + 2);
187
+ if (pair.length === 2) out[i / 2] = parseInt(pair, 16);
188
+ }
189
+ return out;
190
+ }
191
+ function decodeBext(bytes) {
192
+ if (bytes.length < VERSION_OFFSET + 2) return void 0;
193
+ const dv = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
194
+ const timeRefLow = dv.getUint32(338, true);
195
+ const timeRefHigh = dv.getUint32(342, true);
196
+ const version = dv.getUint16(VERSION_OFFSET, true);
197
+ const result = {
198
+ description: readFixedString(bytes, 0, 256),
199
+ originator: readFixedString(bytes, 256, 32),
200
+ originatorReference: readFixedString(bytes, 288, 32),
201
+ originationDate: readFixedString(bytes, 320, 10),
202
+ originationTime: readFixedString(bytes, 330, 8),
203
+ timeReferenceSamples: BigInt(timeRefHigh) << 32n | BigInt(timeRefLow),
204
+ version,
205
+ codingHistory: bytes.length > FIXED_PREFIX_LEN ? readFixedString(
206
+ bytes,
207
+ FIXED_PREFIX_LEN,
208
+ bytes.length - FIXED_PREFIX_LEN
209
+ ) : ""
210
+ };
211
+ if (version >= 1 && bytes.length >= UMID_OFFSET + UMID_LEN) {
212
+ result.umid = bytesToHex(
213
+ bytes.subarray(UMID_OFFSET, UMID_OFFSET + UMID_LEN)
214
+ );
215
+ }
216
+ if (version >= 2 && bytes.length >= LOUDNESS_OFFSET + 10) {
217
+ const lv = loudnessFromRaw(dv.getInt16(LOUDNESS_OFFSET, true));
218
+ const lr = loudnessFromRaw(dv.getInt16(LOUDNESS_OFFSET + 2, true));
219
+ const mtp = loudnessFromRaw(dv.getInt16(LOUDNESS_OFFSET + 4, true));
220
+ const mml = loudnessFromRaw(dv.getInt16(LOUDNESS_OFFSET + 6, true));
221
+ const msl = loudnessFromRaw(dv.getInt16(LOUDNESS_OFFSET + 8, true));
222
+ if (lv !== void 0) result.loudnessValueDb = lv;
223
+ if (lr !== void 0) result.loudnessRangeDb = lr;
224
+ if (mtp !== void 0) result.maxTruePeakLevelDbtp = mtp;
225
+ if (mml !== void 0) result.maxMomentaryLoudnessDb = mml;
226
+ if (msl !== void 0) result.maxShortTermLoudnessDb = msl;
227
+ }
228
+ return result;
229
+ }
230
+ function encodeBext(b) {
231
+ const codingHistory = b.codingHistory ?? "";
232
+ const bytes = new Uint8Array(FIXED_PREFIX_LEN + codingHistory.length);
233
+ const dv = new DataView(bytes.buffer);
234
+ const hasLoudness = b.loudnessValueDb !== void 0 || b.loudnessRangeDb !== void 0 || b.maxTruePeakLevelDbtp !== void 0 || b.maxMomentaryLoudnessDb !== void 0 || b.maxShortTermLoudnessDb !== void 0;
235
+ const version = Number.isInteger(b.version) ? b.version : hasLoudness ? 2 : b.umid ? 1 : 0;
236
+ writeFixedString(bytes, 0, 256, b.description ?? "");
237
+ writeFixedString(bytes, 256, 32, b.originator ?? "");
238
+ writeFixedString(bytes, 288, 32, b.originatorReference ?? "");
239
+ writeFixedString(bytes, 320, 10, b.originationDate ?? "");
240
+ writeFixedString(bytes, 330, 8, b.originationTime ?? "");
241
+ const tr = b.timeReferenceSamples ?? 0n;
242
+ dv.setUint32(338, Number(tr & 0xffffffffn), true);
243
+ dv.setUint32(342, Number(tr >> 32n & 0xffffffffn), true);
244
+ dv.setUint16(VERSION_OFFSET, version, true);
245
+ if (version >= 1 && b.umid) {
246
+ bytes.set(hexToBytes(b.umid, UMID_LEN), UMID_OFFSET);
247
+ }
248
+ if (version >= 2) {
249
+ dv.setInt16(LOUDNESS_OFFSET, loudnessRaw(b.loudnessValueDb), true);
250
+ dv.setInt16(LOUDNESS_OFFSET + 2, loudnessRaw(b.loudnessRangeDb), true);
251
+ dv.setInt16(LOUDNESS_OFFSET + 4, loudnessRaw(b.maxTruePeakLevelDbtp), true);
252
+ dv.setInt16(
253
+ LOUDNESS_OFFSET + 6,
254
+ loudnessRaw(b.maxMomentaryLoudnessDb),
255
+ true
256
+ );
257
+ dv.setInt16(
258
+ LOUDNESS_OFFSET + 8,
259
+ loudnessRaw(b.maxShortTermLoudnessDb),
260
+ true
261
+ );
262
+ }
263
+ writeFixedString(
264
+ bytes,
265
+ FIXED_PREFIX_LEN,
266
+ codingHistory.length,
267
+ codingHistory
268
+ );
269
+ return bytes;
270
+ }
271
+ var FIXED_PREFIX_LEN, VERSION_OFFSET, UMID_OFFSET, UMID_LEN, LOUDNESS_OFFSET, LOUDNESS_UNSET;
272
+ var init_bext = __esm({
273
+ "src/bwf/bext.ts"() {
274
+ "use strict";
275
+ FIXED_PREFIX_LEN = 602;
276
+ VERSION_OFFSET = 346;
277
+ UMID_OFFSET = 348;
278
+ UMID_LEN = 64;
279
+ LOUDNESS_OFFSET = 412;
280
+ LOUDNESS_UNSET = 32767;
281
+ }
282
+ });
283
+
138
284
  // src/errors/base.ts
139
285
  var SUPPORTED_FORMATS, TagLibError;
140
286
  var init_base = __esm({
@@ -377,6 +523,47 @@ var init_errors2 = __esm({
377
523
  }
378
524
  });
379
525
 
526
+ // src/taglib/audio-file-bwf.ts
527
+ function requireBwf(format) {
528
+ if (!BWF_FORMATS.has(format)) {
529
+ throw new UnsupportedFormatError(format, ["WAV", "FLAC"], {
530
+ operation: "BWF metadata"
531
+ });
532
+ }
533
+ }
534
+ function getBextData(handle) {
535
+ const raw = handle.getBextData();
536
+ return raw && raw.length > 0 ? raw : void 0;
537
+ }
538
+ function setBextData(handle, format, data) {
539
+ requireBwf(format);
540
+ handle.setBextData(data);
541
+ }
542
+ function getBext(handle) {
543
+ const raw = handle.getBextData();
544
+ return raw && raw.length > 0 ? decodeBext(raw) : void 0;
545
+ }
546
+ function setBext(handle, format, bext) {
547
+ requireBwf(format);
548
+ handle.setBextData(encodeBext(bext));
549
+ }
550
+ function getIxml(handle) {
551
+ return handle.getIxml();
552
+ }
553
+ function setIxml(handle, format, data) {
554
+ requireBwf(format);
555
+ handle.setIxml(data);
556
+ }
557
+ var BWF_FORMATS;
558
+ var init_audio_file_bwf = __esm({
559
+ "src/taglib/audio-file-bwf.ts"() {
560
+ "use strict";
561
+ init_bext();
562
+ init_errors2();
563
+ BWF_FORMATS = /* @__PURE__ */ new Set(["WAV", "FLAC"]);
564
+ }
565
+ });
566
+
380
567
  // browser-stub:platform-io-browser-stub
381
568
  function getPlatformIO() {
382
569
  throw new Error("Filesystem operations are not available in the browser.");
@@ -1234,61 +1421,63 @@ var init_audio_file_base = __esm({
1234
1421
  return this.getFormat() === format;
1235
1422
  }
1236
1423
  tag() {
1237
- const tagWrapper = this.handle.getTag();
1238
- if (!tagWrapper) {
1239
- throw new MetadataError(
1240
- "read",
1241
- "Tag may be corrupted or format not fully supported"
1242
- );
1243
- }
1424
+ const handle = this.handle;
1425
+ let data = handle.getTagData();
1244
1426
  const tag = {
1245
1427
  get title() {
1246
- return tagWrapper.title();
1428
+ return data.title;
1247
1429
  },
1248
1430
  get artist() {
1249
- return tagWrapper.artist();
1431
+ return data.artist;
1250
1432
  },
1251
1433
  get album() {
1252
- return tagWrapper.album();
1434
+ return data.album;
1253
1435
  },
1254
1436
  get comment() {
1255
- return tagWrapper.comment();
1437
+ return data.comment;
1256
1438
  },
1257
1439
  get genre() {
1258
- return tagWrapper.genre();
1440
+ return data.genre;
1259
1441
  },
1260
1442
  get year() {
1261
- return tagWrapper.year();
1443
+ return data.year;
1262
1444
  },
1263
1445
  get track() {
1264
- return tagWrapper.track();
1446
+ return data.track;
1265
1447
  },
1266
1448
  setTitle: (value) => {
1267
- tagWrapper.setTitle(value);
1449
+ handle.setTagData({ title: value });
1450
+ data = handle.getTagData();
1268
1451
  return tag;
1269
1452
  },
1270
1453
  setArtist: (value) => {
1271
- tagWrapper.setArtist(value);
1454
+ handle.setTagData({ artist: value });
1455
+ data = handle.getTagData();
1272
1456
  return tag;
1273
1457
  },
1274
1458
  setAlbum: (value) => {
1275
- tagWrapper.setAlbum(value);
1459
+ handle.setTagData({ album: value });
1460
+ data = handle.getTagData();
1276
1461
  return tag;
1277
1462
  },
1278
1463
  setComment: (value) => {
1279
- tagWrapper.setComment(value);
1464
+ handle.setTagData({ comment: value });
1465
+ data = handle.getTagData();
1280
1466
  return tag;
1281
1467
  },
1282
1468
  setGenre: (value) => {
1283
- tagWrapper.setGenre(value);
1469
+ handle.setTagData({ genre: value });
1470
+ data = handle.getTagData();
1284
1471
  return tag;
1285
1472
  },
1286
1473
  setYear: (value) => {
1287
- tagWrapper.setYear(value);
1474
+ handle.setTagData({ year: value });
1475
+ data = handle.getTagData();
1288
1476
  return tag;
1289
1477
  },
1290
1478
  setTrack: (value) => {
1291
- tagWrapper.setTrack(value);
1479
+ handle.setTagData({ track: value });
1480
+ data = handle.getTagData();
1292
1481
  return tag;
1293
1482
  }
1294
1483
  };
@@ -1296,28 +1485,9 @@ var init_audio_file_base = __esm({
1296
1485
  }
1297
1486
  audioProperties() {
1298
1487
  if (!this.cachedAudioProperties) {
1299
- const propsWrapper = this.handle.getAudioProperties();
1300
- if (!propsWrapper) {
1301
- return void 0;
1302
- }
1303
- const containerFormat = propsWrapper.containerFormat() || "unknown";
1304
- const mpegVersion = propsWrapper.mpegVersion();
1305
- const formatVersion = propsWrapper.formatVersion();
1306
- this.cachedAudioProperties = {
1307
- duration: propsWrapper.lengthInSeconds(),
1308
- bitrate: propsWrapper.bitrate(),
1309
- sampleRate: propsWrapper.sampleRate(),
1310
- channels: propsWrapper.channels(),
1311
- bitsPerSample: propsWrapper.bitsPerSample(),
1312
- codec: propsWrapper.codec() || "unknown",
1313
- containerFormat,
1314
- isLossless: propsWrapper.isLossless(),
1315
- ...mpegVersion > 0 ? { mpegVersion, mpegLayer: propsWrapper.mpegLayer() } : {},
1316
- ...containerFormat === "MP4" || containerFormat === "ASF" ? { isEncrypted: propsWrapper.isEncrypted() } : {},
1317
- ...formatVersion > 0 ? { formatVersion } : {}
1318
- };
1488
+ this.cachedAudioProperties = this.handle.getAudioProperties() ?? null;
1319
1489
  }
1320
- return this.cachedAudioProperties;
1490
+ return this.cachedAudioProperties ?? void 0;
1321
1491
  }
1322
1492
  properties() {
1323
1493
  return remapKeysFromTagLib(this.handle.getProperties());
@@ -1375,7 +1545,102 @@ var init_audio_file_base = __esm({
1375
1545
  }
1376
1546
  });
1377
1547
 
1548
+ // src/taglib/embind-adapter.ts
1549
+ function isValidBitrateMode(value) {
1550
+ return value === "CBR" || value === "VBR" || value === "ABR";
1551
+ }
1552
+ function wrapEmbindHandle(raw) {
1553
+ const overrides = {
1554
+ getTagData() {
1555
+ const tw = raw.getTag();
1556
+ return {
1557
+ title: tw.title(),
1558
+ artist: tw.artist(),
1559
+ album: tw.album(),
1560
+ comment: tw.comment(),
1561
+ genre: tw.genre(),
1562
+ year: tw.year(),
1563
+ track: tw.track()
1564
+ };
1565
+ },
1566
+ setTagData(data) {
1567
+ const tw = raw.getTag();
1568
+ if (data.title !== void 0) tw.setTitle(data.title);
1569
+ if (data.artist !== void 0) tw.setArtist(data.artist);
1570
+ if (data.album !== void 0) tw.setAlbum(data.album);
1571
+ if (data.comment !== void 0) tw.setComment(data.comment);
1572
+ if (data.genre !== void 0) tw.setGenre(data.genre);
1573
+ if (data.year !== void 0) tw.setYear(data.year);
1574
+ if (data.track !== void 0) tw.setTrack(data.track);
1575
+ },
1576
+ getBextData() {
1577
+ const v = raw.getBextData();
1578
+ if (v === void 0 || v === null) return void 0;
1579
+ const u8 = v instanceof Uint8Array ? v : new Uint8Array(v);
1580
+ return u8.length > 0 ? u8 : void 0;
1581
+ },
1582
+ setBextData(data) {
1583
+ raw.setBextData(data ?? null);
1584
+ },
1585
+ getIxml() {
1586
+ const v = raw.getIxml();
1587
+ return typeof v === "string" && v.length > 0 ? v : void 0;
1588
+ },
1589
+ setIxml(data) {
1590
+ raw.setIxml(
1591
+ data ?? null
1592
+ );
1593
+ },
1594
+ getAudioProperties() {
1595
+ const pw = raw.getAudioProperties();
1596
+ if (!pw) return null;
1597
+ const containerFormat = pw.containerFormat() || "unknown";
1598
+ const codec = pw.codec() || "unknown";
1599
+ const mpegVersion = pw.mpegVersion();
1600
+ const formatVersion = pw.formatVersion();
1601
+ const bitrateMode = pw.bitrateMode();
1602
+ return {
1603
+ duration: pw.lengthInSeconds(),
1604
+ durationMs: pw.lengthInMilliseconds(),
1605
+ bitrate: pw.bitrate(),
1606
+ sampleRate: pw.sampleRate(),
1607
+ channels: pw.channels(),
1608
+ bitsPerSample: pw.bitsPerSample(),
1609
+ codec,
1610
+ containerFormat,
1611
+ isLossless: pw.isLossless(),
1612
+ ...mpegVersion > 0 ? { mpegVersion, mpegLayer: pw.mpegLayer() } : {},
1613
+ ...containerFormat === "MP4" || containerFormat === "ASF" ? { isEncrypted: pw.isEncrypted() } : {},
1614
+ ...formatVersion > 0 ? { formatVersion } : {},
1615
+ ...isValidBitrateMode(bitrateMode) ? { bitrateMode } : {},
1616
+ ...codec === "Opus" ? { outputGainDb: pw.outputGainDb() } : {}
1617
+ };
1618
+ }
1619
+ };
1620
+ return new Proxy(raw, {
1621
+ get(target, prop, receiver) {
1622
+ if (prop in overrides) return overrides[prop];
1623
+ const value = Reflect.get(target, prop, receiver);
1624
+ return typeof value === "function" ? value.bind(target) : value;
1625
+ }
1626
+ });
1627
+ }
1628
+ var init_embind_adapter = __esm({
1629
+ "src/taglib/embind-adapter.ts"() {
1630
+ "use strict";
1631
+ }
1632
+ });
1633
+
1378
1634
  // src/taglib/audio-file-impl.ts
1635
+ function sortChapters(list) {
1636
+ return [...list].sort((a, b) => a.startTimeMs - b.startTimeMs);
1637
+ }
1638
+ function inferEndTimeMs(sorted, index, trackEndMs) {
1639
+ const own = sorted[index].endTimeMs;
1640
+ if (own !== void 0) return own;
1641
+ const next = sorted[index + 1];
1642
+ return next ? next.startTimeMs : trackEndMs;
1643
+ }
1379
1644
  function readFileSync(path) {
1380
1645
  if (typeof Deno !== "undefined") return Deno.readFileSync(path);
1381
1646
  if (_nodeFs === void 0) {
@@ -1393,10 +1658,12 @@ var init_audio_file_impl = __esm({
1393
1658
  "src/taglib/audio-file-impl.ts"() {
1394
1659
  "use strict";
1395
1660
  init_types2();
1661
+ init_audio_file_bwf();
1396
1662
  init_errors2();
1397
1663
  init_file();
1398
1664
  init_write();
1399
1665
  init_audio_file_base();
1666
+ init_embind_adapter();
1400
1667
  AudioFileImpl = class extends BaseAudioFileImpl {
1401
1668
  constructor(module, fileHandle, sourcePath, originalSource, isPartiallyLoaded = false, partialLoadOptions) {
1402
1669
  super(
@@ -1442,7 +1709,8 @@ var init_audio_file_impl = __esm({
1442
1709
  );
1443
1710
  }
1444
1711
  if (this.isPartiallyLoaded && this.originalSource) {
1445
- const fullFileHandle = this.module.createFileHandle();
1712
+ const rawFullHandle = this.module.createFileHandle();
1713
+ const fullFileHandle = this.module.isWasi ? rawFullHandle : wrapEmbindHandle(rawFullHandle);
1446
1714
  try {
1447
1715
  const success = await (async () => {
1448
1716
  const data = await readFileData(this.originalSource);
@@ -1453,19 +1721,13 @@ var init_audio_file_impl = __esm({
1453
1721
  "Failed to load full audio file for saving"
1454
1722
  );
1455
1723
  }
1456
- const partialTag = this.handle.getTag();
1457
- const fullTag = fullFileHandle.getTag();
1458
- if (partialTag && fullTag) {
1459
- fullTag.setTitle(partialTag.title());
1460
- fullTag.setArtist(partialTag.artist());
1461
- fullTag.setAlbum(partialTag.album());
1462
- fullTag.setComment(partialTag.comment());
1463
- fullTag.setGenre(partialTag.genre());
1464
- fullTag.setYear(partialTag.year());
1465
- fullTag.setTrack(partialTag.track());
1466
- }
1724
+ fullFileHandle.setTagData(this.handle.getTagData());
1467
1725
  fullFileHandle.setProperties(this.handle.getProperties());
1468
1726
  fullFileHandle.setPictures(this.handle.getPictures());
1727
+ const bextBytes = this.handle.getBextData();
1728
+ if (bextBytes !== void 0) fullFileHandle.setBextData(bextBytes);
1729
+ const ixmlStr = this.handle.getIxml();
1730
+ if (ixmlStr !== void 0) fullFileHandle.setIxml(ixmlStr);
1469
1731
  if (!fullFileHandle.save()) {
1470
1732
  throw new FileOperationError(
1471
1733
  "save",
@@ -1520,6 +1782,52 @@ var init_audio_file_impl = __esm({
1520
1782
  removePictures() {
1521
1783
  this.handle.removePictures();
1522
1784
  }
1785
+ getChapters() {
1786
+ const sorted = sortChapters(this.handle.getChapters());
1787
+ const trackEndMs = this.audioProperties()?.durationMs;
1788
+ return sorted.map((c, i) => ({
1789
+ startTimeMs: c.startTimeMs,
1790
+ endTimeMs: inferEndTimeMs(sorted, i, trackEndMs),
1791
+ title: c.title || void 0,
1792
+ id: c.id || void 0,
1793
+ source: c.source
1794
+ }));
1795
+ }
1796
+ setChapters(chapters, options) {
1797
+ const fmt = this.getFormat();
1798
+ if (fmt !== "MP3" && fmt !== "MP4") {
1799
+ throw new UnsupportedFormatError(fmt, ["MP3", "MP4"], {
1800
+ operation: "setChapters"
1801
+ });
1802
+ }
1803
+ const sorted = sortChapters(chapters);
1804
+ const trackEndMs = this.audioProperties()?.durationMs;
1805
+ const raw = sorted.map((c, i) => ({
1806
+ id: c.id,
1807
+ startTimeMs: c.startTimeMs,
1808
+ endTimeMs: inferEndTimeMs(sorted, i, trackEndMs) ?? c.startTimeMs,
1809
+ title: c.title
1810
+ }));
1811
+ this.handle.setChapters(raw, options?.mp4ChapterStyle ?? "quicktime");
1812
+ }
1813
+ getBext() {
1814
+ return getBext(this.handle);
1815
+ }
1816
+ setBext(bext) {
1817
+ setBext(this.handle, this.getFormat(), bext);
1818
+ }
1819
+ getBextData() {
1820
+ return getBextData(this.handle);
1821
+ }
1822
+ setBextData(data) {
1823
+ setBextData(this.handle, this.getFormat(), data);
1824
+ }
1825
+ getIxml() {
1826
+ return getIxml(this.handle);
1827
+ }
1828
+ setIxml(data) {
1829
+ setIxml(this.handle, this.getFormat(), data);
1830
+ }
1523
1831
  getRatings() {
1524
1832
  return this.handle.getRatings().map(
1525
1833
  (r) => ({
@@ -1693,7 +2001,7 @@ var VERSION;
1693
2001
  var init_version = __esm({
1694
2002
  "src/version.ts"() {
1695
2003
  "use strict";
1696
- VERSION = "1.1.1";
2004
+ VERSION = "1.2.0";
1697
2005
  }
1698
2006
  });
1699
2007
 
@@ -1781,6 +2089,7 @@ var init_taglib_class = __esm({
1781
2089
  init_tag_mapping();
1782
2090
  init_errors2();
1783
2091
  init_version();
2092
+ init_embind_adapter();
1784
2093
  TagLib = class _TagLib {
1785
2094
  constructor(module) {
1786
2095
  __publicField(this, "module");
@@ -1856,7 +2165,8 @@ var init_taglib_class = __esm({
1856
2165
  audioData.byteOffset + audioData.byteLength
1857
2166
  )
1858
2167
  ) : audioData;
1859
- const fileHandle = this.module.createFileHandle();
2168
+ const rawHandle = this.module.createFileHandle();
2169
+ const fileHandle = this.module.isWasi ? rawHandle : wrapEmbindHandle(rawHandle);
1860
2170
  try {
1861
2171
  const success = fileHandle.loadFromBuffer(uint8Array);
1862
2172
  if (!success) {
package/dist/index.d.ts CHANGED
@@ -45,7 +45,7 @@ export type { PropertyMetadata } from "./src/constants/property-types.js";
45
45
  export { copyCoverArt, exportAllPictures, exportCoverArt, exportPictureByType, findCoverArtFiles, importCoverArt, importPictureWithType, loadPictureFromFile, savePictureToFile, } from "./src/file-utils/index.js";
46
46
  export { type AudioDynamics, type AudioFileMetadata, type DuplicateGroup, exportFolderMetadata, findDuplicates, type FolderScanItem, type FolderScanOptions, type FolderScanResult, type FolderUpdateItem, type FolderUpdateResult, scanFolder, updateFolderTags, } from "./src/folder-api/index.js";
47
47
  export { canvasToPicture, createPictureDownloadURL, createPictureGallery, dataURLToPicture, displayPicture, imageFileToPicture, pictureToDataURL, setCoverArtFromCanvas, } from "./src/web-utils/index.js";
48
- export type { AudioCodec, AudioFileInput, AudioProperties, BitrateControlMode, ContainerFormat, ExtendedTag, FieldMapping, FileType, NamedAudioInput, OpenOptions, Picture, PictureType, PropertyMap, Tag, TagInput, TagName, } from "./src/types.js";
48
+ export type { AudioCodec, AudioFileInput, AudioProperties, BitrateControlMode, BroadcastAudioExtension, Chapter, ContainerFormat, ExtendedTag, FieldMapping, FileType, NamedAudioInput, OpenOptions, Picture, PictureType, PropertyMap, SetChaptersOptions, Tag, TagInput, TagName, } from "./src/types.js";
49
49
  export { BITRATE_CONTROL_MODE_NAMES, BITRATE_CONTROL_MODE_VALUES, PICTURE_TYPE_NAMES, PICTURE_TYPE_VALUES, } from "./src/types.js";
50
50
  export type { PropertyKey, PropertyValue } from "./src/constants.js";
51
51
  export type { FormatPropertyKey, TagFormat, } from "./src/types/format-property-keys.js";
@@ -54,6 +54,7 @@ export { COMPLEX_PROPERTIES, COMPLEX_PROPERTY_KEY, } from "./src/constants/compl
54
54
  export type { ComplexPropertyKey, ComplexPropertyKeyMap, ComplexPropertyValueMap, Rating, UnsyncedLyrics, VariantMap, } from "./src/constants/complex-properties.js";
55
55
  export { RatingUtils } from "./src/utils/rating.js";
56
56
  export type { NormalizedRating, PopmRating } from "./src/utils/rating.js";
57
+ export * as bwf from "./src/bwf/bext.js";
57
58
  export type { TagLibModule, WasmModule } from "./src/wasm.js";
58
59
  export type { LoadTagLibOptions } from "./src/runtime/loader-types.js";
59
60
  export { loadTagLibModule } from "./src/runtime/module-loader.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -97,6 +97,7 @@ import {
97
97
  COMPLEX_PROPERTY_KEY
98
98
  } from "./src/constants/complex-properties.js";
99
99
  import { RatingUtils } from "./src/utils/rating.js";
100
+ import * as bwf from "./src/bwf/bext.js";
100
101
  import { loadTagLibModule } from "./src/runtime/module-loader.js";
101
102
  export {
102
103
  AudioFileImpl,
@@ -125,6 +126,7 @@ export {
125
126
  applyPictures,
126
127
  applyTags,
127
128
  applyTagsToFile,
129
+ bwf,
128
130
  canvasToPicture,
129
131
  clearPictures,
130
132
  clearTags,