taglib-wasm 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.browser.js +212 -89
- package/dist/simple.browser.js +212 -89
- package/dist/src/constants/complex-properties.d.ts +0 -14
- package/dist/src/constants/complex-properties.d.ts.map +1 -1
- package/dist/src/msgpack/encoder.d.ts +6 -0
- package/dist/src/msgpack/encoder.d.ts.map +1 -1
- package/dist/src/msgpack/encoder.js +12 -0
- package/dist/src/runtime/wasi-adapter/file-handle.d.ts +3 -1
- package/dist/src/runtime/wasi-adapter/file-handle.d.ts.map +1 -1
- package/dist/src/runtime/wasi-adapter/file-handle.js +17 -0
- package/dist/src/runtime/wasi-memory.d.ts +0 -5
- package/dist/src/runtime/wasi-memory.d.ts.map +1 -1
- package/dist/src/runtime/wasi-memory.js +1 -8
- package/dist/src/taglib/audio-file-base.d.ts.map +1 -1
- package/dist/src/taglib/audio-file-base.js +12 -0
- package/dist/src/taglib/audio-file-impl.d.ts.map +1 -1
- package/dist/src/taglib/audio-file-impl.js +22 -39
- package/dist/src/taglib/embind-adapter.d.ts.map +1 -1
- package/dist/src/taglib/embind-adapter.js +18 -0
- package/dist/src/taglib/extra-state-registry.d.ts +26 -0
- package/dist/src/taglib/extra-state-registry.d.ts.map +1 -0
- package/dist/src/taglib/extra-state-registry.js +59 -0
- package/dist/src/taglib/mutable-tag.d.ts +7 -0
- package/dist/src/taglib/mutable-tag.d.ts.map +1 -1
- package/dist/src/taglib/save-reconstruct.d.ts +13 -0
- package/dist/src/taglib/save-reconstruct.d.ts.map +1 -0
- package/dist/src/taglib/save-reconstruct.js +39 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/wasm.d.ts +14 -0
- package/dist/src/wasm.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.browser.js
CHANGED
|
@@ -573,60 +573,6 @@ var init_platform_io_browser_stub = __esm({
|
|
|
573
573
|
}
|
|
574
574
|
});
|
|
575
575
|
|
|
576
|
-
// src/utils/file.ts
|
|
577
|
-
async function readFileData(file) {
|
|
578
|
-
if (file instanceof Uint8Array) return file;
|
|
579
|
-
if (file instanceof ArrayBuffer) return new Uint8Array(file);
|
|
580
|
-
if (typeof File !== "undefined" && file instanceof File) {
|
|
581
|
-
return new Uint8Array(await file.arrayBuffer());
|
|
582
|
-
}
|
|
583
|
-
if (typeof file === "string") {
|
|
584
|
-
try {
|
|
585
|
-
return await getPlatformIO().readFile(file);
|
|
586
|
-
} catch (error) {
|
|
587
|
-
if (error instanceof EnvironmentError) throw error;
|
|
588
|
-
throw new FileOperationError("read", error.message, file);
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
const inputType = Object.prototype.toString.call(file);
|
|
592
|
-
throw new FileOperationError(
|
|
593
|
-
"read",
|
|
594
|
-
`Invalid file input type: ${inputType}. Expected string path, Uint8Array, ArrayBuffer, or File object.`
|
|
595
|
-
);
|
|
596
|
-
}
|
|
597
|
-
async function getFileSize(path) {
|
|
598
|
-
try {
|
|
599
|
-
const s = await getPlatformIO().stat(path);
|
|
600
|
-
return s.size;
|
|
601
|
-
} catch (error) {
|
|
602
|
-
if (error instanceof EnvironmentError) throw error;
|
|
603
|
-
throw new FileOperationError("stat", error.message, path);
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
async function readPartialFileData(path, headerSize, footerSize) {
|
|
607
|
-
const io = getPlatformIO();
|
|
608
|
-
if (!io.readPartial) {
|
|
609
|
-
throw new EnvironmentError(
|
|
610
|
-
"current runtime",
|
|
611
|
-
"does not support partial file reading",
|
|
612
|
-
"filesystem access with seek support"
|
|
613
|
-
);
|
|
614
|
-
}
|
|
615
|
-
try {
|
|
616
|
-
return await io.readPartial(path, headerSize, footerSize);
|
|
617
|
-
} catch (error) {
|
|
618
|
-
if (error instanceof EnvironmentError) throw error;
|
|
619
|
-
throw new FileOperationError("read", error.message, path);
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
var init_file = __esm({
|
|
623
|
-
"src/utils/file.ts"() {
|
|
624
|
-
"use strict";
|
|
625
|
-
init_errors2();
|
|
626
|
-
init_platform_io_browser_stub();
|
|
627
|
-
}
|
|
628
|
-
});
|
|
629
|
-
|
|
630
576
|
// src/utils/write.ts
|
|
631
577
|
async function writeFileData(path, data) {
|
|
632
578
|
try {
|
|
@@ -1445,6 +1391,9 @@ var init_audio_file_base = __esm({
|
|
|
1445
1391
|
get track() {
|
|
1446
1392
|
return data.track;
|
|
1447
1393
|
},
|
|
1394
|
+
get date() {
|
|
1395
|
+
return handle.getProperty("DATE") || void 0;
|
|
1396
|
+
},
|
|
1448
1397
|
setTitle: (value) => {
|
|
1449
1398
|
handle.setTagData({ title: value });
|
|
1450
1399
|
data = handle.getTagData();
|
|
@@ -1479,6 +1428,15 @@ var init_audio_file_base = __esm({
|
|
|
1479
1428
|
handle.setTagData({ track: value });
|
|
1480
1429
|
data = handle.getTagData();
|
|
1481
1430
|
return tag;
|
|
1431
|
+
},
|
|
1432
|
+
setDate: (value) => {
|
|
1433
|
+
if (value === "") {
|
|
1434
|
+
handle.setTagData({ year: 0 });
|
|
1435
|
+
} else {
|
|
1436
|
+
handle.setProperty("DATE", value);
|
|
1437
|
+
}
|
|
1438
|
+
data = handle.getTagData();
|
|
1439
|
+
return tag;
|
|
1482
1440
|
}
|
|
1483
1441
|
};
|
|
1484
1442
|
return tag;
|
|
@@ -1545,6 +1503,60 @@ var init_audio_file_base = __esm({
|
|
|
1545
1503
|
}
|
|
1546
1504
|
});
|
|
1547
1505
|
|
|
1506
|
+
// src/utils/file.ts
|
|
1507
|
+
async function readFileData(file) {
|
|
1508
|
+
if (file instanceof Uint8Array) return file;
|
|
1509
|
+
if (file instanceof ArrayBuffer) return new Uint8Array(file);
|
|
1510
|
+
if (typeof File !== "undefined" && file instanceof File) {
|
|
1511
|
+
return new Uint8Array(await file.arrayBuffer());
|
|
1512
|
+
}
|
|
1513
|
+
if (typeof file === "string") {
|
|
1514
|
+
try {
|
|
1515
|
+
return await getPlatformIO().readFile(file);
|
|
1516
|
+
} catch (error) {
|
|
1517
|
+
if (error instanceof EnvironmentError) throw error;
|
|
1518
|
+
throw new FileOperationError("read", error.message, file);
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
const inputType = Object.prototype.toString.call(file);
|
|
1522
|
+
throw new FileOperationError(
|
|
1523
|
+
"read",
|
|
1524
|
+
`Invalid file input type: ${inputType}. Expected string path, Uint8Array, ArrayBuffer, or File object.`
|
|
1525
|
+
);
|
|
1526
|
+
}
|
|
1527
|
+
async function getFileSize(path) {
|
|
1528
|
+
try {
|
|
1529
|
+
const s = await getPlatformIO().stat(path);
|
|
1530
|
+
return s.size;
|
|
1531
|
+
} catch (error) {
|
|
1532
|
+
if (error instanceof EnvironmentError) throw error;
|
|
1533
|
+
throw new FileOperationError("stat", error.message, path);
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
async function readPartialFileData(path, headerSize, footerSize) {
|
|
1537
|
+
const io = getPlatformIO();
|
|
1538
|
+
if (!io.readPartial) {
|
|
1539
|
+
throw new EnvironmentError(
|
|
1540
|
+
"current runtime",
|
|
1541
|
+
"does not support partial file reading",
|
|
1542
|
+
"filesystem access with seek support"
|
|
1543
|
+
);
|
|
1544
|
+
}
|
|
1545
|
+
try {
|
|
1546
|
+
return await io.readPartial(path, headerSize, footerSize);
|
|
1547
|
+
} catch (error) {
|
|
1548
|
+
if (error instanceof EnvironmentError) throw error;
|
|
1549
|
+
throw new FileOperationError("read", error.message, path);
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
var init_file = __esm({
|
|
1553
|
+
"src/utils/file.ts"() {
|
|
1554
|
+
"use strict";
|
|
1555
|
+
init_errors2();
|
|
1556
|
+
init_platform_io_browser_stub();
|
|
1557
|
+
}
|
|
1558
|
+
});
|
|
1559
|
+
|
|
1548
1560
|
// src/taglib/embind-adapter.ts
|
|
1549
1561
|
function isValidBitrateMode(value) {
|
|
1550
1562
|
return value === "CBR" || value === "VBR" || value === "ABR";
|
|
@@ -1591,6 +1603,24 @@ function wrapEmbindHandle(raw) {
|
|
|
1591
1603
|
data ?? null
|
|
1592
1604
|
);
|
|
1593
1605
|
},
|
|
1606
|
+
// Emscripten exposes USLT only through the PropertyMap "LYRICS" key (no
|
|
1607
|
+
// dedicated Embind binding), so bridge get/setLyrics to get/setProperties.
|
|
1608
|
+
// Text only — language/description are not surfaced by the PropertyMap.
|
|
1609
|
+
getLyrics() {
|
|
1610
|
+
const props = raw.getProperties();
|
|
1611
|
+
return (props["LYRICS"] ?? []).map((text) => ({
|
|
1612
|
+
text,
|
|
1613
|
+
description: "",
|
|
1614
|
+
language: ""
|
|
1615
|
+
}));
|
|
1616
|
+
},
|
|
1617
|
+
setLyrics(lyrics) {
|
|
1618
|
+
const handle = raw;
|
|
1619
|
+
const props = handle.getProperties();
|
|
1620
|
+
if (lyrics.length > 0) props["LYRICS"] = lyrics.map((l) => l.text);
|
|
1621
|
+
else delete props["LYRICS"];
|
|
1622
|
+
handle.setProperties(props);
|
|
1623
|
+
},
|
|
1594
1624
|
hasId3Tags() {
|
|
1595
1625
|
const v = raw.hasId3Tags();
|
|
1596
1626
|
if (!v || typeof v !== "object") return { v1: false, v2: false };
|
|
@@ -1640,6 +1670,112 @@ var init_embind_adapter = __esm({
|
|
|
1640
1670
|
}
|
|
1641
1671
|
});
|
|
1642
1672
|
|
|
1673
|
+
// src/taglib/extra-state-registry.ts
|
|
1674
|
+
function chapterStyle(chapters) {
|
|
1675
|
+
const s = chapters[0]?.source;
|
|
1676
|
+
return s === "nero" || s === "both" ? s : "quicktime";
|
|
1677
|
+
}
|
|
1678
|
+
function copyExtraState(target, source, sourceComplete) {
|
|
1679
|
+
for (const field of EXTRA_FIELDS) {
|
|
1680
|
+
field.copy(target, source, sourceComplete);
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
var EXTRA_FIELDS;
|
|
1684
|
+
var init_extra_state_registry = __esm({
|
|
1685
|
+
"src/taglib/extra-state-registry.ts"() {
|
|
1686
|
+
"use strict";
|
|
1687
|
+
EXTRA_FIELDS = [
|
|
1688
|
+
{
|
|
1689
|
+
name: "pictures",
|
|
1690
|
+
copy(target, source, complete) {
|
|
1691
|
+
const v = source.getPictures();
|
|
1692
|
+
if (complete || v.length > 0) target.setPictures(v);
|
|
1693
|
+
}
|
|
1694
|
+
},
|
|
1695
|
+
{
|
|
1696
|
+
name: "ratings",
|
|
1697
|
+
copy(target, source, complete) {
|
|
1698
|
+
const v = source.getRatings();
|
|
1699
|
+
if (complete || v.length > 0) target.setRatings(v);
|
|
1700
|
+
}
|
|
1701
|
+
},
|
|
1702
|
+
{
|
|
1703
|
+
name: "lyrics",
|
|
1704
|
+
copy(target, source, complete) {
|
|
1705
|
+
const v = source.getLyrics();
|
|
1706
|
+
if (complete || v.length > 0) target.setLyrics(v);
|
|
1707
|
+
}
|
|
1708
|
+
},
|
|
1709
|
+
{
|
|
1710
|
+
name: "chapters",
|
|
1711
|
+
copy(target, source, complete) {
|
|
1712
|
+
const v = source.getChapters();
|
|
1713
|
+
if (complete || v.length > 0) target.setChapters(v, chapterStyle(v));
|
|
1714
|
+
}
|
|
1715
|
+
},
|
|
1716
|
+
{
|
|
1717
|
+
name: "bextData",
|
|
1718
|
+
copy(target, source, complete) {
|
|
1719
|
+
const v = source.getBextData();
|
|
1720
|
+
if (v !== void 0) target.setBextData(v);
|
|
1721
|
+
else if (complete) target.setBextData(null);
|
|
1722
|
+
}
|
|
1723
|
+
},
|
|
1724
|
+
{
|
|
1725
|
+
name: "ixml",
|
|
1726
|
+
copy(target, source, complete) {
|
|
1727
|
+
const v = source.getIxml();
|
|
1728
|
+
if (v !== void 0) target.setIxml(v);
|
|
1729
|
+
else if (complete) target.setIxml(null);
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
];
|
|
1733
|
+
}
|
|
1734
|
+
});
|
|
1735
|
+
|
|
1736
|
+
// src/taglib/save-reconstruct.ts
|
|
1737
|
+
function copyEditedState(target, source, sourceComplete) {
|
|
1738
|
+
target.setTagData(source.getTagData());
|
|
1739
|
+
target.setProperties(
|
|
1740
|
+
sourceComplete ? source.getProperties() : { ...target.getProperties(), ...source.getProperties() }
|
|
1741
|
+
);
|
|
1742
|
+
copyExtraState(target, source, sourceComplete);
|
|
1743
|
+
}
|
|
1744
|
+
async function saveViaFreshHandle(module, editing, source, targetPath, sourceComplete) {
|
|
1745
|
+
const rawFullHandle = module.createFileHandle();
|
|
1746
|
+
const fullFileHandle = module.isWasi ? rawFullHandle : wrapEmbindHandle(rawFullHandle);
|
|
1747
|
+
try {
|
|
1748
|
+
{
|
|
1749
|
+
const data = await readFileData(source);
|
|
1750
|
+
if (!fullFileHandle.loadFromBuffer(data)) {
|
|
1751
|
+
throw new InvalidFormatError(
|
|
1752
|
+
"Failed to load full audio file for saving"
|
|
1753
|
+
);
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
copyEditedState(fullFileHandle, editing, sourceComplete);
|
|
1757
|
+
if (!fullFileHandle.save()) {
|
|
1758
|
+
throw new FileOperationError(
|
|
1759
|
+
"save",
|
|
1760
|
+
"Failed to save changes to full file"
|
|
1761
|
+
);
|
|
1762
|
+
}
|
|
1763
|
+
await writeFileData(targetPath, fullFileHandle.getBuffer());
|
|
1764
|
+
} finally {
|
|
1765
|
+
fullFileHandle.destroy();
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
var init_save_reconstruct = __esm({
|
|
1769
|
+
"src/taglib/save-reconstruct.ts"() {
|
|
1770
|
+
"use strict";
|
|
1771
|
+
init_errors2();
|
|
1772
|
+
init_file();
|
|
1773
|
+
init_write();
|
|
1774
|
+
init_embind_adapter();
|
|
1775
|
+
init_extra_state_registry();
|
|
1776
|
+
}
|
|
1777
|
+
});
|
|
1778
|
+
|
|
1643
1779
|
// src/taglib/audio-file-impl.ts
|
|
1644
1780
|
function sortChapters(list) {
|
|
1645
1781
|
return [...list].sort((a, b) => a.startTimeMs - b.startTimeMs);
|
|
@@ -1669,10 +1805,9 @@ var init_audio_file_impl = __esm({
|
|
|
1669
1805
|
init_types2();
|
|
1670
1806
|
init_audio_file_bwf();
|
|
1671
1807
|
init_errors2();
|
|
1672
|
-
init_file();
|
|
1673
1808
|
init_write();
|
|
1674
1809
|
init_audio_file_base();
|
|
1675
|
-
|
|
1810
|
+
init_save_reconstruct();
|
|
1676
1811
|
AudioFileImpl = class extends BaseAudioFileImpl {
|
|
1677
1812
|
constructor(module, fileHandle, sourcePath, originalSource, isPartiallyLoaded = false, partialLoadOptions) {
|
|
1678
1813
|
super(
|
|
@@ -1718,38 +1853,23 @@ var init_audio_file_impl = __esm({
|
|
|
1718
1853
|
);
|
|
1719
1854
|
}
|
|
1720
1855
|
if (this.isPartiallyLoaded && this.originalSource) {
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
if (!success) {
|
|
1729
|
-
throw new InvalidFormatError(
|
|
1730
|
-
"Failed to load full audio file for saving"
|
|
1731
|
-
);
|
|
1732
|
-
}
|
|
1733
|
-
fullFileHandle.setTagData(this.handle.getTagData());
|
|
1734
|
-
fullFileHandle.setProperties(this.handle.getProperties());
|
|
1735
|
-
fullFileHandle.setPictures(this.handle.getPictures());
|
|
1736
|
-
const bextBytes = this.handle.getBextData();
|
|
1737
|
-
if (bextBytes !== void 0) fullFileHandle.setBextData(bextBytes);
|
|
1738
|
-
const ixmlStr = this.handle.getIxml();
|
|
1739
|
-
if (ixmlStr !== void 0) fullFileHandle.setIxml(ixmlStr);
|
|
1740
|
-
if (!fullFileHandle.save()) {
|
|
1741
|
-
throw new FileOperationError(
|
|
1742
|
-
"save",
|
|
1743
|
-
"Failed to save changes to full file"
|
|
1744
|
-
);
|
|
1745
|
-
}
|
|
1746
|
-
const buffer = fullFileHandle.getBuffer();
|
|
1747
|
-
await writeFileData(targetPath, buffer);
|
|
1748
|
-
} finally {
|
|
1749
|
-
fullFileHandle.destroy();
|
|
1750
|
-
}
|
|
1856
|
+
await saveViaFreshHandle(
|
|
1857
|
+
this.module,
|
|
1858
|
+
this.handle,
|
|
1859
|
+
this.originalSource,
|
|
1860
|
+
targetPath,
|
|
1861
|
+
false
|
|
1862
|
+
);
|
|
1751
1863
|
this.isPartiallyLoaded = false;
|
|
1752
1864
|
this.originalSource = void 0;
|
|
1865
|
+
} else if (this.module.isWasi && this.sourcePath && targetPath !== this.sourcePath) {
|
|
1866
|
+
await saveViaFreshHandle(
|
|
1867
|
+
this.module,
|
|
1868
|
+
this.handle,
|
|
1869
|
+
this.sourcePath,
|
|
1870
|
+
targetPath,
|
|
1871
|
+
true
|
|
1872
|
+
);
|
|
1753
1873
|
} else {
|
|
1754
1874
|
if (!this.save()) {
|
|
1755
1875
|
throw new FileOperationError(
|
|
@@ -1811,13 +1931,16 @@ var init_audio_file_impl = __esm({
|
|
|
1811
1931
|
}
|
|
1812
1932
|
const sorted = sortChapters(chapters);
|
|
1813
1933
|
const trackEndMs = this.audioProperties()?.durationMs;
|
|
1934
|
+
const style = options?.mp4ChapterStyle ?? "quicktime";
|
|
1935
|
+
const source = fmt === "MP4" ? style : "id3";
|
|
1814
1936
|
const raw = sorted.map((c, i) => ({
|
|
1815
1937
|
id: c.id,
|
|
1816
1938
|
startTimeMs: c.startTimeMs,
|
|
1817
1939
|
endTimeMs: inferEndTimeMs(sorted, i, trackEndMs) ?? c.startTimeMs,
|
|
1818
|
-
title: c.title
|
|
1940
|
+
title: c.title,
|
|
1941
|
+
source
|
|
1819
1942
|
}));
|
|
1820
|
-
this.handle.setChapters(raw,
|
|
1943
|
+
this.handle.setChapters(raw, style);
|
|
1821
1944
|
}
|
|
1822
1945
|
getBext() {
|
|
1823
1946
|
return getBext(this.handle);
|
|
@@ -2026,7 +2149,7 @@ var VERSION;
|
|
|
2026
2149
|
var init_version = __esm({
|
|
2027
2150
|
"src/version.ts"() {
|
|
2028
2151
|
"use strict";
|
|
2029
|
-
VERSION = "1.
|
|
2152
|
+
VERSION = "1.3.0";
|
|
2030
2153
|
}
|
|
2031
2154
|
});
|
|
2032
2155
|
|