taglib-wasm 0.2.6 → 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/enhanced-api.ts
DELETED
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Enhanced API patterns inspired by node-taglib
|
|
3
|
-
*
|
|
4
|
-
* This file demonstrates potential API improvements that could be added
|
|
5
|
-
* to taglib-wasm to improve developer experience.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type { AudioFile, TagLibConfig } from "./types";
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Enhanced error handling with error codes
|
|
12
|
-
*/
|
|
13
|
-
export interface TagLibError extends Error {
|
|
14
|
-
code:
|
|
15
|
-
| "FILE_NOT_FOUND"
|
|
16
|
-
| "INVALID_FORMAT"
|
|
17
|
-
| "MEMORY_ERROR"
|
|
18
|
-
| "PERMISSION_DENIED"
|
|
19
|
-
| "WASM_ERROR";
|
|
20
|
-
path?: string;
|
|
21
|
-
format?: string;
|
|
22
|
-
details?: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Callback-style async operations (Node.js pattern)
|
|
27
|
-
*/
|
|
28
|
-
export type TagLibCallback<T> = (err: TagLibError | null, result?: T) => void;
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Enhanced input types
|
|
32
|
-
*/
|
|
33
|
-
export type AudioInput =
|
|
34
|
-
| string // File path (Node.js/Deno/Bun only)
|
|
35
|
-
| Uint8Array // Raw bytes
|
|
36
|
-
| ArrayBuffer // ArrayBuffer
|
|
37
|
-
| Buffer // Node.js Buffer
|
|
38
|
-
| File; // Browser File object
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Enhanced TagLib class with multiple API patterns
|
|
42
|
-
*/
|
|
43
|
-
export class EnhancedTagLib {
|
|
44
|
-
/**
|
|
45
|
-
* Synchronous initialization (for server environments)
|
|
46
|
-
*/
|
|
47
|
-
static initializeSync(config?: TagLibConfig): EnhancedTagLib {
|
|
48
|
-
// Implementation would be synchronous version
|
|
49
|
-
throw new Error("Not implemented");
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Asynchronous initialization (current pattern)
|
|
54
|
-
*/
|
|
55
|
-
static async initialize(config?: TagLibConfig): Promise<EnhancedTagLib> {
|
|
56
|
-
// Current implementation
|
|
57
|
-
throw new Error("Not implemented");
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Open file with flexible input types
|
|
62
|
-
*/
|
|
63
|
-
openFile(input: AudioInput): EnhancedAudioFile {
|
|
64
|
-
if (typeof input === "string") {
|
|
65
|
-
return this.openFileFromPath(input);
|
|
66
|
-
} else if (input instanceof File) {
|
|
67
|
-
return this.openFileFromBrowserFile(input);
|
|
68
|
-
} else if (input instanceof ArrayBuffer) {
|
|
69
|
-
return this.openFileFromBuffer(new Uint8Array(input));
|
|
70
|
-
} else if (Buffer && Buffer.isBuffer(input)) {
|
|
71
|
-
return this.openFileFromBuffer(new Uint8Array(input));
|
|
72
|
-
} else {
|
|
73
|
-
return this.openFileFromBuffer(input);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Async file opening with callback pattern
|
|
79
|
-
*/
|
|
80
|
-
openFileAsync(
|
|
81
|
-
input: AudioInput,
|
|
82
|
-
callback: TagLibCallback<EnhancedAudioFile>,
|
|
83
|
-
): void {
|
|
84
|
-
try {
|
|
85
|
-
const file = this.openFile(input);
|
|
86
|
-
callback(null, file);
|
|
87
|
-
} catch (error) {
|
|
88
|
-
const tagLibError: TagLibError = {
|
|
89
|
-
name: "TagLibError",
|
|
90
|
-
message: (error as Error).message,
|
|
91
|
-
code: "INVALID_FORMAT",
|
|
92
|
-
details: (error as Error).stack,
|
|
93
|
-
};
|
|
94
|
-
callback(tagLibError);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Sync file opening (Node.js/Bun/Deno only)
|
|
100
|
-
*/
|
|
101
|
-
openFileSync(path: string): EnhancedAudioFile {
|
|
102
|
-
// Runtime-specific implementation
|
|
103
|
-
if (typeof (globalThis as any).Deno !== "undefined") {
|
|
104
|
-
const data = (globalThis as any).Deno.readFileSync(path);
|
|
105
|
-
return this.openFileFromBuffer(data);
|
|
106
|
-
} else if (typeof (globalThis as any).Bun !== "undefined") {
|
|
107
|
-
const file = (globalThis as any).Bun.file(path);
|
|
108
|
-
const data = new Uint8Array(file.arrayBufferSync());
|
|
109
|
-
return this.openFileFromBuffer(data);
|
|
110
|
-
} else if (typeof require !== "undefined") {
|
|
111
|
-
const fs = require("fs");
|
|
112
|
-
const data = fs.readFileSync(path);
|
|
113
|
-
return this.openFileFromBuffer(new Uint8Array(data));
|
|
114
|
-
} else {
|
|
115
|
-
throw new Error(
|
|
116
|
-
"Synchronous file reading not supported in browser environment",
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
private openFileFromPath(path: string): EnhancedAudioFile {
|
|
122
|
-
throw new Error("Not implemented");
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
private openFileFromBrowserFile(file: File): EnhancedAudioFile {
|
|
126
|
-
throw new Error("Not implemented - requires async operation");
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
private openFileFromBuffer(buffer: Uint8Array): EnhancedAudioFile {
|
|
130
|
-
throw new Error("Not implemented");
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Enhanced AudioFile with property accessors and better error handling
|
|
136
|
-
*/
|
|
137
|
-
export class EnhancedAudioFile {
|
|
138
|
-
// Property accessors (more intuitive than method calls)
|
|
139
|
-
get title(): string | undefined {
|
|
140
|
-
return this.tag().title;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
set title(value: string | undefined) {
|
|
144
|
-
if (value !== undefined) {
|
|
145
|
-
this.setTitle(value);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
get artist(): string | undefined {
|
|
150
|
-
return this.tag().artist;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
set artist(value: string | undefined) {
|
|
154
|
-
if (value !== undefined) {
|
|
155
|
-
this.setArtist(value);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
get album(): string | undefined {
|
|
160
|
-
return this.tag().album;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
set album(value: string | undefined) {
|
|
164
|
-
if (value !== undefined) {
|
|
165
|
-
this.setAlbum(value);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Async operations with callbacks
|
|
170
|
-
tagAsync(callback: TagLibCallback<any>): void {
|
|
171
|
-
try {
|
|
172
|
-
const tags = this.tag();
|
|
173
|
-
callback(null, tags);
|
|
174
|
-
} catch (error) {
|
|
175
|
-
const tagLibError: TagLibError = {
|
|
176
|
-
name: "TagLibError",
|
|
177
|
-
message: (error as Error).message,
|
|
178
|
-
code: "MEMORY_ERROR",
|
|
179
|
-
};
|
|
180
|
-
callback(tagLibError);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
saveAsync(callback: TagLibCallback<boolean>): void {
|
|
185
|
-
try {
|
|
186
|
-
const result = this.save();
|
|
187
|
-
callback(null, result);
|
|
188
|
-
} catch (error) {
|
|
189
|
-
const tagLibError: TagLibError = {
|
|
190
|
-
name: "TagLibError",
|
|
191
|
-
message: (error as Error).message,
|
|
192
|
-
code: "PERMISSION_DENIED",
|
|
193
|
-
};
|
|
194
|
-
callback(tagLibError);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Bulk tag setting (convenience method)
|
|
199
|
-
setTags(tags: {
|
|
200
|
-
title?: string;
|
|
201
|
-
artist?: string;
|
|
202
|
-
album?: string;
|
|
203
|
-
year?: number;
|
|
204
|
-
genre?: string;
|
|
205
|
-
track?: number;
|
|
206
|
-
comment?: string;
|
|
207
|
-
}): void {
|
|
208
|
-
Object.entries(tags).forEach(([key, value]) => {
|
|
209
|
-
if (value !== undefined) {
|
|
210
|
-
(this as any)[key] = value;
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// Enhanced error handling for save operations
|
|
216
|
-
saveWithValidation(): { success: boolean; errors: TagLibError[] } {
|
|
217
|
-
const errors: TagLibError[] = [];
|
|
218
|
-
|
|
219
|
-
try {
|
|
220
|
-
// Validate before saving
|
|
221
|
-
if (!this.isValid()) {
|
|
222
|
-
errors.push({
|
|
223
|
-
name: "TagLibError",
|
|
224
|
-
message: "File is not valid for writing",
|
|
225
|
-
code: "INVALID_FORMAT",
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const success = this.save();
|
|
230
|
-
return { success, errors };
|
|
231
|
-
} catch (error) {
|
|
232
|
-
errors.push({
|
|
233
|
-
name: "TagLibError",
|
|
234
|
-
message: (error as Error).message,
|
|
235
|
-
code: "PERMISSION_DENIED",
|
|
236
|
-
});
|
|
237
|
-
return { success: false, errors };
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Method stubs (would delegate to existing implementation)
|
|
242
|
-
private tag(): any {
|
|
243
|
-
throw new Error("Not implemented");
|
|
244
|
-
}
|
|
245
|
-
private setTitle(title: string): void {
|
|
246
|
-
throw new Error("Not implemented");
|
|
247
|
-
}
|
|
248
|
-
private setArtist(artist: string): void {
|
|
249
|
-
throw new Error("Not implemented");
|
|
250
|
-
}
|
|
251
|
-
private setAlbum(album: string): void {
|
|
252
|
-
throw new Error("Not implemented");
|
|
253
|
-
}
|
|
254
|
-
private save(): boolean {
|
|
255
|
-
throw new Error("Not implemented");
|
|
256
|
-
}
|
|
257
|
-
private isValid(): boolean {
|
|
258
|
-
throw new Error("Not implemented");
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Usage examples demonstrating enhanced API
|
|
264
|
-
*/
|
|
265
|
-
export function demonstrateEnhancedAPI() {
|
|
266
|
-
// Example 1: Property-based access
|
|
267
|
-
const file = new EnhancedAudioFile();
|
|
268
|
-
file.title = "New Song";
|
|
269
|
-
file.artist = "New Artist";
|
|
270
|
-
console.log(`${file.artist} - ${file.title}`);
|
|
271
|
-
|
|
272
|
-
// Example 2: Bulk tag setting
|
|
273
|
-
file.setTags({
|
|
274
|
-
title: "Song Title",
|
|
275
|
-
artist: "Artist Name",
|
|
276
|
-
album: "Album Name",
|
|
277
|
-
year: 2024,
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
// Example 3: Enhanced error handling
|
|
281
|
-
const result = file.saveWithValidation();
|
|
282
|
-
if (!result.success) {
|
|
283
|
-
result.errors.forEach((error) => {
|
|
284
|
-
console.error(`Error ${error.code}: ${error.message}`);
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// Example 4: Callback-style async operations
|
|
289
|
-
file.tagAsync((err, tags) => {
|
|
290
|
-
if (err) {
|
|
291
|
-
console.error(`Failed to read tags: ${err.message}`);
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
console.log("Tags:", tags);
|
|
295
|
-
});
|
|
296
|
-
}
|
package/src/taglib-embind.ts
DELETED
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
import type { TagLibModule, WasmModule } from "./wasm-embind.ts";
|
|
2
|
-
import type { AudioFile as AudioFileInterface, AudioProperties, FileType, PropertyMap, Tag } from "./types.ts";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Audio file wrapper using Embind API
|
|
6
|
-
*/
|
|
7
|
-
export class AudioFile implements AudioFileInterface {
|
|
8
|
-
private fileHandle: any;
|
|
9
|
-
private cachedTag: Tag | null = null;
|
|
10
|
-
private cachedAudioProperties: AudioProperties | null = null;
|
|
11
|
-
|
|
12
|
-
constructor(
|
|
13
|
-
private module: TagLibModule,
|
|
14
|
-
fileHandle: any,
|
|
15
|
-
) {
|
|
16
|
-
this.fileHandle = fileHandle;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Get file format
|
|
21
|
-
*/
|
|
22
|
-
getFormat(): FileType {
|
|
23
|
-
return this.fileHandle.getFormat() as FileType;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Get tag object for reading/writing metadata
|
|
28
|
-
*/
|
|
29
|
-
tag(): Tag {
|
|
30
|
-
if (!this.cachedTag) {
|
|
31
|
-
const tagWrapper = this.fileHandle.getTag();
|
|
32
|
-
if (!tagWrapper) {
|
|
33
|
-
throw new Error("Failed to get tag from file");
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
this.cachedTag = {
|
|
37
|
-
title: () => tagWrapper.title(),
|
|
38
|
-
artist: () => tagWrapper.artist(),
|
|
39
|
-
album: () => tagWrapper.album(),
|
|
40
|
-
comment: () => tagWrapper.comment(),
|
|
41
|
-
genre: () => tagWrapper.genre(),
|
|
42
|
-
year: () => tagWrapper.year(),
|
|
43
|
-
track: () => tagWrapper.track(),
|
|
44
|
-
|
|
45
|
-
setTitle: (value: string) => tagWrapper.setTitle(value),
|
|
46
|
-
setArtist: (value: string) => tagWrapper.setArtist(value),
|
|
47
|
-
setAlbum: (value: string) => tagWrapper.setAlbum(value),
|
|
48
|
-
setComment: (value: string) => tagWrapper.setComment(value),
|
|
49
|
-
setGenre: (value: string) => tagWrapper.setGenre(value),
|
|
50
|
-
setYear: (value: number) => tagWrapper.setYear(value),
|
|
51
|
-
setTrack: (value: number) => tagWrapper.setTrack(value),
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return this.cachedTag;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Get audio properties
|
|
60
|
-
*/
|
|
61
|
-
audioProperties(): AudioProperties | null {
|
|
62
|
-
if (!this.cachedAudioProperties) {
|
|
63
|
-
const propsWrapper = this.fileHandle.getAudioProperties();
|
|
64
|
-
if (!propsWrapper) {
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
this.cachedAudioProperties = {
|
|
69
|
-
length: propsWrapper.lengthInSeconds(),
|
|
70
|
-
lengthInMilliseconds: propsWrapper.lengthInMilliseconds(),
|
|
71
|
-
bitrate: propsWrapper.bitrate(),
|
|
72
|
-
sampleRate: propsWrapper.sampleRate(),
|
|
73
|
-
channels: propsWrapper.channels(),
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return this.cachedAudioProperties;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Get all properties as a PropertyMap
|
|
82
|
-
*/
|
|
83
|
-
properties(): PropertyMap {
|
|
84
|
-
const jsObj = this.fileHandle.getProperties();
|
|
85
|
-
const result: PropertyMap = {};
|
|
86
|
-
|
|
87
|
-
// Convert from Emscripten val to plain object
|
|
88
|
-
const keys = Object.keys(jsObj);
|
|
89
|
-
for (const key of keys) {
|
|
90
|
-
result[key] = jsObj[key];
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return result;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Set properties from a PropertyMap
|
|
98
|
-
*/
|
|
99
|
-
setProperties(properties: PropertyMap): void {
|
|
100
|
-
this.fileHandle.setProperties(properties);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Get a single property value
|
|
105
|
-
*/
|
|
106
|
-
getProperty(key: string): string | undefined {
|
|
107
|
-
const value = this.fileHandle.getProperty(key);
|
|
108
|
-
return value === "" ? undefined : value;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Set a single property value
|
|
113
|
-
*/
|
|
114
|
-
setProperty(key: string, value: string): void {
|
|
115
|
-
this.fileHandle.setProperty(key, value);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Check if this is an MP4 file
|
|
120
|
-
*/
|
|
121
|
-
isMP4(): boolean {
|
|
122
|
-
return this.fileHandle.isMP4();
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Get MP4-specific item
|
|
127
|
-
*/
|
|
128
|
-
getMP4Item(key: string): string | undefined {
|
|
129
|
-
if (!this.isMP4()) {
|
|
130
|
-
throw new Error("Not an MP4 file");
|
|
131
|
-
}
|
|
132
|
-
const value = this.fileHandle.getMP4Item(key);
|
|
133
|
-
return value === "" ? undefined : value;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Set MP4-specific item
|
|
138
|
-
*/
|
|
139
|
-
setMP4Item(key: string, value: string): void {
|
|
140
|
-
if (!this.isMP4()) {
|
|
141
|
-
throw new Error("Not an MP4 file");
|
|
142
|
-
}
|
|
143
|
-
this.fileHandle.setMP4Item(key, value);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Remove MP4-specific item
|
|
148
|
-
*/
|
|
149
|
-
removeMP4Item(key: string): void {
|
|
150
|
-
if (!this.isMP4()) {
|
|
151
|
-
throw new Error("Not an MP4 file");
|
|
152
|
-
}
|
|
153
|
-
this.fileHandle.removeMP4Item(key);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Save changes to the file
|
|
158
|
-
*/
|
|
159
|
-
save(): boolean {
|
|
160
|
-
// Clear caches since values may have changed
|
|
161
|
-
this.cachedTag = null;
|
|
162
|
-
this.cachedAudioProperties = null;
|
|
163
|
-
|
|
164
|
-
return this.fileHandle.save();
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Check if the file is valid
|
|
169
|
-
*/
|
|
170
|
-
isValid(): boolean {
|
|
171
|
-
return this.fileHandle.isValid();
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* Free resources
|
|
176
|
-
*/
|
|
177
|
-
dispose(): void {
|
|
178
|
-
if (this.fileHandle) {
|
|
179
|
-
// Embind will handle cleanup when the object goes out of scope
|
|
180
|
-
// But we can help by clearing our references
|
|
181
|
-
this.fileHandle = null;
|
|
182
|
-
this.cachedTag = null;
|
|
183
|
-
this.cachedAudioProperties = null;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Main TagLib interface using Embind
|
|
190
|
-
*/
|
|
191
|
-
export class TagLib {
|
|
192
|
-
private module: TagLibModule;
|
|
193
|
-
|
|
194
|
-
constructor(module: WasmModule) {
|
|
195
|
-
this.module = module as TagLibModule;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Open a file from a buffer
|
|
200
|
-
*/
|
|
201
|
-
async openFile(buffer: ArrayBuffer): Promise<AudioFile> {
|
|
202
|
-
// Convert ArrayBuffer to string for Embind
|
|
203
|
-
const uint8Array = new Uint8Array(buffer);
|
|
204
|
-
const binaryString = Array.from(uint8Array, byte => String.fromCharCode(byte)).join('');
|
|
205
|
-
|
|
206
|
-
// Create a new FileHandle
|
|
207
|
-
const fileHandle = this.module.createFileHandle();
|
|
208
|
-
|
|
209
|
-
// Load the buffer
|
|
210
|
-
const success = fileHandle.loadFromBuffer(binaryString);
|
|
211
|
-
if (!success) {
|
|
212
|
-
throw new Error("Failed to load file from buffer");
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return new AudioFile(this.module, fileHandle);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Get version information
|
|
220
|
-
*/
|
|
221
|
-
version(): string {
|
|
222
|
-
return "2.1.0"; // TagLib version we're using
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Create a TagLib instance
|
|
228
|
-
*/
|
|
229
|
-
export async function createTagLib(module: WasmModule): Promise<TagLib> {
|
|
230
|
-
return new TagLib(module);
|
|
231
|
-
}
|
package/src/wasm-embind.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WebAssembly module interface for Embind version
|
|
3
|
-
*/
|
|
4
|
-
export interface WasmModule {
|
|
5
|
-
// Memory access
|
|
6
|
-
HEAP8: Int8Array;
|
|
7
|
-
HEAP16: Int16Array;
|
|
8
|
-
HEAP32: Int32Array;
|
|
9
|
-
HEAPU8: Uint8Array;
|
|
10
|
-
HEAPU16: Uint16Array;
|
|
11
|
-
HEAPU32: Uint32Array;
|
|
12
|
-
HEAPF32: Float32Array;
|
|
13
|
-
HEAPF64: Float64Array;
|
|
14
|
-
|
|
15
|
-
// Runtime methods
|
|
16
|
-
allocate: (size: number, type: number) => number;
|
|
17
|
-
_malloc: (size: number) => number;
|
|
18
|
-
_free: (ptr: number) => void;
|
|
19
|
-
getValue: (ptr: number, type: string) => number;
|
|
20
|
-
setValue: (ptr: number, value: number, type: string) => void;
|
|
21
|
-
UTF8ToString: (ptr: number) => string;
|
|
22
|
-
stringToUTF8: (str: string, outPtr: number, maxBytesToWrite: number) => void;
|
|
23
|
-
lengthBytesUTF8: (str: string) => number;
|
|
24
|
-
|
|
25
|
-
// Allocation types
|
|
26
|
-
ALLOC_NORMAL: number;
|
|
27
|
-
ALLOC_STACK: number;
|
|
28
|
-
|
|
29
|
-
// Embind classes (these will be available after module loads)
|
|
30
|
-
FileHandle: any;
|
|
31
|
-
TagWrapper: any;
|
|
32
|
-
AudioPropertiesWrapper: any;
|
|
33
|
-
createFileHandle: () => any;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Extended module interface with our Embind classes
|
|
38
|
-
*/
|
|
39
|
-
export interface TagLibModule extends WasmModule {
|
|
40
|
-
// These are the actual class constructors from Embind
|
|
41
|
-
FileHandle: {
|
|
42
|
-
new(): any;
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
TagWrapper: {
|
|
46
|
-
new(tagPtr: number): any;
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
AudioPropertiesWrapper: {
|
|
50
|
-
new(propsPtr: number): any;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
// Factory function
|
|
54
|
-
createFileHandle: () => any;
|
|
55
|
-
}
|