audio-channel-queue 1.11.0 → 1.12.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/README.md +48 -25
- package/dist/core.js +3 -3
- package/dist/errors.d.ts +4 -4
- package/dist/errors.js +12 -11
- package/dist/index.d.ts +2 -2
- package/dist/index.js +5 -5
- package/dist/info.d.ts +20 -15
- package/dist/info.js +20 -15
- package/dist/types.d.ts +66 -24
- package/dist/types.js +17 -4
- package/dist/volume.d.ts +0 -14
- package/dist/volume.js +2 -19
- package/package.json +1 -1
- package/src/core.ts +3 -3
- package/src/errors.ts +14 -15
- package/src/index.ts +11 -5
- package/src/info.ts +20 -15
- package/src/types.ts +67 -24
- package/src/volume.ts +1 -23
package/README.md
CHANGED
|
@@ -75,8 +75,8 @@ Install this package by running either of these commands (typescript packages ar
|
|
|
75
75
|
```typescript
|
|
76
76
|
// Add an audio file to the queue and start playing it automatically.
|
|
77
77
|
queueAudio(audioUrl, channelNumber?, options?);
|
|
78
|
-
queueAudio('hello.mp3'); // Add to default channel 0
|
|
79
|
-
queueAudio('laser.mp3', 1, { loop: true, volume: 0.8 }); // Add to channel 1 with options
|
|
78
|
+
await queueAudio('hello.mp3'); // Add to default channel 0
|
|
79
|
+
await queueAudio('laser.mp3', 1, { loop: true, volume: 0.8 }); // Add to channel 1 with options
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
|
|
@@ -84,8 +84,8 @@ queueAudio('laser.mp3', 1, { loop: true, volume: 0.8 }); // Add to channel 1 wit
|
|
|
84
84
|
```typescript
|
|
85
85
|
// Add a file to the front of the queue (plays after current audio finishes).
|
|
86
86
|
queueAudioPriority(audioUrl, channelNumber?, options?);
|
|
87
|
-
queueAudioPriority('urgent.mp3'); // Add to front of default channel 0
|
|
88
|
-
queueAudioPriority('announcement.mp3', 1, { volume: 1.0 }); // Add to front of channel 1
|
|
87
|
+
await queueAudioPriority('urgent.mp3'); // Add to front of default channel 0
|
|
88
|
+
await queueAudioPriority('announcement.mp3', 1, { volume: 1.0 }); // Add to front of channel 1
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
|
|
@@ -93,8 +93,8 @@ queueAudioPriority('announcement.mp3', 1, { volume: 1.0 }); // Add to front of c
|
|
|
93
93
|
```typescript
|
|
94
94
|
// Stop the current audio and automatically start playing the next one in queue.
|
|
95
95
|
stopCurrentAudioInChannel(channelNumber?);
|
|
96
|
-
stopCurrentAudioInChannel(); // Stop current audio in default channel (0)
|
|
97
|
-
stopCurrentAudioInChannel(2); // Stop current audio in channel 2
|
|
96
|
+
await stopCurrentAudioInChannel(); // Stop current audio in default channel (0)
|
|
97
|
+
await stopCurrentAudioInChannel(2); // Stop current audio in channel 2
|
|
98
98
|
```
|
|
99
99
|
|
|
100
100
|
|
|
@@ -102,14 +102,14 @@ stopCurrentAudioInChannel(2); // Stop current audio in channel 2
|
|
|
102
102
|
```typescript
|
|
103
103
|
// Stop all audio in a channel and remove all enqueued files.
|
|
104
104
|
stopAllAudioInChannel(channelNumber?);
|
|
105
|
-
stopAllAudioInChannel(); // Stop and clear all audio in default channel (0)
|
|
106
|
-
stopAllAudioInChannel(1); // Stop and clear all audio in channel 1
|
|
105
|
+
await stopAllAudioInChannel(); // Stop and clear all audio in default channel (0)
|
|
106
|
+
await stopAllAudioInChannel(1); // Stop and clear all audio in channel 1
|
|
107
107
|
```
|
|
108
108
|
|
|
109
109
|
### Stop All Audio
|
|
110
110
|
```typescript
|
|
111
111
|
// Stop all audio in all channels and remove all enqueued files.
|
|
112
|
-
stopAllAudio();
|
|
112
|
+
await stopAllAudio();
|
|
113
113
|
```
|
|
114
114
|
|
|
115
115
|
## 🔄 Advanced Queue Manipulation:
|
|
@@ -118,32 +118,32 @@ stopAllAudio();
|
|
|
118
118
|
```typescript
|
|
119
119
|
// Remove a specific item from the queue by its position (cannot remove currently playing item at index 0).
|
|
120
120
|
removeQueuedItem(queuedSlotNumber, channelNumber?);
|
|
121
|
-
const result = removeQueuedItem(2); // Remove item at index 2 from default channel (0)
|
|
122
|
-
const result = removeQueuedItem(1, 1); // Remove item at index 1 from channel 1
|
|
121
|
+
const result = await removeQueuedItem(2); // Remove item at index 2 from default channel (0)
|
|
122
|
+
const result = await removeQueuedItem(1, 1); // Remove item at index 1 from channel 1
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
### Reorder Queue Items
|
|
126
126
|
```typescript
|
|
127
127
|
// Move a queue item from one position to another (cannot move currently playing item at index 0).
|
|
128
128
|
reorderQueue(currentQueuedSlotNumber, newQueuedSlotNumber, channelNumber?);
|
|
129
|
-
const result = reorderQueue(3, 1); // Move item from index 3 to index 1 in default channel (0)
|
|
130
|
-
const result = reorderQueue(2, 4, 1); // Move item from index 2 to index 4 in channel 1
|
|
129
|
+
const result = await reorderQueue(3, 1); // Move item from index 3 to index 1 in default channel (0)
|
|
130
|
+
const result = await reorderQueue(2, 4, 1); // Move item from index 2 to index 4 in channel 1
|
|
131
131
|
```
|
|
132
132
|
|
|
133
133
|
### Clear Queue After Current
|
|
134
134
|
```typescript
|
|
135
135
|
// Remove all items from the queue except the currently playing audio.
|
|
136
136
|
clearQueueAfterCurrent(channelNumber?);
|
|
137
|
-
const result = clearQueueAfterCurrent(); // Clear queue after current in default channel (0)
|
|
138
|
-
const result = clearQueueAfterCurrent(2); // Clear queue after current in channel 2
|
|
137
|
+
const result = await clearQueueAfterCurrent(); // Clear queue after current in default channel (0)
|
|
138
|
+
const result = await clearQueueAfterCurrent(2); // Clear queue after current in channel 2
|
|
139
139
|
```
|
|
140
140
|
|
|
141
141
|
### Swap Queue Items
|
|
142
142
|
```typescript
|
|
143
143
|
// Swap the positions of two items in the queue (cannot involve currently playing item at index 0).
|
|
144
144
|
swapQueueItems(firstQueuedSlotNumber, secondQueuedSlotNumber, channelNumber?);
|
|
145
|
-
const result = swapQueueItems(1, 3); // Swap items at index 1 and 3 in default channel (0)
|
|
146
|
-
const result = swapQueueItems(2, 4, 1); // Swap items at index 2 and 4 in channel 1
|
|
145
|
+
const result = await swapQueueItems(1, 3); // Swap items at index 1 and 3 in default channel (0)
|
|
146
|
+
const result = await swapQueueItems(2, 4, 1); // Swap items at index 2 and 4 in channel 1
|
|
147
147
|
```
|
|
148
148
|
|
|
149
149
|
### Get Queue Item Info
|
|
@@ -177,8 +177,8 @@ interface QueueManipulationResult {
|
|
|
177
177
|
```typescript
|
|
178
178
|
// Set the volume for a specific channel (0-1 range).
|
|
179
179
|
setChannelVolume(channelNumber, volume);
|
|
180
|
-
setChannelVolume(0, 0.5); // Set channel 0 to 50% volume
|
|
181
|
-
setChannelVolume(1, 0.8); // Set channel 1 to 80% volume
|
|
180
|
+
await setChannelVolume(0, 0.5); // Set channel 0 to 50% volume
|
|
181
|
+
await setChannelVolume(1, 0.8); // Set channel 1 to 80% volume
|
|
182
182
|
```
|
|
183
183
|
|
|
184
184
|
### Get Channel Volume
|
|
@@ -193,8 +193,8 @@ console.log(`Channel volume: ${(getChannelVolume(2) * 100).toFixed(0)}%`); // Ge
|
|
|
193
193
|
```typescript
|
|
194
194
|
// Set the same volume level for all channels.
|
|
195
195
|
setAllChannelsVolume(volume);
|
|
196
|
-
setAllChannelsVolume(0.6); // Set all channels to 60% volume
|
|
197
|
-
setAllChannelsVolume(0.0); // Mute all channels
|
|
196
|
+
await setAllChannelsVolume(0.6); // Set all channels to 60% volume
|
|
197
|
+
await setAllChannelsVolume(0.0); // Mute all channels
|
|
198
198
|
```
|
|
199
199
|
|
|
200
200
|
### Volume Ducking (Background Audio Reduction)
|
|
@@ -356,6 +356,13 @@ onQueueChange(channelNumber, callback);
|
|
|
356
356
|
onQueueChange(0, (snapshot) => updateQueueDisplay(snapshot)); // Update UI on queue changes
|
|
357
357
|
```
|
|
358
358
|
|
|
359
|
+
```typescript
|
|
360
|
+
// Unsubscribe from queue change events (removes ALL queue change callbacks for the channel)
|
|
361
|
+
offQueueChange(channelNumber?);
|
|
362
|
+
offQueueChange(); // Stop receiving all queue change notifications for default channel (0)
|
|
363
|
+
offQueueChange(1); // Stop receiving all queue change notifications for channel 1
|
|
364
|
+
```
|
|
365
|
+
|
|
359
366
|
```typescript
|
|
360
367
|
// Subscribe to audio start events.
|
|
361
368
|
onAudioStart(channelNumber, callback);
|
|
@@ -364,8 +371,9 @@ onAudioStart(0, (info) => console.log(`Started: ${info.fileName}`)); // Log audi
|
|
|
364
371
|
|
|
365
372
|
```typescript
|
|
366
373
|
// Unsubscribe from audio start events (removes ALL start callbacks for the channel)
|
|
367
|
-
offAudioStart(channelNumber);
|
|
368
|
-
offAudioStart(
|
|
374
|
+
offAudioStart(channelNumber?);
|
|
375
|
+
offAudioStart(); // Stop receiving all start notifications for default channel (0)
|
|
376
|
+
offAudioStart(1); // Stop receiving all start notifications for channel 1
|
|
369
377
|
```
|
|
370
378
|
|
|
371
379
|
```typescript
|
|
@@ -376,8 +384,9 @@ onAudioComplete(0, (info) => logPlayHistory(info)); // Track completed audio
|
|
|
376
384
|
|
|
377
385
|
```typescript
|
|
378
386
|
// Unsubscribe from audio completion events (removes ALL complete callbacks for the channel)
|
|
379
|
-
offAudioComplete(channelNumber);
|
|
380
|
-
offAudioComplete(
|
|
387
|
+
offAudioComplete(channelNumber?);
|
|
388
|
+
offAudioComplete(); // Stop receiving all completion notifications for default channel (0)
|
|
389
|
+
offAudioComplete(1); // Stop receiving all completion notifications for channel 1
|
|
381
390
|
```
|
|
382
391
|
|
|
383
392
|
```typescript
|
|
@@ -386,12 +395,26 @@ onAudioPause(channelNumber, callback);
|
|
|
386
395
|
onAudioPause(0, (info) => showPauseIcon(info)); // Show pause state in UI
|
|
387
396
|
```
|
|
388
397
|
|
|
398
|
+
```typescript
|
|
399
|
+
// Unsubscribe from audio pause events (removes ALL pause callbacks for the channel)
|
|
400
|
+
offAudioPause(channelNumber?);
|
|
401
|
+
offAudioPause(); // Stop receiving all pause notifications for default channel (0)
|
|
402
|
+
offAudioPause(1); // Stop receiving all pause notifications for channel 1
|
|
403
|
+
```
|
|
404
|
+
|
|
389
405
|
```typescript
|
|
390
406
|
// Subscribe to audio resume events.
|
|
391
407
|
onAudioResume(channelNumber, callback);
|
|
392
408
|
onAudioResume(0, (info) => showPlayIcon(info)); // Show play state in UI
|
|
393
409
|
```
|
|
394
410
|
|
|
411
|
+
```typescript
|
|
412
|
+
// Unsubscribe from audio resume events (removes ALL resume callbacks for the channel)
|
|
413
|
+
offAudioResume(channelNumber?);
|
|
414
|
+
offAudioResume(); // Stop receiving all resume notifications for default channel (0)
|
|
415
|
+
offAudioResume(1); // Stop receiving all resume notifications for channel 1
|
|
416
|
+
```
|
|
417
|
+
|
|
395
418
|
### TypeScript Support
|
|
396
419
|
If you cannot import audio files into your app, you may need a `custom.d.ts` file in the root directory. An example of one is shown here:
|
|
397
420
|
|
package/dist/core.js
CHANGED
|
@@ -260,9 +260,9 @@ const queueAudio = (audioUrl_1, ...args_1) => __awaiter(void 0, [audioUrl_1, ...
|
|
|
260
260
|
channel.maxQueueSize = options.maxQueueSize;
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
|
-
// Handle
|
|
264
|
-
const shouldAddToFront =
|
|
265
|
-
// Add to queue based on
|
|
263
|
+
// Handle addToFront option
|
|
264
|
+
const shouldAddToFront = options === null || options === void 0 ? void 0 : options.addToFront;
|
|
265
|
+
// Add to queue based on addToFront option
|
|
266
266
|
if (shouldAddToFront && channel.queue.length > 0) {
|
|
267
267
|
// Insert after currently playing track (at index 1)
|
|
268
268
|
channel.queue.splice(1, 0, audio);
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Error handling, retry logic, and recovery mechanisms for the audio-channel-queue package
|
|
3
3
|
*/
|
|
4
|
-
import { AudioErrorInfo, AudioErrorCallback, RetryConfig, ErrorRecoveryOptions, ExtendedAudioQueueChannel } from './types';
|
|
4
|
+
import { AudioErrorInfo, AudioErrorCallback, AudioErrorType, RetryConfig, ErrorRecoveryOptions, ExtendedAudioQueueChannel } from './types';
|
|
5
5
|
/**
|
|
6
6
|
* Subscribes to audio error events for a specific channel
|
|
7
7
|
* @param channelNumber - The channel number to listen to (defaults to 0)
|
|
@@ -61,10 +61,10 @@ export declare const getRetryConfig: () => RetryConfig;
|
|
|
61
61
|
* ```typescript
|
|
62
62
|
* setErrorRecovery({
|
|
63
63
|
* autoRetry: true,
|
|
64
|
-
*
|
|
64
|
+
* fallbackToNextTrack: true,
|
|
65
65
|
* logErrorsToAnalytics: true,
|
|
66
66
|
* preserveQueueOnError: true,
|
|
67
|
-
*
|
|
67
|
+
* showUserFeedback: true
|
|
68
68
|
* });
|
|
69
69
|
* ```
|
|
70
70
|
*/
|
|
@@ -109,7 +109,7 @@ export declare const emitAudioError: (channelNumber: number, errorInfo: AudioErr
|
|
|
109
109
|
* @returns The categorized error type
|
|
110
110
|
* @internal
|
|
111
111
|
*/
|
|
112
|
-
export declare const categorizeError: (error: Error, audio: HTMLAudioElement) =>
|
|
112
|
+
export declare const categorizeError: (error: Error, audio: HTMLAudioElement) => AudioErrorType;
|
|
113
113
|
/**
|
|
114
114
|
* Sets up comprehensive error handling for an audio element
|
|
115
115
|
* @param audio - The audio element to set up error handling for
|
package/dist/errors.js
CHANGED
|
@@ -43,6 +43,7 @@ let globalRetryConfig = {
|
|
|
43
43
|
baseDelay: 1000,
|
|
44
44
|
enabled: true,
|
|
45
45
|
exponentialBackoff: true,
|
|
46
|
+
fallbackUrls: [],
|
|
46
47
|
maxRetries: 3,
|
|
47
48
|
skipOnFailure: false,
|
|
48
49
|
timeoutMs: 10000
|
|
@@ -161,10 +162,10 @@ exports.getRetryConfig = getRetryConfig;
|
|
|
161
162
|
* ```typescript
|
|
162
163
|
* setErrorRecovery({
|
|
163
164
|
* autoRetry: true,
|
|
164
|
-
*
|
|
165
|
+
* fallbackToNextTrack: true,
|
|
165
166
|
* logErrorsToAnalytics: true,
|
|
166
167
|
* preserveQueueOnError: true,
|
|
167
|
-
*
|
|
168
|
+
* showUserFeedback: true
|
|
168
169
|
* });
|
|
169
170
|
* ```
|
|
170
171
|
*/
|
|
@@ -263,34 +264,34 @@ exports.emitAudioError = emitAudioError;
|
|
|
263
264
|
const categorizeError = (error, audio) => {
|
|
264
265
|
const errorMessage = error.message.toLowerCase();
|
|
265
266
|
if (errorMessage.includes('network') || errorMessage.includes('fetch')) {
|
|
266
|
-
return
|
|
267
|
+
return types_1.AudioErrorType.Network;
|
|
267
268
|
}
|
|
268
269
|
// Check for unsupported format first (more specific than decode)
|
|
269
270
|
if (errorMessage.includes('not supported') ||
|
|
270
271
|
errorMessage.includes('unsupported') ||
|
|
271
272
|
errorMessage.includes('format not supported')) {
|
|
272
|
-
return
|
|
273
|
+
return types_1.AudioErrorType.Unsupported;
|
|
273
274
|
}
|
|
274
275
|
if (errorMessage.includes('decode') || errorMessage.includes('format')) {
|
|
275
|
-
return
|
|
276
|
+
return types_1.AudioErrorType.Decode;
|
|
276
277
|
}
|
|
277
278
|
if (errorMessage.includes('permission') || errorMessage.includes('blocked')) {
|
|
278
|
-
return
|
|
279
|
+
return types_1.AudioErrorType.Permission;
|
|
279
280
|
}
|
|
280
281
|
if (errorMessage.includes('abort')) {
|
|
281
|
-
return
|
|
282
|
+
return types_1.AudioErrorType.Abort;
|
|
282
283
|
}
|
|
283
284
|
if (errorMessage.includes('timeout')) {
|
|
284
|
-
return
|
|
285
|
+
return types_1.AudioErrorType.Timeout;
|
|
285
286
|
}
|
|
286
287
|
// Check audio element network state for more context
|
|
287
288
|
if (audio.networkState === HTMLMediaElement.NETWORK_NO_SOURCE) {
|
|
288
|
-
return
|
|
289
|
+
return types_1.AudioErrorType.Network;
|
|
289
290
|
}
|
|
290
291
|
if (audio.networkState === HTMLMediaElement.NETWORK_LOADING) {
|
|
291
|
-
return
|
|
292
|
+
return types_1.AudioErrorType.Timeout;
|
|
292
293
|
}
|
|
293
|
-
return
|
|
294
|
+
return types_1.AudioErrorType.Unknown;
|
|
294
295
|
};
|
|
295
296
|
exports.categorizeError = categorizeError;
|
|
296
297
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -7,9 +7,9 @@ export { queueAudio, queueAudioPriority, stopCurrentAudioInChannel, stopAllAudio
|
|
|
7
7
|
export { clearQueueAfterCurrent, getQueueItemInfo, getQueueLength, removeQueuedItem, reorderQueue, swapQueueItems } from './queue-manipulation';
|
|
8
8
|
export { getErrorRecovery, getRetryConfig, offAudioError, onAudioError, retryFailedAudio, setErrorRecovery, setRetryConfig } from './errors';
|
|
9
9
|
export { getAllChannelsPauseState, isChannelPaused, pauseAllChannels, pauseAllWithFade, pauseChannel, pauseWithFade, resumeAllChannels, resumeAllWithFade, resumeChannel, resumeWithFade, togglePauseAllChannels, togglePauseAllWithFade, togglePauseChannel, togglePauseWithFade } from './pause';
|
|
10
|
-
export {
|
|
10
|
+
export { cancelAllVolumeTransitions, cancelVolumeTransition, clearVolumeDucking, getAllChannelsVolume, getChannelVolume, getFadeConfig, setAllChannelsVolume, setChannelVolume, setVolumeDucking, transitionVolume } from './volume';
|
|
11
11
|
export { getAllChannelsInfo, getCurrentAudioInfo, getQueueSnapshot, offAudioComplete, offAudioPause, offAudioProgress, offAudioResume, offAudioStart, offQueueChange, onAudioComplete, onAudioPause, onAudioProgress, onAudioResume, onAudioStart, onQueueChange } from './info';
|
|
12
12
|
export { audioChannels } from './info';
|
|
13
13
|
export { cleanWebpackFilename, createQueueSnapshot, extractFileName, getAudioInfoFromElement, sanitizeForDisplay, validateAudioUrl } from './utils';
|
|
14
14
|
export type { AudioCompleteCallback, AudioCompleteInfo, AudioErrorCallback, AudioErrorInfo, AudioInfo, AudioPauseCallback, AudioQueueOptions, AudioResumeCallback, AudioStartCallback, AudioStartInfo, ChannelFadeState, ErrorRecoveryOptions, ExtendedAudioQueueChannel, FadeConfig, ProgressCallback, QueueChangeCallback, QueueItem, QueueManipulationResult, QueueSnapshot, RetryConfig, VolumeConfig, QueueConfig } from './types';
|
|
15
|
-
export { EasingType, FadeType, MAX_CHANNELS, TimerType, GLOBAL_PROGRESS_KEY } from './types';
|
|
15
|
+
export { AudioErrorType, EasingType, FadeType, MAX_CHANNELS, TimerType, GLOBAL_PROGRESS_KEY } from './types';
|
package/dist/index.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* volume management with ducking, progress tracking, and comprehensive event system
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.
|
|
9
|
-
exports.GLOBAL_PROGRESS_KEY = exports.TimerType = exports.MAX_CHANNELS = exports.FadeType = exports.EasingType = exports.validateAudioUrl = exports.sanitizeForDisplay = exports.getAudioInfoFromElement = exports.extractFileName = exports.createQueueSnapshot = exports.cleanWebpackFilename = exports.audioChannels = exports.onQueueChange = exports.onAudioStart = exports.onAudioResume = exports.onAudioProgress = exports.onAudioPause = exports.onAudioComplete = exports.offQueueChange = exports.offAudioStart = exports.offAudioResume = exports.offAudioProgress = exports.offAudioPause = exports.offAudioComplete = exports.getQueueSnapshot =
|
|
8
|
+
exports.getCurrentAudioInfo = exports.getAllChannelsInfo = exports.transitionVolume = exports.setVolumeDucking = exports.setChannelVolume = exports.setAllChannelsVolume = exports.getFadeConfig = exports.getChannelVolume = exports.getAllChannelsVolume = exports.clearVolumeDucking = exports.cancelVolumeTransition = exports.cancelAllVolumeTransitions = exports.togglePauseWithFade = exports.togglePauseChannel = exports.togglePauseAllWithFade = exports.togglePauseAllChannels = exports.resumeWithFade = exports.resumeChannel = exports.resumeAllWithFade = exports.resumeAllChannels = exports.pauseWithFade = exports.pauseChannel = exports.pauseAllWithFade = exports.pauseAllChannels = exports.isChannelPaused = exports.getAllChannelsPauseState = exports.setRetryConfig = exports.setErrorRecovery = exports.retryFailedAudio = exports.onAudioError = exports.offAudioError = exports.getRetryConfig = exports.getErrorRecovery = exports.swapQueueItems = exports.reorderQueue = exports.removeQueuedItem = exports.getQueueLength = exports.getQueueItemInfo = exports.clearQueueAfterCurrent = exports.setChannelQueueLimit = exports.getQueueConfig = exports.setQueueConfig = exports.destroyAllChannels = exports.destroyChannel = exports.playAudioQueue = exports.stopAllAudio = exports.stopAllAudioInChannel = exports.stopCurrentAudioInChannel = exports.queueAudioPriority = exports.queueAudio = void 0;
|
|
9
|
+
exports.GLOBAL_PROGRESS_KEY = exports.TimerType = exports.MAX_CHANNELS = exports.FadeType = exports.EasingType = exports.AudioErrorType = exports.validateAudioUrl = exports.sanitizeForDisplay = exports.getAudioInfoFromElement = exports.extractFileName = exports.createQueueSnapshot = exports.cleanWebpackFilename = exports.audioChannels = exports.onQueueChange = exports.onAudioStart = exports.onAudioResume = exports.onAudioProgress = exports.onAudioPause = exports.onAudioComplete = exports.offQueueChange = exports.offAudioStart = exports.offAudioResume = exports.offAudioProgress = exports.offAudioPause = exports.offAudioComplete = exports.getQueueSnapshot = void 0;
|
|
10
10
|
// Core queue management functions
|
|
11
11
|
var core_1 = require("./core");
|
|
12
12
|
Object.defineProperty(exports, "queueAudio", { enumerable: true, get: function () { return core_1.queueAudio; } });
|
|
@@ -55,8 +55,9 @@ Object.defineProperty(exports, "togglePauseChannel", { enumerable: true, get: fu
|
|
|
55
55
|
Object.defineProperty(exports, "togglePauseWithFade", { enumerable: true, get: function () { return pause_1.togglePauseWithFade; } });
|
|
56
56
|
// Volume control and ducking functions
|
|
57
57
|
var volume_1 = require("./volume");
|
|
58
|
+
Object.defineProperty(exports, "cancelAllVolumeTransitions", { enumerable: true, get: function () { return volume_1.cancelAllVolumeTransitions; } });
|
|
59
|
+
Object.defineProperty(exports, "cancelVolumeTransition", { enumerable: true, get: function () { return volume_1.cancelVolumeTransition; } });
|
|
58
60
|
Object.defineProperty(exports, "clearVolumeDucking", { enumerable: true, get: function () { return volume_1.clearVolumeDucking; } });
|
|
59
|
-
Object.defineProperty(exports, "fadeVolume", { enumerable: true, get: function () { return volume_1.fadeVolume; } });
|
|
60
61
|
Object.defineProperty(exports, "getAllChannelsVolume", { enumerable: true, get: function () { return volume_1.getAllChannelsVolume; } });
|
|
61
62
|
Object.defineProperty(exports, "getChannelVolume", { enumerable: true, get: function () { return volume_1.getChannelVolume; } });
|
|
62
63
|
Object.defineProperty(exports, "getFadeConfig", { enumerable: true, get: function () { return volume_1.getFadeConfig; } });
|
|
@@ -64,8 +65,6 @@ Object.defineProperty(exports, "setAllChannelsVolume", { enumerable: true, get:
|
|
|
64
65
|
Object.defineProperty(exports, "setChannelVolume", { enumerable: true, get: function () { return volume_1.setChannelVolume; } });
|
|
65
66
|
Object.defineProperty(exports, "setVolumeDucking", { enumerable: true, get: function () { return volume_1.setVolumeDucking; } });
|
|
66
67
|
Object.defineProperty(exports, "transitionVolume", { enumerable: true, get: function () { return volume_1.transitionVolume; } });
|
|
67
|
-
Object.defineProperty(exports, "cancelVolumeTransition", { enumerable: true, get: function () { return volume_1.cancelVolumeTransition; } });
|
|
68
|
-
Object.defineProperty(exports, "cancelAllVolumeTransitions", { enumerable: true, get: function () { return volume_1.cancelAllVolumeTransitions; } });
|
|
69
68
|
// Audio information and progress tracking functions
|
|
70
69
|
var info_1 = require("./info");
|
|
71
70
|
Object.defineProperty(exports, "getAllChannelsInfo", { enumerable: true, get: function () { return info_1.getAllChannelsInfo; } });
|
|
@@ -96,6 +95,7 @@ Object.defineProperty(exports, "sanitizeForDisplay", { enumerable: true, get: fu
|
|
|
96
95
|
Object.defineProperty(exports, "validateAudioUrl", { enumerable: true, get: function () { return utils_1.validateAudioUrl; } });
|
|
97
96
|
// Enums and constants
|
|
98
97
|
var types_1 = require("./types");
|
|
98
|
+
Object.defineProperty(exports, "AudioErrorType", { enumerable: true, get: function () { return types_1.AudioErrorType; } });
|
|
99
99
|
Object.defineProperty(exports, "EasingType", { enumerable: true, get: function () { return types_1.EasingType; } });
|
|
100
100
|
Object.defineProperty(exports, "FadeType", { enumerable: true, get: function () { return types_1.FadeType; } });
|
|
101
101
|
Object.defineProperty(exports, "MAX_CHANNELS", { enumerable: true, get: function () { return types_1.MAX_CHANNELS; } });
|
package/dist/info.d.ts
CHANGED
|
@@ -116,13 +116,14 @@ export declare function offAudioProgress(channelNumber?: number): void;
|
|
|
116
116
|
export declare const onQueueChange: (channelNumber: number, callback: QueueChangeCallback) => void;
|
|
117
117
|
/**
|
|
118
118
|
* Removes queue change listeners for a specific channel
|
|
119
|
-
* @param channelNumber - The channel number
|
|
119
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
120
120
|
* @example
|
|
121
121
|
* ```typescript
|
|
122
|
-
* offQueueChange(
|
|
122
|
+
* offQueueChange(); // Stop receiving queue change notifications for default channel (0)
|
|
123
|
+
* offQueueChange(1); // Stop receiving queue change notifications for channel 1
|
|
123
124
|
* ```
|
|
124
125
|
*/
|
|
125
|
-
export declare const offQueueChange: (channelNumber
|
|
126
|
+
export declare const offQueueChange: (channelNumber?: number) => void;
|
|
126
127
|
/**
|
|
127
128
|
* Subscribes to audio start events for a specific channel
|
|
128
129
|
* @param channelNumber - The channel number to monitor
|
|
@@ -183,37 +184,41 @@ export declare const onAudioPause: (channelNumber: number, callback: AudioPauseC
|
|
|
183
184
|
export declare const onAudioResume: (channelNumber: number, callback: AudioResumeCallback) => void;
|
|
184
185
|
/**
|
|
185
186
|
* Removes pause event listeners for a specific channel
|
|
186
|
-
* @param channelNumber - The channel number
|
|
187
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
187
188
|
* @example
|
|
188
189
|
* ```typescript
|
|
189
|
-
* offAudioPause(
|
|
190
|
+
* offAudioPause(); // Stop receiving pause notifications for default channel (0)
|
|
191
|
+
* offAudioPause(1); // Stop receiving pause notifications for channel 1
|
|
190
192
|
* ```
|
|
191
193
|
*/
|
|
192
|
-
export declare const offAudioPause: (channelNumber
|
|
194
|
+
export declare const offAudioPause: (channelNumber?: number) => void;
|
|
193
195
|
/**
|
|
194
196
|
* Removes resume event listeners for a specific channel
|
|
195
|
-
* @param channelNumber - The channel number
|
|
197
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
196
198
|
* @example
|
|
197
199
|
* ```typescript
|
|
198
|
-
* offAudioResume(
|
|
200
|
+
* offAudioResume(); // Stop receiving resume notifications for default channel (0)
|
|
201
|
+
* offAudioResume(1); // Stop receiving resume notifications for channel 1
|
|
199
202
|
* ```
|
|
200
203
|
*/
|
|
201
|
-
export declare const offAudioResume: (channelNumber
|
|
204
|
+
export declare const offAudioResume: (channelNumber?: number) => void;
|
|
202
205
|
/**
|
|
203
206
|
* Removes audio start event listeners for a specific channel
|
|
204
|
-
* @param channelNumber - The channel number
|
|
207
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
205
208
|
* @example
|
|
206
209
|
* ```typescript
|
|
207
|
-
* offAudioStart(
|
|
210
|
+
* offAudioStart(); // Stop receiving start notifications for default channel (0)
|
|
211
|
+
* offAudioStart(1); // Stop receiving start notifications for channel 1
|
|
208
212
|
* ```
|
|
209
213
|
*/
|
|
210
|
-
export declare const offAudioStart: (channelNumber
|
|
214
|
+
export declare const offAudioStart: (channelNumber?: number) => void;
|
|
211
215
|
/**
|
|
212
216
|
* Removes audio complete event listeners for a specific channel
|
|
213
|
-
* @param channelNumber - The channel number
|
|
217
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
214
218
|
* @example
|
|
215
219
|
* ```typescript
|
|
216
|
-
* offAudioComplete(
|
|
220
|
+
* offAudioComplete(); // Stop receiving completion notifications for default channel (0)
|
|
221
|
+
* offAudioComplete(1); // Stop receiving completion notifications for channel 1
|
|
217
222
|
* ```
|
|
218
223
|
*/
|
|
219
|
-
export declare const offAudioComplete: (channelNumber
|
|
224
|
+
export declare const offAudioComplete: (channelNumber?: number) => void;
|
package/dist/info.js
CHANGED
|
@@ -301,13 +301,14 @@ const onQueueChange = (channelNumber, callback) => {
|
|
|
301
301
|
exports.onQueueChange = onQueueChange;
|
|
302
302
|
/**
|
|
303
303
|
* Removes queue change listeners for a specific channel
|
|
304
|
-
* @param channelNumber - The channel number
|
|
304
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
305
305
|
* @example
|
|
306
306
|
* ```typescript
|
|
307
|
-
* offQueueChange(
|
|
307
|
+
* offQueueChange(); // Stop receiving queue change notifications for default channel (0)
|
|
308
|
+
* offQueueChange(1); // Stop receiving queue change notifications for channel 1
|
|
308
309
|
* ```
|
|
309
310
|
*/
|
|
310
|
-
const offQueueChange = (channelNumber) => {
|
|
311
|
+
const offQueueChange = (channelNumber = 0) => {
|
|
311
312
|
const channel = exports.audioChannels[channelNumber];
|
|
312
313
|
if (!(channel === null || channel === void 0 ? void 0 : channel.queueChangeCallbacks))
|
|
313
314
|
return;
|
|
@@ -462,13 +463,14 @@ const onAudioResume = (channelNumber, callback) => {
|
|
|
462
463
|
exports.onAudioResume = onAudioResume;
|
|
463
464
|
/**
|
|
464
465
|
* Removes pause event listeners for a specific channel
|
|
465
|
-
* @param channelNumber - The channel number
|
|
466
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
466
467
|
* @example
|
|
467
468
|
* ```typescript
|
|
468
|
-
* offAudioPause(
|
|
469
|
+
* offAudioPause(); // Stop receiving pause notifications for default channel (0)
|
|
470
|
+
* offAudioPause(1); // Stop receiving pause notifications for channel 1
|
|
469
471
|
* ```
|
|
470
472
|
*/
|
|
471
|
-
const offAudioPause = (channelNumber) => {
|
|
473
|
+
const offAudioPause = (channelNumber = 0) => {
|
|
472
474
|
const channel = exports.audioChannels[channelNumber];
|
|
473
475
|
if (!(channel === null || channel === void 0 ? void 0 : channel.audioPauseCallbacks))
|
|
474
476
|
return;
|
|
@@ -477,13 +479,14 @@ const offAudioPause = (channelNumber) => {
|
|
|
477
479
|
exports.offAudioPause = offAudioPause;
|
|
478
480
|
/**
|
|
479
481
|
* Removes resume event listeners for a specific channel
|
|
480
|
-
* @param channelNumber - The channel number
|
|
482
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
481
483
|
* @example
|
|
482
484
|
* ```typescript
|
|
483
|
-
* offAudioResume(
|
|
485
|
+
* offAudioResume(); // Stop receiving resume notifications for default channel (0)
|
|
486
|
+
* offAudioResume(1); // Stop receiving resume notifications for channel 1
|
|
484
487
|
* ```
|
|
485
488
|
*/
|
|
486
|
-
const offAudioResume = (channelNumber) => {
|
|
489
|
+
const offAudioResume = (channelNumber = 0) => {
|
|
487
490
|
const channel = exports.audioChannels[channelNumber];
|
|
488
491
|
if (!(channel === null || channel === void 0 ? void 0 : channel.audioResumeCallbacks))
|
|
489
492
|
return;
|
|
@@ -492,13 +495,14 @@ const offAudioResume = (channelNumber) => {
|
|
|
492
495
|
exports.offAudioResume = offAudioResume;
|
|
493
496
|
/**
|
|
494
497
|
* Removes audio start event listeners for a specific channel
|
|
495
|
-
* @param channelNumber - The channel number
|
|
498
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
496
499
|
* @example
|
|
497
500
|
* ```typescript
|
|
498
|
-
* offAudioStart(
|
|
501
|
+
* offAudioStart(); // Stop receiving start notifications for default channel (0)
|
|
502
|
+
* offAudioStart(1); // Stop receiving start notifications for channel 1
|
|
499
503
|
* ```
|
|
500
504
|
*/
|
|
501
|
-
const offAudioStart = (channelNumber) => {
|
|
505
|
+
const offAudioStart = (channelNumber = 0) => {
|
|
502
506
|
const channel = exports.audioChannels[channelNumber];
|
|
503
507
|
if (!(channel === null || channel === void 0 ? void 0 : channel.audioStartCallbacks))
|
|
504
508
|
return;
|
|
@@ -507,13 +511,14 @@ const offAudioStart = (channelNumber) => {
|
|
|
507
511
|
exports.offAudioStart = offAudioStart;
|
|
508
512
|
/**
|
|
509
513
|
* Removes audio complete event listeners for a specific channel
|
|
510
|
-
* @param channelNumber - The channel number
|
|
514
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
511
515
|
* @example
|
|
512
516
|
* ```typescript
|
|
513
|
-
* offAudioComplete(
|
|
517
|
+
* offAudioComplete(); // Stop receiving completion notifications for default channel (0)
|
|
518
|
+
* offAudioComplete(1); // Stop receiving completion notifications for channel 1
|
|
514
519
|
* ```
|
|
515
520
|
*/
|
|
516
|
-
const offAudioComplete = (channelNumber) => {
|
|
521
|
+
const offAudioComplete = (channelNumber = 0) => {
|
|
517
522
|
const channel = exports.audioChannels[channelNumber];
|
|
518
523
|
if (!(channel === null || channel === void 0 ? void 0 : channel.audioCompleteCallbacks))
|
|
519
524
|
return;
|
package/dist/types.d.ts
CHANGED
|
@@ -24,15 +24,15 @@ export interface AudioQueueChannel {
|
|
|
24
24
|
* Volume ducking configuration for channels
|
|
25
25
|
*/
|
|
26
26
|
export interface VolumeConfig {
|
|
27
|
+
/** Duration in milliseconds for volume duck transition (defaults to 250ms) */
|
|
28
|
+
duckTransitionDuration?: number;
|
|
29
|
+
/** Volume level for all other channels when priority channel is active (0-1) */
|
|
30
|
+
duckingVolume: number;
|
|
27
31
|
/** The channel number that should have priority */
|
|
28
32
|
priorityChannel: number;
|
|
29
33
|
/** Volume level for the priority channel (0-1) */
|
|
30
34
|
priorityVolume: number;
|
|
31
|
-
/**
|
|
32
|
-
duckingVolume: number;
|
|
33
|
-
/** Duration in milliseconds for volume duck transition (defaults to 250ms) */
|
|
34
|
-
duckTransitionDuration?: number;
|
|
35
|
-
/** Duration in milliseconds for volume restore transition (defaults to 500ms) */
|
|
35
|
+
/** Duration in milliseconds for volume restore transition (defaults to 250ms) */
|
|
36
36
|
restoreTransitionDuration?: number;
|
|
37
37
|
/** Easing function for volume transitions (defaults to 'ease-out') */
|
|
38
38
|
transitionEasing?: EasingType;
|
|
@@ -47,8 +47,6 @@ export interface AudioQueueOptions {
|
|
|
47
47
|
loop?: boolean;
|
|
48
48
|
/** Maximum number of items allowed in the queue (defaults to unlimited) */
|
|
49
49
|
maxQueueSize?: number;
|
|
50
|
-
/** @deprecated Use addToFront instead. Legacy support for priority queuing */
|
|
51
|
-
priority?: boolean;
|
|
52
50
|
/** Volume level for this specific audio (0-1) */
|
|
53
51
|
volume?: number;
|
|
54
52
|
}
|
|
@@ -192,67 +190,111 @@ export type AudioPauseCallback = (channelNumber: number, audioInfo: AudioInfo) =
|
|
|
192
190
|
*/
|
|
193
191
|
export type AudioResumeCallback = (channelNumber: number, audioInfo: AudioInfo) => void;
|
|
194
192
|
/**
|
|
195
|
-
*
|
|
193
|
+
* Types of audio errors that can occur during playback
|
|
194
|
+
*/
|
|
195
|
+
export declare enum AudioErrorType {
|
|
196
|
+
Abort = "abort",
|
|
197
|
+
Decode = "decode",
|
|
198
|
+
Network = "network",
|
|
199
|
+
Permission = "permission",
|
|
200
|
+
Timeout = "timeout",
|
|
201
|
+
Unknown = "unknown",
|
|
202
|
+
Unsupported = "unsupported"
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Information about an audio error that occurred during playback or loading
|
|
196
206
|
*/
|
|
197
207
|
export interface AudioErrorInfo {
|
|
208
|
+
/** Channel number where the error occurred */
|
|
198
209
|
channelNumber: number;
|
|
199
|
-
|
|
200
|
-
fileName: string;
|
|
210
|
+
/** The actual error object that was thrown */
|
|
201
211
|
error: Error;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
212
|
+
/** Categorized type of error for handling different scenarios */
|
|
213
|
+
errorType: AudioErrorType;
|
|
214
|
+
/** Extracted filename from the source URL */
|
|
215
|
+
fileName: string;
|
|
216
|
+
/** Number of audio files remaining in the queue after this error */
|
|
205
217
|
remainingInQueue: number;
|
|
218
|
+
/** Current retry attempt number (if retrying is enabled) */
|
|
219
|
+
retryAttempt?: number;
|
|
220
|
+
/** Audio file source URL that failed */
|
|
221
|
+
src: string;
|
|
222
|
+
/** Unix timestamp when the error occurred */
|
|
223
|
+
timestamp: number;
|
|
206
224
|
}
|
|
207
225
|
/**
|
|
208
226
|
* Configuration for automatic retry behavior when audio fails to load or play
|
|
209
227
|
*/
|
|
210
228
|
export interface RetryConfig {
|
|
211
|
-
|
|
212
|
-
maxRetries: number;
|
|
229
|
+
/** Initial delay in milliseconds before first retry attempt */
|
|
213
230
|
baseDelay: number;
|
|
231
|
+
/** Whether automatic retries are enabled for this channel */
|
|
232
|
+
enabled: boolean;
|
|
233
|
+
/** Whether to use exponential backoff (doubling delay each retry) */
|
|
214
234
|
exponentialBackoff: boolean;
|
|
215
|
-
|
|
216
|
-
fallbackUrls
|
|
235
|
+
/** Alternative URLs to try if the primary source fails */
|
|
236
|
+
fallbackUrls: string[];
|
|
237
|
+
/** Maximum number of retry attempts before giving up */
|
|
238
|
+
maxRetries: number;
|
|
239
|
+
/** Whether to skip to next track in queue if all retries fail */
|
|
217
240
|
skipOnFailure: boolean;
|
|
241
|
+
/** Timeout in milliseconds for each individual retry attempt */
|
|
242
|
+
timeoutMs: number;
|
|
218
243
|
}
|
|
219
244
|
/**
|
|
220
|
-
* Configuration options for error recovery mechanisms
|
|
245
|
+
* Configuration options for error recovery mechanisms across the audio system
|
|
221
246
|
*/
|
|
222
247
|
export interface ErrorRecoveryOptions {
|
|
248
|
+
/** Whether to automatically retry failed audio loads/plays */
|
|
223
249
|
autoRetry: boolean;
|
|
224
|
-
|
|
250
|
+
/** Whether to automatically skip to next track when current fails */
|
|
251
|
+
fallbackToNextTrack: boolean;
|
|
252
|
+
/** Whether to send error data to analytics systems */
|
|
225
253
|
logErrorsToAnalytics: boolean;
|
|
254
|
+
/** Whether to maintain queue integrity when errors occur */
|
|
226
255
|
preserveQueueOnError: boolean;
|
|
227
|
-
|
|
256
|
+
/** Whether to display user-visible error feedback */
|
|
257
|
+
showUserFeedback: boolean;
|
|
228
258
|
}
|
|
229
259
|
/**
|
|
230
260
|
* Callback function type for audio error events
|
|
231
261
|
*/
|
|
232
262
|
export type AudioErrorCallback = (errorInfo: AudioErrorInfo) => void;
|
|
233
263
|
/**
|
|
234
|
-
* Extended audio channel with queue management and
|
|
264
|
+
* Extended audio channel with comprehensive queue management, callback support, and state tracking
|
|
235
265
|
*/
|
|
236
266
|
export interface ExtendedAudioQueueChannel {
|
|
267
|
+
/** Set of callbacks triggered when audio completes playback */
|
|
237
268
|
audioCompleteCallbacks: Set<AudioCompleteCallback>;
|
|
269
|
+
/** Set of callbacks triggered when audio errors occur */
|
|
238
270
|
audioErrorCallbacks: Set<AudioErrorCallback>;
|
|
271
|
+
/** Set of callbacks triggered when audio is paused */
|
|
239
272
|
audioPauseCallbacks: Set<AudioPauseCallback>;
|
|
273
|
+
/** Set of callbacks triggered when audio is resumed */
|
|
240
274
|
audioResumeCallbacks: Set<AudioResumeCallback>;
|
|
275
|
+
/** Set of callbacks triggered when audio starts playing */
|
|
241
276
|
audioStartCallbacks: Set<AudioStartCallback>;
|
|
277
|
+
/** Current fade state if pause/resume with fade is active */
|
|
242
278
|
fadeState?: ChannelFadeState;
|
|
279
|
+
/** Whether the channel is currently paused */
|
|
243
280
|
isPaused: boolean;
|
|
244
281
|
/** Active operation lock to prevent race conditions */
|
|
245
282
|
isLocked?: boolean;
|
|
246
283
|
/** Maximum allowed queue size for this channel */
|
|
247
284
|
maxQueueSize?: number;
|
|
285
|
+
/** Map of progress callbacks keyed by audio element or global symbol */
|
|
248
286
|
progressCallbacks: Map<HTMLAudioElement | typeof GLOBAL_PROGRESS_KEY, Set<ProgressCallback>>;
|
|
287
|
+
/** Array of HTMLAudioElement objects in the queue */
|
|
249
288
|
queue: HTMLAudioElement[];
|
|
289
|
+
/** Set of callbacks triggered when the queue changes */
|
|
250
290
|
queueChangeCallbacks: Set<QueueChangeCallback>;
|
|
291
|
+
/** Retry configuration for failed audio loads/plays */
|
|
251
292
|
retryConfig?: RetryConfig;
|
|
293
|
+
/** Current volume level for the channel (0-1) */
|
|
252
294
|
volume: number;
|
|
253
295
|
}
|
|
254
296
|
/**
|
|
255
|
-
* Easing function types for volume transitions
|
|
297
|
+
* Easing function types for smooth volume transitions and animations
|
|
256
298
|
*/
|
|
257
299
|
export declare enum EasingType {
|
|
258
300
|
Linear = "linear",
|
|
@@ -261,7 +303,7 @@ export declare enum EasingType {
|
|
|
261
303
|
EaseInOut = "ease-in-out"
|
|
262
304
|
}
|
|
263
305
|
/**
|
|
264
|
-
*
|
|
306
|
+
* Predefined fade types for pause/resume operations with different transition characteristics
|
|
265
307
|
*/
|
|
266
308
|
export declare enum FadeType {
|
|
267
309
|
Linear = "linear",
|
|
@@ -269,7 +311,7 @@ export declare enum FadeType {
|
|
|
269
311
|
Dramatic = "dramatic"
|
|
270
312
|
}
|
|
271
313
|
/**
|
|
272
|
-
* Timer types for volume transitions to ensure proper cleanup
|
|
314
|
+
* Timer implementation types used for volume transitions to ensure proper cleanup
|
|
273
315
|
*/
|
|
274
316
|
export declare enum TimerType {
|
|
275
317
|
RequestAnimationFrame = "raf",
|
package/dist/types.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @fileoverview Type definitions for the audio-channel-queue package
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.TimerType = exports.FadeType = exports.EasingType = exports.GLOBAL_PROGRESS_KEY = exports.MAX_CHANNELS = void 0;
|
|
6
|
+
exports.TimerType = exports.FadeType = exports.EasingType = exports.AudioErrorType = exports.GLOBAL_PROGRESS_KEY = exports.MAX_CHANNELS = void 0;
|
|
7
7
|
/**
|
|
8
8
|
* Maximum number of audio channels allowed to prevent memory exhaustion
|
|
9
9
|
*/
|
|
@@ -14,7 +14,20 @@ exports.MAX_CHANNELS = 64;
|
|
|
14
14
|
*/
|
|
15
15
|
exports.GLOBAL_PROGRESS_KEY = Symbol('global-progress-callbacks');
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Types of audio errors that can occur during playback
|
|
18
|
+
*/
|
|
19
|
+
var AudioErrorType;
|
|
20
|
+
(function (AudioErrorType) {
|
|
21
|
+
AudioErrorType["Abort"] = "abort";
|
|
22
|
+
AudioErrorType["Decode"] = "decode";
|
|
23
|
+
AudioErrorType["Network"] = "network";
|
|
24
|
+
AudioErrorType["Permission"] = "permission";
|
|
25
|
+
AudioErrorType["Timeout"] = "timeout";
|
|
26
|
+
AudioErrorType["Unknown"] = "unknown";
|
|
27
|
+
AudioErrorType["Unsupported"] = "unsupported";
|
|
28
|
+
})(AudioErrorType || (exports.AudioErrorType = AudioErrorType = {}));
|
|
29
|
+
/**
|
|
30
|
+
* Easing function types for smooth volume transitions and animations
|
|
18
31
|
*/
|
|
19
32
|
var EasingType;
|
|
20
33
|
(function (EasingType) {
|
|
@@ -24,7 +37,7 @@ var EasingType;
|
|
|
24
37
|
EasingType["EaseInOut"] = "ease-in-out";
|
|
25
38
|
})(EasingType || (exports.EasingType = EasingType = {}));
|
|
26
39
|
/**
|
|
27
|
-
*
|
|
40
|
+
* Predefined fade types for pause/resume operations with different transition characteristics
|
|
28
41
|
*/
|
|
29
42
|
var FadeType;
|
|
30
43
|
(function (FadeType) {
|
|
@@ -33,7 +46,7 @@ var FadeType;
|
|
|
33
46
|
FadeType["Dramatic"] = "dramatic";
|
|
34
47
|
})(FadeType || (exports.FadeType = FadeType = {}));
|
|
35
48
|
/**
|
|
36
|
-
* Timer types for volume transitions to ensure proper cleanup
|
|
49
|
+
* Timer implementation types used for volume transitions to ensure proper cleanup
|
|
37
50
|
*/
|
|
38
51
|
var TimerType;
|
|
39
52
|
(function (TimerType) {
|
package/dist/volume.d.ts
CHANGED
|
@@ -103,20 +103,6 @@ export declare const clearVolumeDucking: () => void;
|
|
|
103
103
|
* @internal
|
|
104
104
|
*/
|
|
105
105
|
export declare const applyVolumeDucking: (activeChannelNumber: number) => Promise<void>;
|
|
106
|
-
/**
|
|
107
|
-
* Fades the volume for a specific channel over time (alias for transitionVolume with improved naming)
|
|
108
|
-
* @param channelNumber - The channel number to fade
|
|
109
|
-
* @param targetVolume - Target volume level (0-1)
|
|
110
|
-
* @param duration - Fade duration in milliseconds (defaults to 250)
|
|
111
|
-
* @param easing - Easing function type (defaults to 'ease-out')
|
|
112
|
-
* @returns Promise that resolves when fade completes
|
|
113
|
-
* @example
|
|
114
|
-
* ```typescript
|
|
115
|
-
* await fadeVolume(0, 0, 800, 'ease-in'); // Fade out over 800ms
|
|
116
|
-
* await fadeVolume(0, 1, 600, 'ease-out'); // Fade in over 600ms
|
|
117
|
-
* ```
|
|
118
|
-
*/
|
|
119
|
-
export declare const fadeVolume: (channelNumber: number, targetVolume: number, duration?: number, easing?: EasingType) => Promise<void>;
|
|
120
106
|
/**
|
|
121
107
|
* Restores normal volume levels when priority channel queue becomes empty
|
|
122
108
|
* @param stoppedChannelNumber - The channel that just stopped playing
|
package/dist/volume.js
CHANGED
|
@@ -12,7 +12,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
12
12
|
});
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.cancelAllVolumeTransitions = exports.cancelVolumeTransition = exports.restoreVolumeLevels = exports.
|
|
15
|
+
exports.cancelAllVolumeTransitions = exports.cancelVolumeTransition = exports.restoreVolumeLevels = exports.applyVolumeDucking = exports.clearVolumeDucking = exports.setVolumeDucking = exports.setAllChannelsVolume = exports.getAllChannelsVolume = exports.getChannelVolume = exports.setChannelVolume = exports.transitionVolume = exports.getFadeConfig = void 0;
|
|
16
16
|
const types_1 = require("./types");
|
|
17
17
|
const info_1 = require("./info");
|
|
18
18
|
// Store active volume transitions to handle interruptions
|
|
@@ -346,23 +346,6 @@ const applyVolumeDucking = (activeChannelNumber) => __awaiter(void 0, void 0, vo
|
|
|
346
346
|
yield Promise.all(transitionPromises);
|
|
347
347
|
});
|
|
348
348
|
exports.applyVolumeDucking = applyVolumeDucking;
|
|
349
|
-
/**
|
|
350
|
-
* Fades the volume for a specific channel over time (alias for transitionVolume with improved naming)
|
|
351
|
-
* @param channelNumber - The channel number to fade
|
|
352
|
-
* @param targetVolume - Target volume level (0-1)
|
|
353
|
-
* @param duration - Fade duration in milliseconds (defaults to 250)
|
|
354
|
-
* @param easing - Easing function type (defaults to 'ease-out')
|
|
355
|
-
* @returns Promise that resolves when fade completes
|
|
356
|
-
* @example
|
|
357
|
-
* ```typescript
|
|
358
|
-
* await fadeVolume(0, 0, 800, 'ease-in'); // Fade out over 800ms
|
|
359
|
-
* await fadeVolume(0, 1, 600, 'ease-out'); // Fade in over 600ms
|
|
360
|
-
* ```
|
|
361
|
-
*/
|
|
362
|
-
const fadeVolume = (channelNumber_1, targetVolume_1, ...args_1) => __awaiter(void 0, [channelNumber_1, targetVolume_1, ...args_1], void 0, function* (channelNumber, targetVolume, duration = 250, easing = types_1.EasingType.EaseOut) {
|
|
363
|
-
return (0, exports.transitionVolume)(channelNumber, targetVolume, duration, easing);
|
|
364
|
-
});
|
|
365
|
-
exports.fadeVolume = fadeVolume;
|
|
366
349
|
/**
|
|
367
350
|
* Restores normal volume levels when priority channel queue becomes empty
|
|
368
351
|
* @param stoppedChannelNumber - The channel that just stopped playing
|
|
@@ -388,7 +371,7 @@ const restoreVolumeLevels = (stoppedChannelNumber) => __awaiter(void 0, void 0,
|
|
|
388
371
|
return;
|
|
389
372
|
}
|
|
390
373
|
// Restore this channel to its desired volume
|
|
391
|
-
const duration = (_a = config.restoreTransitionDuration) !== null && _a !== void 0 ? _a :
|
|
374
|
+
const duration = (_a = config.restoreTransitionDuration) !== null && _a !== void 0 ? _a : 250;
|
|
392
375
|
const easing = (_b = config.transitionEasing) !== null && _b !== void 0 ? _b : types_1.EasingType.EaseOut;
|
|
393
376
|
const targetVolume = (_c = channel.volume) !== null && _c !== void 0 ? _c : 1.0;
|
|
394
377
|
// Only transition the audio element volume, keep channel.volume as the desired volume
|
package/package.json
CHANGED
package/src/core.ts
CHANGED
|
@@ -300,10 +300,10 @@ export const queueAudio = async (
|
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
302
|
|
|
303
|
-
// Handle
|
|
304
|
-
const shouldAddToFront = options?.addToFront
|
|
303
|
+
// Handle addToFront option
|
|
304
|
+
const shouldAddToFront = options?.addToFront;
|
|
305
305
|
|
|
306
|
-
// Add to queue based on
|
|
306
|
+
// Add to queue based on addToFront option
|
|
307
307
|
if (shouldAddToFront && channel.queue.length > 0) {
|
|
308
308
|
// Insert after currently playing track (at index 1)
|
|
309
309
|
channel.queue.splice(1, 0, audio);
|
package/src/errors.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import {
|
|
6
6
|
AudioErrorInfo,
|
|
7
7
|
AudioErrorCallback,
|
|
8
|
+
AudioErrorType,
|
|
8
9
|
RetryConfig,
|
|
9
10
|
ErrorRecoveryOptions,
|
|
10
11
|
ExtendedAudioQueueChannel,
|
|
@@ -17,6 +18,7 @@ let globalRetryConfig: RetryConfig = {
|
|
|
17
18
|
baseDelay: 1000,
|
|
18
19
|
enabled: true,
|
|
19
20
|
exponentialBackoff: true,
|
|
21
|
+
fallbackUrls: [],
|
|
20
22
|
maxRetries: 3,
|
|
21
23
|
skipOnFailure: false,
|
|
22
24
|
timeoutMs: 10000
|
|
@@ -143,10 +145,10 @@ export const getRetryConfig = (): RetryConfig => {
|
|
|
143
145
|
* ```typescript
|
|
144
146
|
* setErrorRecovery({
|
|
145
147
|
* autoRetry: true,
|
|
146
|
-
*
|
|
148
|
+
* fallbackToNextTrack: true,
|
|
147
149
|
* logErrorsToAnalytics: true,
|
|
148
150
|
* preserveQueueOnError: true,
|
|
149
|
-
*
|
|
151
|
+
* showUserFeedback: true
|
|
150
152
|
* });
|
|
151
153
|
* ```
|
|
152
154
|
*/
|
|
@@ -247,14 +249,11 @@ export const emitAudioError = (
|
|
|
247
249
|
* @returns The categorized error type
|
|
248
250
|
* @internal
|
|
249
251
|
*/
|
|
250
|
-
export const categorizeError = (
|
|
251
|
-
error: Error,
|
|
252
|
-
audio: HTMLAudioElement
|
|
253
|
-
): AudioErrorInfo['errorType'] => {
|
|
252
|
+
export const categorizeError = (error: Error, audio: HTMLAudioElement): AudioErrorType => {
|
|
254
253
|
const errorMessage = error.message.toLowerCase();
|
|
255
254
|
|
|
256
255
|
if (errorMessage.includes('network') || errorMessage.includes('fetch')) {
|
|
257
|
-
return
|
|
256
|
+
return AudioErrorType.Network;
|
|
258
257
|
}
|
|
259
258
|
|
|
260
259
|
// Check for unsupported format first (more specific than decode)
|
|
@@ -263,35 +262,35 @@ export const categorizeError = (
|
|
|
263
262
|
errorMessage.includes('unsupported') ||
|
|
264
263
|
errorMessage.includes('format not supported')
|
|
265
264
|
) {
|
|
266
|
-
return
|
|
265
|
+
return AudioErrorType.Unsupported;
|
|
267
266
|
}
|
|
268
267
|
|
|
269
268
|
if (errorMessage.includes('decode') || errorMessage.includes('format')) {
|
|
270
|
-
return
|
|
269
|
+
return AudioErrorType.Decode;
|
|
271
270
|
}
|
|
272
271
|
|
|
273
272
|
if (errorMessage.includes('permission') || errorMessage.includes('blocked')) {
|
|
274
|
-
return
|
|
273
|
+
return AudioErrorType.Permission;
|
|
275
274
|
}
|
|
276
275
|
|
|
277
276
|
if (errorMessage.includes('abort')) {
|
|
278
|
-
return
|
|
277
|
+
return AudioErrorType.Abort;
|
|
279
278
|
}
|
|
280
279
|
|
|
281
280
|
if (errorMessage.includes('timeout')) {
|
|
282
|
-
return
|
|
281
|
+
return AudioErrorType.Timeout;
|
|
283
282
|
}
|
|
284
283
|
|
|
285
284
|
// Check audio element network state for more context
|
|
286
285
|
if (audio.networkState === HTMLMediaElement.NETWORK_NO_SOURCE) {
|
|
287
|
-
return
|
|
286
|
+
return AudioErrorType.Network;
|
|
288
287
|
}
|
|
289
288
|
|
|
290
289
|
if (audio.networkState === HTMLMediaElement.NETWORK_LOADING) {
|
|
291
|
-
return
|
|
290
|
+
return AudioErrorType.Timeout;
|
|
292
291
|
}
|
|
293
292
|
|
|
294
|
-
return
|
|
293
|
+
return AudioErrorType.Unknown;
|
|
295
294
|
};
|
|
296
295
|
|
|
297
296
|
/**
|
package/src/index.ts
CHANGED
|
@@ -60,17 +60,16 @@ export {
|
|
|
60
60
|
|
|
61
61
|
// Volume control and ducking functions
|
|
62
62
|
export {
|
|
63
|
+
cancelAllVolumeTransitions,
|
|
64
|
+
cancelVolumeTransition,
|
|
63
65
|
clearVolumeDucking,
|
|
64
|
-
fadeVolume,
|
|
65
66
|
getAllChannelsVolume,
|
|
66
67
|
getChannelVolume,
|
|
67
68
|
getFadeConfig,
|
|
68
69
|
setAllChannelsVolume,
|
|
69
70
|
setChannelVolume,
|
|
70
71
|
setVolumeDucking,
|
|
71
|
-
transitionVolume
|
|
72
|
-
cancelVolumeTransition,
|
|
73
|
-
cancelAllVolumeTransitions
|
|
72
|
+
transitionVolume
|
|
74
73
|
} from './volume';
|
|
75
74
|
|
|
76
75
|
// Audio information and progress tracking functions
|
|
@@ -132,4 +131,11 @@ export type {
|
|
|
132
131
|
} from './types';
|
|
133
132
|
|
|
134
133
|
// Enums and constants
|
|
135
|
-
export {
|
|
134
|
+
export {
|
|
135
|
+
AudioErrorType,
|
|
136
|
+
EasingType,
|
|
137
|
+
FadeType,
|
|
138
|
+
MAX_CHANNELS,
|
|
139
|
+
TimerType,
|
|
140
|
+
GLOBAL_PROGRESS_KEY
|
|
141
|
+
} from './types';
|
package/src/info.ts
CHANGED
|
@@ -351,13 +351,14 @@ export const onQueueChange = (channelNumber: number, callback: QueueChangeCallba
|
|
|
351
351
|
|
|
352
352
|
/**
|
|
353
353
|
* Removes queue change listeners for a specific channel
|
|
354
|
-
* @param channelNumber - The channel number
|
|
354
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
355
355
|
* @example
|
|
356
356
|
* ```typescript
|
|
357
|
-
* offQueueChange(
|
|
357
|
+
* offQueueChange(); // Stop receiving queue change notifications for default channel (0)
|
|
358
|
+
* offQueueChange(1); // Stop receiving queue change notifications for channel 1
|
|
358
359
|
* ```
|
|
359
360
|
*/
|
|
360
|
-
export const offQueueChange = (channelNumber: number): void => {
|
|
361
|
+
export const offQueueChange = (channelNumber: number = 0): void => {
|
|
361
362
|
const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
|
|
362
363
|
if (!channel?.queueChangeCallbacks) return;
|
|
363
364
|
|
|
@@ -524,13 +525,14 @@ export const onAudioResume = (channelNumber: number, callback: AudioResumeCallba
|
|
|
524
525
|
|
|
525
526
|
/**
|
|
526
527
|
* Removes pause event listeners for a specific channel
|
|
527
|
-
* @param channelNumber - The channel number
|
|
528
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
528
529
|
* @example
|
|
529
530
|
* ```typescript
|
|
530
|
-
* offAudioPause(
|
|
531
|
+
* offAudioPause(); // Stop receiving pause notifications for default channel (0)
|
|
532
|
+
* offAudioPause(1); // Stop receiving pause notifications for channel 1
|
|
531
533
|
* ```
|
|
532
534
|
*/
|
|
533
|
-
export const offAudioPause = (channelNumber: number): void => {
|
|
535
|
+
export const offAudioPause = (channelNumber: number = 0): void => {
|
|
534
536
|
const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
|
|
535
537
|
if (!channel?.audioPauseCallbacks) return;
|
|
536
538
|
|
|
@@ -539,13 +541,14 @@ export const offAudioPause = (channelNumber: number): void => {
|
|
|
539
541
|
|
|
540
542
|
/**
|
|
541
543
|
* Removes resume event listeners for a specific channel
|
|
542
|
-
* @param channelNumber - The channel number
|
|
544
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
543
545
|
* @example
|
|
544
546
|
* ```typescript
|
|
545
|
-
* offAudioResume(
|
|
547
|
+
* offAudioResume(); // Stop receiving resume notifications for default channel (0)
|
|
548
|
+
* offAudioResume(1); // Stop receiving resume notifications for channel 1
|
|
546
549
|
* ```
|
|
547
550
|
*/
|
|
548
|
-
export const offAudioResume = (channelNumber: number): void => {
|
|
551
|
+
export const offAudioResume = (channelNumber: number = 0): void => {
|
|
549
552
|
const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
|
|
550
553
|
if (!channel?.audioResumeCallbacks) return;
|
|
551
554
|
|
|
@@ -554,13 +557,14 @@ export const offAudioResume = (channelNumber: number): void => {
|
|
|
554
557
|
|
|
555
558
|
/**
|
|
556
559
|
* Removes audio start event listeners for a specific channel
|
|
557
|
-
* @param channelNumber - The channel number
|
|
560
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
558
561
|
* @example
|
|
559
562
|
* ```typescript
|
|
560
|
-
* offAudioStart(
|
|
563
|
+
* offAudioStart(); // Stop receiving start notifications for default channel (0)
|
|
564
|
+
* offAudioStart(1); // Stop receiving start notifications for channel 1
|
|
561
565
|
* ```
|
|
562
566
|
*/
|
|
563
|
-
export const offAudioStart = (channelNumber: number): void => {
|
|
567
|
+
export const offAudioStart = (channelNumber: number = 0): void => {
|
|
564
568
|
const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
|
|
565
569
|
if (!channel?.audioStartCallbacks) return;
|
|
566
570
|
|
|
@@ -569,13 +573,14 @@ export const offAudioStart = (channelNumber: number): void => {
|
|
|
569
573
|
|
|
570
574
|
/**
|
|
571
575
|
* Removes audio complete event listeners for a specific channel
|
|
572
|
-
* @param channelNumber - The channel number
|
|
576
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
573
577
|
* @example
|
|
574
578
|
* ```typescript
|
|
575
|
-
* offAudioComplete(
|
|
579
|
+
* offAudioComplete(); // Stop receiving completion notifications for default channel (0)
|
|
580
|
+
* offAudioComplete(1); // Stop receiving completion notifications for channel 1
|
|
576
581
|
* ```
|
|
577
582
|
*/
|
|
578
|
-
export const offAudioComplete = (channelNumber: number): void => {
|
|
583
|
+
export const offAudioComplete = (channelNumber: number = 0): void => {
|
|
579
584
|
const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
|
|
580
585
|
if (!channel?.audioCompleteCallbacks) return;
|
|
581
586
|
|
package/src/types.ts
CHANGED
|
@@ -29,15 +29,15 @@ export interface AudioQueueChannel {
|
|
|
29
29
|
* Volume ducking configuration for channels
|
|
30
30
|
*/
|
|
31
31
|
export interface VolumeConfig {
|
|
32
|
+
/** Duration in milliseconds for volume duck transition (defaults to 250ms) */
|
|
33
|
+
duckTransitionDuration?: number;
|
|
34
|
+
/** Volume level for all other channels when priority channel is active (0-1) */
|
|
35
|
+
duckingVolume: number;
|
|
32
36
|
/** The channel number that should have priority */
|
|
33
37
|
priorityChannel: number;
|
|
34
38
|
/** Volume level for the priority channel (0-1) */
|
|
35
39
|
priorityVolume: number;
|
|
36
|
-
/**
|
|
37
|
-
duckingVolume: number;
|
|
38
|
-
/** Duration in milliseconds for volume duck transition (defaults to 250ms) */
|
|
39
|
-
duckTransitionDuration?: number;
|
|
40
|
-
/** Duration in milliseconds for volume restore transition (defaults to 500ms) */
|
|
40
|
+
/** Duration in milliseconds for volume restore transition (defaults to 250ms) */
|
|
41
41
|
restoreTransitionDuration?: number;
|
|
42
42
|
/** Easing function for volume transitions (defaults to 'ease-out') */
|
|
43
43
|
transitionEasing?: EasingType;
|
|
@@ -53,8 +53,6 @@ export interface AudioQueueOptions {
|
|
|
53
53
|
loop?: boolean;
|
|
54
54
|
/** Maximum number of items allowed in the queue (defaults to unlimited) */
|
|
55
55
|
maxQueueSize?: number;
|
|
56
|
-
/** @deprecated Use addToFront instead. Legacy support for priority queuing */
|
|
57
|
-
priority?: boolean;
|
|
58
56
|
/** Volume level for this specific audio (0-1) */
|
|
59
57
|
volume?: number;
|
|
60
58
|
}
|
|
@@ -212,41 +210,74 @@ export type AudioPauseCallback = (channelNumber: number, audioInfo: AudioInfo) =
|
|
|
212
210
|
export type AudioResumeCallback = (channelNumber: number, audioInfo: AudioInfo) => void;
|
|
213
211
|
|
|
214
212
|
/**
|
|
215
|
-
*
|
|
213
|
+
* Types of audio errors that can occur during playback
|
|
214
|
+
*/
|
|
215
|
+
export enum AudioErrorType {
|
|
216
|
+
Abort = 'abort',
|
|
217
|
+
Decode = 'decode',
|
|
218
|
+
Network = 'network',
|
|
219
|
+
Permission = 'permission',
|
|
220
|
+
Timeout = 'timeout',
|
|
221
|
+
Unknown = 'unknown',
|
|
222
|
+
Unsupported = 'unsupported'
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Information about an audio error that occurred during playback or loading
|
|
216
227
|
*/
|
|
217
228
|
export interface AudioErrorInfo {
|
|
229
|
+
/** Channel number where the error occurred */
|
|
218
230
|
channelNumber: number;
|
|
219
|
-
|
|
220
|
-
fileName: string;
|
|
231
|
+
/** The actual error object that was thrown */
|
|
221
232
|
error: Error;
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
233
|
+
/** Categorized type of error for handling different scenarios */
|
|
234
|
+
errorType: AudioErrorType;
|
|
235
|
+
/** Extracted filename from the source URL */
|
|
236
|
+
fileName: string;
|
|
237
|
+
/** Number of audio files remaining in the queue after this error */
|
|
225
238
|
remainingInQueue: number;
|
|
239
|
+
/** Current retry attempt number (if retrying is enabled) */
|
|
240
|
+
retryAttempt?: number;
|
|
241
|
+
/** Audio file source URL that failed */
|
|
242
|
+
src: string;
|
|
243
|
+
/** Unix timestamp when the error occurred */
|
|
244
|
+
timestamp: number;
|
|
226
245
|
}
|
|
227
246
|
|
|
228
247
|
/**
|
|
229
248
|
* Configuration for automatic retry behavior when audio fails to load or play
|
|
230
249
|
*/
|
|
231
250
|
export interface RetryConfig {
|
|
232
|
-
|
|
233
|
-
maxRetries: number;
|
|
251
|
+
/** Initial delay in milliseconds before first retry attempt */
|
|
234
252
|
baseDelay: number;
|
|
253
|
+
/** Whether automatic retries are enabled for this channel */
|
|
254
|
+
enabled: boolean;
|
|
255
|
+
/** Whether to use exponential backoff (doubling delay each retry) */
|
|
235
256
|
exponentialBackoff: boolean;
|
|
236
|
-
|
|
237
|
-
fallbackUrls
|
|
257
|
+
/** Alternative URLs to try if the primary source fails */
|
|
258
|
+
fallbackUrls: string[];
|
|
259
|
+
/** Maximum number of retry attempts before giving up */
|
|
260
|
+
maxRetries: number;
|
|
261
|
+
/** Whether to skip to next track in queue if all retries fail */
|
|
238
262
|
skipOnFailure: boolean;
|
|
263
|
+
/** Timeout in milliseconds for each individual retry attempt */
|
|
264
|
+
timeoutMs: number;
|
|
239
265
|
}
|
|
240
266
|
|
|
241
267
|
/**
|
|
242
|
-
* Configuration options for error recovery mechanisms
|
|
268
|
+
* Configuration options for error recovery mechanisms across the audio system
|
|
243
269
|
*/
|
|
244
270
|
export interface ErrorRecoveryOptions {
|
|
271
|
+
/** Whether to automatically retry failed audio loads/plays */
|
|
245
272
|
autoRetry: boolean;
|
|
246
|
-
|
|
273
|
+
/** Whether to automatically skip to next track when current fails */
|
|
274
|
+
fallbackToNextTrack: boolean;
|
|
275
|
+
/** Whether to send error data to analytics systems */
|
|
247
276
|
logErrorsToAnalytics: boolean;
|
|
277
|
+
/** Whether to maintain queue integrity when errors occur */
|
|
248
278
|
preserveQueueOnError: boolean;
|
|
249
|
-
|
|
279
|
+
/** Whether to display user-visible error feedback */
|
|
280
|
+
showUserFeedback: boolean;
|
|
250
281
|
}
|
|
251
282
|
|
|
252
283
|
/**
|
|
@@ -255,29 +286,41 @@ export interface ErrorRecoveryOptions {
|
|
|
255
286
|
export type AudioErrorCallback = (errorInfo: AudioErrorInfo) => void;
|
|
256
287
|
|
|
257
288
|
/**
|
|
258
|
-
* Extended audio channel with queue management and
|
|
289
|
+
* Extended audio channel with comprehensive queue management, callback support, and state tracking
|
|
259
290
|
*/
|
|
260
291
|
export interface ExtendedAudioQueueChannel {
|
|
292
|
+
/** Set of callbacks triggered when audio completes playback */
|
|
261
293
|
audioCompleteCallbacks: Set<AudioCompleteCallback>;
|
|
294
|
+
/** Set of callbacks triggered when audio errors occur */
|
|
262
295
|
audioErrorCallbacks: Set<AudioErrorCallback>;
|
|
296
|
+
/** Set of callbacks triggered when audio is paused */
|
|
263
297
|
audioPauseCallbacks: Set<AudioPauseCallback>;
|
|
298
|
+
/** Set of callbacks triggered when audio is resumed */
|
|
264
299
|
audioResumeCallbacks: Set<AudioResumeCallback>;
|
|
300
|
+
/** Set of callbacks triggered when audio starts playing */
|
|
265
301
|
audioStartCallbacks: Set<AudioStartCallback>;
|
|
302
|
+
/** Current fade state if pause/resume with fade is active */
|
|
266
303
|
fadeState?: ChannelFadeState;
|
|
304
|
+
/** Whether the channel is currently paused */
|
|
267
305
|
isPaused: boolean;
|
|
268
306
|
/** Active operation lock to prevent race conditions */
|
|
269
307
|
isLocked?: boolean;
|
|
270
308
|
/** Maximum allowed queue size for this channel */
|
|
271
309
|
maxQueueSize?: number;
|
|
310
|
+
/** Map of progress callbacks keyed by audio element or global symbol */
|
|
272
311
|
progressCallbacks: Map<HTMLAudioElement | typeof GLOBAL_PROGRESS_KEY, Set<ProgressCallback>>;
|
|
312
|
+
/** Array of HTMLAudioElement objects in the queue */
|
|
273
313
|
queue: HTMLAudioElement[];
|
|
314
|
+
/** Set of callbacks triggered when the queue changes */
|
|
274
315
|
queueChangeCallbacks: Set<QueueChangeCallback>;
|
|
316
|
+
/** Retry configuration for failed audio loads/plays */
|
|
275
317
|
retryConfig?: RetryConfig;
|
|
318
|
+
/** Current volume level for the channel (0-1) */
|
|
276
319
|
volume: number;
|
|
277
320
|
}
|
|
278
321
|
|
|
279
322
|
/**
|
|
280
|
-
* Easing function types for volume transitions
|
|
323
|
+
* Easing function types for smooth volume transitions and animations
|
|
281
324
|
*/
|
|
282
325
|
export enum EasingType {
|
|
283
326
|
Linear = 'linear',
|
|
@@ -287,7 +330,7 @@ export enum EasingType {
|
|
|
287
330
|
}
|
|
288
331
|
|
|
289
332
|
/**
|
|
290
|
-
*
|
|
333
|
+
* Predefined fade types for pause/resume operations with different transition characteristics
|
|
291
334
|
*/
|
|
292
335
|
export enum FadeType {
|
|
293
336
|
Linear = 'linear',
|
|
@@ -296,7 +339,7 @@ export enum FadeType {
|
|
|
296
339
|
}
|
|
297
340
|
|
|
298
341
|
/**
|
|
299
|
-
* Timer types for volume transitions to ensure proper cleanup
|
|
342
|
+
* Timer implementation types used for volume transitions to ensure proper cleanup
|
|
300
343
|
*/
|
|
301
344
|
export enum TimerType {
|
|
302
345
|
RequestAnimationFrame = 'raf',
|
package/src/volume.ts
CHANGED
|
@@ -380,28 +380,6 @@ export const applyVolumeDucking = async (activeChannelNumber: number): Promise<v
|
|
|
380
380
|
await Promise.all(transitionPromises);
|
|
381
381
|
};
|
|
382
382
|
|
|
383
|
-
/**
|
|
384
|
-
* Fades the volume for a specific channel over time (alias for transitionVolume with improved naming)
|
|
385
|
-
* @param channelNumber - The channel number to fade
|
|
386
|
-
* @param targetVolume - Target volume level (0-1)
|
|
387
|
-
* @param duration - Fade duration in milliseconds (defaults to 250)
|
|
388
|
-
* @param easing - Easing function type (defaults to 'ease-out')
|
|
389
|
-
* @returns Promise that resolves when fade completes
|
|
390
|
-
* @example
|
|
391
|
-
* ```typescript
|
|
392
|
-
* await fadeVolume(0, 0, 800, 'ease-in'); // Fade out over 800ms
|
|
393
|
-
* await fadeVolume(0, 1, 600, 'ease-out'); // Fade in over 600ms
|
|
394
|
-
* ```
|
|
395
|
-
*/
|
|
396
|
-
export const fadeVolume = async (
|
|
397
|
-
channelNumber: number,
|
|
398
|
-
targetVolume: number,
|
|
399
|
-
duration: number = 250,
|
|
400
|
-
easing: EasingType = EasingType.EaseOut
|
|
401
|
-
): Promise<void> => {
|
|
402
|
-
return transitionVolume(channelNumber, targetVolume, duration, easing);
|
|
403
|
-
};
|
|
404
|
-
|
|
405
383
|
/**
|
|
406
384
|
* Restores normal volume levels when priority channel queue becomes empty
|
|
407
385
|
* @param stoppedChannelNumber - The channel that just stopped playing
|
|
@@ -430,7 +408,7 @@ export const restoreVolumeLevels = async (stoppedChannelNumber: number): Promise
|
|
|
430
408
|
}
|
|
431
409
|
|
|
432
410
|
// Restore this channel to its desired volume
|
|
433
|
-
const duration = config.restoreTransitionDuration ??
|
|
411
|
+
const duration = config.restoreTransitionDuration ?? 250;
|
|
434
412
|
const easing = config.transitionEasing ?? EasingType.EaseOut;
|
|
435
413
|
const targetVolume = channel.volume ?? 1.0;
|
|
436
414
|
|