audio-channel-queue 1.8.0 → 1.10.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 +197 -313
- package/dist/core.d.ts +59 -1
- package/dist/core.js +333 -41
- package/dist/errors.d.ts +1 -0
- package/dist/errors.js +37 -18
- package/dist/events.js +21 -14
- package/dist/index.d.ts +9 -8
- package/dist/index.js +23 -3
- package/dist/info.d.ts +17 -6
- package/dist/info.js +89 -17
- package/dist/pause.d.ts +24 -12
- package/dist/pause.js +93 -41
- package/dist/queue-manipulation.d.ts +104 -0
- package/dist/queue-manipulation.js +319 -0
- package/dist/types.d.ts +58 -11
- package/dist/types.js +18 -1
- package/dist/utils.d.ts +25 -0
- package/dist/utils.js +102 -13
- package/dist/volume.d.ts +14 -1
- package/dist/volume.js +201 -60
- package/package.json +18 -3
- package/src/core.ts +437 -81
- package/src/errors.ts +516 -480
- package/src/events.ts +36 -27
- package/src/index.ts +68 -43
- package/src/info.ts +129 -30
- package/src/pause.ts +169 -88
- package/src/queue-manipulation.ts +378 -0
- package/src/types.ts +63 -11
- package/src/utils.ts +117 -16
- package/src/volume.ts +250 -81
package/dist/info.js
CHANGED
|
@@ -3,14 +3,73 @@
|
|
|
3
3
|
* @fileoverview Audio information and progress tracking functions for the audio-channel-queue package
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.offAudioResume = exports.offAudioPause = exports.onAudioResume = exports.onAudioPause = exports.onAudioComplete = exports.onAudioStart = exports.offQueueChange = exports.onQueueChange = exports.
|
|
6
|
+
exports.offAudioResume = exports.offAudioPause = exports.onAudioResume = exports.onAudioPause = exports.onAudioComplete = exports.onAudioStart = exports.offQueueChange = exports.onQueueChange = exports.onAudioProgress = exports.getQueueSnapshot = exports.getAllChannelsInfo = exports.getCurrentAudioInfo = exports.audioChannels = void 0;
|
|
7
|
+
exports.offAudioProgress = offAudioProgress;
|
|
8
|
+
const types_1 = require("./types");
|
|
7
9
|
const utils_1 = require("./utils");
|
|
8
10
|
const events_1 = require("./events");
|
|
9
11
|
/**
|
|
10
12
|
* Global array to store audio channels with their queues and callback management
|
|
11
13
|
* Each channel maintains its own audio queue and event callback sets
|
|
14
|
+
*
|
|
15
|
+
* Note: While you can inspect this array for debugging, direct modification is discouraged.
|
|
16
|
+
* Use the provided API functions for safe channel management.
|
|
12
17
|
*/
|
|
13
|
-
exports.audioChannels = []
|
|
18
|
+
exports.audioChannels = new Proxy([], {
|
|
19
|
+
deleteProperty(target, prop) {
|
|
20
|
+
if (typeof prop === 'string' && !isNaN(Number(prop))) {
|
|
21
|
+
// eslint-disable-next-line no-console
|
|
22
|
+
console.warn('Warning: Direct deletion from audioChannels detected. ' +
|
|
23
|
+
'Consider using stopAllAudioInChannel() for proper cleanup.');
|
|
24
|
+
}
|
|
25
|
+
delete target[prop];
|
|
26
|
+
return true;
|
|
27
|
+
},
|
|
28
|
+
get(target, prop) {
|
|
29
|
+
const value = target[prop];
|
|
30
|
+
// Return channel objects with warnings on modification attempts
|
|
31
|
+
if (typeof value === 'object' &&
|
|
32
|
+
value !== null &&
|
|
33
|
+
typeof prop === 'string' &&
|
|
34
|
+
!isNaN(Number(prop))) {
|
|
35
|
+
return new Proxy(value, {
|
|
36
|
+
set(channelTarget, channelProp, channelValue) {
|
|
37
|
+
// Allow internal modifications but warn about direct property changes
|
|
38
|
+
if (typeof channelProp === 'string' &&
|
|
39
|
+
!['queue', 'volume', 'isPaused', 'isLocked', 'volumeConfig'].includes(channelProp)) {
|
|
40
|
+
// eslint-disable-next-line no-console
|
|
41
|
+
console.warn(`Warning: Direct modification of channel.${channelProp} detected. ` +
|
|
42
|
+
'Use API functions for safer channel management.');
|
|
43
|
+
}
|
|
44
|
+
const key = typeof channelProp === 'symbol' ? channelProp.toString() : channelProp;
|
|
45
|
+
channelTarget[key] = channelValue;
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return value;
|
|
51
|
+
},
|
|
52
|
+
set(target, prop, value) {
|
|
53
|
+
// Allow normal array operations
|
|
54
|
+
const key = typeof prop === 'symbol' ? prop.toString() : prop;
|
|
55
|
+
target[key] = value;
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* Validates a channel number against MAX_CHANNELS limit
|
|
61
|
+
* @param channelNumber - The channel number to validate
|
|
62
|
+
* @throws Error if the channel number is invalid
|
|
63
|
+
* @internal
|
|
64
|
+
*/
|
|
65
|
+
const validateChannelNumber = (channelNumber) => {
|
|
66
|
+
if (channelNumber < 0) {
|
|
67
|
+
throw new Error('Channel number must be non-negative');
|
|
68
|
+
}
|
|
69
|
+
if (channelNumber >= types_1.MAX_CHANNELS) {
|
|
70
|
+
throw new Error(`Channel number ${channelNumber} exceeds maximum allowed channels (${types_1.MAX_CHANNELS})`);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
14
73
|
/**
|
|
15
74
|
* Gets current audio information for a specific channel
|
|
16
75
|
* @param channelNumber - The channel number (defaults to 0)
|
|
@@ -56,18 +115,19 @@ const getAllChannelsInfo = () => {
|
|
|
56
115
|
exports.getAllChannelsInfo = getAllChannelsInfo;
|
|
57
116
|
/**
|
|
58
117
|
* Gets a complete snapshot of the queue state for a specific channel
|
|
59
|
-
* @param channelNumber - The channel number
|
|
118
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
60
119
|
* @returns QueueSnapshot object or null if channel doesn't exist
|
|
61
120
|
* @example
|
|
62
121
|
* ```typescript
|
|
63
|
-
* const snapshot = getQueueSnapshot(
|
|
122
|
+
* const snapshot = getQueueSnapshot();
|
|
64
123
|
* if (snapshot) {
|
|
65
124
|
* console.log(`Queue has ${snapshot.totalItems} items`);
|
|
66
125
|
* console.log(`Currently playing: ${snapshot.items[0]?.fileName}`);
|
|
67
126
|
* }
|
|
127
|
+
* const channelSnapshot = getQueueSnapshot(2);
|
|
68
128
|
* ```
|
|
69
129
|
*/
|
|
70
|
-
const getQueueSnapshot = (channelNumber) => {
|
|
130
|
+
const getQueueSnapshot = (channelNumber = 0) => {
|
|
71
131
|
return (0, utils_1.createQueueSnapshot)(channelNumber, exports.audioChannels);
|
|
72
132
|
};
|
|
73
133
|
exports.getQueueSnapshot = getQueueSnapshot;
|
|
@@ -75,6 +135,7 @@ exports.getQueueSnapshot = getQueueSnapshot;
|
|
|
75
135
|
* Subscribes to real-time progress updates for a specific channel
|
|
76
136
|
* @param channelNumber - The channel number
|
|
77
137
|
* @param callback - Function to call with audio info updates
|
|
138
|
+
* @throws Error if the channel number exceeds the maximum allowed channels
|
|
78
139
|
* @example
|
|
79
140
|
* ```typescript
|
|
80
141
|
* onAudioProgress(0, (info) => {
|
|
@@ -84,6 +145,7 @@ exports.getQueueSnapshot = getQueueSnapshot;
|
|
|
84
145
|
* ```
|
|
85
146
|
*/
|
|
86
147
|
const onAudioProgress = (channelNumber, callback) => {
|
|
148
|
+
validateChannelNumber(channelNumber);
|
|
87
149
|
if (!exports.audioChannels[channelNumber]) {
|
|
88
150
|
exports.audioChannels[channelNumber] = {
|
|
89
151
|
audioCompleteCallbacks: new Set(),
|
|
@@ -113,23 +175,24 @@ const onAudioProgress = (channelNumber, callback) => {
|
|
|
113
175
|
(0, events_1.setupProgressTracking)(currentAudio, channelNumber, exports.audioChannels);
|
|
114
176
|
}
|
|
115
177
|
// Store callback for future audio elements in this channel
|
|
116
|
-
if (!channel.progressCallbacks.has(
|
|
117
|
-
channel.progressCallbacks.set(
|
|
178
|
+
if (!channel.progressCallbacks.has(types_1.GLOBAL_PROGRESS_KEY)) {
|
|
179
|
+
channel.progressCallbacks.set(types_1.GLOBAL_PROGRESS_KEY, new Set());
|
|
118
180
|
}
|
|
119
|
-
channel.progressCallbacks.get(
|
|
181
|
+
channel.progressCallbacks.get(types_1.GLOBAL_PROGRESS_KEY).add(callback);
|
|
120
182
|
};
|
|
121
183
|
exports.onAudioProgress = onAudioProgress;
|
|
122
184
|
/**
|
|
123
185
|
* Removes progress listeners for a specific channel
|
|
124
|
-
* @param channelNumber - The channel number
|
|
186
|
+
* @param channelNumber - The channel number (defaults to 0)
|
|
125
187
|
* @example
|
|
126
188
|
* ```typescript
|
|
127
|
-
* offAudioProgress(
|
|
189
|
+
* offAudioProgress();
|
|
190
|
+
* offAudioProgress(1); // Stop receiving progress updates for channel 1
|
|
128
191
|
* ```
|
|
129
192
|
*/
|
|
130
|
-
|
|
193
|
+
function offAudioProgress(channelNumber = 0) {
|
|
131
194
|
const channel = exports.audioChannels[channelNumber];
|
|
132
|
-
if (!channel ||
|
|
195
|
+
if (!(channel === null || channel === void 0 ? void 0 : channel.progressCallbacks))
|
|
133
196
|
return;
|
|
134
197
|
// Clean up event listeners for current audio if exists
|
|
135
198
|
if (channel.queue.length > 0) {
|
|
@@ -138,12 +201,12 @@ const offAudioProgress = (channelNumber) => {
|
|
|
138
201
|
}
|
|
139
202
|
// Clear all callbacks for this channel
|
|
140
203
|
channel.progressCallbacks.clear();
|
|
141
|
-
}
|
|
142
|
-
exports.offAudioProgress = offAudioProgress;
|
|
204
|
+
}
|
|
143
205
|
/**
|
|
144
206
|
* Subscribes to queue change events for a specific channel
|
|
145
207
|
* @param channelNumber - The channel number to monitor
|
|
146
208
|
* @param callback - Function to call when queue changes
|
|
209
|
+
* @throws Error if the channel number exceeds the maximum allowed channels
|
|
147
210
|
* @example
|
|
148
211
|
* ```typescript
|
|
149
212
|
* onQueueChange(0, (snapshot) => {
|
|
@@ -153,6 +216,7 @@ exports.offAudioProgress = offAudioProgress;
|
|
|
153
216
|
* ```
|
|
154
217
|
*/
|
|
155
218
|
const onQueueChange = (channelNumber, callback) => {
|
|
219
|
+
validateChannelNumber(channelNumber);
|
|
156
220
|
if (!exports.audioChannels[channelNumber]) {
|
|
157
221
|
exports.audioChannels[channelNumber] = {
|
|
158
222
|
audioCompleteCallbacks: new Set(),
|
|
@@ -184,7 +248,7 @@ exports.onQueueChange = onQueueChange;
|
|
|
184
248
|
*/
|
|
185
249
|
const offQueueChange = (channelNumber) => {
|
|
186
250
|
const channel = exports.audioChannels[channelNumber];
|
|
187
|
-
if (!channel ||
|
|
251
|
+
if (!(channel === null || channel === void 0 ? void 0 : channel.queueChangeCallbacks))
|
|
188
252
|
return;
|
|
189
253
|
channel.queueChangeCallbacks.clear();
|
|
190
254
|
};
|
|
@@ -193,6 +257,7 @@ exports.offQueueChange = offQueueChange;
|
|
|
193
257
|
* Subscribes to audio start events for a specific channel
|
|
194
258
|
* @param channelNumber - The channel number to monitor
|
|
195
259
|
* @param callback - Function to call when audio starts playing
|
|
260
|
+
* @throws Error if the channel number exceeds the maximum allowed channels
|
|
196
261
|
* @example
|
|
197
262
|
* ```typescript
|
|
198
263
|
* onAudioStart(0, (info) => {
|
|
@@ -202,6 +267,7 @@ exports.offQueueChange = offQueueChange;
|
|
|
202
267
|
* ```
|
|
203
268
|
*/
|
|
204
269
|
const onAudioStart = (channelNumber, callback) => {
|
|
270
|
+
validateChannelNumber(channelNumber);
|
|
205
271
|
if (!exports.audioChannels[channelNumber]) {
|
|
206
272
|
exports.audioChannels[channelNumber] = {
|
|
207
273
|
audioCompleteCallbacks: new Set(),
|
|
@@ -227,6 +293,7 @@ exports.onAudioStart = onAudioStart;
|
|
|
227
293
|
* Subscribes to audio complete events for a specific channel
|
|
228
294
|
* @param channelNumber - The channel number to monitor
|
|
229
295
|
* @param callback - Function to call when audio completes
|
|
296
|
+
* @throws Error if the channel number exceeds the maximum allowed channels
|
|
230
297
|
* @example
|
|
231
298
|
* ```typescript
|
|
232
299
|
* onAudioComplete(0, (info) => {
|
|
@@ -238,6 +305,7 @@ exports.onAudioStart = onAudioStart;
|
|
|
238
305
|
* ```
|
|
239
306
|
*/
|
|
240
307
|
const onAudioComplete = (channelNumber, callback) => {
|
|
308
|
+
validateChannelNumber(channelNumber);
|
|
241
309
|
if (!exports.audioChannels[channelNumber]) {
|
|
242
310
|
exports.audioChannels[channelNumber] = {
|
|
243
311
|
audioCompleteCallbacks: new Set(),
|
|
@@ -263,6 +331,7 @@ exports.onAudioComplete = onAudioComplete;
|
|
|
263
331
|
* Subscribes to audio pause events for a specific channel
|
|
264
332
|
* @param channelNumber - The channel number to monitor
|
|
265
333
|
* @param callback - Function to call when audio is paused
|
|
334
|
+
* @throws Error if the channel number exceeds the maximum allowed channels
|
|
266
335
|
* @example
|
|
267
336
|
* ```typescript
|
|
268
337
|
* onAudioPause(0, (channelNumber, info) => {
|
|
@@ -272,6 +341,7 @@ exports.onAudioComplete = onAudioComplete;
|
|
|
272
341
|
* ```
|
|
273
342
|
*/
|
|
274
343
|
const onAudioPause = (channelNumber, callback) => {
|
|
344
|
+
validateChannelNumber(channelNumber);
|
|
275
345
|
if (!exports.audioChannels[channelNumber]) {
|
|
276
346
|
exports.audioChannels[channelNumber] = {
|
|
277
347
|
audioCompleteCallbacks: new Set(),
|
|
@@ -297,6 +367,7 @@ exports.onAudioPause = onAudioPause;
|
|
|
297
367
|
* Subscribes to audio resume events for a specific channel
|
|
298
368
|
* @param channelNumber - The channel number to monitor
|
|
299
369
|
* @param callback - Function to call when audio is resumed
|
|
370
|
+
* @throws Error if the channel number exceeds the maximum allowed channels
|
|
300
371
|
* @example
|
|
301
372
|
* ```typescript
|
|
302
373
|
* onAudioResume(0, (channelNumber, info) => {
|
|
@@ -306,6 +377,7 @@ exports.onAudioPause = onAudioPause;
|
|
|
306
377
|
* ```
|
|
307
378
|
*/
|
|
308
379
|
const onAudioResume = (channelNumber, callback) => {
|
|
380
|
+
validateChannelNumber(channelNumber);
|
|
309
381
|
if (!exports.audioChannels[channelNumber]) {
|
|
310
382
|
exports.audioChannels[channelNumber] = {
|
|
311
383
|
audioCompleteCallbacks: new Set(),
|
|
@@ -337,7 +409,7 @@ exports.onAudioResume = onAudioResume;
|
|
|
337
409
|
*/
|
|
338
410
|
const offAudioPause = (channelNumber) => {
|
|
339
411
|
const channel = exports.audioChannels[channelNumber];
|
|
340
|
-
if (!channel ||
|
|
412
|
+
if (!(channel === null || channel === void 0 ? void 0 : channel.audioPauseCallbacks))
|
|
341
413
|
return;
|
|
342
414
|
channel.audioPauseCallbacks.clear();
|
|
343
415
|
};
|
|
@@ -352,7 +424,7 @@ exports.offAudioPause = offAudioPause;
|
|
|
352
424
|
*/
|
|
353
425
|
const offAudioResume = (channelNumber) => {
|
|
354
426
|
const channel = exports.audioChannels[channelNumber];
|
|
355
|
-
if (!channel ||
|
|
427
|
+
if (!(channel === null || channel === void 0 ? void 0 : channel.audioResumeCallbacks))
|
|
356
428
|
return;
|
|
357
429
|
channel.audioResumeCallbacks.clear();
|
|
358
430
|
};
|
package/dist/pause.d.ts
CHANGED
|
@@ -6,72 +6,84 @@ import { FadeType } from './types';
|
|
|
6
6
|
* Pauses the currently playing audio in a specific channel with smooth volume fade
|
|
7
7
|
* @param fadeType - Type of fade transition to apply
|
|
8
8
|
* @param channelNumber - The channel number to pause (defaults to 0)
|
|
9
|
+
* @param duration - Optional custom fade duration in milliseconds (uses fadeType default if not provided)
|
|
9
10
|
* @returns Promise that resolves when the pause and fade are complete
|
|
10
11
|
* @example
|
|
11
12
|
* ```typescript
|
|
12
13
|
* await pauseWithFade(FadeType.Gentle, 0); // Pause with gentle fade out over 800ms
|
|
13
|
-
* await pauseWithFade(FadeType.Dramatic, 1); // Pause with dramatic fade out over
|
|
14
|
-
* await pauseWithFade(FadeType.Linear, 2); // Linear pause with
|
|
14
|
+
* await pauseWithFade(FadeType.Dramatic, 1, 1500); // Pause with dramatic fade out over 1.5s
|
|
15
|
+
* await pauseWithFade(FadeType.Linear, 2, 500); // Linear pause with custom 500ms fade
|
|
15
16
|
* ```
|
|
16
17
|
*/
|
|
17
|
-
export declare const pauseWithFade: (fadeType?: FadeType, channelNumber?: number) => Promise<void>;
|
|
18
|
+
export declare const pauseWithFade: (fadeType?: FadeType, channelNumber?: number, duration?: number) => Promise<void>;
|
|
18
19
|
/**
|
|
19
20
|
* Resumes the currently paused audio in a specific channel with smooth volume fade
|
|
20
21
|
* Uses the complementary fade curve automatically based on the pause fade type, or allows override
|
|
21
22
|
* @param fadeType - Optional fade type to override the stored fade type from pause
|
|
22
23
|
* @param channelNumber - The channel number to resume (defaults to 0)
|
|
24
|
+
* @param duration - Optional custom fade duration in milliseconds (uses stored or fadeType default if not provided)
|
|
23
25
|
* @returns Promise that resolves when the resume and fade are complete
|
|
24
26
|
* @example
|
|
25
27
|
* ```typescript
|
|
26
28
|
* await resumeWithFade(); // Resume with automatically paired fade curve from pause
|
|
27
29
|
* await resumeWithFade(FadeType.Dramatic, 0); // Override with dramatic fade
|
|
28
|
-
* await resumeWithFade(FadeType.Linear); // Override with linear fade
|
|
30
|
+
* await resumeWithFade(FadeType.Linear, 0, 1000); // Override with linear fade over 1 second
|
|
29
31
|
* ```
|
|
30
32
|
*/
|
|
31
|
-
export declare const resumeWithFade: (fadeType?: FadeType, channelNumber?: number) => Promise<void>;
|
|
33
|
+
export declare const resumeWithFade: (fadeType?: FadeType, channelNumber?: number, duration?: number) => Promise<void>;
|
|
32
34
|
/**
|
|
33
35
|
* Toggles pause/resume state for a specific channel with integrated fade
|
|
34
36
|
* @param fadeType - Type of fade transition to apply when pausing
|
|
35
37
|
* @param channelNumber - The channel number to toggle (defaults to 0)
|
|
38
|
+
* @param duration - Optional custom fade duration in milliseconds (uses fadeType default if not provided)
|
|
36
39
|
* @returns Promise that resolves when the toggle and fade are complete
|
|
37
40
|
* @example
|
|
38
41
|
* ```typescript
|
|
39
42
|
* await togglePauseWithFade(FadeType.Gentle, 0); // Toggle with gentle fade
|
|
43
|
+
* await togglePauseWithFade(FadeType.Dramatic, 0, 500); // Toggle with custom 500ms fade
|
|
40
44
|
* ```
|
|
41
45
|
*/
|
|
42
|
-
export declare const togglePauseWithFade: (fadeType?: FadeType, channelNumber?: number) => Promise<void>;
|
|
46
|
+
export declare const togglePauseWithFade: (fadeType?: FadeType, channelNumber?: number, duration?: number) => Promise<void>;
|
|
43
47
|
/**
|
|
44
48
|
* Pauses all currently playing audio across all channels with smooth volume fade
|
|
45
49
|
* @param fadeType - Type of fade transition to apply to all channels
|
|
50
|
+
* @param duration - Optional custom fade duration in milliseconds (uses fadeType default if not provided)
|
|
46
51
|
* @returns Promise that resolves when all channels are paused and faded
|
|
47
52
|
* @example
|
|
48
53
|
* ```typescript
|
|
49
|
-
* await pauseAllWithFade(
|
|
54
|
+
* await pauseAllWithFade(FadeType.Dramatic); // Pause everything with dramatic fade
|
|
55
|
+
* await pauseAllWithFade(FadeType.Gentle, 1200); // Pause all channels with custom 1.2s fade
|
|
50
56
|
* ```
|
|
51
57
|
*/
|
|
52
|
-
export declare const pauseAllWithFade: (fadeType?: FadeType) => Promise<void>;
|
|
58
|
+
export declare const pauseAllWithFade: (fadeType?: FadeType, duration?: number) => Promise<void>;
|
|
53
59
|
/**
|
|
54
60
|
* Resumes all currently paused audio across all channels with smooth volume fade
|
|
55
|
-
* Uses automatically paired fade curves based on each channel's pause fade type
|
|
61
|
+
* Uses automatically paired fade curves based on each channel's pause fade type, or allows override
|
|
62
|
+
* @param fadeType - Optional fade type to override stored fade types for all channels
|
|
63
|
+
* @param duration - Optional custom fade duration in milliseconds (uses stored or fadeType default if not provided)
|
|
56
64
|
* @returns Promise that resolves when all channels are resumed and faded
|
|
57
65
|
* @example
|
|
58
66
|
* ```typescript
|
|
59
67
|
* await resumeAllWithFade(); // Resume everything with paired fade curves
|
|
68
|
+
* await resumeAllWithFade(FadeType.Gentle, 800); // Override all channels with gentle fade over 800ms
|
|
69
|
+
* await resumeAllWithFade(undefined, 600); // Use stored fade types with custom 600ms duration
|
|
60
70
|
* ```
|
|
61
71
|
*/
|
|
62
|
-
export declare const resumeAllWithFade: () => Promise<void>;
|
|
72
|
+
export declare const resumeAllWithFade: (fadeType?: FadeType, duration?: number) => Promise<void>;
|
|
63
73
|
/**
|
|
64
74
|
* Toggles pause/resume state for all channels with integrated fade
|
|
65
75
|
* If any channels are playing, all will be paused with fade
|
|
66
76
|
* If all channels are paused, all will be resumed with fade
|
|
67
77
|
* @param fadeType - Type of fade transition to apply when pausing
|
|
78
|
+
* @param duration - Optional custom fade duration in milliseconds (uses fadeType default if not provided)
|
|
68
79
|
* @returns Promise that resolves when all toggles and fades are complete
|
|
69
80
|
* @example
|
|
70
81
|
* ```typescript
|
|
71
|
-
* await togglePauseAllWithFade(
|
|
82
|
+
* await togglePauseAllWithFade(FadeType.Gentle); // Global toggle with gentle fade
|
|
83
|
+
* await togglePauseAllWithFade(FadeType.Dramatic, 600); // Global toggle with custom 600ms fade
|
|
72
84
|
* ```
|
|
73
85
|
*/
|
|
74
|
-
export declare const togglePauseAllWithFade: (fadeType?: FadeType) => Promise<void>;
|
|
86
|
+
export declare const togglePauseAllWithFade: (fadeType?: FadeType, duration?: number) => Promise<void>;
|
|
75
87
|
/**
|
|
76
88
|
* Pauses the currently playing audio in a specific channel
|
|
77
89
|
* @param channelNumber - The channel number to pause (defaults to 0)
|
package/dist/pause.js
CHANGED
|
@@ -18,22 +18,15 @@ const info_1 = require("./info");
|
|
|
18
18
|
const utils_1 = require("./utils");
|
|
19
19
|
const events_1 = require("./events");
|
|
20
20
|
const volume_1 = require("./volume");
|
|
21
|
-
/**
|
|
22
|
-
* Predefined fade configurations for different transition types
|
|
23
|
-
*/
|
|
24
|
-
const FADE_CONFIGS = {
|
|
25
|
-
[types_1.FadeType.Linear]: { duration: 800, pauseCurve: types_1.EasingType.Linear, resumeCurve: types_1.EasingType.Linear },
|
|
26
|
-
[types_1.FadeType.Gentle]: { duration: 800, pauseCurve: types_1.EasingType.EaseOut, resumeCurve: types_1.EasingType.EaseIn },
|
|
27
|
-
[types_1.FadeType.Dramatic]: { duration: 800, pauseCurve: types_1.EasingType.EaseIn, resumeCurve: types_1.EasingType.EaseOut }
|
|
28
|
-
};
|
|
29
21
|
/**
|
|
30
22
|
* Gets the current volume for a channel, accounting for synchronous state
|
|
31
23
|
* @param channelNumber - The channel number
|
|
32
24
|
* @returns Current volume level (0-1)
|
|
33
25
|
*/
|
|
34
26
|
const getChannelVolumeSync = (channelNumber) => {
|
|
27
|
+
var _a;
|
|
35
28
|
const channel = info_1.audioChannels[channelNumber];
|
|
36
|
-
return (channel === null || channel === void 0 ? void 0 : channel.volume)
|
|
29
|
+
return (_a = channel === null || channel === void 0 ? void 0 : channel.volume) !== null && _a !== void 0 ? _a : 1.0;
|
|
37
30
|
};
|
|
38
31
|
/**
|
|
39
32
|
* Sets the channel volume synchronously in internal state
|
|
@@ -53,15 +46,17 @@ const setChannelVolumeSync = (channelNumber, volume) => {
|
|
|
53
46
|
* Pauses the currently playing audio in a specific channel with smooth volume fade
|
|
54
47
|
* @param fadeType - Type of fade transition to apply
|
|
55
48
|
* @param channelNumber - The channel number to pause (defaults to 0)
|
|
49
|
+
* @param duration - Optional custom fade duration in milliseconds (uses fadeType default if not provided)
|
|
56
50
|
* @returns Promise that resolves when the pause and fade are complete
|
|
57
51
|
* @example
|
|
58
52
|
* ```typescript
|
|
59
53
|
* await pauseWithFade(FadeType.Gentle, 0); // Pause with gentle fade out over 800ms
|
|
60
|
-
* await pauseWithFade(FadeType.Dramatic, 1); // Pause with dramatic fade out over
|
|
61
|
-
* await pauseWithFade(FadeType.Linear, 2); // Linear pause with
|
|
54
|
+
* await pauseWithFade(FadeType.Dramatic, 1, 1500); // Pause with dramatic fade out over 1.5s
|
|
55
|
+
* await pauseWithFade(FadeType.Linear, 2, 500); // Linear pause with custom 500ms fade
|
|
62
56
|
* ```
|
|
63
57
|
*/
|
|
64
|
-
const pauseWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (fadeType = types_1.FadeType.Gentle, channelNumber = 0) {
|
|
58
|
+
const pauseWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (fadeType = types_1.FadeType.Gentle, channelNumber = 0, duration) {
|
|
59
|
+
var _a, _b, _c;
|
|
65
60
|
const channel = info_1.audioChannels[channelNumber];
|
|
66
61
|
if (!channel || channel.queue.length === 0)
|
|
67
62
|
return;
|
|
@@ -69,24 +64,49 @@ const pauseWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, func
|
|
|
69
64
|
// Don't pause if already paused or ended
|
|
70
65
|
if (currentAudio.paused || currentAudio.ended)
|
|
71
66
|
return;
|
|
72
|
-
const config =
|
|
73
|
-
const
|
|
74
|
-
//
|
|
67
|
+
const config = (0, volume_1.getFadeConfig)(fadeType);
|
|
68
|
+
const effectiveDuration = duration !== null && duration !== void 0 ? duration : config.duration;
|
|
69
|
+
// Race condition fix: Use existing fadeState originalVolume if already transitioning,
|
|
70
|
+
// otherwise capture current volume
|
|
71
|
+
let originalVolume;
|
|
72
|
+
if ((_a = channel.fadeState) === null || _a === void 0 ? void 0 : _a.isTransitioning) {
|
|
73
|
+
// We're already in any kind of transition (pause or resume), preserve original volume
|
|
74
|
+
originalVolume = channel.fadeState.originalVolume;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// First fade or no transition in progress, capture current volume
|
|
78
|
+
// But ensure we don't capture a volume of 0 during a transition
|
|
79
|
+
const currentVolume = getChannelVolumeSync(channelNumber);
|
|
80
|
+
originalVolume = currentVolume > 0 ? currentVolume : ((_c = (_b = channel.fadeState) === null || _b === void 0 ? void 0 : _b.originalVolume) !== null && _c !== void 0 ? _c : 1.0);
|
|
81
|
+
}
|
|
82
|
+
// Store fade state for resumeWithFade to use (including custom duration)
|
|
75
83
|
channel.fadeState = {
|
|
76
|
-
|
|
84
|
+
customDuration: duration,
|
|
77
85
|
fadeType,
|
|
78
|
-
isPaused: true
|
|
86
|
+
isPaused: true,
|
|
87
|
+
isTransitioning: true,
|
|
88
|
+
originalVolume
|
|
79
89
|
};
|
|
80
|
-
if (
|
|
90
|
+
if (effectiveDuration === 0) {
|
|
81
91
|
// Instant pause
|
|
82
92
|
yield (0, exports.pauseChannel)(channelNumber);
|
|
93
|
+
// Reset volume to original for resume (synchronously to avoid state issues)
|
|
94
|
+
setChannelVolumeSync(channelNumber, originalVolume);
|
|
95
|
+
// Mark transition as complete for instant pause
|
|
96
|
+
if (channel.fadeState) {
|
|
97
|
+
channel.fadeState.isTransitioning = false;
|
|
98
|
+
}
|
|
83
99
|
return;
|
|
84
100
|
}
|
|
85
101
|
// Fade to 0 with pause curve, then pause
|
|
86
|
-
yield (0, volume_1.transitionVolume)(channelNumber, 0,
|
|
102
|
+
yield (0, volume_1.transitionVolume)(channelNumber, 0, effectiveDuration, config.pauseCurve);
|
|
87
103
|
yield (0, exports.pauseChannel)(channelNumber);
|
|
88
104
|
// Reset volume to original for resume (synchronously to avoid state issues)
|
|
89
105
|
setChannelVolumeSync(channelNumber, originalVolume);
|
|
106
|
+
// Mark transition as complete
|
|
107
|
+
if (channel.fadeState) {
|
|
108
|
+
channel.fadeState.isTransitioning = false;
|
|
109
|
+
}
|
|
90
110
|
});
|
|
91
111
|
exports.pauseWithFade = pauseWithFade;
|
|
92
112
|
/**
|
|
@@ -94,93 +114,122 @@ exports.pauseWithFade = pauseWithFade;
|
|
|
94
114
|
* Uses the complementary fade curve automatically based on the pause fade type, or allows override
|
|
95
115
|
* @param fadeType - Optional fade type to override the stored fade type from pause
|
|
96
116
|
* @param channelNumber - The channel number to resume (defaults to 0)
|
|
117
|
+
* @param duration - Optional custom fade duration in milliseconds (uses stored or fadeType default if not provided)
|
|
97
118
|
* @returns Promise that resolves when the resume and fade are complete
|
|
98
119
|
* @example
|
|
99
120
|
* ```typescript
|
|
100
121
|
* await resumeWithFade(); // Resume with automatically paired fade curve from pause
|
|
101
122
|
* await resumeWithFade(FadeType.Dramatic, 0); // Override with dramatic fade
|
|
102
|
-
* await resumeWithFade(FadeType.Linear); // Override with linear fade
|
|
123
|
+
* await resumeWithFade(FadeType.Linear, 0, 1000); // Override with linear fade over 1 second
|
|
103
124
|
* ```
|
|
104
125
|
*/
|
|
105
|
-
const resumeWithFade = (fadeType_1, ...args_1) => __awaiter(void 0, [fadeType_1, ...args_1], void 0, function* (fadeType, channelNumber = 0) {
|
|
126
|
+
const resumeWithFade = (fadeType_1, ...args_1) => __awaiter(void 0, [fadeType_1, ...args_1], void 0, function* (fadeType, channelNumber = 0, duration) {
|
|
106
127
|
const channel = info_1.audioChannels[channelNumber];
|
|
107
128
|
if (!channel || channel.queue.length === 0)
|
|
108
129
|
return;
|
|
109
130
|
const fadeState = channel.fadeState;
|
|
110
|
-
if (!fadeState ||
|
|
131
|
+
if (!(fadeState === null || fadeState === void 0 ? void 0 : fadeState.isPaused)) {
|
|
111
132
|
// Fall back to regular resume if no fade state
|
|
112
133
|
yield (0, exports.resumeChannel)(channelNumber);
|
|
113
134
|
return;
|
|
114
135
|
}
|
|
115
136
|
// Use provided fadeType or fall back to stored fadeType from pause
|
|
116
|
-
const effectiveFadeType = fadeType
|
|
117
|
-
const config =
|
|
118
|
-
|
|
137
|
+
const effectiveFadeType = fadeType !== null && fadeType !== void 0 ? fadeType : fadeState.fadeType;
|
|
138
|
+
const config = (0, volume_1.getFadeConfig)(effectiveFadeType);
|
|
139
|
+
// Determine effective duration: custom parameter > stored custom > fadeType default
|
|
140
|
+
let effectiveDuration;
|
|
141
|
+
if (duration !== undefined) {
|
|
142
|
+
effectiveDuration = duration;
|
|
143
|
+
}
|
|
144
|
+
else if (fadeState.customDuration !== undefined) {
|
|
145
|
+
effectiveDuration = fadeState.customDuration;
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
effectiveDuration = config.duration;
|
|
149
|
+
}
|
|
150
|
+
if (effectiveDuration === 0) {
|
|
119
151
|
// Instant resume
|
|
152
|
+
const targetVolume = fadeState.originalVolume > 0 ? fadeState.originalVolume : 1.0;
|
|
153
|
+
setChannelVolumeSync(channelNumber, targetVolume);
|
|
120
154
|
yield (0, exports.resumeChannel)(channelNumber);
|
|
121
155
|
fadeState.isPaused = false;
|
|
156
|
+
fadeState.isTransitioning = false;
|
|
122
157
|
return;
|
|
123
158
|
}
|
|
159
|
+
// Race condition fix: Ensure we have a valid original volume to restore to
|
|
160
|
+
const targetVolume = fadeState.originalVolume > 0 ? fadeState.originalVolume : 1.0;
|
|
161
|
+
// Mark as transitioning to prevent volume capture during rapid toggles
|
|
162
|
+
fadeState.isTransitioning = true;
|
|
124
163
|
// Set volume to 0, resume, then fade to original with resume curve
|
|
125
164
|
setChannelVolumeSync(channelNumber, 0);
|
|
126
165
|
yield (0, exports.resumeChannel)(channelNumber);
|
|
127
|
-
|
|
166
|
+
// Use the stored original volume, not current volume, to prevent race conditions
|
|
167
|
+
yield (0, volume_1.transitionVolume)(channelNumber, targetVolume, effectiveDuration, config.resumeCurve);
|
|
128
168
|
fadeState.isPaused = false;
|
|
169
|
+
fadeState.isTransitioning = false;
|
|
129
170
|
});
|
|
130
171
|
exports.resumeWithFade = resumeWithFade;
|
|
131
172
|
/**
|
|
132
173
|
* Toggles pause/resume state for a specific channel with integrated fade
|
|
133
174
|
* @param fadeType - Type of fade transition to apply when pausing
|
|
134
175
|
* @param channelNumber - The channel number to toggle (defaults to 0)
|
|
176
|
+
* @param duration - Optional custom fade duration in milliseconds (uses fadeType default if not provided)
|
|
135
177
|
* @returns Promise that resolves when the toggle and fade are complete
|
|
136
178
|
* @example
|
|
137
179
|
* ```typescript
|
|
138
180
|
* await togglePauseWithFade(FadeType.Gentle, 0); // Toggle with gentle fade
|
|
181
|
+
* await togglePauseWithFade(FadeType.Dramatic, 0, 500); // Toggle with custom 500ms fade
|
|
139
182
|
* ```
|
|
140
183
|
*/
|
|
141
|
-
const togglePauseWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (fadeType = types_1.FadeType.Gentle, channelNumber = 0) {
|
|
184
|
+
const togglePauseWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (fadeType = types_1.FadeType.Gentle, channelNumber = 0, duration) {
|
|
142
185
|
const channel = info_1.audioChannels[channelNumber];
|
|
143
186
|
if (!channel || channel.queue.length === 0)
|
|
144
187
|
return;
|
|
145
188
|
const currentAudio = channel.queue[0];
|
|
146
189
|
if (currentAudio.paused) {
|
|
147
|
-
yield (0, exports.resumeWithFade)(undefined, channelNumber);
|
|
190
|
+
yield (0, exports.resumeWithFade)(undefined, channelNumber, duration);
|
|
148
191
|
}
|
|
149
192
|
else {
|
|
150
|
-
yield (0, exports.pauseWithFade)(fadeType, channelNumber);
|
|
193
|
+
yield (0, exports.pauseWithFade)(fadeType, channelNumber, duration);
|
|
151
194
|
}
|
|
152
195
|
});
|
|
153
196
|
exports.togglePauseWithFade = togglePauseWithFade;
|
|
154
197
|
/**
|
|
155
198
|
* Pauses all currently playing audio across all channels with smooth volume fade
|
|
156
199
|
* @param fadeType - Type of fade transition to apply to all channels
|
|
200
|
+
* @param duration - Optional custom fade duration in milliseconds (uses fadeType default if not provided)
|
|
157
201
|
* @returns Promise that resolves when all channels are paused and faded
|
|
158
202
|
* @example
|
|
159
203
|
* ```typescript
|
|
160
|
-
* await pauseAllWithFade(
|
|
204
|
+
* await pauseAllWithFade(FadeType.Dramatic); // Pause everything with dramatic fade
|
|
205
|
+
* await pauseAllWithFade(FadeType.Gentle, 1200); // Pause all channels with custom 1.2s fade
|
|
161
206
|
* ```
|
|
162
207
|
*/
|
|
163
|
-
const pauseAllWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (fadeType = types_1.FadeType.Gentle) {
|
|
208
|
+
const pauseAllWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (fadeType = types_1.FadeType.Gentle, duration) {
|
|
164
209
|
const pausePromises = [];
|
|
165
210
|
info_1.audioChannels.forEach((_channel, index) => {
|
|
166
|
-
pausePromises.push((0, exports.pauseWithFade)(fadeType, index));
|
|
211
|
+
pausePromises.push((0, exports.pauseWithFade)(fadeType, index, duration));
|
|
167
212
|
});
|
|
168
213
|
yield Promise.all(pausePromises);
|
|
169
214
|
});
|
|
170
215
|
exports.pauseAllWithFade = pauseAllWithFade;
|
|
171
216
|
/**
|
|
172
217
|
* Resumes all currently paused audio across all channels with smooth volume fade
|
|
173
|
-
* Uses automatically paired fade curves based on each channel's pause fade type
|
|
218
|
+
* Uses automatically paired fade curves based on each channel's pause fade type, or allows override
|
|
219
|
+
* @param fadeType - Optional fade type to override stored fade types for all channels
|
|
220
|
+
* @param duration - Optional custom fade duration in milliseconds (uses stored or fadeType default if not provided)
|
|
174
221
|
* @returns Promise that resolves when all channels are resumed and faded
|
|
175
222
|
* @example
|
|
176
223
|
* ```typescript
|
|
177
224
|
* await resumeAllWithFade(); // Resume everything with paired fade curves
|
|
225
|
+
* await resumeAllWithFade(FadeType.Gentle, 800); // Override all channels with gentle fade over 800ms
|
|
226
|
+
* await resumeAllWithFade(undefined, 600); // Use stored fade types with custom 600ms duration
|
|
178
227
|
* ```
|
|
179
228
|
*/
|
|
180
|
-
const resumeAllWithFade = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
229
|
+
const resumeAllWithFade = (fadeType, duration) => __awaiter(void 0, void 0, void 0, function* () {
|
|
181
230
|
const resumePromises = [];
|
|
182
231
|
info_1.audioChannels.forEach((_channel, index) => {
|
|
183
|
-
resumePromises.push((0, exports.resumeWithFade)(
|
|
232
|
+
resumePromises.push((0, exports.resumeWithFade)(fadeType, index, duration));
|
|
184
233
|
});
|
|
185
234
|
yield Promise.all(resumePromises);
|
|
186
235
|
});
|
|
@@ -190,13 +239,15 @@ exports.resumeAllWithFade = resumeAllWithFade;
|
|
|
190
239
|
* If any channels are playing, all will be paused with fade
|
|
191
240
|
* If all channels are paused, all will be resumed with fade
|
|
192
241
|
* @param fadeType - Type of fade transition to apply when pausing
|
|
242
|
+
* @param duration - Optional custom fade duration in milliseconds (uses fadeType default if not provided)
|
|
193
243
|
* @returns Promise that resolves when all toggles and fades are complete
|
|
194
244
|
* @example
|
|
195
245
|
* ```typescript
|
|
196
|
-
* await togglePauseAllWithFade(
|
|
246
|
+
* await togglePauseAllWithFade(FadeType.Gentle); // Global toggle with gentle fade
|
|
247
|
+
* await togglePauseAllWithFade(FadeType.Dramatic, 600); // Global toggle with custom 600ms fade
|
|
197
248
|
* ```
|
|
198
249
|
*/
|
|
199
|
-
const togglePauseAllWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (fadeType = types_1.FadeType.Gentle) {
|
|
250
|
+
const togglePauseAllWithFade = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (fadeType = types_1.FadeType.Gentle, duration) {
|
|
200
251
|
let hasPlayingChannel = false;
|
|
201
252
|
// Check if any channel is currently playing
|
|
202
253
|
for (let i = 0; i < info_1.audioChannels.length; i++) {
|
|
@@ -212,10 +263,10 @@ const togglePauseAllWithFade = (...args_1) => __awaiter(void 0, [...args_1], voi
|
|
|
212
263
|
// If any channel is playing, pause all with fade
|
|
213
264
|
// If no channels are playing, resume all with fade
|
|
214
265
|
if (hasPlayingChannel) {
|
|
215
|
-
yield (0, exports.pauseAllWithFade)(fadeType);
|
|
266
|
+
yield (0, exports.pauseAllWithFade)(fadeType, duration);
|
|
216
267
|
}
|
|
217
268
|
else {
|
|
218
|
-
yield (0, exports.resumeAllWithFade)();
|
|
269
|
+
yield (0, exports.resumeAllWithFade)(fadeType, duration);
|
|
219
270
|
}
|
|
220
271
|
});
|
|
221
272
|
exports.togglePauseAllWithFade = togglePauseAllWithFade;
|
|
@@ -335,8 +386,9 @@ exports.resumeAllChannels = resumeAllChannels;
|
|
|
335
386
|
* ```
|
|
336
387
|
*/
|
|
337
388
|
const isChannelPaused = (channelNumber = 0) => {
|
|
389
|
+
var _a;
|
|
338
390
|
const channel = info_1.audioChannels[channelNumber];
|
|
339
|
-
return (channel === null || channel === void 0 ? void 0 : channel.isPaused)
|
|
391
|
+
return (_a = channel === null || channel === void 0 ? void 0 : channel.isPaused) !== null && _a !== void 0 ? _a : false;
|
|
340
392
|
};
|
|
341
393
|
exports.isChannelPaused = isChannelPaused;
|
|
342
394
|
/**
|
|
@@ -351,7 +403,7 @@ exports.isChannelPaused = isChannelPaused;
|
|
|
351
403
|
* ```
|
|
352
404
|
*/
|
|
353
405
|
const getAllChannelsPauseState = () => {
|
|
354
|
-
return info_1.audioChannels.map((channel) => (channel === null || channel === void 0 ? void 0 : channel.isPaused)
|
|
406
|
+
return info_1.audioChannels.map((channel) => { var _a; return (_a = channel === null || channel === void 0 ? void 0 : channel.isPaused) !== null && _a !== void 0 ? _a : false; });
|
|
355
407
|
};
|
|
356
408
|
exports.getAllChannelsPauseState = getAllChannelsPauseState;
|
|
357
409
|
/**
|