taglib-wasm 0.2.8 → 0.3.1

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/src/workers.ts CHANGED
@@ -28,22 +28,22 @@ export class AudioFileWorkers {
28
28
  constructor(module: TagLibModule, fileId: number) {
29
29
  this.module = module;
30
30
  this.fileId = fileId;
31
- this.tagPtr = module._taglib_file_tag(fileId);
32
- this.propsPtr = module._taglib_file_audioproperties(fileId);
31
+ this.tagPtr = module._taglib_file_tag?.(fileId) || 0;
32
+ this.propsPtr = module._taglib_file_audioproperties?.(fileId) || 0;
33
33
  }
34
34
 
35
35
  /**
36
36
  * Check if the file is valid and was loaded successfully
37
37
  */
38
38
  isValid(): boolean {
39
- return this.module._taglib_file_is_valid(this.fileId) !== 0;
39
+ return this.module._taglib_file_is_valid?.(this.fileId) !== 0;
40
40
  }
41
41
 
42
42
  /**
43
43
  * Get the file format
44
44
  */
45
45
  format(): AudioFormat {
46
- const formatPtr = this.module._taglib_file_format(this.fileId);
46
+ const formatPtr = this.module._taglib_file_format?.(this.fileId) || 0;
47
47
  if (formatPtr === 0) return "MP3"; // fallback
48
48
  const formatStr = cStringToJS(this.module, formatPtr);
49
49
  return formatStr as AudioFormat;
@@ -55,13 +55,13 @@ export class AudioFileWorkers {
55
55
  tag(): Tag {
56
56
  if (this.tagPtr === 0) return {};
57
57
 
58
- const title = this.module._taglib_tag_title(this.tagPtr);
59
- const artist = this.module._taglib_tag_artist(this.tagPtr);
60
- const album = this.module._taglib_tag_album(this.tagPtr);
61
- const comment = this.module._taglib_tag_comment(this.tagPtr);
62
- const genre = this.module._taglib_tag_genre(this.tagPtr);
63
- const year = this.module._taglib_tag_year(this.tagPtr);
64
- const track = this.module._taglib_tag_track(this.tagPtr);
58
+ const title = this.module._taglib_tag_title?.(this.tagPtr) || 0;
59
+ const artist = this.module._taglib_tag_artist?.(this.tagPtr) || 0;
60
+ const album = this.module._taglib_tag_album?.(this.tagPtr) || 0;
61
+ const comment = this.module._taglib_tag_comment?.(this.tagPtr) || 0;
62
+ const genre = this.module._taglib_tag_genre?.(this.tagPtr) || 0;
63
+ const year = this.module._taglib_tag_year?.(this.tagPtr) || 0;
64
+ const track = this.module._taglib_tag_track?.(this.tagPtr) || 0;
65
65
 
66
66
  return {
67
67
  title: title ? cStringToJS(this.module, title) : undefined,
@@ -80,14 +80,14 @@ export class AudioFileWorkers {
80
80
  audioProperties(): AudioProperties | null {
81
81
  if (this.propsPtr === 0) return null;
82
82
 
83
- const length = this.module._taglib_audioproperties_length(this.propsPtr);
84
- const bitrate = this.module._taglib_audioproperties_bitrate(this.propsPtr);
85
- const sampleRate = this.module._taglib_audioproperties_samplerate(
83
+ const length = this.module._taglib_audioproperties_length?.(this.propsPtr) || 0;
84
+ const bitrate = this.module._taglib_audioproperties_bitrate?.(this.propsPtr) || 0;
85
+ const sampleRate = this.module._taglib_audioproperties_samplerate?.(
86
86
  this.propsPtr,
87
- );
88
- const channels = this.module._taglib_audioproperties_channels(
87
+ ) || 0;
88
+ const channels = this.module._taglib_audioproperties_channels?.(
89
89
  this.propsPtr,
90
- );
90
+ ) || 0;
91
91
 
92
92
  return {
93
93
  length,
@@ -104,7 +104,7 @@ export class AudioFileWorkers {
104
104
  setTitle(title: string): void {
105
105
  if (this.tagPtr === 0) return;
106
106
  const titlePtr = jsToCString(this.module, title);
107
- this.module._taglib_tag_set_title(this.tagPtr, titlePtr);
107
+ this.module._taglib_tag_set_title?.(this.tagPtr, titlePtr);
108
108
  this.module._free(titlePtr);
109
109
  }
110
110
 
@@ -114,7 +114,7 @@ export class AudioFileWorkers {
114
114
  setArtist(artist: string): void {
115
115
  if (this.tagPtr === 0) return;
116
116
  const artistPtr = jsToCString(this.module, artist);
117
- this.module._taglib_tag_set_artist(this.tagPtr, artistPtr);
117
+ this.module._taglib_tag_set_artist?.(this.tagPtr, artistPtr);
118
118
  this.module._free(artistPtr);
119
119
  }
120
120
 
@@ -124,7 +124,7 @@ export class AudioFileWorkers {
124
124
  setAlbum(album: string): void {
125
125
  if (this.tagPtr === 0) return;
126
126
  const albumPtr = jsToCString(this.module, album);
127
- this.module._taglib_tag_set_album(this.tagPtr, albumPtr);
127
+ this.module._taglib_tag_set_album?.(this.tagPtr, albumPtr);
128
128
  this.module._free(albumPtr);
129
129
  }
130
130
 
@@ -134,7 +134,7 @@ export class AudioFileWorkers {
134
134
  setComment(comment: string): void {
135
135
  if (this.tagPtr === 0) return;
136
136
  const commentPtr = jsToCString(this.module, comment);
137
- this.module._taglib_tag_set_comment(this.tagPtr, commentPtr);
137
+ this.module._taglib_tag_set_comment?.(this.tagPtr, commentPtr);
138
138
  this.module._free(commentPtr);
139
139
  }
140
140
 
@@ -144,7 +144,7 @@ export class AudioFileWorkers {
144
144
  setGenre(genre: string): void {
145
145
  if (this.tagPtr === 0) return;
146
146
  const genrePtr = jsToCString(this.module, genre);
147
- this.module._taglib_tag_set_genre(this.tagPtr, genrePtr);
147
+ this.module._taglib_tag_set_genre?.(this.tagPtr, genrePtr);
148
148
  this.module._free(genrePtr);
149
149
  }
150
150
 
@@ -153,7 +153,7 @@ export class AudioFileWorkers {
153
153
  */
154
154
  setYear(year: number): void {
155
155
  if (this.tagPtr === 0) return;
156
- this.module._taglib_tag_set_year(this.tagPtr, year);
156
+ this.module._taglib_tag_set_year?.(this.tagPtr, year);
157
157
  }
158
158
 
159
159
  /**
@@ -161,18 +161,29 @@ export class AudioFileWorkers {
161
161
  */
162
162
  setTrack(track: number): void {
163
163
  if (this.tagPtr === 0) return;
164
- this.module._taglib_tag_set_track(this.tagPtr, track);
164
+ this.module._taglib_tag_set_track?.(this.tagPtr, track);
165
165
  }
166
166
 
167
167
  /**
168
- * Save changes to the file (read-only in Workers context)
169
- * Note: This would require returning modified buffer data
168
+ * Save changes to the file
169
+ * Note: In Workers context, this saves to the in-memory buffer only
170
170
  */
171
171
  save(): boolean {
172
- console.warn("save(): File saving not implemented in Workers context");
172
+ if (this.fileId !== 0) {
173
+ return this.module._taglib_file_save?.(this.fileId) !== 0;
174
+ }
173
175
  return false;
174
176
  }
175
177
 
178
+ /**
179
+ * Get the current file buffer after modifications
180
+ * Note: This is not implemented in the Workers API
181
+ */
182
+ getFileBuffer(): Uint8Array {
183
+ console.warn("getFileBuffer() is not implemented in Workers API. Use Core API for this functionality.");
184
+ return new Uint8Array(0);
185
+ }
186
+
176
187
  /**
177
188
  * Get extended metadata with format-agnostic field names
178
189
  */
@@ -224,7 +235,7 @@ export class AudioFileWorkers {
224
235
  */
225
236
  dispose(): void {
226
237
  if (this.fileId !== 0) {
227
- this.module._taglib_file_delete(this.fileId);
238
+ this.module._taglib_file_delete?.(this.fileId);
228
239
  this.fileId = 0;
229
240
  }
230
241
  }
@@ -273,8 +284,18 @@ export class TagLibWorkers {
273
284
  }
274
285
 
275
286
  // Use Emscripten's allocate function for proper memory management
276
- const dataPtr = this.module.allocate(buffer, this.module.ALLOC_NORMAL);
287
+ let dataPtr: number;
288
+ if (this.module.allocate && this.module.ALLOC_NORMAL !== undefined) {
289
+ dataPtr = this.module.allocate(buffer, this.module.ALLOC_NORMAL);
290
+ } else {
291
+ dataPtr = this.module._malloc(buffer.length);
292
+ this.module.HEAPU8.set(buffer, dataPtr);
293
+ }
277
294
 
295
+ if (!this.module._taglib_file_new_from_buffer) {
296
+ throw new Error("Workers API requires C-style functions. Use Core API instead.");
297
+ }
298
+
278
299
  const fileId = this.module._taglib_file_new_from_buffer(
279
300
  dataPtr,
280
301
  buffer.length,
package/src/simple-jsr.ts DELETED
@@ -1,204 +0,0 @@
1
- /**
2
- * @fileoverview JSR-compatible simple API (uses taglib-jsr.ts instead of taglib.ts)
3
- */
4
-
5
- import { TagLibJSR, AudioFileJSR } from "./taglib-jsr.ts";
6
- import type { AudioProperties, Tag } from "./types.ts";
7
-
8
- // Track TagLib instance
9
- let taglib: TagLibJSR | null = null;
10
-
11
- /**
12
- * Ensure TagLib is initialized
13
- */
14
- async function ensureInitialized(): Promise<TagLibJSR> {
15
- if (!taglib) {
16
- await TagLibJSR.initialize();
17
- taglib = await TagLibJSR.getInstance();
18
- }
19
- return taglib;
20
- }
21
-
22
- /**
23
- * Read a file's data from various sources
24
- */
25
- async function readFileData(file: string | Uint8Array | ArrayBuffer | File): Promise<Uint8Array> {
26
- // Already a Uint8Array
27
- if (file instanceof Uint8Array) {
28
- return file;
29
- }
30
-
31
- // ArrayBuffer - convert to Uint8Array
32
- if (file instanceof ArrayBuffer) {
33
- return new Uint8Array(file);
34
- }
35
-
36
- // File object (browser)
37
- if (typeof File !== 'undefined' && file instanceof File) {
38
- return new Uint8Array(await file.arrayBuffer());
39
- }
40
-
41
- // String path - read from filesystem
42
- if (typeof file === 'string') {
43
- // Deno
44
- if (typeof Deno !== 'undefined') {
45
- return await Deno.readFile(file);
46
- }
47
-
48
- throw new Error('File path reading not supported in this environment');
49
- }
50
-
51
- throw new Error('Invalid file input type');
52
- }
53
-
54
- /**
55
- * Read metadata tags from an audio file
56
- */
57
- export async function readTags(file: string | Uint8Array | ArrayBuffer | File): Promise<Tag> {
58
- const taglib = await ensureInitialized();
59
- const audioData = await readFileData(file);
60
-
61
- const audioFile = await taglib.openFile(audioData.buffer as ArrayBuffer);
62
- try {
63
- if (!audioFile.isValid()) {
64
- throw new Error('Invalid audio file');
65
- }
66
-
67
- return audioFile.tag();
68
- } finally {
69
- audioFile.dispose();
70
- }
71
- }
72
-
73
- /**
74
- * Write metadata tags to an audio file
75
- */
76
- export async function writeTags(
77
- file: string | Uint8Array | ArrayBuffer | File,
78
- tags: Partial<Tag>,
79
- options?: number
80
- ): Promise<Uint8Array> {
81
- const taglib = await ensureInitialized();
82
- const audioData = await readFileData(file);
83
-
84
- const audioFile = await taglib.openFile(audioData.buffer as ArrayBuffer);
85
- try {
86
- if (!audioFile.isValid()) {
87
- throw new Error('Invalid audio file');
88
- }
89
-
90
- // Set the tags
91
- const tag = audioFile.tag();
92
- if (tags.title !== undefined) tag.setTitle(tags.title);
93
- if (tags.artist !== undefined) tag.setArtist(tags.artist);
94
- if (tags.album !== undefined) tag.setAlbum(tags.album);
95
- if (tags.comment !== undefined) tag.setComment(tags.comment);
96
- if (tags.genre !== undefined) tag.setGenre(tags.genre);
97
- if (tags.year !== undefined) tag.setYear(tags.year);
98
- if (tags.track !== undefined) tag.setTrack(tags.track);
99
-
100
- // Save changes
101
- const success = audioFile.save();
102
- if (!success) {
103
- throw new Error('Failed to save tags');
104
- }
105
-
106
- // TODO: Return the modified file data
107
- // For now, return the original data
108
- return audioData;
109
- } finally {
110
- audioFile.dispose();
111
- }
112
- }
113
-
114
- /**
115
- * Read audio properties from a file
116
- */
117
- export async function readProperties(file: string | Uint8Array | ArrayBuffer | File): Promise<AudioProperties> {
118
- const taglib = await ensureInitialized();
119
- const audioData = await readFileData(file);
120
-
121
- const audioFile = await taglib.openFile(audioData.buffer as ArrayBuffer);
122
- try {
123
- if (!audioFile.isValid()) {
124
- throw new Error('Invalid audio file');
125
- }
126
-
127
- const props = audioFile.audioProperties();
128
- if (!props) {
129
- throw new Error('Failed to read audio properties');
130
- }
131
- return props;
132
- } finally {
133
- audioFile.dispose();
134
- }
135
- }
136
-
137
- /**
138
- * Tag field constants for go-taglib compatibility
139
- */
140
- export const Title = "title";
141
- export const Artist = "artist";
142
- export const Album = "album";
143
- export const Comment = "comment";
144
- export const Genre = "genre";
145
- export const Year = "year";
146
- export const Track = "track";
147
- export const AlbumArtist = "albumartist";
148
- export const Composer = "composer";
149
- export const DiscNumber = "discnumber";
150
-
151
- /**
152
- * Check if a file is a valid audio file
153
- */
154
- export async function isValidAudioFile(file: string | Uint8Array | ArrayBuffer | File): Promise<boolean> {
155
- try {
156
- const taglib = await ensureInitialized();
157
- const audioData = await readFileData(file);
158
-
159
- const audioFile = await taglib.openFile(audioData.buffer as ArrayBuffer);
160
- const valid = audioFile.isValid();
161
- audioFile.dispose();
162
-
163
- return valid;
164
- } catch {
165
- return false;
166
- }
167
- }
168
-
169
- /**
170
- * Get the audio format of a file
171
- */
172
- export async function getFormat(file: string | Uint8Array | ArrayBuffer | File): Promise<string | undefined> {
173
- const taglib = await ensureInitialized();
174
- const audioData = await readFileData(file);
175
-
176
- const audioFile = await taglib.openFile(audioData.buffer as ArrayBuffer);
177
- try {
178
- if (!audioFile.isValid()) {
179
- return undefined;
180
- }
181
-
182
- return audioFile.getFormat();
183
- } finally {
184
- audioFile.dispose();
185
- }
186
- }
187
-
188
- /**
189
- * Clear all tags from a file
190
- */
191
- export async function clearTags(file: string | Uint8Array | ArrayBuffer | File): Promise<Uint8Array> {
192
- return writeTags(file, {
193
- title: "",
194
- artist: "",
195
- album: "",
196
- comment: "",
197
- genre: "",
198
- year: 0,
199
- track: 0,
200
- });
201
- }
202
-
203
- // Type exports for convenience
204
- export type { Tag, AudioProperties } from "./types.ts";
package/src/taglib-jsr.ts DELETED
@@ -1,48 +0,0 @@
1
- /**
2
- * @fileoverview JSR-compatible TagLib implementation
3
- *
4
- * This version uses direct WASM loading without Emscripten's JS file
5
- * to be compatible with JSR publishing requirements.
6
- */
7
-
8
- import { AudioFileImpl, TagLib as TagLibBase, createTagLib } from "./taglib.ts";
9
- import type { AudioFile, Tag, AudioProperties, FileType, PropertyMap } from "./taglib.ts";
10
- import type { TagLibConfig } from "./types.ts";
11
- import type { WasmModule } from "./wasm-jsr.ts";
12
-
13
- // Re-export types and implementations
14
- export { AudioFileImpl as AudioFileJSR } from "./taglib.ts";
15
- export type { Tag, AudioProperties, FileType, PropertyMap } from "./taglib.ts";
16
-
17
- /**
18
- * JSR-compatible TagLib singleton for WASM module management
19
- */
20
- export class TagLibJSR extends TagLibBase {
21
- private static instance: TagLibJSR | null = null;
22
- private static initialized = false;
23
-
24
- static async getInstance(): Promise<TagLibJSR> {
25
- if (!TagLibJSR.instance) {
26
- // For JSR, we need to load the module directly without Node.js dependencies
27
- // This is a placeholder - the actual implementation would need to load WASM directly
28
- throw new Error("JSR version requires direct WASM loading implementation. Please use the NPM version for now.");
29
- }
30
- return TagLibJSR.instance;
31
- }
32
-
33
- static async initialize(config?: TagLibConfig): Promise<void> {
34
- if (!TagLibJSR.initialized) {
35
- await TagLibJSR.getInstance();
36
- }
37
- }
38
-
39
- /**
40
- * Open a file from a buffer (JSR-compatible version)
41
- */
42
- override async openFile(buffer: ArrayBuffer): Promise<AudioFile> {
43
- return super.openFile(buffer);
44
- }
45
- }
46
-
47
- // Export alias for compatibility
48
- export { TagLibJSR as TagLib };
package/src/wasm-jsr.ts DELETED
@@ -1,13 +0,0 @@
1
- /**
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";