audio-channel-queue 1.3.0 → 1.5.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 CHANGED
@@ -1,5 +1,5 @@
1
- # Audio Queue Package
2
- The purpose of this package is to help queue audio files so they do not play on top of each other. You can also enqueue audio files to different queues. This allows you to play sounds concurrently, but not have them overlap in their given audio queue.
1
+ # Audio Channel Queue
2
+ The purpose of this package is to help queue audio files so they do not play on top of each other. You can also enqueue audio files to different queues. This allows you to play sounds concurrently, but not have them overlap in their given audio queue. The package also supports real-time audio progress tracking, duration information, and playback metadata! 🎵📊
3
3
 
4
4
  This package offers TypeScript support 📘, boasts zero dependencies 🚫, and is released under the MIT license 📜. As an added bonus, it's NON-GMO 🌱 and 100% Free Range Organic 🐓.
5
5
 
@@ -9,55 +9,291 @@ NPM package can be found [here](https://www.npmjs.com/package/audio-channel-queu
9
9
 
10
10
  GitHub Repo can be found [here](https://github.com/tonycarpenter21/audio-channel-queue).
11
11
 
12
+ ## Architecture & Code Organization 🏗️
13
+
14
+ Modular architecture for maintainability and extensibility:
15
+
16
+ ```
17
+ src/
18
+ ├── index.ts # Main entry point with organized exports
19
+ ├── types.ts # TypeScript interfaces and type definitions
20
+ ├── core.ts # Core queue management functions
21
+ ├── info.ts # Audio information and progress tracking
22
+ ├── events.ts # Event handling and emission logic
23
+ └── utils.ts # Helper functions and utilities
24
+ ```
25
+
12
26
  ## How To Install This Package:
13
27
  Install this package by running either of these commands (typescript packages are included automatically):
14
28
  - For npm run `npm install audio-channel-queue`
15
29
  - For yarn run `yarn add audio-channel-queue`
16
30
 
17
- ### How To Use This Package:
18
- ```queueAudio(audioFileGoesHere);```
31
+ ## Basic Queue Management Functions:
32
+
33
+ ### Queue Audio
34
+ ```queueAudio(audioFileGoesHere, channelNumber);```
19
35
  Use the `queueAudio()` function to add a file to the queue and start playing it automatically. It takes two arguments:
20
36
  - The first argument is an imported sound file.
21
37
  - The second argument is optional and it allows you to choose a different queue channel.
22
38
 
39
+ ### Stop Current Audio
23
40
  ```stopCurrentAudioInChannel(queueChannelNumberGoesHere);```
24
41
  Use the `stopCurrentAudioInChannel()` function to stop the current playback of a file in a queue and start playing the next one automatically. It takes one argument:
25
42
  - The first argument is optional and it allows you to choose a different queue channel. If you are only using the default channel, just use `stopCurrentAudioInChannel()`.
26
43
 
44
+ ### Stop All Audio in Channel
27
45
  ```stopAllAudioInChannel(queueChannelNumberGoesHere);```
28
46
  Use the `stopAllAudioInChannel()` function to stop the current playback of all files in a queue and removes all enqueued files. It takes one argument:
29
47
  - The first argument is optional and it allows you to choose a different queue channel. If you are only using the default channel, just use `stopAllAudioInChannel()`.
30
48
 
31
- ```stopAllAudio(queueChannelNumberGoesHere);```
49
+ ### Stop All Audio
50
+ ```stopAllAudio();```
32
51
  Use the `stopAllAudio()` function to stop the current playback of all files in all queues. It takes no arguments.
33
52
 
34
- If you need to expose the queue array for logging or other purposes, it is available to you as well: `audioChannels`.
53
+ ## Audio Information and Progress Tracking:
54
+
55
+ ### AudioInfo Interface
56
+ The package now provides detailed information about audio playback through the `AudioInfo` interface:
57
+ ```typescript
58
+ interface AudioInfo {
59
+ currentTime: number; // Current position in milliseconds
60
+ duration: number; // Total duration in milliseconds
61
+ fileName: string; // Extracted filename from URL
62
+ isPlaying: boolean; // Whether audio is currently playing
63
+ progress: number; // Progress as percentage (0-1)
64
+ src: string; // Audio file source URL
65
+ }
66
+ ```
35
67
 
36
- ### Example Usage in React:
68
+ ### Get Current Audio Info
69
+ ```getCurrentAudioInfo(channelNumber);```
70
+ Get information about the currently playing audio in a specific channel. Returns `AudioInfo | null`.
71
+ - `channelNumber` (optional): The channel number (defaults to 0)
72
+ - Returns `null` if no audio is currently playing in the channel
37
73
 
38
- `App.tsx`
74
+ ### Get All Channels Info
75
+ ```getAllChannelsInfo();```
76
+ Get audio information for all channels. Returns an array of `AudioInfo | null` objects.
77
+ - Returns an array where each index corresponds to a channel number
78
+ - `null` values indicate channels with no currently playing audio
79
+
80
+ ### Queue State Management
81
+ ```getQueueSnapshot(channelNumber);```
82
+ Get a complete snapshot of the queue state for a specific channel. Returns `QueueSnapshot | null`.
83
+
84
+ ```typescript
85
+ interface QueueSnapshot {
86
+ channelNumber: number; // Channel this snapshot represents
87
+ totalItems: number; // Total items in queue
88
+ currentIndex: number; // Index of currently playing item
89
+ items: Array<{ // Array of queue items with metadata
90
+ src: string;
91
+ fileName: string;
92
+ duration: number;
93
+ isCurrentlyPlaying: boolean;
94
+ }>;
95
+ }
39
96
  ```
97
+
98
+ ### Real-time Progress Tracking
99
+ ```onAudioProgress(channelNumber, callback);```
100
+ Subscribe to real-time progress updates for a specific channel.
101
+ - `channelNumber`: The channel number to monitor
102
+ - `callback`: Function that receives `AudioInfo` updates
103
+
104
+ ```offAudioProgress(channelNumber);```
105
+ Remove all progress listeners for a specific channel.
106
+ - `channelNumber`: The channel number to stop monitoring
107
+
108
+ ### Queue Change Events
109
+ ```onQueueChange(channelNumber, callback);```
110
+ Subscribe to queue change events for visual updates.
111
+ - Triggered when items are added, removed, or when playback moves to next item
112
+ - Perfect for updating UI queue displays
113
+
114
+ ```offQueueChange(channelNumber);```
115
+ Remove queue change listeners for a specific channel.
116
+
117
+ ### Audio Lifecycle Events
118
+ ```onAudioStart(channelNumber, callback);```
119
+ Subscribe to audio start events.
120
+ - Triggered when audio begins playing (after metadata loads)
121
+ - Provides duration, filename, and source information
122
+
123
+ ```onAudioComplete(channelNumber, callback);```
124
+ Subscribe to audio completion events.
125
+ - Triggered when audio finishes or is stopped
126
+ - Includes remaining queue count information
127
+
128
+ ### Example Usage with Progress Tracking:
129
+
130
+ `App.tsx`
131
+ ```typescript
40
132
  import redTeamWins from './audio/red_team_wins.mp3';
41
- import { queueAudio } from 'audio-channel-queue';
133
+ import {
134
+ queueAudio,
135
+ getCurrentAudioInfo,
136
+ onAudioProgress,
137
+ offAudioProgress,
138
+ onQueueChange,
139
+ onAudioStart,
140
+ onAudioComplete,
141
+ getQueueSnapshot,
142
+ AudioInfo,
143
+ QueueSnapshot
144
+ } from 'audio-channel-queue';
145
+ import { useState, useEffect } from 'react';
42
146
 
43
147
  function App(): JSX.Element {
148
+ const [currentInfo, setCurrentInfo] = useState<AudioInfo | null>(null);
149
+ const [queueSnapshot, setQueueSnapshot] = useState<QueueSnapshot | null>(null);
150
+ const [isTracking, setIsTracking] = useState(false);
151
+
152
+ const playSound = () => {
153
+ queueAudio(redTeamWins);
154
+
155
+ // Get initial audio info
156
+ setTimeout(() => {
157
+ const info = getCurrentAudioInfo();
158
+ setCurrentInfo(info);
159
+ }, 100);
160
+ };
161
+
162
+ const startTracking = () => {
163
+ setIsTracking(true);
164
+
165
+ // Track real-time progress
166
+ onAudioProgress(0, (info: AudioInfo) => {
167
+ setCurrentInfo(info);
168
+ console.log(`Progress: ${(info.progress * 100).toFixed(1)}%`);
169
+ });
170
+
171
+ // Track queue changes
172
+ onQueueChange(0, (snapshot: QueueSnapshot) => {
173
+ setQueueSnapshot(snapshot);
174
+ console.log(`Queue updated: ${snapshot.totalItems} items`);
175
+ });
176
+
177
+ // Track audio lifecycle
178
+ onAudioStart(0, (info) => {
179
+ console.log(`Started playing: ${info.fileName}`);
180
+ });
181
+
182
+ onAudioComplete(0, (info) => {
183
+ console.log(`Completed: ${info.fileName}, ${info.remainingInQueue} remaining`);
184
+ });
185
+ };
186
+
187
+ const stopTracking = () => {
188
+ setIsTracking(false);
189
+ offAudioProgress(0);
190
+ offQueueChange(0);
191
+ };
192
+
193
+ const addMoreAudio = () => {
194
+ queueAudio('./sounds/notification.wav');
195
+ queueAudio('./sounds/alert.mp3');
196
+ };
44
197
 
45
198
  return (
46
199
  <div className="App">
47
- <button onClick={()=> queueAudio(redTeamWins)}>Play sound</button>
200
+ <button onClick={playSound}>Play Sound</button>
201
+ <button onClick={addMoreAudio}>Add More to Queue</button>
202
+ <button onClick={startTracking} disabled={isTracking}>
203
+ Start Progress Tracking
204
+ </button>
205
+ <button onClick={stopTracking} disabled={!isTracking}>
206
+ Stop Progress Tracking
207
+ </button>
208
+
209
+ {currentInfo && (
210
+ <div>
211
+ <h3>Now Playing:</h3>
212
+ <p>File: {currentInfo.fileName}</p>
213
+ <p>Duration: {(currentInfo.duration / 1000).toFixed(1)}s</p>
214
+ <p>Current Time: {(currentInfo.currentTime / 1000).toFixed(1)}s</p>
215
+ <p>Progress: {(currentInfo.progress * 100).toFixed(1)}%</p>
216
+ <p>Playing: {currentInfo.isPlaying ? 'Yes' : 'No'}</p>
217
+ </div>
218
+ )}
219
+
220
+ {queueSnapshot && (
221
+ <div>
222
+ <h3>Queue Status:</h3>
223
+ <p>Channel: {queueSnapshot.channelNumber}</p>
224
+ <p>Total Items: {queueSnapshot.totalItems}</p>
225
+ <p>Current Index: {queueSnapshot.currentIndex}</p>
226
+ <ul>
227
+ {queueSnapshot.items.map((item, index) => (
228
+ <li key={index} style={{
229
+ fontWeight: item.isCurrentlyPlaying ? 'bold' : 'normal'
230
+ }}>
231
+ {item.fileName} ({(item.duration / 1000).toFixed(1)}s)
232
+ {item.isCurrentlyPlaying && ' ▶️'}
233
+ </li>
234
+ ))}
235
+ </ul>
236
+ </div>
237
+ )}
48
238
  </div>
49
- )
50
- };
239
+ );
240
+ }
51
241
 
52
242
  export default App;
53
243
  ```
54
244
 
245
+ ### Legacy Access
246
+ If you need to expose the queue array for logging or other purposes, it is available to you as well: `audioChannels`.
247
+
248
+ ### TypeScript Support
55
249
  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:
56
250
 
57
251
  `custom.d.ts`
58
- ```
252
+ ```typescript
59
253
  declare module '*.mp3' {
60
254
  const src: string;
61
255
  export default src;
62
256
  }
63
- ```
257
+ ```
258
+
259
+ ## Features:
260
+ - ✅ Queue management across multiple channels
261
+ - ✅ Real-time audio progress tracking
262
+ - ✅ Audio duration and metadata extraction
263
+ - ✅ Automatic filename extraction from URLs
264
+ - ✅ Queue state snapshots and change events
265
+ - ✅ Audio lifecycle events (start/complete)
266
+ - ✅ TypeScript support with full type definitions
267
+ - ✅ Modular architecture with clean separation of concerns
268
+ - ✅ Comprehensive JSDoc documentation with examples
269
+ - ✅ Zero dependencies
270
+ - ✅ Backward compatible with existing implementations
271
+ - ✅ Comprehensive error handling
272
+
273
+ ## Development & Contributing 🛠️
274
+
275
+ The package uses a modular TypeScript architecture that makes it easy to contribute and extend:
276
+
277
+ ### File Structure:
278
+ - **`src/types.ts`** - Interface definitions and type exports
279
+ - **`src/core.ts`** - Main queue management logic
280
+ - **`src/info.ts`** - Audio information and progress tracking
281
+ - **`src/events.ts`** - Event system and callback management
282
+ - **`src/utils.ts`** - Helper functions and utilities
283
+ - **`src/index.ts`** - Public API exports
284
+
285
+ ### Testing:
286
+ The package includes a comprehensive test suite with 64+ tests covering all functionality:
287
+
288
+ ```bash
289
+ # Run tests once
290
+ npm test
291
+
292
+ # Run tests in watch mode during development
293
+ npm run test:watch
294
+
295
+ # Run tests with coverage report
296
+ npm run test:coverage
297
+ ```
298
+
299
+ **Test Coverage**: 85%+ code coverage across all modules with realistic HTMLAudioElement mocking using jsdom.
package/dist/core.d.ts ADDED
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @fileoverview Core queue management functions for the audio-channel-queue package
3
+ */
4
+ /**
5
+ * Queues an audio file to a specific channel and starts playing if it's the first in queue
6
+ * @param audioUrl - The URL of the audio file to queue
7
+ * @param channelNumber - The channel number to queue the audio to (defaults to 0)
8
+ * @returns Promise that resolves when the audio is queued and starts playing (if first in queue)
9
+ * @example
10
+ * ```typescript
11
+ * await queueAudio('https://example.com/song.mp3', 0);
12
+ * await queueAudio('./sounds/notification.wav'); // Uses default channel 0
13
+ * ```
14
+ */
15
+ export declare const queueAudio: (audioUrl: string, channelNumber?: number) => Promise<void>;
16
+ /**
17
+ * Plays the audio queue for a specific channel
18
+ * @param channelNumber - The channel number to play
19
+ * @returns Promise that resolves when the current audio finishes playing
20
+ * @example
21
+ * ```typescript
22
+ * await playAudioQueue(0); // Play queue for channel 0
23
+ * ```
24
+ */
25
+ export declare const playAudioQueue: (channelNumber: number) => Promise<void>;
26
+ /**
27
+ * Stops the currently playing audio in a specific channel and plays the next audio in queue
28
+ * @param channelNumber - The channel number (defaults to 0)
29
+ * @example
30
+ * ```typescript
31
+ * stopCurrentAudioInChannel(0); // Stop current audio in channel 0
32
+ * stopCurrentAudioInChannel(); // Stop current audio in default channel
33
+ * ```
34
+ */
35
+ export declare const stopCurrentAudioInChannel: (channelNumber?: number) => void;
36
+ /**
37
+ * Stops all audio in a specific channel and clears the entire queue
38
+ * @param channelNumber - The channel number (defaults to 0)
39
+ * @example
40
+ * ```typescript
41
+ * stopAllAudioInChannel(0); // Clear all audio in channel 0
42
+ * stopAllAudioInChannel(); // Clear all audio in default channel
43
+ * ```
44
+ */
45
+ export declare const stopAllAudioInChannel: (channelNumber?: number) => void;
46
+ /**
47
+ * Stops all audio across all channels and clears all queues
48
+ * @example
49
+ * ```typescript
50
+ * stopAllAudio(); // Emergency stop - clears everything
51
+ * ```
52
+ */
53
+ export declare const stopAllAudio: () => void;
package/dist/core.js ADDED
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Core queue management functions for the audio-channel-queue package
4
+ */
5
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
6
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7
+ return new (P || (P = Promise))(function (resolve, reject) {
8
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
9
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
10
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
11
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
12
+ });
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.stopAllAudio = exports.stopAllAudioInChannel = exports.stopCurrentAudioInChannel = exports.playAudioQueue = exports.queueAudio = void 0;
16
+ const info_1 = require("./info");
17
+ const utils_1 = require("./utils");
18
+ const events_1 = require("./events");
19
+ /**
20
+ * Queues an audio file to a specific channel and starts playing if it's the first in queue
21
+ * @param audioUrl - The URL of the audio file to queue
22
+ * @param channelNumber - The channel number to queue the audio to (defaults to 0)
23
+ * @returns Promise that resolves when the audio is queued and starts playing (if first in queue)
24
+ * @example
25
+ * ```typescript
26
+ * await queueAudio('https://example.com/song.mp3', 0);
27
+ * await queueAudio('./sounds/notification.wav'); // Uses default channel 0
28
+ * ```
29
+ */
30
+ const queueAudio = (audioUrl_1, ...args_1) => __awaiter(void 0, [audioUrl_1, ...args_1], void 0, function* (audioUrl, channelNumber = 0) {
31
+ if (!info_1.audioChannels[channelNumber]) {
32
+ info_1.audioChannels[channelNumber] = {
33
+ audioCompleteCallbacks: new Set(),
34
+ audioStartCallbacks: new Set(),
35
+ progressCallbacks: new Map(),
36
+ queue: [],
37
+ queueChangeCallbacks: new Set()
38
+ };
39
+ }
40
+ const audio = new Audio(audioUrl);
41
+ info_1.audioChannels[channelNumber].queue.push(audio);
42
+ (0, events_1.emitQueueChange)(channelNumber, info_1.audioChannels);
43
+ if (info_1.audioChannels[channelNumber].queue.length === 1) {
44
+ (0, exports.playAudioQueue)(channelNumber);
45
+ }
46
+ });
47
+ exports.queueAudio = queueAudio;
48
+ /**
49
+ * Plays the audio queue for a specific channel
50
+ * @param channelNumber - The channel number to play
51
+ * @returns Promise that resolves when the current audio finishes playing
52
+ * @example
53
+ * ```typescript
54
+ * await playAudioQueue(0); // Play queue for channel 0
55
+ * ```
56
+ */
57
+ const playAudioQueue = (channelNumber) => __awaiter(void 0, void 0, void 0, function* () {
58
+ const channel = info_1.audioChannels[channelNumber];
59
+ if (channel.queue.length === 0)
60
+ return;
61
+ const currentAudio = channel.queue[0];
62
+ (0, events_1.setupProgressTracking)(currentAudio, channelNumber, info_1.audioChannels);
63
+ return new Promise((resolve) => {
64
+ let hasStarted = false;
65
+ let metadataLoaded = false;
66
+ let playStarted = false;
67
+ // Check if we should fire onAudioStart (both conditions met)
68
+ const tryFireAudioStart = () => {
69
+ if (!hasStarted && metadataLoaded && playStarted) {
70
+ hasStarted = true;
71
+ (0, events_1.emitAudioStart)(channelNumber, {
72
+ channelNumber,
73
+ duration: currentAudio.duration * 1000, // Now guaranteed to have valid duration
74
+ fileName: (0, utils_1.extractFileName)(currentAudio.src),
75
+ src: currentAudio.src
76
+ }, info_1.audioChannels);
77
+ }
78
+ };
79
+ // Event handler for when metadata loads (duration becomes available)
80
+ const handleLoadedMetadata = () => {
81
+ metadataLoaded = true;
82
+ tryFireAudioStart();
83
+ };
84
+ // Event handler for when audio actually starts playing
85
+ const handlePlay = () => {
86
+ playStarted = true;
87
+ tryFireAudioStart();
88
+ };
89
+ // Event handler for when audio ends
90
+ const handleEnded = () => __awaiter(void 0, void 0, void 0, function* () {
91
+ (0, events_1.emitAudioComplete)(channelNumber, {
92
+ channelNumber,
93
+ fileName: (0, utils_1.extractFileName)(currentAudio.src),
94
+ remainingInQueue: channel.queue.length - 1,
95
+ src: currentAudio.src
96
+ }, info_1.audioChannels);
97
+ // Clean up event listeners
98
+ currentAudio.removeEventListener('loadedmetadata', handleLoadedMetadata);
99
+ currentAudio.removeEventListener('play', handlePlay);
100
+ currentAudio.removeEventListener('ended', handleEnded);
101
+ (0, events_1.cleanupProgressTracking)(currentAudio, channelNumber, info_1.audioChannels);
102
+ channel.queue.shift();
103
+ // Emit queue change after completion
104
+ setTimeout(() => (0, events_1.emitQueueChange)(channelNumber, info_1.audioChannels), 10);
105
+ yield (0, exports.playAudioQueue)(channelNumber);
106
+ resolve();
107
+ });
108
+ // Add event listeners
109
+ currentAudio.addEventListener('loadedmetadata', handleLoadedMetadata);
110
+ currentAudio.addEventListener('play', handlePlay);
111
+ currentAudio.addEventListener('ended', handleEnded);
112
+ // Check if metadata is already loaded (in case it loads before we add the listener)
113
+ if (currentAudio.readyState >= 1) { // HAVE_METADATA or higher
114
+ metadataLoaded = true;
115
+ }
116
+ currentAudio.play();
117
+ });
118
+ });
119
+ exports.playAudioQueue = playAudioQueue;
120
+ /**
121
+ * Stops the currently playing audio in a specific channel and plays the next audio in queue
122
+ * @param channelNumber - The channel number (defaults to 0)
123
+ * @example
124
+ * ```typescript
125
+ * stopCurrentAudioInChannel(0); // Stop current audio in channel 0
126
+ * stopCurrentAudioInChannel(); // Stop current audio in default channel
127
+ * ```
128
+ */
129
+ const stopCurrentAudioInChannel = (channelNumber = 0) => {
130
+ const channel = info_1.audioChannels[channelNumber];
131
+ if (channel && channel.queue.length > 0) {
132
+ const currentAudio = channel.queue[0];
133
+ (0, events_1.emitAudioComplete)(channelNumber, {
134
+ channelNumber,
135
+ fileName: (0, utils_1.extractFileName)(currentAudio.src),
136
+ remainingInQueue: channel.queue.length - 1,
137
+ src: currentAudio.src
138
+ }, info_1.audioChannels);
139
+ currentAudio.pause();
140
+ (0, events_1.cleanupProgressTracking)(currentAudio, channelNumber, info_1.audioChannels);
141
+ channel.queue.shift();
142
+ (0, events_1.emitQueueChange)(channelNumber, info_1.audioChannels);
143
+ (0, exports.playAudioQueue)(channelNumber);
144
+ }
145
+ };
146
+ exports.stopCurrentAudioInChannel = stopCurrentAudioInChannel;
147
+ /**
148
+ * Stops all audio in a specific channel and clears the entire queue
149
+ * @param channelNumber - The channel number (defaults to 0)
150
+ * @example
151
+ * ```typescript
152
+ * stopAllAudioInChannel(0); // Clear all audio in channel 0
153
+ * stopAllAudioInChannel(); // Clear all audio in default channel
154
+ * ```
155
+ */
156
+ const stopAllAudioInChannel = (channelNumber = 0) => {
157
+ const channel = info_1.audioChannels[channelNumber];
158
+ if (channel) {
159
+ if (channel.queue.length > 0) {
160
+ const currentAudio = channel.queue[0];
161
+ (0, events_1.emitAudioComplete)(channelNumber, {
162
+ channelNumber,
163
+ fileName: (0, utils_1.extractFileName)(currentAudio.src),
164
+ remainingInQueue: 0, // Will be 0 since we're clearing the queue
165
+ src: currentAudio.src
166
+ }, info_1.audioChannels);
167
+ currentAudio.pause();
168
+ (0, events_1.cleanupProgressTracking)(currentAudio, channelNumber, info_1.audioChannels);
169
+ }
170
+ // Clean up all progress tracking for this channel
171
+ channel.queue.forEach(audio => (0, events_1.cleanupProgressTracking)(audio, channelNumber, info_1.audioChannels));
172
+ channel.queue = [];
173
+ (0, events_1.emitQueueChange)(channelNumber, info_1.audioChannels);
174
+ }
175
+ };
176
+ exports.stopAllAudioInChannel = stopAllAudioInChannel;
177
+ /**
178
+ * Stops all audio across all channels and clears all queues
179
+ * @example
180
+ * ```typescript
181
+ * stopAllAudio(); // Emergency stop - clears everything
182
+ * ```
183
+ */
184
+ const stopAllAudio = () => {
185
+ info_1.audioChannels.forEach((_channel, index) => {
186
+ (0, exports.stopAllAudioInChannel)(index);
187
+ });
188
+ };
189
+ exports.stopAllAudio = stopAllAudio;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @fileoverview Event handling and emission for the audio-channel-queue package
3
+ */
4
+ import { AudioStartInfo, AudioCompleteInfo, ExtendedAudioQueueChannel } from './types';
5
+ /**
6
+ * Emits a queue change event to all registered listeners for a specific channel
7
+ * @param channelNumber - The channel number that experienced a queue change
8
+ * @param audioChannels - Array of audio channels
9
+ * @example
10
+ * ```typescript
11
+ * emitQueueChange(0, audioChannels); // Notifies all queue change listeners
12
+ * ```
13
+ */
14
+ export declare const emitQueueChange: (channelNumber: number, audioChannels: ExtendedAudioQueueChannel[]) => void;
15
+ /**
16
+ * Emits an audio start event to all registered listeners for a specific channel
17
+ * @param channelNumber - The channel number where audio started
18
+ * @param audioInfo - Information about the audio that started
19
+ * @param audioChannels - Array of audio channels
20
+ * @example
21
+ * ```typescript
22
+ * emitAudioStart(0, { src: 'song.mp3', fileName: 'song.mp3', duration: 180000, channelNumber: 0 }, audioChannels);
23
+ * ```
24
+ */
25
+ export declare const emitAudioStart: (channelNumber: number, audioInfo: AudioStartInfo, audioChannels: ExtendedAudioQueueChannel[]) => void;
26
+ /**
27
+ * Emits an audio complete event to all registered listeners for a specific channel
28
+ * @param channelNumber - The channel number where audio completed
29
+ * @param audioInfo - Information about the audio that completed
30
+ * @param audioChannels - Array of audio channels
31
+ * @example
32
+ * ```typescript
33
+ * emitAudioComplete(0, { src: 'song.mp3', fileName: 'song.mp3', channelNumber: 0, remainingInQueue: 2 }, audioChannels);
34
+ * ```
35
+ */
36
+ export declare const emitAudioComplete: (channelNumber: number, audioInfo: AudioCompleteInfo, audioChannels: ExtendedAudioQueueChannel[]) => void;
37
+ /**
38
+ * Sets up comprehensive progress tracking for an audio element
39
+ * @param audio - The HTML audio element to track
40
+ * @param channelNumber - The channel number this audio belongs to
41
+ * @param audioChannels - Array of audio channels
42
+ * @example
43
+ * ```typescript
44
+ * const audioElement = new Audio('song.mp3');
45
+ * setupProgressTracking(audioElement, 0, audioChannels);
46
+ * ```
47
+ */
48
+ export declare const setupProgressTracking: (audio: HTMLAudioElement, channelNumber: number, audioChannels: ExtendedAudioQueueChannel[]) => void;
49
+ /**
50
+ * Cleans up progress tracking for an audio element to prevent memory leaks
51
+ * @param audio - The HTML audio element to clean up
52
+ * @param channelNumber - The channel number this audio belongs to
53
+ * @param audioChannels - Array of audio channels
54
+ * @example
55
+ * ```typescript
56
+ * cleanupProgressTracking(audioElement, 0, audioChannels);
57
+ * ```
58
+ */
59
+ export declare const cleanupProgressTracking: (audio: HTMLAudioElement, channelNumber: number, audioChannels: ExtendedAudioQueueChannel[]) => void;