audio-channel-queue 1.4.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/dist/events.js ADDED
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Event handling and emission for the audio-channel-queue package
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.cleanupProgressTracking = exports.setupProgressTracking = exports.emitAudioComplete = exports.emitAudioStart = exports.emitQueueChange = void 0;
7
+ const utils_1 = require("./utils");
8
+ /**
9
+ * Emits a queue change event to all registered listeners for a specific channel
10
+ * @param channelNumber - The channel number that experienced a queue change
11
+ * @param audioChannels - Array of audio channels
12
+ * @example
13
+ * ```typescript
14
+ * emitQueueChange(0, audioChannels); // Notifies all queue change listeners
15
+ * ```
16
+ */
17
+ const emitQueueChange = (channelNumber, audioChannels) => {
18
+ const channel = audioChannels[channelNumber];
19
+ if (!channel || !channel.queueChangeCallbacks)
20
+ return;
21
+ const snapshot = (0, utils_1.createQueueSnapshot)(channelNumber, audioChannels);
22
+ if (!snapshot)
23
+ return;
24
+ channel.queueChangeCallbacks.forEach(callback => {
25
+ try {
26
+ callback(snapshot);
27
+ }
28
+ catch (error) {
29
+ console.error('Error in queue change callback:', error);
30
+ }
31
+ });
32
+ };
33
+ exports.emitQueueChange = emitQueueChange;
34
+ /**
35
+ * Emits an audio start event to all registered listeners for a specific channel
36
+ * @param channelNumber - The channel number where audio started
37
+ * @param audioInfo - Information about the audio that started
38
+ * @param audioChannels - Array of audio channels
39
+ * @example
40
+ * ```typescript
41
+ * emitAudioStart(0, { src: 'song.mp3', fileName: 'song.mp3', duration: 180000, channelNumber: 0 }, audioChannels);
42
+ * ```
43
+ */
44
+ const emitAudioStart = (channelNumber, audioInfo, audioChannels) => {
45
+ const channel = audioChannels[channelNumber];
46
+ if (!channel || !channel.audioStartCallbacks)
47
+ return;
48
+ channel.audioStartCallbacks.forEach(callback => {
49
+ try {
50
+ callback(audioInfo);
51
+ }
52
+ catch (error) {
53
+ console.error('Error in audio start callback:', error);
54
+ }
55
+ });
56
+ };
57
+ exports.emitAudioStart = emitAudioStart;
58
+ /**
59
+ * Emits an audio complete event to all registered listeners for a specific channel
60
+ * @param channelNumber - The channel number where audio completed
61
+ * @param audioInfo - Information about the audio that completed
62
+ * @param audioChannels - Array of audio channels
63
+ * @example
64
+ * ```typescript
65
+ * emitAudioComplete(0, { src: 'song.mp3', fileName: 'song.mp3', channelNumber: 0, remainingInQueue: 2 }, audioChannels);
66
+ * ```
67
+ */
68
+ const emitAudioComplete = (channelNumber, audioInfo, audioChannels) => {
69
+ const channel = audioChannels[channelNumber];
70
+ if (!channel || !channel.audioCompleteCallbacks)
71
+ return;
72
+ channel.audioCompleteCallbacks.forEach(callback => {
73
+ try {
74
+ callback(audioInfo);
75
+ }
76
+ catch (error) {
77
+ console.error('Error in audio complete callback:', error);
78
+ }
79
+ });
80
+ };
81
+ exports.emitAudioComplete = emitAudioComplete;
82
+ // Store listener functions for cleanup
83
+ const progressListeners = new WeakMap();
84
+ /**
85
+ * Sets up comprehensive progress tracking for an audio element
86
+ * @param audio - The HTML audio element to track
87
+ * @param channelNumber - The channel number this audio belongs to
88
+ * @param audioChannels - Array of audio channels
89
+ * @example
90
+ * ```typescript
91
+ * const audioElement = new Audio('song.mp3');
92
+ * setupProgressTracking(audioElement, 0, audioChannels);
93
+ * ```
94
+ */
95
+ const setupProgressTracking = (audio, channelNumber, audioChannels) => {
96
+ const channel = audioChannels[channelNumber];
97
+ if (!channel)
98
+ return;
99
+ if (!channel.progressCallbacks) {
100
+ channel.progressCallbacks = new Map();
101
+ }
102
+ // Don't set up tracking if already exists
103
+ if (progressListeners.has(audio))
104
+ return;
105
+ const updateProgress = () => {
106
+ var _a, _b;
107
+ // Get callbacks for this specific audio element AND the channel-wide callbacks
108
+ const audioCallbacks = ((_a = channel.progressCallbacks) === null || _a === void 0 ? void 0 : _a.get(audio)) || new Set();
109
+ const channelCallbacks = ((_b = channel.progressCallbacks) === null || _b === void 0 ? void 0 : _b.get(null)) || new Set();
110
+ // Combine both sets of callbacks
111
+ const allCallbacks = new Set([...audioCallbacks, ...channelCallbacks]);
112
+ if (allCallbacks.size === 0)
113
+ return;
114
+ const info = (0, utils_1.getAudioInfoFromElement)(audio);
115
+ if (info) {
116
+ allCallbacks.forEach((callback) => {
117
+ try {
118
+ callback(info);
119
+ }
120
+ catch (error) {
121
+ console.error('Error in progress callback:', error);
122
+ }
123
+ });
124
+ }
125
+ };
126
+ // Store the listener function for cleanup
127
+ progressListeners.set(audio, updateProgress);
128
+ // Set up comprehensive event listeners for progress tracking
129
+ audio.addEventListener('timeupdate', updateProgress);
130
+ audio.addEventListener('loadedmetadata', updateProgress);
131
+ audio.addEventListener('play', updateProgress);
132
+ audio.addEventListener('pause', updateProgress);
133
+ audio.addEventListener('ended', updateProgress);
134
+ };
135
+ exports.setupProgressTracking = setupProgressTracking;
136
+ /**
137
+ * Cleans up progress tracking for an audio element to prevent memory leaks
138
+ * @param audio - The HTML audio element to clean up
139
+ * @param channelNumber - The channel number this audio belongs to
140
+ * @param audioChannels - Array of audio channels
141
+ * @example
142
+ * ```typescript
143
+ * cleanupProgressTracking(audioElement, 0, audioChannels);
144
+ * ```
145
+ */
146
+ const cleanupProgressTracking = (audio, channelNumber, audioChannels) => {
147
+ const channel = audioChannels[channelNumber];
148
+ if (!channel || !channel.progressCallbacks)
149
+ return;
150
+ // Remove event listeners
151
+ const updateProgress = progressListeners.get(audio);
152
+ if (updateProgress) {
153
+ audio.removeEventListener('timeupdate', updateProgress);
154
+ audio.removeEventListener('loadedmetadata', updateProgress);
155
+ audio.removeEventListener('play', updateProgress);
156
+ audio.removeEventListener('pause', updateProgress);
157
+ audio.removeEventListener('ended', updateProgress);
158
+ progressListeners.delete(audio);
159
+ }
160
+ channel.progressCallbacks.delete(audio);
161
+ };
162
+ exports.cleanupProgressTracking = cleanupProgressTracking;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @fileoverview Main entry point for the audio-channel-queue package
3
+ *
4
+ * A comprehensive audio queue management system with real-time progress tracking,
5
+ * multi-channel support, and extensive event handling capabilities.
6
+ *
7
+ * @example Basic Usage
8
+ * ```typescript
9
+ * import { queueAudio, onAudioProgress } from 'audio-channel-queue';
10
+ *
11
+ * // Queue an audio file
12
+ * await queueAudio('song.mp3');
13
+ *
14
+ * // Track progress
15
+ * onAudioProgress(0, (info) => {
16
+ * console.log(`Progress: ${info.progress * 100}%`);
17
+ * });
18
+ * ```
19
+ */
20
+ export type { AudioCompleteCallback, AudioCompleteInfo, AudioInfo, AudioQueue, AudioQueueChannel, AudioStartCallback, AudioStartInfo, ExtendedAudioQueueChannel, ProgressCallback, QueueChangeCallback, QueueItem, QueueSnapshot } from './types';
21
+ export { playAudioQueue, queueAudio, stopAllAudio, stopAllAudioInChannel, stopCurrentAudioInChannel } from './core';
22
+ export { audioChannels, getAllChannelsInfo, getCurrentAudioInfo, getQueueSnapshot, offAudioProgress, onAudioComplete, onAudioProgress, onAudioStart, onQueueChange, offQueueChange } from './info';
23
+ export { cleanWebpackFilename, createQueueSnapshot, extractFileName, getAudioInfoFromElement } from './utils';
package/dist/index.js ADDED
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Main entry point for the audio-channel-queue package
4
+ *
5
+ * A comprehensive audio queue management system with real-time progress tracking,
6
+ * multi-channel support, and extensive event handling capabilities.
7
+ *
8
+ * @example Basic Usage
9
+ * ```typescript
10
+ * import { queueAudio, onAudioProgress } from 'audio-channel-queue';
11
+ *
12
+ * // Queue an audio file
13
+ * await queueAudio('song.mp3');
14
+ *
15
+ * // Track progress
16
+ * onAudioProgress(0, (info) => {
17
+ * console.log(`Progress: ${info.progress * 100}%`);
18
+ * });
19
+ * ```
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.getAudioInfoFromElement = exports.extractFileName = exports.createQueueSnapshot = exports.cleanWebpackFilename = exports.offQueueChange = exports.onQueueChange = exports.onAudioStart = exports.onAudioProgress = exports.onAudioComplete = exports.offAudioProgress = exports.getQueueSnapshot = exports.getCurrentAudioInfo = exports.getAllChannelsInfo = exports.audioChannels = exports.stopCurrentAudioInChannel = exports.stopAllAudioInChannel = exports.stopAllAudio = exports.queueAudio = exports.playAudioQueue = void 0;
23
+ // Export core queue management functions
24
+ var core_1 = require("./core");
25
+ Object.defineProperty(exports, "playAudioQueue", { enumerable: true, get: function () { return core_1.playAudioQueue; } });
26
+ Object.defineProperty(exports, "queueAudio", { enumerable: true, get: function () { return core_1.queueAudio; } });
27
+ Object.defineProperty(exports, "stopAllAudio", { enumerable: true, get: function () { return core_1.stopAllAudio; } });
28
+ Object.defineProperty(exports, "stopAllAudioInChannel", { enumerable: true, get: function () { return core_1.stopAllAudioInChannel; } });
29
+ Object.defineProperty(exports, "stopCurrentAudioInChannel", { enumerable: true, get: function () { return core_1.stopCurrentAudioInChannel; } });
30
+ // Export audio information and progress tracking functions
31
+ var info_1 = require("./info");
32
+ Object.defineProperty(exports, "audioChannels", { enumerable: true, get: function () { return info_1.audioChannels; } });
33
+ Object.defineProperty(exports, "getAllChannelsInfo", { enumerable: true, get: function () { return info_1.getAllChannelsInfo; } });
34
+ Object.defineProperty(exports, "getCurrentAudioInfo", { enumerable: true, get: function () { return info_1.getCurrentAudioInfo; } });
35
+ Object.defineProperty(exports, "getQueueSnapshot", { enumerable: true, get: function () { return info_1.getQueueSnapshot; } });
36
+ Object.defineProperty(exports, "offAudioProgress", { enumerable: true, get: function () { return info_1.offAudioProgress; } });
37
+ Object.defineProperty(exports, "onAudioComplete", { enumerable: true, get: function () { return info_1.onAudioComplete; } });
38
+ Object.defineProperty(exports, "onAudioProgress", { enumerable: true, get: function () { return info_1.onAudioProgress; } });
39
+ Object.defineProperty(exports, "onAudioStart", { enumerable: true, get: function () { return info_1.onAudioStart; } });
40
+ Object.defineProperty(exports, "onQueueChange", { enumerable: true, get: function () { return info_1.onQueueChange; } });
41
+ Object.defineProperty(exports, "offQueueChange", { enumerable: true, get: function () { return info_1.offQueueChange; } });
42
+ // Export utility functions (for advanced usage)
43
+ var utils_1 = require("./utils");
44
+ Object.defineProperty(exports, "cleanWebpackFilename", { enumerable: true, get: function () { return utils_1.cleanWebpackFilename; } });
45
+ Object.defineProperty(exports, "createQueueSnapshot", { enumerable: true, get: function () { return utils_1.createQueueSnapshot; } });
46
+ Object.defineProperty(exports, "extractFileName", { enumerable: true, get: function () { return utils_1.extractFileName; } });
47
+ Object.defineProperty(exports, "getAudioInfoFromElement", { enumerable: true, get: function () { return utils_1.getAudioInfoFromElement; } });
package/dist/info.d.ts ADDED
@@ -0,0 +1,122 @@
1
+ /**
2
+ * @fileoverview Audio information and progress tracking functions for the audio-channel-queue package
3
+ */
4
+ import { AudioInfo, QueueSnapshot, ProgressCallback, QueueChangeCallback, AudioStartCallback, AudioCompleteCallback, ExtendedAudioQueueChannel } from './types';
5
+ /**
6
+ * Global array of extended audio queue channels
7
+ */
8
+ export declare const audioChannels: ExtendedAudioQueueChannel[];
9
+ /**
10
+ * Gets current audio information for a specific channel
11
+ * @param channelNumber - The channel number (defaults to 0)
12
+ * @returns AudioInfo object or null if no audio is playing
13
+ * @example
14
+ * ```typescript
15
+ * const info = getCurrentAudioInfo(0);
16
+ * if (info) {
17
+ * console.log(`Currently playing: ${info.fileName}`);
18
+ * console.log(`Progress: ${(info.progress * 100).toFixed(1)}%`);
19
+ * }
20
+ * ```
21
+ */
22
+ export declare const getCurrentAudioInfo: (channelNumber?: number) => AudioInfo | null;
23
+ /**
24
+ * Gets audio information for all channels
25
+ * @returns Array of AudioInfo objects (null for channels with no audio)
26
+ * @example
27
+ * ```typescript
28
+ * const allInfo = getAllChannelsInfo();
29
+ * allInfo.forEach((info, channel) => {
30
+ * if (info) {
31
+ * console.log(`Channel ${channel}: ${info.fileName}`);
32
+ * }
33
+ * });
34
+ * ```
35
+ */
36
+ export declare const getAllChannelsInfo: () => (AudioInfo | null)[];
37
+ /**
38
+ * Gets a complete snapshot of the queue state for a specific channel
39
+ * @param channelNumber - The channel number
40
+ * @returns QueueSnapshot object or null if channel doesn't exist
41
+ * @example
42
+ * ```typescript
43
+ * const snapshot = getQueueSnapshot(0);
44
+ * if (snapshot) {
45
+ * console.log(`Queue has ${snapshot.totalItems} items`);
46
+ * console.log(`Currently playing: ${snapshot.items[0]?.fileName}`);
47
+ * }
48
+ * ```
49
+ */
50
+ export declare const getQueueSnapshot: (channelNumber: number) => QueueSnapshot | null;
51
+ /**
52
+ * Subscribes to real-time progress updates for a specific channel
53
+ * @param channelNumber - The channel number
54
+ * @param callback - Function to call with audio info updates
55
+ * @example
56
+ * ```typescript
57
+ * onAudioProgress(0, (info) => {
58
+ * updateProgressBar(info.progress);
59
+ * updateTimeDisplay(info.currentTime, info.duration);
60
+ * });
61
+ * ```
62
+ */
63
+ export declare const onAudioProgress: (channelNumber: number, callback: ProgressCallback) => void;
64
+ /**
65
+ * Removes progress listeners for a specific channel
66
+ * @param channelNumber - The channel number
67
+ * @example
68
+ * ```typescript
69
+ * offAudioProgress(0); // Stop receiving progress updates for channel 0
70
+ * ```
71
+ */
72
+ export declare const offAudioProgress: (channelNumber: number) => void;
73
+ /**
74
+ * Subscribes to queue change events for a specific channel
75
+ * @param channelNumber - The channel number to monitor
76
+ * @param callback - Function to call when queue changes
77
+ * @example
78
+ * ```typescript
79
+ * onQueueChange(0, (snapshot) => {
80
+ * updateQueueDisplay(snapshot.items);
81
+ * updateQueueCount(snapshot.totalItems);
82
+ * });
83
+ * ```
84
+ */
85
+ export declare const onQueueChange: (channelNumber: number, callback: QueueChangeCallback) => void;
86
+ /**
87
+ * Removes queue change listeners for a specific channel
88
+ * @param channelNumber - The channel number
89
+ * @example
90
+ * ```typescript
91
+ * offQueueChange(0); // Stop receiving queue change notifications for channel 0
92
+ * ```
93
+ */
94
+ export declare const offQueueChange: (channelNumber: number) => void;
95
+ /**
96
+ * Subscribes to audio start events for a specific channel
97
+ * @param channelNumber - The channel number to monitor
98
+ * @param callback - Function to call when audio starts playing
99
+ * @example
100
+ * ```typescript
101
+ * onAudioStart(0, (info) => {
102
+ * showNowPlaying(info.fileName);
103
+ * setTotalDuration(info.duration);
104
+ * });
105
+ * ```
106
+ */
107
+ export declare const onAudioStart: (channelNumber: number, callback: AudioStartCallback) => void;
108
+ /**
109
+ * Subscribes to audio complete events for a specific channel
110
+ * @param channelNumber - The channel number to monitor
111
+ * @param callback - Function to call when audio completes
112
+ * @example
113
+ * ```typescript
114
+ * onAudioComplete(0, (info) => {
115
+ * logPlaybackComplete(info.fileName);
116
+ * if (info.remainingInQueue === 0) {
117
+ * showQueueComplete();
118
+ * }
119
+ * });
120
+ * ```
121
+ */
122
+ export declare const onAudioComplete: (channelNumber: number, callback: AudioCompleteCallback) => void;
package/dist/info.js ADDED
@@ -0,0 +1,240 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Audio information and progress tracking functions for the audio-channel-queue package
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.onAudioComplete = exports.onAudioStart = exports.offQueueChange = exports.onQueueChange = exports.offAudioProgress = exports.onAudioProgress = exports.getQueueSnapshot = exports.getAllChannelsInfo = exports.getCurrentAudioInfo = exports.audioChannels = void 0;
7
+ const utils_1 = require("./utils");
8
+ const events_1 = require("./events");
9
+ /**
10
+ * Global array of extended audio queue channels
11
+ */
12
+ exports.audioChannels = [];
13
+ /**
14
+ * Gets current audio information for a specific channel
15
+ * @param channelNumber - The channel number (defaults to 0)
16
+ * @returns AudioInfo object or null if no audio is playing
17
+ * @example
18
+ * ```typescript
19
+ * const info = getCurrentAudioInfo(0);
20
+ * if (info) {
21
+ * console.log(`Currently playing: ${info.fileName}`);
22
+ * console.log(`Progress: ${(info.progress * 100).toFixed(1)}%`);
23
+ * }
24
+ * ```
25
+ */
26
+ const getCurrentAudioInfo = (channelNumber = 0) => {
27
+ const channel = exports.audioChannels[channelNumber];
28
+ if (!channel || channel.queue.length === 0) {
29
+ return null;
30
+ }
31
+ const currentAudio = channel.queue[0];
32
+ return (0, utils_1.getAudioInfoFromElement)(currentAudio);
33
+ };
34
+ exports.getCurrentAudioInfo = getCurrentAudioInfo;
35
+ /**
36
+ * Gets audio information for all channels
37
+ * @returns Array of AudioInfo objects (null for channels with no audio)
38
+ * @example
39
+ * ```typescript
40
+ * const allInfo = getAllChannelsInfo();
41
+ * allInfo.forEach((info, channel) => {
42
+ * if (info) {
43
+ * console.log(`Channel ${channel}: ${info.fileName}`);
44
+ * }
45
+ * });
46
+ * ```
47
+ */
48
+ const getAllChannelsInfo = () => {
49
+ const allChannelsInfo = [];
50
+ for (let i = 0; i < exports.audioChannels.length; i++) {
51
+ allChannelsInfo.push((0, exports.getCurrentAudioInfo)(i));
52
+ }
53
+ return allChannelsInfo;
54
+ };
55
+ exports.getAllChannelsInfo = getAllChannelsInfo;
56
+ /**
57
+ * Gets a complete snapshot of the queue state for a specific channel
58
+ * @param channelNumber - The channel number
59
+ * @returns QueueSnapshot object or null if channel doesn't exist
60
+ * @example
61
+ * ```typescript
62
+ * const snapshot = getQueueSnapshot(0);
63
+ * if (snapshot) {
64
+ * console.log(`Queue has ${snapshot.totalItems} items`);
65
+ * console.log(`Currently playing: ${snapshot.items[0]?.fileName}`);
66
+ * }
67
+ * ```
68
+ */
69
+ const getQueueSnapshot = (channelNumber) => {
70
+ return (0, utils_1.createQueueSnapshot)(channelNumber, exports.audioChannels);
71
+ };
72
+ exports.getQueueSnapshot = getQueueSnapshot;
73
+ /**
74
+ * Subscribes to real-time progress updates for a specific channel
75
+ * @param channelNumber - The channel number
76
+ * @param callback - Function to call with audio info updates
77
+ * @example
78
+ * ```typescript
79
+ * onAudioProgress(0, (info) => {
80
+ * updateProgressBar(info.progress);
81
+ * updateTimeDisplay(info.currentTime, info.duration);
82
+ * });
83
+ * ```
84
+ */
85
+ const onAudioProgress = (channelNumber, callback) => {
86
+ if (!exports.audioChannels[channelNumber]) {
87
+ exports.audioChannels[channelNumber] = {
88
+ audioCompleteCallbacks: new Set(),
89
+ audioStartCallbacks: new Set(),
90
+ progressCallbacks: new Map(),
91
+ queue: [],
92
+ queueChangeCallbacks: new Set()
93
+ };
94
+ }
95
+ const channel = exports.audioChannels[channelNumber];
96
+ if (!channel.progressCallbacks) {
97
+ channel.progressCallbacks = new Map();
98
+ }
99
+ // Add callback for current audio if exists
100
+ if (channel.queue.length > 0) {
101
+ const currentAudio = channel.queue[0];
102
+ if (!channel.progressCallbacks.has(currentAudio)) {
103
+ channel.progressCallbacks.set(currentAudio, new Set());
104
+ }
105
+ channel.progressCallbacks.get(currentAudio).add(callback);
106
+ // Set up tracking if not already done
107
+ (0, events_1.setupProgressTracking)(currentAudio, channelNumber, exports.audioChannels);
108
+ }
109
+ // Store callback for future audio elements in this channel
110
+ if (!channel.progressCallbacks.has(null)) {
111
+ channel.progressCallbacks.set(null, new Set());
112
+ }
113
+ channel.progressCallbacks.get(null).add(callback);
114
+ };
115
+ exports.onAudioProgress = onAudioProgress;
116
+ /**
117
+ * Removes progress listeners for a specific channel
118
+ * @param channelNumber - The channel number
119
+ * @example
120
+ * ```typescript
121
+ * offAudioProgress(0); // Stop receiving progress updates for channel 0
122
+ * ```
123
+ */
124
+ const offAudioProgress = (channelNumber) => {
125
+ const channel = exports.audioChannels[channelNumber];
126
+ if (!channel || !channel.progressCallbacks)
127
+ return;
128
+ // Clean up event listeners for current audio if exists
129
+ if (channel.queue.length > 0) {
130
+ const currentAudio = channel.queue[0];
131
+ (0, events_1.cleanupProgressTracking)(currentAudio, channelNumber, exports.audioChannels);
132
+ }
133
+ // Clear all callbacks for this channel
134
+ channel.progressCallbacks.clear();
135
+ };
136
+ exports.offAudioProgress = offAudioProgress;
137
+ /**
138
+ * Subscribes to queue change events for a specific channel
139
+ * @param channelNumber - The channel number to monitor
140
+ * @param callback - Function to call when queue changes
141
+ * @example
142
+ * ```typescript
143
+ * onQueueChange(0, (snapshot) => {
144
+ * updateQueueDisplay(snapshot.items);
145
+ * updateQueueCount(snapshot.totalItems);
146
+ * });
147
+ * ```
148
+ */
149
+ const onQueueChange = (channelNumber, callback) => {
150
+ if (!exports.audioChannels[channelNumber]) {
151
+ exports.audioChannels[channelNumber] = {
152
+ audioCompleteCallbacks: new Set(),
153
+ audioStartCallbacks: new Set(),
154
+ progressCallbacks: new Map(),
155
+ queue: [],
156
+ queueChangeCallbacks: new Set()
157
+ };
158
+ }
159
+ const channel = exports.audioChannels[channelNumber];
160
+ if (!channel.queueChangeCallbacks) {
161
+ channel.queueChangeCallbacks = new Set();
162
+ }
163
+ channel.queueChangeCallbacks.add(callback);
164
+ };
165
+ exports.onQueueChange = onQueueChange;
166
+ /**
167
+ * Removes queue change listeners for a specific channel
168
+ * @param channelNumber - The channel number
169
+ * @example
170
+ * ```typescript
171
+ * offQueueChange(0); // Stop receiving queue change notifications for channel 0
172
+ * ```
173
+ */
174
+ const offQueueChange = (channelNumber) => {
175
+ const channel = exports.audioChannels[channelNumber];
176
+ if (!channel || !channel.queueChangeCallbacks)
177
+ return;
178
+ channel.queueChangeCallbacks.clear();
179
+ };
180
+ exports.offQueueChange = offQueueChange;
181
+ /**
182
+ * Subscribes to audio start events for a specific channel
183
+ * @param channelNumber - The channel number to monitor
184
+ * @param callback - Function to call when audio starts playing
185
+ * @example
186
+ * ```typescript
187
+ * onAudioStart(0, (info) => {
188
+ * showNowPlaying(info.fileName);
189
+ * setTotalDuration(info.duration);
190
+ * });
191
+ * ```
192
+ */
193
+ const onAudioStart = (channelNumber, callback) => {
194
+ if (!exports.audioChannels[channelNumber]) {
195
+ exports.audioChannels[channelNumber] = {
196
+ audioCompleteCallbacks: new Set(),
197
+ audioStartCallbacks: new Set(),
198
+ progressCallbacks: new Map(),
199
+ queue: [],
200
+ queueChangeCallbacks: new Set()
201
+ };
202
+ }
203
+ const channel = exports.audioChannels[channelNumber];
204
+ if (!channel.audioStartCallbacks) {
205
+ channel.audioStartCallbacks = new Set();
206
+ }
207
+ channel.audioStartCallbacks.add(callback);
208
+ };
209
+ exports.onAudioStart = onAudioStart;
210
+ /**
211
+ * Subscribes to audio complete events for a specific channel
212
+ * @param channelNumber - The channel number to monitor
213
+ * @param callback - Function to call when audio completes
214
+ * @example
215
+ * ```typescript
216
+ * onAudioComplete(0, (info) => {
217
+ * logPlaybackComplete(info.fileName);
218
+ * if (info.remainingInQueue === 0) {
219
+ * showQueueComplete();
220
+ * }
221
+ * });
222
+ * ```
223
+ */
224
+ const onAudioComplete = (channelNumber, callback) => {
225
+ if (!exports.audioChannels[channelNumber]) {
226
+ exports.audioChannels[channelNumber] = {
227
+ audioCompleteCallbacks: new Set(),
228
+ audioStartCallbacks: new Set(),
229
+ progressCallbacks: new Map(),
230
+ queue: [],
231
+ queueChangeCallbacks: new Set()
232
+ };
233
+ }
234
+ const channel = exports.audioChannels[channelNumber];
235
+ if (!channel.audioCompleteCallbacks) {
236
+ channel.audioCompleteCallbacks = new Set();
237
+ }
238
+ channel.audioCompleteCallbacks.add(callback);
239
+ };
240
+ exports.onAudioComplete = onAudioComplete;