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/src/pause.ts
CHANGED
|
@@ -2,20 +2,17 @@
|
|
|
2
2
|
* @fileoverview Pause and resume management functions for the audio-channel-queue package
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
ExtendedAudioQueueChannel,
|
|
7
|
+
AudioInfo,
|
|
8
|
+
FadeType,
|
|
9
|
+
FadeConfig,
|
|
10
|
+
ChannelFadeState
|
|
11
|
+
} from './types';
|
|
6
12
|
import { audioChannels } from './info';
|
|
7
13
|
import { getAudioInfoFromElement } from './utils';
|
|
8
14
|
import { emitAudioPause, emitAudioResume } from './events';
|
|
9
|
-
import { transitionVolume } from './volume';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Predefined fade configurations for different transition types
|
|
13
|
-
*/
|
|
14
|
-
const FADE_CONFIGS: Record<FadeType, FadeConfig> = {
|
|
15
|
-
[FadeType.Linear]: { duration: 800, pauseCurve: EasingType.Linear, resumeCurve: EasingType.Linear },
|
|
16
|
-
[FadeType.Gentle]: { duration: 800, pauseCurve: EasingType.EaseOut, resumeCurve: EasingType.EaseIn },
|
|
17
|
-
[FadeType.Dramatic]: { duration: 800, pauseCurve: EasingType.EaseIn, resumeCurve: EasingType.EaseOut }
|
|
18
|
-
};
|
|
15
|
+
import { transitionVolume, getFadeConfig } from './volume';
|
|
19
16
|
|
|
20
17
|
/**
|
|
21
18
|
* Gets the current volume for a channel, accounting for synchronous state
|
|
@@ -24,7 +21,7 @@ const FADE_CONFIGS: Record<FadeType, FadeConfig> = {
|
|
|
24
21
|
*/
|
|
25
22
|
const getChannelVolumeSync = (channelNumber: number): number => {
|
|
26
23
|
const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
|
|
27
|
-
return channel?.volume
|
|
24
|
+
return channel?.volume ?? 1.0;
|
|
28
25
|
};
|
|
29
26
|
|
|
30
27
|
/**
|
|
@@ -46,46 +43,77 @@ const setChannelVolumeSync = (channelNumber: number, volume: number): void => {
|
|
|
46
43
|
* Pauses the currently playing audio in a specific channel with smooth volume fade
|
|
47
44
|
* @param fadeType - Type of fade transition to apply
|
|
48
45
|
* @param channelNumber - The channel number to pause (defaults to 0)
|
|
46
|
+
* @param duration - Optional custom fade duration in milliseconds (uses fadeType default if not provided)
|
|
49
47
|
* @returns Promise that resolves when the pause and fade are complete
|
|
50
48
|
* @example
|
|
51
49
|
* ```typescript
|
|
52
50
|
* await pauseWithFade(FadeType.Gentle, 0); // Pause with gentle fade out over 800ms
|
|
53
|
-
* await pauseWithFade(FadeType.Dramatic, 1); // Pause with dramatic fade out over
|
|
54
|
-
* await pauseWithFade(FadeType.Linear, 2); // Linear pause with
|
|
51
|
+
* await pauseWithFade(FadeType.Dramatic, 1, 1500); // Pause with dramatic fade out over 1.5s
|
|
52
|
+
* await pauseWithFade(FadeType.Linear, 2, 500); // Linear pause with custom 500ms fade
|
|
55
53
|
* ```
|
|
56
54
|
*/
|
|
57
|
-
export const pauseWithFade = async (
|
|
55
|
+
export const pauseWithFade = async (
|
|
56
|
+
fadeType: FadeType = FadeType.Gentle,
|
|
57
|
+
channelNumber: number = 0,
|
|
58
|
+
duration?: number
|
|
59
|
+
): Promise<void> => {
|
|
58
60
|
const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
|
|
59
|
-
|
|
61
|
+
|
|
60
62
|
if (!channel || channel.queue.length === 0) return;
|
|
61
|
-
|
|
63
|
+
|
|
62
64
|
const currentAudio: HTMLAudioElement = channel.queue[0];
|
|
63
|
-
|
|
65
|
+
|
|
64
66
|
// Don't pause if already paused or ended
|
|
65
67
|
if (currentAudio.paused || currentAudio.ended) return;
|
|
66
|
-
|
|
67
|
-
const config: FadeConfig =
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
//
|
|
68
|
+
|
|
69
|
+
const config: FadeConfig = getFadeConfig(fadeType);
|
|
70
|
+
const effectiveDuration: number = duration ?? config.duration;
|
|
71
|
+
|
|
72
|
+
// Race condition fix: Use existing fadeState originalVolume if already transitioning,
|
|
73
|
+
// otherwise capture current volume
|
|
74
|
+
let originalVolume: number;
|
|
75
|
+
if (channel.fadeState?.isTransitioning) {
|
|
76
|
+
// We're already in any kind of transition (pause or resume), preserve original volume
|
|
77
|
+
originalVolume = channel.fadeState.originalVolume;
|
|
78
|
+
} else {
|
|
79
|
+
// First fade or no transition in progress, capture current volume
|
|
80
|
+
// But ensure we don't capture a volume of 0 during a transition
|
|
81
|
+
const currentVolume = getChannelVolumeSync(channelNumber);
|
|
82
|
+
originalVolume = currentVolume > 0 ? currentVolume : (channel.fadeState?.originalVolume ?? 1.0);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Store fade state for resumeWithFade to use (including custom duration)
|
|
71
86
|
channel.fadeState = {
|
|
72
|
-
|
|
87
|
+
customDuration: duration,
|
|
73
88
|
fadeType,
|
|
74
|
-
isPaused: true
|
|
89
|
+
isPaused: true,
|
|
90
|
+
isTransitioning: true,
|
|
91
|
+
originalVolume
|
|
75
92
|
};
|
|
76
|
-
|
|
77
|
-
if (
|
|
93
|
+
|
|
94
|
+
if (effectiveDuration === 0) {
|
|
78
95
|
// Instant pause
|
|
79
96
|
await pauseChannel(channelNumber);
|
|
97
|
+
// Reset volume to original for resume (synchronously to avoid state issues)
|
|
98
|
+
setChannelVolumeSync(channelNumber, originalVolume);
|
|
99
|
+
// Mark transition as complete for instant pause
|
|
100
|
+
if (channel.fadeState) {
|
|
101
|
+
channel.fadeState.isTransitioning = false;
|
|
102
|
+
}
|
|
80
103
|
return;
|
|
81
104
|
}
|
|
82
|
-
|
|
105
|
+
|
|
83
106
|
// Fade to 0 with pause curve, then pause
|
|
84
|
-
await transitionVolume(channelNumber, 0,
|
|
107
|
+
await transitionVolume(channelNumber, 0, effectiveDuration, config.pauseCurve);
|
|
85
108
|
await pauseChannel(channelNumber);
|
|
86
|
-
|
|
109
|
+
|
|
87
110
|
// Reset volume to original for resume (synchronously to avoid state issues)
|
|
88
111
|
setChannelVolumeSync(channelNumber, originalVolume);
|
|
112
|
+
|
|
113
|
+
// Mark transition as complete
|
|
114
|
+
if (channel.fadeState) {
|
|
115
|
+
channel.fadeState.isTransitioning = false;
|
|
116
|
+
}
|
|
89
117
|
};
|
|
90
118
|
|
|
91
119
|
/**
|
|
@@ -93,104 +121,146 @@ export const pauseWithFade = async (fadeType: FadeType = FadeType.Gentle, channe
|
|
|
93
121
|
* Uses the complementary fade curve automatically based on the pause fade type, or allows override
|
|
94
122
|
* @param fadeType - Optional fade type to override the stored fade type from pause
|
|
95
123
|
* @param channelNumber - The channel number to resume (defaults to 0)
|
|
124
|
+
* @param duration - Optional custom fade duration in milliseconds (uses stored or fadeType default if not provided)
|
|
96
125
|
* @returns Promise that resolves when the resume and fade are complete
|
|
97
126
|
* @example
|
|
98
127
|
* ```typescript
|
|
99
128
|
* await resumeWithFade(); // Resume with automatically paired fade curve from pause
|
|
100
129
|
* await resumeWithFade(FadeType.Dramatic, 0); // Override with dramatic fade
|
|
101
|
-
* await resumeWithFade(FadeType.Linear); // Override with linear fade
|
|
130
|
+
* await resumeWithFade(FadeType.Linear, 0, 1000); // Override with linear fade over 1 second
|
|
102
131
|
* ```
|
|
103
132
|
*/
|
|
104
|
-
export const resumeWithFade = async (
|
|
133
|
+
export const resumeWithFade = async (
|
|
134
|
+
fadeType?: FadeType,
|
|
135
|
+
channelNumber: number = 0,
|
|
136
|
+
duration?: number
|
|
137
|
+
): Promise<void> => {
|
|
105
138
|
const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
|
|
106
|
-
|
|
139
|
+
|
|
107
140
|
if (!channel || channel.queue.length === 0) return;
|
|
108
|
-
|
|
141
|
+
|
|
109
142
|
const fadeState: ChannelFadeState | undefined = channel.fadeState;
|
|
110
|
-
if (!fadeState
|
|
143
|
+
if (!fadeState?.isPaused) {
|
|
111
144
|
// Fall back to regular resume if no fade state
|
|
112
145
|
await resumeChannel(channelNumber);
|
|
113
146
|
return;
|
|
114
147
|
}
|
|
115
|
-
|
|
148
|
+
|
|
116
149
|
// Use provided fadeType or fall back to stored fadeType from pause
|
|
117
|
-
const effectiveFadeType: FadeType = fadeType
|
|
118
|
-
const config: FadeConfig =
|
|
119
|
-
|
|
120
|
-
|
|
150
|
+
const effectiveFadeType: FadeType = fadeType ?? fadeState.fadeType;
|
|
151
|
+
const config: FadeConfig = getFadeConfig(effectiveFadeType);
|
|
152
|
+
|
|
153
|
+
// Determine effective duration: custom parameter > stored custom > fadeType default
|
|
154
|
+
let effectiveDuration: number;
|
|
155
|
+
if (duration !== undefined) {
|
|
156
|
+
effectiveDuration = duration;
|
|
157
|
+
} else if (fadeState.customDuration !== undefined) {
|
|
158
|
+
effectiveDuration = fadeState.customDuration;
|
|
159
|
+
} else {
|
|
160
|
+
effectiveDuration = config.duration;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (effectiveDuration === 0) {
|
|
121
164
|
// Instant resume
|
|
165
|
+
const targetVolume = fadeState.originalVolume > 0 ? fadeState.originalVolume : 1.0;
|
|
166
|
+
setChannelVolumeSync(channelNumber, targetVolume);
|
|
122
167
|
await resumeChannel(channelNumber);
|
|
123
168
|
fadeState.isPaused = false;
|
|
169
|
+
fadeState.isTransitioning = false;
|
|
124
170
|
return;
|
|
125
171
|
}
|
|
126
|
-
|
|
172
|
+
|
|
173
|
+
// Race condition fix: Ensure we have a valid original volume to restore to
|
|
174
|
+
const targetVolume = fadeState.originalVolume > 0 ? fadeState.originalVolume : 1.0;
|
|
175
|
+
|
|
176
|
+
// Mark as transitioning to prevent volume capture during rapid toggles
|
|
177
|
+
fadeState.isTransitioning = true;
|
|
178
|
+
|
|
127
179
|
// Set volume to 0, resume, then fade to original with resume curve
|
|
128
180
|
setChannelVolumeSync(channelNumber, 0);
|
|
129
181
|
await resumeChannel(channelNumber);
|
|
130
|
-
|
|
131
|
-
|
|
182
|
+
|
|
183
|
+
// Use the stored original volume, not current volume, to prevent race conditions
|
|
184
|
+
await transitionVolume(channelNumber, targetVolume, effectiveDuration, config.resumeCurve);
|
|
185
|
+
|
|
132
186
|
fadeState.isPaused = false;
|
|
187
|
+
fadeState.isTransitioning = false;
|
|
133
188
|
};
|
|
134
189
|
|
|
135
190
|
/**
|
|
136
191
|
* Toggles pause/resume state for a specific channel with integrated fade
|
|
137
192
|
* @param fadeType - Type of fade transition to apply when pausing
|
|
138
193
|
* @param channelNumber - The channel number to toggle (defaults to 0)
|
|
194
|
+
* @param duration - Optional custom fade duration in milliseconds (uses fadeType default if not provided)
|
|
139
195
|
* @returns Promise that resolves when the toggle and fade are complete
|
|
140
196
|
* @example
|
|
141
197
|
* ```typescript
|
|
142
198
|
* await togglePauseWithFade(FadeType.Gentle, 0); // Toggle with gentle fade
|
|
199
|
+
* await togglePauseWithFade(FadeType.Dramatic, 0, 500); // Toggle with custom 500ms fade
|
|
143
200
|
* ```
|
|
144
201
|
*/
|
|
145
|
-
export const togglePauseWithFade = async (
|
|
202
|
+
export const togglePauseWithFade = async (
|
|
203
|
+
fadeType: FadeType = FadeType.Gentle,
|
|
204
|
+
channelNumber: number = 0,
|
|
205
|
+
duration?: number
|
|
206
|
+
): Promise<void> => {
|
|
146
207
|
const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
|
|
147
|
-
|
|
208
|
+
|
|
148
209
|
if (!channel || channel.queue.length === 0) return;
|
|
149
|
-
|
|
210
|
+
|
|
150
211
|
const currentAudio: HTMLAudioElement = channel.queue[0];
|
|
151
|
-
|
|
212
|
+
|
|
152
213
|
if (currentAudio.paused) {
|
|
153
|
-
await resumeWithFade(undefined, channelNumber);
|
|
214
|
+
await resumeWithFade(undefined, channelNumber, duration);
|
|
154
215
|
} else {
|
|
155
|
-
await pauseWithFade(fadeType, channelNumber);
|
|
216
|
+
await pauseWithFade(fadeType, channelNumber, duration);
|
|
156
217
|
}
|
|
157
218
|
};
|
|
158
219
|
|
|
159
220
|
/**
|
|
160
221
|
* Pauses all currently playing audio across all channels with smooth volume fade
|
|
161
222
|
* @param fadeType - Type of fade transition to apply to all channels
|
|
223
|
+
* @param duration - Optional custom fade duration in milliseconds (uses fadeType default if not provided)
|
|
162
224
|
* @returns Promise that resolves when all channels are paused and faded
|
|
163
225
|
* @example
|
|
164
226
|
* ```typescript
|
|
165
|
-
* await pauseAllWithFade(
|
|
227
|
+
* await pauseAllWithFade(FadeType.Dramatic); // Pause everything with dramatic fade
|
|
228
|
+
* await pauseAllWithFade(FadeType.Gentle, 1200); // Pause all channels with custom 1.2s fade
|
|
166
229
|
* ```
|
|
167
230
|
*/
|
|
168
|
-
export const pauseAllWithFade = async (
|
|
231
|
+
export const pauseAllWithFade = async (
|
|
232
|
+
fadeType: FadeType = FadeType.Gentle,
|
|
233
|
+
duration?: number
|
|
234
|
+
): Promise<void> => {
|
|
169
235
|
const pausePromises: Promise<void>[] = [];
|
|
170
|
-
|
|
236
|
+
|
|
171
237
|
audioChannels.forEach((_channel: ExtendedAudioQueueChannel, index: number) => {
|
|
172
|
-
pausePromises.push(pauseWithFade(fadeType, index));
|
|
238
|
+
pausePromises.push(pauseWithFade(fadeType, index, duration));
|
|
173
239
|
});
|
|
174
|
-
|
|
240
|
+
|
|
175
241
|
await Promise.all(pausePromises);
|
|
176
242
|
};
|
|
177
243
|
|
|
178
244
|
/**
|
|
179
245
|
* Resumes all currently paused audio across all channels with smooth volume fade
|
|
180
|
-
* Uses automatically paired fade curves based on each channel's pause fade type
|
|
246
|
+
* Uses automatically paired fade curves based on each channel's pause fade type, or allows override
|
|
247
|
+
* @param fadeType - Optional fade type to override stored fade types for all channels
|
|
248
|
+
* @param duration - Optional custom fade duration in milliseconds (uses stored or fadeType default if not provided)
|
|
181
249
|
* @returns Promise that resolves when all channels are resumed and faded
|
|
182
250
|
* @example
|
|
183
251
|
* ```typescript
|
|
184
252
|
* await resumeAllWithFade(); // Resume everything with paired fade curves
|
|
253
|
+
* await resumeAllWithFade(FadeType.Gentle, 800); // Override all channels with gentle fade over 800ms
|
|
254
|
+
* await resumeAllWithFade(undefined, 600); // Use stored fade types with custom 600ms duration
|
|
185
255
|
* ```
|
|
186
256
|
*/
|
|
187
|
-
export const resumeAllWithFade = async (): Promise<void> => {
|
|
257
|
+
export const resumeAllWithFade = async (fadeType?: FadeType, duration?: number): Promise<void> => {
|
|
188
258
|
const resumePromises: Promise<void>[] = [];
|
|
189
|
-
|
|
259
|
+
|
|
190
260
|
audioChannels.forEach((_channel: ExtendedAudioQueueChannel, index: number) => {
|
|
191
|
-
resumePromises.push(resumeWithFade(
|
|
261
|
+
resumePromises.push(resumeWithFade(fadeType, index, duration));
|
|
192
262
|
});
|
|
193
|
-
|
|
263
|
+
|
|
194
264
|
await Promise.all(resumePromises);
|
|
195
265
|
};
|
|
196
266
|
|
|
@@ -199,17 +269,22 @@ export const resumeAllWithFade = async (): Promise<void> => {
|
|
|
199
269
|
* If any channels are playing, all will be paused with fade
|
|
200
270
|
* If all channels are paused, all will be resumed with fade
|
|
201
271
|
* @param fadeType - Type of fade transition to apply when pausing
|
|
272
|
+
* @param duration - Optional custom fade duration in milliseconds (uses fadeType default if not provided)
|
|
202
273
|
* @returns Promise that resolves when all toggles and fades are complete
|
|
203
274
|
* @example
|
|
204
275
|
* ```typescript
|
|
205
|
-
* await togglePauseAllWithFade(
|
|
276
|
+
* await togglePauseAllWithFade(FadeType.Gentle); // Global toggle with gentle fade
|
|
277
|
+
* await togglePauseAllWithFade(FadeType.Dramatic, 600); // Global toggle with custom 600ms fade
|
|
206
278
|
* ```
|
|
207
279
|
*/
|
|
208
|
-
export const togglePauseAllWithFade = async (
|
|
280
|
+
export const togglePauseAllWithFade = async (
|
|
281
|
+
fadeType: FadeType = FadeType.Gentle,
|
|
282
|
+
duration?: number
|
|
283
|
+
): Promise<void> => {
|
|
209
284
|
let hasPlayingChannel: boolean = false;
|
|
210
|
-
|
|
285
|
+
|
|
211
286
|
// Check if any channel is currently playing
|
|
212
|
-
for (let i = 0; i < audioChannels.length; i++) {
|
|
287
|
+
for (let i: number = 0; i < audioChannels.length; i++) {
|
|
213
288
|
const channel: ExtendedAudioQueueChannel = audioChannels[i];
|
|
214
289
|
if (channel && channel.queue.length > 0) {
|
|
215
290
|
const currentAudio: HTMLAudioElement = channel.queue[0];
|
|
@@ -219,13 +294,13 @@ export const togglePauseAllWithFade = async (fadeType: FadeType = FadeType.Gentl
|
|
|
219
294
|
}
|
|
220
295
|
}
|
|
221
296
|
}
|
|
222
|
-
|
|
297
|
+
|
|
223
298
|
// If any channel is playing, pause all with fade
|
|
224
299
|
// If no channels are playing, resume all with fade
|
|
225
300
|
if (hasPlayingChannel) {
|
|
226
|
-
await pauseAllWithFade(fadeType);
|
|
301
|
+
await pauseAllWithFade(fadeType, duration);
|
|
227
302
|
} else {
|
|
228
|
-
await resumeAllWithFade();
|
|
303
|
+
await resumeAllWithFade(fadeType, duration);
|
|
229
304
|
}
|
|
230
305
|
};
|
|
231
306
|
|
|
@@ -241,15 +316,19 @@ export const togglePauseAllWithFade = async (fadeType: FadeType = FadeType.Gentl
|
|
|
241
316
|
*/
|
|
242
317
|
export const pauseChannel = async (channelNumber: number = 0): Promise<void> => {
|
|
243
318
|
const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
|
|
244
|
-
|
|
319
|
+
|
|
245
320
|
if (channel && channel.queue.length > 0) {
|
|
246
321
|
const currentAudio: HTMLAudioElement = channel.queue[0];
|
|
247
|
-
|
|
322
|
+
|
|
248
323
|
if (!currentAudio.paused && !currentAudio.ended) {
|
|
249
324
|
currentAudio.pause();
|
|
250
325
|
channel.isPaused = true;
|
|
251
|
-
|
|
252
|
-
const audioInfo: AudioInfo | null = getAudioInfoFromElement(
|
|
326
|
+
|
|
327
|
+
const audioInfo: AudioInfo | null = getAudioInfoFromElement(
|
|
328
|
+
currentAudio,
|
|
329
|
+
channelNumber,
|
|
330
|
+
audioChannels
|
|
331
|
+
);
|
|
253
332
|
if (audioInfo) {
|
|
254
333
|
emitAudioPause(channelNumber, audioInfo, audioChannels);
|
|
255
334
|
}
|
|
@@ -269,16 +348,20 @@ export const pauseChannel = async (channelNumber: number = 0): Promise<void> =>
|
|
|
269
348
|
*/
|
|
270
349
|
export const resumeChannel = async (channelNumber: number = 0): Promise<void> => {
|
|
271
350
|
const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
|
|
272
|
-
|
|
351
|
+
|
|
273
352
|
if (channel && channel.queue.length > 0) {
|
|
274
353
|
const currentAudio: HTMLAudioElement = channel.queue[0];
|
|
275
|
-
|
|
354
|
+
|
|
276
355
|
// Only resume if both the channel is marked as paused AND the audio element is actually paused AND not ended
|
|
277
356
|
if (channel.isPaused && currentAudio.paused && !currentAudio.ended) {
|
|
278
357
|
await currentAudio.play();
|
|
279
358
|
channel.isPaused = false;
|
|
280
|
-
|
|
281
|
-
const audioInfo: AudioInfo | null = getAudioInfoFromElement(
|
|
359
|
+
|
|
360
|
+
const audioInfo: AudioInfo | null = getAudioInfoFromElement(
|
|
361
|
+
currentAudio,
|
|
362
|
+
channelNumber,
|
|
363
|
+
audioChannels
|
|
364
|
+
);
|
|
282
365
|
if (audioInfo) {
|
|
283
366
|
emitAudioResume(channelNumber, audioInfo, audioChannels);
|
|
284
367
|
}
|
|
@@ -297,10 +380,10 @@ export const resumeChannel = async (channelNumber: number = 0): Promise<void> =>
|
|
|
297
380
|
*/
|
|
298
381
|
export const togglePauseChannel = async (channelNumber: number = 0): Promise<void> => {
|
|
299
382
|
const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
|
|
300
|
-
|
|
383
|
+
|
|
301
384
|
if (channel && channel.queue.length > 0) {
|
|
302
385
|
const currentAudio: HTMLAudioElement = channel.queue[0];
|
|
303
|
-
|
|
386
|
+
|
|
304
387
|
if (currentAudio.paused) {
|
|
305
388
|
await resumeChannel(channelNumber);
|
|
306
389
|
} else {
|
|
@@ -319,11 +402,11 @@ export const togglePauseChannel = async (channelNumber: number = 0): Promise<voi
|
|
|
319
402
|
*/
|
|
320
403
|
export const pauseAllChannels = async (): Promise<void> => {
|
|
321
404
|
const pausePromises: Promise<void>[] = [];
|
|
322
|
-
|
|
405
|
+
|
|
323
406
|
audioChannels.forEach((_channel: ExtendedAudioQueueChannel, index: number) => {
|
|
324
407
|
pausePromises.push(pauseChannel(index));
|
|
325
408
|
});
|
|
326
|
-
|
|
409
|
+
|
|
327
410
|
await Promise.all(pausePromises);
|
|
328
411
|
};
|
|
329
412
|
|
|
@@ -337,11 +420,11 @@ export const pauseAllChannels = async (): Promise<void> => {
|
|
|
337
420
|
*/
|
|
338
421
|
export const resumeAllChannels = async (): Promise<void> => {
|
|
339
422
|
const resumePromises: Promise<void>[] = [];
|
|
340
|
-
|
|
423
|
+
|
|
341
424
|
audioChannels.forEach((_channel: ExtendedAudioQueueChannel, index: number) => {
|
|
342
425
|
resumePromises.push(resumeChannel(index));
|
|
343
426
|
});
|
|
344
|
-
|
|
427
|
+
|
|
345
428
|
await Promise.all(resumePromises);
|
|
346
429
|
};
|
|
347
430
|
|
|
@@ -357,7 +440,7 @@ export const resumeAllChannels = async (): Promise<void> => {
|
|
|
357
440
|
*/
|
|
358
441
|
export const isChannelPaused = (channelNumber: number = 0): boolean => {
|
|
359
442
|
const channel: ExtendedAudioQueueChannel = audioChannels[channelNumber];
|
|
360
|
-
return channel?.isPaused
|
|
443
|
+
return channel?.isPaused ?? false;
|
|
361
444
|
};
|
|
362
445
|
|
|
363
446
|
/**
|
|
@@ -372,9 +455,7 @@ export const isChannelPaused = (channelNumber: number = 0): boolean => {
|
|
|
372
455
|
* ```
|
|
373
456
|
*/
|
|
374
457
|
export const getAllChannelsPauseState = (): boolean[] => {
|
|
375
|
-
return audioChannels.map((channel: ExtendedAudioQueueChannel) =>
|
|
376
|
-
channel?.isPaused || false
|
|
377
|
-
);
|
|
458
|
+
return audioChannels.map((channel: ExtendedAudioQueueChannel) => channel?.isPaused ?? false);
|
|
378
459
|
};
|
|
379
460
|
|
|
380
461
|
/**
|
|
@@ -389,9 +470,9 @@ export const getAllChannelsPauseState = (): boolean[] => {
|
|
|
389
470
|
*/
|
|
390
471
|
export const togglePauseAllChannels = async (): Promise<void> => {
|
|
391
472
|
let hasPlayingChannel: boolean = false;
|
|
392
|
-
|
|
473
|
+
|
|
393
474
|
// Check if any channel is currently playing
|
|
394
|
-
for (let i = 0; i < audioChannels.length; i++) {
|
|
475
|
+
for (let i: number = 0; i < audioChannels.length; i++) {
|
|
395
476
|
const channel: ExtendedAudioQueueChannel = audioChannels[i];
|
|
396
477
|
if (channel && channel.queue.length > 0) {
|
|
397
478
|
const currentAudio: HTMLAudioElement = channel.queue[0];
|
|
@@ -401,7 +482,7 @@ export const togglePauseAllChannels = async (): Promise<void> => {
|
|
|
401
482
|
}
|
|
402
483
|
}
|
|
403
484
|
}
|
|
404
|
-
|
|
485
|
+
|
|
405
486
|
// If any channel is playing, pause all channels
|
|
406
487
|
// If no channels are playing, resume all channels
|
|
407
488
|
if (hasPlayingChannel) {
|
|
@@ -409,4 +490,4 @@ export const togglePauseAllChannels = async (): Promise<void> => {
|
|
|
409
490
|
} else {
|
|
410
491
|
await resumeAllChannels();
|
|
411
492
|
}
|
|
412
|
-
};
|
|
493
|
+
};
|