taglib-wasm 0.2.7 → 0.2.8
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/README.md +18 -52
- package/build/taglib.js +4 -10
- package/build/taglib.wasm +0 -0
- package/index.ts +13 -3
- package/package.json +3 -1
- package/src/simple-jsr.ts +40 -37
- package/src/simple.ts +19 -22
- package/src/taglib-jsr.ts +22 -518
- package/src/taglib.ts +160 -505
- package/src/types.ts +6 -3
- package/src/wasm-jsr.ts +12 -279
- package/src/wasm.ts +75 -244
- package/src/enhanced-api.ts +0 -296
- package/src/taglib-embind.ts +0 -231
- package/src/wasm-embind.ts +0 -55
package/src/types.ts
CHANGED
|
@@ -3,9 +3,14 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
// Re-export commonly used classes from other modules
|
|
6
|
-
export type { TagLibModule } from "./wasm
|
|
6
|
+
export type { TagLibModule } from "./wasm.ts";
|
|
7
7
|
// Note: AudioFile is not needed for JSR exports
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Supported file types
|
|
11
|
+
*/
|
|
12
|
+
export type FileType = "MP3" | "MP4" | "FLAC" | "OGG" | "OPUS" | "WAV" | "AIFF" | "UNKNOWN";
|
|
13
|
+
|
|
9
14
|
/**
|
|
10
15
|
* Audio format types supported by TagLib
|
|
11
16
|
*/
|
|
@@ -40,8 +45,6 @@ export interface AudioProperties {
|
|
|
40
45
|
readonly sampleRate: number;
|
|
41
46
|
/** Number of audio channels */
|
|
42
47
|
readonly channels: number;
|
|
43
|
-
/** Audio format */
|
|
44
|
-
readonly format: AudioFormat;
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
/**
|
package/src/wasm-jsr.ts
CHANGED
|
@@ -1,280 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview JSR-compatible WASM
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// Standard Emscripten memory arrays
|
|
15
|
-
HEAPU8: Uint8Array;
|
|
16
|
-
HEAP8: Int8Array;
|
|
17
|
-
HEAP16: Int16Array;
|
|
18
|
-
HEAP32: Int32Array;
|
|
19
|
-
HEAPU16: Uint16Array;
|
|
20
|
-
HEAPU32: Uint32Array;
|
|
21
|
-
HEAPF32: Float32Array;
|
|
22
|
-
HEAPF64: Float64Array;
|
|
23
|
-
|
|
24
|
-
// Standard functions
|
|
25
|
-
_malloc: (size: number) => number;
|
|
26
|
-
_free: (ptr: number) => void;
|
|
27
|
-
allocate: (array: Uint8Array, type: number) => number;
|
|
28
|
-
|
|
29
|
-
// Allocation constants
|
|
30
|
-
ALLOC_NORMAL: number;
|
|
31
|
-
ALLOC_STACK: number;
|
|
32
|
-
ALLOC_STATIC: number;
|
|
33
|
-
ALLOC_DYNAMIC: number;
|
|
34
|
-
ALLOC_NONE: number;
|
|
35
|
-
|
|
36
|
-
// TagLib-specific functions
|
|
37
|
-
_taglib_file_new_from_buffer: (data: number, size: number) => number;
|
|
38
|
-
_taglib_file_delete: (fileId: number) => void;
|
|
39
|
-
_taglib_file_save: (fileId: number) => number;
|
|
40
|
-
_taglib_file_is_valid: (fileId: number) => number;
|
|
41
|
-
_taglib_file_format: (fileId: number) => number;
|
|
42
|
-
_taglib_file_tag: (fileId: number) => number;
|
|
43
|
-
_taglib_tag_title: (tag: number) => number;
|
|
44
|
-
_taglib_tag_artist: (tag: number) => number;
|
|
45
|
-
_taglib_tag_album: (tag: number) => number;
|
|
46
|
-
_taglib_tag_comment: (tag: number) => number;
|
|
47
|
-
_taglib_tag_genre: (tag: number) => number;
|
|
48
|
-
_taglib_tag_year: (tag: number) => number;
|
|
49
|
-
_taglib_tag_track: (tag: number) => number;
|
|
50
|
-
_taglib_tag_set_title: (tag: number, title: number) => void;
|
|
51
|
-
_taglib_tag_set_artist: (tag: number, artist: number) => void;
|
|
52
|
-
_taglib_tag_set_album: (tag: number, album: number) => void;
|
|
53
|
-
_taglib_tag_set_comment: (tag: number, comment: number) => void;
|
|
54
|
-
_taglib_tag_set_genre: (tag: number, genre: number) => void;
|
|
55
|
-
_taglib_tag_set_year: (tag: number, year: number) => void;
|
|
56
|
-
_taglib_tag_set_track: (tag: number, track: number) => void;
|
|
57
|
-
_taglib_file_audioproperties: (fileId: number) => number;
|
|
58
|
-
_taglib_audioproperties_length: (props: number) => number;
|
|
59
|
-
_taglib_audioproperties_bitrate: (props: number) => number;
|
|
60
|
-
_taglib_audioproperties_samplerate: (props: number) => number;
|
|
61
|
-
_taglib_audioproperties_channels: (props: number) => number;
|
|
62
|
-
|
|
63
|
-
// PropertyMap operations
|
|
64
|
-
_taglib_file_properties_json: (fileId: number) => number;
|
|
65
|
-
_taglib_file_set_properties_json: (fileId: number, json: number) => number;
|
|
66
|
-
_taglib_file_get_property: (fileId: number, key: number) => number;
|
|
67
|
-
_taglib_file_set_property: (fileId: number, key: number, value: number) => number;
|
|
68
|
-
|
|
69
|
-
// MP4-specific operations
|
|
70
|
-
_taglib_file_is_mp4: (fileId: number) => number;
|
|
71
|
-
_taglib_mp4_get_item: (fileId: number, key: number) => number;
|
|
72
|
-
_taglib_mp4_set_item: (fileId: number, key: number, value: number) => number;
|
|
73
|
-
_taglib_mp4_remove_item: (fileId: number, key: number) => number;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Load taglib-wasm module for JSR
|
|
78
|
-
*/
|
|
79
|
-
export async function loadTagLibModuleJSR(
|
|
80
|
-
config?: TagLibConfig,
|
|
81
|
-
): Promise<TagLibModule> {
|
|
82
|
-
// Load WASM file as bytes (same file for all platforms)
|
|
83
|
-
const wasmUrl = new URL("../build/taglib.wasm", import.meta.url);
|
|
84
|
-
const wasmBytes = await fetch(wasmUrl).then((r) => r.arrayBuffer());
|
|
85
|
-
|
|
86
|
-
// Create memory
|
|
87
|
-
const memory = new WebAssembly.Memory({ initial: 256, maximum: 4096 });
|
|
88
|
-
|
|
89
|
-
// Create heap views (initialized after memory is created)
|
|
90
|
-
let HEAP8!: Int8Array;
|
|
91
|
-
let HEAPU8!: Uint8Array;
|
|
92
|
-
let HEAP16!: Int16Array;
|
|
93
|
-
let HEAPU16!: Uint16Array;
|
|
94
|
-
let HEAP32!: Int32Array;
|
|
95
|
-
let HEAPU32!: Uint32Array;
|
|
96
|
-
let HEAPF32!: Float32Array;
|
|
97
|
-
let HEAPF64!: Float64Array;
|
|
98
|
-
|
|
99
|
-
function updateMemoryViews() {
|
|
100
|
-
const buffer = memory.buffer;
|
|
101
|
-
HEAP8 = new Int8Array(buffer);
|
|
102
|
-
HEAPU8 = new Uint8Array(buffer);
|
|
103
|
-
HEAP16 = new Int16Array(buffer);
|
|
104
|
-
HEAPU16 = new Uint16Array(buffer);
|
|
105
|
-
HEAP32 = new Int32Array(buffer);
|
|
106
|
-
HEAPU32 = new Uint32Array(buffer);
|
|
107
|
-
HEAPF32 = new Float32Array(buffer);
|
|
108
|
-
HEAPF64 = new Float64Array(buffer);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
updateMemoryViews();
|
|
112
|
-
|
|
113
|
-
// Import functions expected by the WASM module (still minified with -O3)
|
|
114
|
-
const wasmImports = {
|
|
115
|
-
a: {
|
|
116
|
-
// a: ___cxa_throw
|
|
117
|
-
a: (ptr: number, type: number, destructor: number) => {
|
|
118
|
-
throw new Error('Exception thrown from WASM');
|
|
119
|
-
},
|
|
120
|
-
// e: __abort_js
|
|
121
|
-
e: () => {
|
|
122
|
-
throw new Error('Abort called from WASM');
|
|
123
|
-
},
|
|
124
|
-
// b: __tzset_js
|
|
125
|
-
b: (timezone: number, daylight: number, std_name: number, dst_name: number) => {
|
|
126
|
-
// Minimal timezone implementation
|
|
127
|
-
},
|
|
128
|
-
// f: _emscripten_resize_heap
|
|
129
|
-
f: (requestedSize: number) => {
|
|
130
|
-
const oldSize = HEAPU8.length;
|
|
131
|
-
const newSize = Math.max(oldSize, requestedSize);
|
|
132
|
-
const pages = Math.ceil((newSize - memory.buffer.byteLength) / 65536);
|
|
133
|
-
try {
|
|
134
|
-
memory.grow(pages);
|
|
135
|
-
updateMemoryViews();
|
|
136
|
-
return 1;
|
|
137
|
-
} catch (e) {
|
|
138
|
-
return 0;
|
|
139
|
-
}
|
|
140
|
-
},
|
|
141
|
-
// c: _environ_get
|
|
142
|
-
c: (__environ: number, environ_buf: number) => 0,
|
|
143
|
-
// d: _environ_sizes_get
|
|
144
|
-
d: (penviron_count: number, penviron_buf_size: number) => {
|
|
145
|
-
HEAPU32[penviron_count >> 2] = 0;
|
|
146
|
-
HEAPU32[penviron_buf_size >> 2] = 0;
|
|
147
|
-
return 0;
|
|
148
|
-
},
|
|
149
|
-
// g: memory
|
|
150
|
-
g: memory,
|
|
151
|
-
},
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
// Instantiate WASM with the expected imports
|
|
155
|
-
const wasmModule = await WebAssembly.instantiate(wasmBytes, wasmImports);
|
|
156
|
-
|
|
157
|
-
const exports = wasmModule.instance.exports as any;
|
|
158
|
-
|
|
159
|
-
// Update memory reference from exports (g is memory in minified version)
|
|
160
|
-
if (exports.g) {
|
|
161
|
-
updateMemoryViews();
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// Initialize runtime (h is the init function in minified version)
|
|
165
|
-
if (exports.h) {
|
|
166
|
-
exports.h();
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Build the module interface
|
|
170
|
-
const module: TagLibModule = {
|
|
171
|
-
// Memory arrays
|
|
172
|
-
HEAPU8,
|
|
173
|
-
HEAP8,
|
|
174
|
-
HEAP16,
|
|
175
|
-
HEAP32,
|
|
176
|
-
HEAPU16,
|
|
177
|
-
HEAPU32,
|
|
178
|
-
HEAPF32,
|
|
179
|
-
HEAPF64,
|
|
180
|
-
|
|
181
|
-
// Standard functions (minified with -O3)
|
|
182
|
-
_malloc: exports.P || (() => {
|
|
183
|
-
throw new Error("malloc not available");
|
|
184
|
-
}),
|
|
185
|
-
_free: exports.Q || (() => {}),
|
|
186
|
-
allocate: (array: Uint8Array, type: number) => {
|
|
187
|
-
const ptr = module._malloc(array.length);
|
|
188
|
-
// Ensure we have the latest memory view
|
|
189
|
-
if (memory.buffer !== module.HEAPU8.buffer) {
|
|
190
|
-
updateMemoryViews();
|
|
191
|
-
module.HEAPU8 = HEAPU8;
|
|
192
|
-
module.HEAP8 = HEAP8;
|
|
193
|
-
module.HEAP16 = HEAP16;
|
|
194
|
-
module.HEAP32 = HEAP32;
|
|
195
|
-
module.HEAPU16 = HEAPU16;
|
|
196
|
-
module.HEAPU32 = HEAPU32;
|
|
197
|
-
module.HEAPF32 = HEAPF32;
|
|
198
|
-
module.HEAPF64 = HEAPF64;
|
|
199
|
-
}
|
|
200
|
-
module.HEAPU8.set(array, ptr);
|
|
201
|
-
return ptr;
|
|
202
|
-
},
|
|
203
|
-
|
|
204
|
-
// Allocation constants
|
|
205
|
-
ALLOC_NORMAL: 0,
|
|
206
|
-
ALLOC_STACK: 1,
|
|
207
|
-
ALLOC_STATIC: 2,
|
|
208
|
-
ALLOC_DYNAMIC: 3,
|
|
209
|
-
ALLOC_NONE: 4,
|
|
210
|
-
|
|
211
|
-
// TagLib functions - map from minified WASM exports (with -O3)
|
|
212
|
-
_taglib_file_new_from_buffer: exports.i,
|
|
213
|
-
_taglib_file_delete: exports.j,
|
|
214
|
-
_taglib_file_save: exports.k,
|
|
215
|
-
_taglib_file_is_valid: exports.l,
|
|
216
|
-
_taglib_file_format: exports.m,
|
|
217
|
-
_taglib_file_tag: exports.n,
|
|
218
|
-
_taglib_tag_title: exports.o,
|
|
219
|
-
_taglib_tag_artist: exports.p,
|
|
220
|
-
_taglib_tag_album: exports.q,
|
|
221
|
-
_taglib_tag_comment: exports.r,
|
|
222
|
-
_taglib_tag_genre: exports.s,
|
|
223
|
-
_taglib_tag_year: exports.t,
|
|
224
|
-
_taglib_tag_track: exports.u,
|
|
225
|
-
_taglib_tag_set_title: exports.v,
|
|
226
|
-
_taglib_tag_set_artist: exports.w,
|
|
227
|
-
_taglib_tag_set_album: exports.x,
|
|
228
|
-
_taglib_tag_set_comment: exports.y,
|
|
229
|
-
_taglib_tag_set_genre: exports.z,
|
|
230
|
-
_taglib_tag_set_year: exports.A,
|
|
231
|
-
_taglib_tag_set_track: exports.B,
|
|
232
|
-
_taglib_file_audioproperties: exports.C,
|
|
233
|
-
_taglib_audioproperties_length: exports.D,
|
|
234
|
-
_taglib_audioproperties_bitrate: exports.E,
|
|
235
|
-
_taglib_audioproperties_samplerate: exports.F,
|
|
236
|
-
_taglib_audioproperties_channels: exports.G,
|
|
237
|
-
|
|
238
|
-
// PropertyMap operations
|
|
239
|
-
_taglib_file_properties_json: exports.H,
|
|
240
|
-
_taglib_file_set_properties_json: exports.I,
|
|
241
|
-
_taglib_file_get_property: exports.J,
|
|
242
|
-
_taglib_file_set_property: exports.K,
|
|
243
|
-
|
|
244
|
-
// MP4-specific operations
|
|
245
|
-
_taglib_file_is_mp4: exports.L,
|
|
246
|
-
_taglib_mp4_get_item: exports.M,
|
|
247
|
-
_taglib_mp4_set_item: exports.N,
|
|
248
|
-
_taglib_mp4_remove_item: exports.O,
|
|
249
|
-
};
|
|
250
|
-
|
|
251
|
-
return module;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Convert JavaScript string to C string pointer
|
|
256
|
-
*/
|
|
257
|
-
export function jsToCStringJSR(module: TagLibModule, str: string): number {
|
|
258
|
-
const encoder = new TextEncoder();
|
|
259
|
-
const bytes = encoder.encode(str + "\0");
|
|
260
|
-
return module.allocate(bytes, module.ALLOC_NORMAL);
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Convert C string pointer to JavaScript string
|
|
265
|
-
*/
|
|
266
|
-
export function cStringToJSJSR(module: TagLibModule, ptr: number): string {
|
|
267
|
-
if (ptr === 0) return "";
|
|
268
|
-
|
|
269
|
-
const bytes: number[] = [];
|
|
270
|
-
let i = 0;
|
|
271
|
-
while (true) {
|
|
272
|
-
const byte = module.HEAPU8[ptr + i];
|
|
273
|
-
if (byte === undefined || byte === 0) break;
|
|
274
|
-
bytes.push(byte);
|
|
275
|
-
i++;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const decoder = new TextDecoder();
|
|
279
|
-
return decoder.decode(new Uint8Array(bytes));
|
|
280
|
-
}
|
|
2
|
+
* @fileoverview JSR-compatible WASM module interface (no Node.js dependencies)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Re-export types only (no implementation imports)
|
|
6
|
+
export type {
|
|
7
|
+
EmscriptenModule,
|
|
8
|
+
FileHandle,
|
|
9
|
+
TagWrapper,
|
|
10
|
+
AudioPropertiesWrapper,
|
|
11
|
+
TagLibModule,
|
|
12
|
+
WasmModule,
|
|
13
|
+
} from "./wasm.ts";
|
package/src/wasm.ts
CHANGED
|
@@ -1,263 +1,94 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview WebAssembly module interface
|
|
2
|
+
* @fileoverview WebAssembly module interface types for Emscripten
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* Emscripten module interface for taglib-wasm
|
|
9
|
-
*/
|
|
10
|
-
export interface TagLibModule {
|
|
11
|
-
// Emscripten standard properties
|
|
12
|
-
HEAPU8: Uint8Array;
|
|
5
|
+
// Basic Emscripten module interface
|
|
6
|
+
export interface EmscriptenModule {
|
|
7
|
+
// Memory
|
|
13
8
|
HEAP8: Int8Array;
|
|
14
9
|
HEAP16: Int16Array;
|
|
15
10
|
HEAP32: Int32Array;
|
|
11
|
+
HEAPU8: Uint8Array;
|
|
16
12
|
HEAPU16: Uint16Array;
|
|
17
13
|
HEAPU32: Uint32Array;
|
|
18
14
|
HEAPF32: Float32Array;
|
|
19
15
|
HEAPF64: Float64Array;
|
|
20
|
-
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
allocate: (array: Uint8Array, type: number) => number;
|
|
38
|
-
|
|
39
|
-
// Allocation types
|
|
40
|
-
ALLOC_NORMAL: number;
|
|
41
|
-
ALLOC_STACK: number;
|
|
42
|
-
ALLOC_STATIC: number;
|
|
43
|
-
ALLOC_DYNAMIC: number;
|
|
44
|
-
ALLOC_NONE: number;
|
|
45
|
-
|
|
46
|
-
// File operations
|
|
47
|
-
_taglib_file_new_from_buffer: (data: number, size: number) => number;
|
|
48
|
-
_taglib_file_delete: (fileId: number) => void;
|
|
49
|
-
_taglib_file_save: (fileId: number) => number;
|
|
50
|
-
_taglib_file_is_valid: (fileId: number) => number;
|
|
51
|
-
_taglib_file_format: (fileId: number) => number;
|
|
52
|
-
|
|
53
|
-
// Tag operations
|
|
54
|
-
_taglib_file_tag: (fileId: number) => number;
|
|
55
|
-
_taglib_tag_title: (tag: number) => number;
|
|
56
|
-
_taglib_tag_artist: (tag: number) => number;
|
|
57
|
-
_taglib_tag_album: (tag: number) => number;
|
|
58
|
-
_taglib_tag_comment: (tag: number) => number;
|
|
59
|
-
_taglib_tag_genre: (tag: number) => number;
|
|
60
|
-
_taglib_tag_year: (tag: number) => number;
|
|
61
|
-
_taglib_tag_track: (tag: number) => number;
|
|
62
|
-
|
|
63
|
-
_taglib_tag_set_title: (tag: number, title: number) => void;
|
|
64
|
-
_taglib_tag_set_artist: (tag: number, artist: number) => void;
|
|
65
|
-
_taglib_tag_set_album: (tag: number, album: number) => void;
|
|
66
|
-
_taglib_tag_set_comment: (tag: number, comment: number) => void;
|
|
67
|
-
_taglib_tag_set_genre: (tag: number, genre: number) => void;
|
|
68
|
-
_taglib_tag_set_year: (tag: number, year: number) => void;
|
|
69
|
-
_taglib_tag_set_track: (tag: number, track: number) => void;
|
|
70
|
-
|
|
71
|
-
// Audio properties
|
|
72
|
-
_taglib_file_audioproperties: (fileId: number) => number;
|
|
73
|
-
_taglib_audioproperties_length: (props: number) => number;
|
|
74
|
-
_taglib_audioproperties_bitrate: (props: number) => number;
|
|
75
|
-
_taglib_audioproperties_samplerate: (props: number) => number;
|
|
76
|
-
_taglib_audioproperties_channels: (props: number) => number;
|
|
77
|
-
|
|
78
|
-
// PropertyMap operations
|
|
79
|
-
_taglib_file_properties_json: (fileId: number) => number;
|
|
80
|
-
_taglib_file_set_properties_json: (fileId: number, json: number) => number;
|
|
81
|
-
_taglib_file_get_property: (fileId: number, key: number) => number;
|
|
82
|
-
_taglib_file_set_property: (fileId: number, key: number, value: number) => number;
|
|
83
|
-
|
|
84
|
-
// MP4-specific operations
|
|
85
|
-
_taglib_file_is_mp4: (fileId: number) => number;
|
|
86
|
-
_taglib_mp4_get_item: (fileId: number, key: number) => number;
|
|
87
|
-
_taglib_mp4_set_item: (fileId: number, key: number, value: number) => number;
|
|
88
|
-
_taglib_mp4_remove_item: (fileId: number, key: number) => number;
|
|
89
|
-
|
|
90
|
-
// String utilities
|
|
91
|
-
_taglib_string_new: (str: number) => number;
|
|
92
|
-
_taglib_string_delete: (str: number) => void;
|
|
93
|
-
_taglib_string_to_cstring: (str: number) => number;
|
|
94
|
-
|
|
95
|
-
// Memory management functions already defined above
|
|
16
|
+
|
|
17
|
+
// Memory management
|
|
18
|
+
_malloc(size: number): number;
|
|
19
|
+
_free(ptr: number): void;
|
|
20
|
+
allocate?(data: number[] | Uint8Array, allocator: number): number;
|
|
21
|
+
ALLOC_NORMAL?: number;
|
|
22
|
+
|
|
23
|
+
// String conversion
|
|
24
|
+
ccall?(ident: string, returnType: string, argTypes: string[], args: any[]): any;
|
|
25
|
+
cwrap?(ident: string, returnType: string, argTypes: string[]): (...args: any[]) => any;
|
|
26
|
+
|
|
27
|
+
// File system (if enabled)
|
|
28
|
+
FS?: any;
|
|
29
|
+
|
|
30
|
+
// Runtime
|
|
31
|
+
then?(callback: (module: EmscriptenModule) => void): void;
|
|
32
|
+
onRuntimeInitialized?: () => void;
|
|
96
33
|
}
|
|
97
34
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
): Promise<TagLibModule> {
|
|
115
|
-
const mergedConfig = { ...DEFAULT_CONFIG, ...config };
|
|
116
|
-
|
|
117
|
-
// Detect runtime environment
|
|
118
|
-
const isNode = typeof (globalThis as any).process !== "undefined" && (globalThis as any).process.versions?.node;
|
|
119
|
-
const isDeno = typeof (globalThis as any).Deno !== "undefined";
|
|
120
|
-
|
|
121
|
-
let wasmPath: string;
|
|
122
|
-
|
|
123
|
-
if (isDeno) {
|
|
124
|
-
// Deno: Use file system path
|
|
125
|
-
wasmPath = new URL("../build/taglib.wasm", import.meta.url).pathname;
|
|
126
|
-
} else if (isNode) {
|
|
127
|
-
// Node.js: Use require.resolve or fs path
|
|
128
|
-
wasmPath = new URL("../build/taglib.wasm", import.meta.url).pathname;
|
|
129
|
-
} else {
|
|
130
|
-
// Browser: Relative path
|
|
131
|
-
wasmPath = "./taglib.wasm";
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Load WASM binary
|
|
135
|
-
let wasmBinary: Uint8Array;
|
|
136
|
-
|
|
137
|
-
if (isDeno) {
|
|
138
|
-
wasmBinary = await (globalThis as any).Deno.readFile(wasmPath);
|
|
139
|
-
} else if (isNode) {
|
|
140
|
-
const fs = await import("node:fs");
|
|
141
|
-
wasmBinary = await fs.promises.readFile(wasmPath);
|
|
142
|
-
} else {
|
|
143
|
-
// Browser
|
|
144
|
-
const response = await fetch(wasmPath);
|
|
145
|
-
wasmBinary = new Uint8Array(await response.arrayBuffer());
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Create Emscripten module configuration
|
|
149
|
-
const moduleConfig = {
|
|
150
|
-
wasmBinary,
|
|
151
|
-
wasmMemory: new WebAssembly.Memory({
|
|
152
|
-
initial: mergedConfig.memory.initial! / (64 * 1024),
|
|
153
|
-
maximum: mergedConfig.memory.maximum! / (64 * 1024),
|
|
154
|
-
}),
|
|
155
|
-
print: mergedConfig.debug ? console.log : () => {},
|
|
156
|
-
printErr: mergedConfig.debug ? console.error : () => {},
|
|
157
|
-
onRuntimeInitialized: () => {
|
|
158
|
-
if (mergedConfig.debug) {
|
|
159
|
-
console.log("taglib-wasm module initialized");
|
|
160
|
-
}
|
|
161
|
-
},
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
// Load the Emscripten-generated module
|
|
165
|
-
try {
|
|
166
|
-
// For Deno, we need to handle the CommonJS-style export
|
|
167
|
-
let TagLibWASM: any;
|
|
168
|
-
|
|
169
|
-
if (isDeno) {
|
|
170
|
-
// In Deno, read and evaluate the JS file
|
|
171
|
-
const jsContent = await (globalThis as any).Deno.readTextFile(
|
|
172
|
-
new URL("../build/taglib.js", import.meta.url).pathname,
|
|
173
|
-
);
|
|
174
|
-
|
|
175
|
-
// Create a minimal CommonJS environment
|
|
176
|
-
const exports = {} as any;
|
|
177
|
-
const module = { exports } as any;
|
|
178
|
-
const define = undefined;
|
|
179
|
-
const require = (name: string) => {
|
|
180
|
-
if (name === "fs") {
|
|
181
|
-
return {
|
|
182
|
-
readFileSync: (path: string) => (globalThis as any).Deno.readFileSync(path),
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
throw new Error(`Module ${name} not found`);
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
// Add a minimal process object for Node.js compatibility
|
|
189
|
-
const process = {
|
|
190
|
-
versions: {},
|
|
191
|
-
argv: [],
|
|
192
|
-
type: "deno",
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
// Execute the WASM JS with the proper context
|
|
196
|
-
const func = new Function(
|
|
197
|
-
"exports",
|
|
198
|
-
"module",
|
|
199
|
-
"define",
|
|
200
|
-
"require",
|
|
201
|
-
"process",
|
|
202
|
-
"__dirname",
|
|
203
|
-
"__filename",
|
|
204
|
-
jsContent +
|
|
205
|
-
'\nreturn typeof TagLibWASM !== "undefined" ? TagLibWASM : module.exports;',
|
|
206
|
-
);
|
|
207
|
-
|
|
208
|
-
TagLibWASM = func(exports, module, define, require, process, "", "");
|
|
209
|
-
} else {
|
|
210
|
-
// For Node.js and browsers, use normal import
|
|
211
|
-
const wasmModule = await import("../build/taglib.js");
|
|
212
|
-
TagLibWASM = wasmModule.default || wasmModule;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (typeof TagLibWASM !== "function") {
|
|
216
|
-
throw new Error("Failed to load taglib-wasm module");
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const wasmInstance = await TagLibWASM(moduleConfig);
|
|
220
|
-
|
|
221
|
-
// Ensure proper memory arrays are set up
|
|
222
|
-
if (!wasmInstance.HEAPU8) {
|
|
223
|
-
// Manual setup if not automatically created
|
|
224
|
-
const buffer = wasmInstance.buffer || wasmInstance.wasmMemory?.buffer;
|
|
225
|
-
if (buffer) {
|
|
226
|
-
wasmInstance.HEAPU8 = new Uint8Array(buffer);
|
|
227
|
-
wasmInstance.HEAP8 = new Int8Array(buffer);
|
|
228
|
-
wasmInstance.HEAP16 = new Int16Array(buffer);
|
|
229
|
-
wasmInstance.HEAP32 = new Int32Array(buffer);
|
|
230
|
-
wasmInstance.HEAPU16 = new Uint16Array(buffer);
|
|
231
|
-
wasmInstance.HEAPU32 = new Uint32Array(buffer);
|
|
232
|
-
wasmInstance.HEAPF32 = new Float32Array(buffer);
|
|
233
|
-
wasmInstance.HEAPF64 = new Float64Array(buffer);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
return wasmInstance as TagLibModule;
|
|
238
|
-
} catch (error) {
|
|
239
|
-
throw new Error(`Failed to load taglib-wasm: ${(error as Error).message}`);
|
|
240
|
-
}
|
|
35
|
+
// Embind class interfaces
|
|
36
|
+
export interface FileHandle {
|
|
37
|
+
loadFromBuffer(data: Uint8Array): boolean;
|
|
38
|
+
isValid(): boolean;
|
|
39
|
+
save(): boolean;
|
|
40
|
+
getFormat(): string;
|
|
41
|
+
getProperties(): any;
|
|
42
|
+
setProperties(props: any): void;
|
|
43
|
+
getProperty(key: string): string;
|
|
44
|
+
setProperty(key: string, value: string): void;
|
|
45
|
+
isMP4(): boolean;
|
|
46
|
+
getMP4Item(key: string): string;
|
|
47
|
+
setMP4Item(key: string, value: string): void;
|
|
48
|
+
removeMP4Item(key: string): void;
|
|
49
|
+
getTag(): TagWrapper;
|
|
50
|
+
getAudioProperties(): AudioPropertiesWrapper;
|
|
241
51
|
}
|
|
242
52
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
53
|
+
export interface TagWrapper {
|
|
54
|
+
title(): string;
|
|
55
|
+
artist(): string;
|
|
56
|
+
album(): string;
|
|
57
|
+
comment(): string;
|
|
58
|
+
genre(): string;
|
|
59
|
+
year(): number;
|
|
60
|
+
track(): number;
|
|
61
|
+
setTitle(value: string): void;
|
|
62
|
+
setArtist(value: string): void;
|
|
63
|
+
setAlbum(value: string): void;
|
|
64
|
+
setComment(value: string): void;
|
|
65
|
+
setGenre(value: string): void;
|
|
66
|
+
setYear(value: number): void;
|
|
67
|
+
setTrack(value: number): void;
|
|
68
|
+
}
|
|
248
69
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
70
|
+
export interface AudioPropertiesWrapper {
|
|
71
|
+
lengthInSeconds(): number;
|
|
72
|
+
lengthInMilliseconds(): number;
|
|
73
|
+
bitrate(): number;
|
|
74
|
+
sampleRate(): number;
|
|
75
|
+
channels(): number;
|
|
76
|
+
}
|
|
252
77
|
|
|
253
|
-
|
|
78
|
+
export interface TagLibModule extends EmscriptenModule {
|
|
79
|
+
// Embind classes
|
|
80
|
+
FileHandle: new () => FileHandle;
|
|
81
|
+
TagWrapper: new () => TagWrapper;
|
|
82
|
+
AudioPropertiesWrapper: new () => AudioPropertiesWrapper;
|
|
83
|
+
|
|
84
|
+
// Embind functions
|
|
85
|
+
createFileHandle(): FileHandle;
|
|
254
86
|
}
|
|
255
87
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
const encoder = new TextEncoder();
|
|
261
|
-
const bytes = encoder.encode(str + "\0");
|
|
262
|
-
return module.allocate(bytes, module.ALLOC_NORMAL);
|
|
88
|
+
export interface WasmModule extends EmscriptenModule {
|
|
89
|
+
// Alias for compatibility
|
|
90
|
+
FileHandle?: new () => FileHandle;
|
|
91
|
+
createFileHandle?(): FileHandle;
|
|
263
92
|
}
|
|
93
|
+
|
|
94
|
+
// Module loading function removed for modular imports
|