@discordjs/voice 0.6.0 → 0.7.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/LICENSE +190 -21
- package/README.md +41 -18
- package/dist/index.d.ts +155 -89
- package/dist/index.js +10 -26
- package/dist/index.js.map +7 -1
- package/dist/index.mjs +10 -0
- package/dist/index.mjs.map +7 -0
- package/package.json +67 -96
- package/dist/DataStore.js +0 -151
- package/dist/DataStore.js.map +0 -1
- package/dist/VoiceConnection.js +0 -529
- package/dist/VoiceConnection.js.map +0 -1
- package/dist/audio/AudioPlayer.js +0 -449
- package/dist/audio/AudioPlayer.js.map +0 -1
- package/dist/audio/AudioPlayerError.js +0 -17
- package/dist/audio/AudioPlayerError.js.map +0 -1
- package/dist/audio/AudioResource.js +0 -162
- package/dist/audio/AudioResource.js.map +0 -1
- package/dist/audio/PlayerSubscription.js +0 -23
- package/dist/audio/PlayerSubscription.js.map +0 -1
- package/dist/audio/TransformerGraph.js +0 -233
- package/dist/audio/TransformerGraph.js.map +0 -1
- package/dist/audio/index.js +0 -18
- package/dist/audio/index.js.map +0 -1
- package/dist/joinVoiceChannel.js +0 -24
- package/dist/joinVoiceChannel.js.map +0 -1
- package/dist/networking/Networking.js +0 -457
- package/dist/networking/Networking.js.map +0 -1
- package/dist/networking/VoiceUDPSocket.js +0 -145
- package/dist/networking/VoiceUDPSocket.js.map +0 -1
- package/dist/networking/VoiceWebSocket.js +0 -129
- package/dist/networking/VoiceWebSocket.js.map +0 -1
- package/dist/networking/index.js +0 -16
- package/dist/networking/index.js.map +0 -1
- package/dist/receive/AudioReceiveStream.js +0 -64
- package/dist/receive/AudioReceiveStream.js.map +0 -1
- package/dist/receive/SSRCMap.js +0 -69
- package/dist/receive/SSRCMap.js.map +0 -1
- package/dist/receive/SpeakingMap.js +0 -38
- package/dist/receive/SpeakingMap.js.map +0 -1
- package/dist/receive/VoiceReceiver.js +0 -149
- package/dist/receive/VoiceReceiver.js.map +0 -1
- package/dist/receive/index.js +0 -16
- package/dist/receive/index.js.map +0 -1
- package/dist/util/Secretbox.js +0 -50
- package/dist/util/Secretbox.js.map +0 -1
- package/dist/util/abortAfter.js +0 -15
- package/dist/util/abortAfter.js.map +0 -1
- package/dist/util/adapter.js +0 -3
- package/dist/util/adapter.js.map +0 -1
- package/dist/util/demuxProbe.js +0 -90
- package/dist/util/demuxProbe.js.map +0 -1
- package/dist/util/entersState.js +0 -26
- package/dist/util/entersState.js.map +0 -1
- package/dist/util/generateDependencyReport.js +0 -82
- package/dist/util/generateDependencyReport.js.map +0 -1
- package/dist/util/index.js +0 -17
- package/dist/util/index.js.map +0 -1
- package/dist/util/util.js +0 -7
- package/dist/util/util.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,29 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@discordjs/voice",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Implementation of the Discord Voice API for Node.js",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"typings": "dist/index.d.ts",
|
|
7
|
-
"author": "Amish Shah <amish@shah.gg>",
|
|
8
|
-
"license": "MIT",
|
|
9
|
-
"directories": {
|
|
10
|
-
"test": "test"
|
|
11
|
-
},
|
|
12
5
|
"scripts": {
|
|
13
|
-
"
|
|
14
|
-
"test
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
6
|
+
"pretest": "npm run build",
|
|
7
|
+
"test": "jest --pass-with-no-tests",
|
|
8
|
+
"test:ci": "jest --no-stack-trace --verbose --pass-with-no-tests",
|
|
9
|
+
"prebuild": "npm run lint",
|
|
10
|
+
"build": "tsup",
|
|
11
|
+
"lint": "eslint src --ext mjs,js,ts",
|
|
12
|
+
"lint:fix": "eslint src --ext mjs,js,ts --fix",
|
|
13
|
+
"format": "prettier --write **/*.{ts,js,json,yml,yaml}",
|
|
14
|
+
"prepare": "is-ci || husky install",
|
|
15
|
+
"docs": "typedoc --json docs/typedoc-out.json src/index.ts && node scripts/docs.mjs",
|
|
16
|
+
"prepublishOnly": "npm run lint",
|
|
17
|
+
"release": "standard-version --preset angular"
|
|
22
18
|
},
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
"main": "./dist/index.js",
|
|
20
|
+
"module": "./dist/index.mjs",
|
|
21
|
+
"typings": "./dist/index.d.ts",
|
|
22
|
+
"exports": {
|
|
23
|
+
"import": "./dist/index.mjs",
|
|
24
|
+
"require": "./dist/index.js"
|
|
26
25
|
},
|
|
26
|
+
"directories": {
|
|
27
|
+
"lib": "src",
|
|
28
|
+
"test": "__tests__"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist"
|
|
32
|
+
],
|
|
33
|
+
"author": "Amish Shah <amish@shah.gg>",
|
|
34
|
+
"license": "Apache-2.0",
|
|
27
35
|
"keywords": [
|
|
28
36
|
"discord",
|
|
29
37
|
"discord.js",
|
|
@@ -31,91 +39,54 @@
|
|
|
31
39
|
"voice",
|
|
32
40
|
"streaming"
|
|
33
41
|
],
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/discordjs/voice.git"
|
|
45
|
+
},
|
|
34
46
|
"bugs": {
|
|
35
47
|
"url": "https://github.com/discordjs/voice/issues"
|
|
36
48
|
},
|
|
37
|
-
"homepage": "https://github.com/discordjs/voice
|
|
38
|
-
"files": [
|
|
39
|
-
"dist/*"
|
|
40
|
-
],
|
|
41
|
-
"engines": {
|
|
42
|
-
"node": ">=16.0.0"
|
|
43
|
-
},
|
|
49
|
+
"homepage": "https://github.com/discordjs/voice",
|
|
44
50
|
"dependencies": {
|
|
45
|
-
"@types/ws": "^
|
|
46
|
-
"discord-api-types": "^0.
|
|
47
|
-
"prism-media": "^1.3.
|
|
48
|
-
"tiny-typed-emitter": "^2.0
|
|
49
|
-
"
|
|
51
|
+
"@types/ws": "^8.2.0",
|
|
52
|
+
"discord-api-types": "^0.24.0",
|
|
53
|
+
"prism-media": "^1.3.2",
|
|
54
|
+
"tiny-typed-emitter": "^2.1.0",
|
|
55
|
+
"tslib": "^2.3.1",
|
|
56
|
+
"ws": "^8.2.3"
|
|
50
57
|
},
|
|
51
58
|
"devDependencies": {
|
|
52
|
-
"@babel/core": "^7.
|
|
53
|
-
"@babel/preset-env": "^7.
|
|
54
|
-
"@babel/preset-typescript": "^7.
|
|
55
|
-
"@commitlint/cli": "^
|
|
56
|
-
"@commitlint/config-angular": "^
|
|
57
|
-
"@
|
|
58
|
-
"@types/jest": "^
|
|
59
|
-
"@types/node": "^16.
|
|
60
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
61
|
-
"@typescript-eslint/parser": "^
|
|
62
|
-
"
|
|
63
|
-
"eslint": "^7.28.0",
|
|
59
|
+
"@babel/core": "^7.16.0",
|
|
60
|
+
"@babel/preset-env": "^7.16.0",
|
|
61
|
+
"@babel/preset-typescript": "^7.16.0",
|
|
62
|
+
"@commitlint/cli": "^13.2.1",
|
|
63
|
+
"@commitlint/config-angular": "^13.2.0",
|
|
64
|
+
"@discordjs/ts-docgen": "^0.3.2",
|
|
65
|
+
"@types/jest": "^27.0.2",
|
|
66
|
+
"@types/node": "^16.11.6",
|
|
67
|
+
"@typescript-eslint/eslint-plugin": "^5.2.0",
|
|
68
|
+
"@typescript-eslint/parser": "^5.2.0",
|
|
69
|
+
"eslint": "^8.1.0",
|
|
64
70
|
"eslint-config-marine": "^9.0.6",
|
|
65
71
|
"eslint-config-prettier": "^8.3.0",
|
|
66
|
-
"eslint-plugin-prettier": "^
|
|
67
|
-
"husky": "^
|
|
68
|
-
"
|
|
69
|
-
"jest
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
72
|
+
"eslint-plugin-prettier": "^4.0.0",
|
|
73
|
+
"husky": "^7.0.4",
|
|
74
|
+
"is-ci": "^3.0.1",
|
|
75
|
+
"jest": "^27.3.1",
|
|
76
|
+
"jest-websocket-mock": "^2.2.1",
|
|
77
|
+
"lint-staged": "^11.2.6",
|
|
78
|
+
"mock-socket": "^9.0.6",
|
|
79
|
+
"prettier": "^2.4.1",
|
|
80
|
+
"standard-version": "^9.3.2",
|
|
81
|
+
"tsup": "^5.5.0",
|
|
82
|
+
"typedoc": "^0.22.7",
|
|
83
|
+
"typescript": "^4.4.4"
|
|
75
84
|
},
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
|
|
79
|
-
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
"lint-staged": {
|
|
83
|
-
"*.{mjs,js,ts}": [
|
|
84
|
-
"eslint --ext .ts --fix"
|
|
85
|
-
],
|
|
86
|
-
"*.{json,yml,yaml}": [
|
|
87
|
-
"prettier --write"
|
|
88
|
-
]
|
|
85
|
+
"engines": {
|
|
86
|
+
"node": ">=16.0.0",
|
|
87
|
+
"npm": ">=7.0.0"
|
|
89
88
|
},
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"@commitlint/config-angular"
|
|
93
|
-
],
|
|
94
|
-
"rules": {
|
|
95
|
-
"type-enum": [
|
|
96
|
-
2,
|
|
97
|
-
"always",
|
|
98
|
-
[
|
|
99
|
-
"chore",
|
|
100
|
-
"build",
|
|
101
|
-
"ci",
|
|
102
|
-
"docs",
|
|
103
|
-
"feat",
|
|
104
|
-
"fix",
|
|
105
|
-
"perf",
|
|
106
|
-
"refactor",
|
|
107
|
-
"revert",
|
|
108
|
-
"style",
|
|
109
|
-
"test",
|
|
110
|
-
"types",
|
|
111
|
-
"wip"
|
|
112
|
-
]
|
|
113
|
-
],
|
|
114
|
-
"scope-case": [
|
|
115
|
-
1,
|
|
116
|
-
"always",
|
|
117
|
-
"pascal-case"
|
|
118
|
-
]
|
|
119
|
-
}
|
|
89
|
+
"publishConfig": {
|
|
90
|
+
"access": "public"
|
|
120
91
|
}
|
|
121
92
|
}
|
package/dist/DataStore.js
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.deleteAudioPlayer = exports.addAudioPlayer = exports.hasAudioPlayer = exports.trackVoiceConnection = exports.untrackVoiceConnection = exports.getVoiceConnection = exports.getVoiceConnections = exports.getGroups = exports.createJoinVoiceChannelPayload = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Sends a voice state update to the main websocket shard of a guild, to indicate joining/leaving/moving across
|
|
6
|
-
* voice channels.
|
|
7
|
-
*
|
|
8
|
-
* @param config - The configuration to use when joining the voice channel
|
|
9
|
-
*/
|
|
10
|
-
function createJoinVoiceChannelPayload(config) {
|
|
11
|
-
return {
|
|
12
|
-
op: 4 /* VoiceStateUpdate */,
|
|
13
|
-
d: {
|
|
14
|
-
guild_id: config.guildId,
|
|
15
|
-
channel_id: config.channelId,
|
|
16
|
-
self_deaf: config.selfDeaf,
|
|
17
|
-
self_mute: config.selfMute,
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
exports.createJoinVoiceChannelPayload = createJoinVoiceChannelPayload;
|
|
22
|
-
// Voice Connections
|
|
23
|
-
const groups = new Map();
|
|
24
|
-
groups.set('default', new Map());
|
|
25
|
-
function getOrCreateGroup(group) {
|
|
26
|
-
const existing = groups.get(group);
|
|
27
|
-
if (existing)
|
|
28
|
-
return existing;
|
|
29
|
-
const map = new Map();
|
|
30
|
-
groups.set(group, map);
|
|
31
|
-
return map;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Retrieves the map of group names to maps of voice connections. By default, all voice connections
|
|
35
|
-
* are created under the 'default' group.
|
|
36
|
-
* @returns The group map
|
|
37
|
-
*/
|
|
38
|
-
function getGroups() {
|
|
39
|
-
return groups;
|
|
40
|
-
}
|
|
41
|
-
exports.getGroups = getGroups;
|
|
42
|
-
/**
|
|
43
|
-
* Retrieves all the voice connections under the given group name. Defaults to the 'default' group.
|
|
44
|
-
* @param group - The group to look up
|
|
45
|
-
* @returns The map of voice connections
|
|
46
|
-
*/
|
|
47
|
-
function getVoiceConnections(group = 'default') {
|
|
48
|
-
return groups.get(group);
|
|
49
|
-
}
|
|
50
|
-
exports.getVoiceConnections = getVoiceConnections;
|
|
51
|
-
/**
|
|
52
|
-
* Finds a voice connection with the given guild ID and group. Defaults to the 'default' group.
|
|
53
|
-
* @param guildId - The guild ID of the voice connection
|
|
54
|
-
* @param group - the group that the voice connection was registered with
|
|
55
|
-
* @returns The voice connection, if it exists
|
|
56
|
-
*/
|
|
57
|
-
function getVoiceConnection(guildId, group = 'default') {
|
|
58
|
-
var _a;
|
|
59
|
-
return (_a = getVoiceConnections(group)) === null || _a === void 0 ? void 0 : _a.get(guildId);
|
|
60
|
-
}
|
|
61
|
-
exports.getVoiceConnection = getVoiceConnection;
|
|
62
|
-
function untrackVoiceConnection(voiceConnection) {
|
|
63
|
-
var _a;
|
|
64
|
-
return (_a = getVoiceConnections(voiceConnection.joinConfig.group)) === null || _a === void 0 ? void 0 : _a.delete(voiceConnection.joinConfig.guildId);
|
|
65
|
-
}
|
|
66
|
-
exports.untrackVoiceConnection = untrackVoiceConnection;
|
|
67
|
-
function trackVoiceConnection(voiceConnection) {
|
|
68
|
-
return getOrCreateGroup(voiceConnection.joinConfig.group).set(voiceConnection.joinConfig.guildId, voiceConnection);
|
|
69
|
-
}
|
|
70
|
-
exports.trackVoiceConnection = trackVoiceConnection;
|
|
71
|
-
// Audio Players
|
|
72
|
-
// Each audio packet is 20ms long
|
|
73
|
-
const FRAME_LENGTH = 20;
|
|
74
|
-
let audioCycleInterval;
|
|
75
|
-
let nextTime = -1;
|
|
76
|
-
/**
|
|
77
|
-
* A list of created audio players that are still active and haven't been destroyed.
|
|
78
|
-
*/
|
|
79
|
-
const audioPlayers = [];
|
|
80
|
-
/**
|
|
81
|
-
* Called roughly every 20 milliseconds. Dispatches audio from all players, and then gets the players to prepare
|
|
82
|
-
* the next audio frame.
|
|
83
|
-
*/
|
|
84
|
-
function audioCycleStep() {
|
|
85
|
-
if (nextTime === -1)
|
|
86
|
-
return;
|
|
87
|
-
nextTime += FRAME_LENGTH;
|
|
88
|
-
const available = audioPlayers.filter((player) => player.checkPlayable());
|
|
89
|
-
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
90
|
-
available.forEach((player) => player['_stepDispatch']());
|
|
91
|
-
prepareNextAudioFrame(available);
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Recursively gets the players that have been passed as parameters to prepare audio frames that can be played.
|
|
95
|
-
* at the start of the next cycle.
|
|
96
|
-
*/
|
|
97
|
-
function prepareNextAudioFrame(players) {
|
|
98
|
-
const nextPlayer = players.shift();
|
|
99
|
-
if (!nextPlayer) {
|
|
100
|
-
if (nextTime !== -1) {
|
|
101
|
-
audioCycleInterval = setTimeout(() => audioCycleStep(), nextTime - Date.now());
|
|
102
|
-
}
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
106
|
-
nextPlayer['_stepPrepare']();
|
|
107
|
-
// setImmediate to avoid long audio player chains blocking other scheduled tasks
|
|
108
|
-
setImmediate(() => prepareNextAudioFrame(players));
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Checks whether or not the given audio player is being driven by the data store clock.
|
|
112
|
-
*
|
|
113
|
-
* @param target - The target to test for
|
|
114
|
-
* @returns true if it is being tracked, false otherwise
|
|
115
|
-
*/
|
|
116
|
-
function hasAudioPlayer(target) {
|
|
117
|
-
return audioPlayers.includes(target);
|
|
118
|
-
}
|
|
119
|
-
exports.hasAudioPlayer = hasAudioPlayer;
|
|
120
|
-
/**
|
|
121
|
-
* Adds an audio player to the data store tracking list, if it isn't already there.
|
|
122
|
-
*
|
|
123
|
-
* @param player - The player to track
|
|
124
|
-
*/
|
|
125
|
-
function addAudioPlayer(player) {
|
|
126
|
-
if (hasAudioPlayer(player))
|
|
127
|
-
return player;
|
|
128
|
-
audioPlayers.push(player);
|
|
129
|
-
if (audioPlayers.length === 1) {
|
|
130
|
-
nextTime = Date.now();
|
|
131
|
-
setImmediate(() => audioCycleStep());
|
|
132
|
-
}
|
|
133
|
-
return player;
|
|
134
|
-
}
|
|
135
|
-
exports.addAudioPlayer = addAudioPlayer;
|
|
136
|
-
/**
|
|
137
|
-
* Removes an audio player from the data store tracking list, if it is present there.
|
|
138
|
-
*/
|
|
139
|
-
function deleteAudioPlayer(player) {
|
|
140
|
-
const index = audioPlayers.indexOf(player);
|
|
141
|
-
if (index === -1)
|
|
142
|
-
return;
|
|
143
|
-
audioPlayers.splice(index, 1);
|
|
144
|
-
if (audioPlayers.length === 0) {
|
|
145
|
-
nextTime = -1;
|
|
146
|
-
if (typeof audioCycleInterval !== 'undefined')
|
|
147
|
-
clearTimeout(audioCycleInterval);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
exports.deleteAudioPlayer = deleteAudioPlayer;
|
|
151
|
-
//# sourceMappingURL=DataStore.js.map
|
package/dist/DataStore.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DataStore.js","sourceRoot":"","sources":["../src/DataStore.ts"],"names":[],"mappings":"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","sourcesContent":["import { GatewayOpcodes } from 'discord-api-types/v9';\nimport { AudioPlayer } from './audio';\nimport { VoiceConnection } from './VoiceConnection';\n\nexport interface JoinConfig {\n\tguildId: string;\n\tchannelId: string | null;\n\tselfDeaf: boolean;\n\tselfMute: boolean;\n\tgroup: string;\n}\n\n/**\n * Sends a voice state update to the main websocket shard of a guild, to indicate joining/leaving/moving across\n * voice channels.\n *\n * @param config - The configuration to use when joining the voice channel\n */\nexport function createJoinVoiceChannelPayload(config: JoinConfig) {\n\treturn {\n\t\top: GatewayOpcodes.VoiceStateUpdate,\n\t\td: {\n\t\t\tguild_id: config.guildId,\n\t\t\tchannel_id: config.channelId,\n\t\t\tself_deaf: config.selfDeaf,\n\t\t\tself_mute: config.selfMute,\n\t\t},\n\t};\n}\n\n// Voice Connections\nconst groups: Map<string, Map<string, VoiceConnection>> = new Map();\ngroups.set('default', new Map());\n\nfunction getOrCreateGroup(group: string) {\n\tconst existing = groups.get(group);\n\tif (existing) return existing;\n\tconst map = new Map();\n\tgroups.set(group, map);\n\treturn map;\n}\n\n/**\n * Retrieves the map of group names to maps of voice connections. By default, all voice connections\n * are created under the 'default' group.\n * @returns The group map\n */\nexport function getGroups() {\n\treturn groups;\n}\n\nexport function getVoiceConnections(group?: 'default'): Map<string, VoiceConnection>;\nexport function getVoiceConnections(group: string): Map<string, VoiceConnection> | undefined;\n/**\n * Retrieves all the voice connections under the given group name. Defaults to the 'default' group.\n * @param group - The group to look up\n * @returns The map of voice connections\n */\nexport function getVoiceConnections(group = 'default') {\n\treturn groups.get(group);\n}\n\n/**\n * Finds a voice connection with the given guild ID and group. Defaults to the 'default' group.\n * @param guildId - The guild ID of the voice connection\n * @param group - the group that the voice connection was registered with\n * @returns The voice connection, if it exists\n */\nexport function getVoiceConnection(guildId: string, group = 'default') {\n\treturn getVoiceConnections(group)?.get(guildId);\n}\n\nexport function untrackVoiceConnection(voiceConnection: VoiceConnection) {\n\treturn getVoiceConnections(voiceConnection.joinConfig.group)?.delete(voiceConnection.joinConfig.guildId);\n}\n\nexport function trackVoiceConnection(voiceConnection: VoiceConnection) {\n\treturn getOrCreateGroup(voiceConnection.joinConfig.group).set(voiceConnection.joinConfig.guildId, voiceConnection);\n}\n\n// Audio Players\n\n// Each audio packet is 20ms long\nconst FRAME_LENGTH = 20;\n\nlet audioCycleInterval: NodeJS.Timeout | undefined;\nlet nextTime = -1;\n\n/**\n * A list of created audio players that are still active and haven't been destroyed.\n */\nconst audioPlayers: AudioPlayer[] = [];\n\n/**\n * Called roughly every 20 milliseconds. Dispatches audio from all players, and then gets the players to prepare\n * the next audio frame.\n */\nfunction audioCycleStep() {\n\tif (nextTime === -1) return;\n\n\tnextTime += FRAME_LENGTH;\n\tconst available = audioPlayers.filter((player) => player.checkPlayable());\n\n\t// eslint-disable-next-line @typescript-eslint/dot-notation\n\tavailable.forEach((player) => player['_stepDispatch']());\n\n\tprepareNextAudioFrame(available);\n}\n\n/**\n * Recursively gets the players that have been passed as parameters to prepare audio frames that can be played.\n * at the start of the next cycle.\n */\nfunction prepareNextAudioFrame(players: AudioPlayer[]) {\n\tconst nextPlayer = players.shift();\n\n\tif (!nextPlayer) {\n\t\tif (nextTime !== -1) {\n\t\t\taudioCycleInterval = setTimeout(() => audioCycleStep(), nextTime - Date.now());\n\t\t}\n\t\treturn;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/dot-notation\n\tnextPlayer['_stepPrepare']();\n\n\t// setImmediate to avoid long audio player chains blocking other scheduled tasks\n\tsetImmediate(() => prepareNextAudioFrame(players));\n}\n\n/**\n * Checks whether or not the given audio player is being driven by the data store clock.\n *\n * @param target - The target to test for\n * @returns true if it is being tracked, false otherwise\n */\nexport function hasAudioPlayer(target: AudioPlayer) {\n\treturn audioPlayers.includes(target);\n}\n\n/**\n * Adds an audio player to the data store tracking list, if it isn't already there.\n *\n * @param player - The player to track\n */\nexport function addAudioPlayer(player: AudioPlayer) {\n\tif (hasAudioPlayer(player)) return player;\n\taudioPlayers.push(player);\n\tif (audioPlayers.length === 1) {\n\t\tnextTime = Date.now();\n\t\tsetImmediate(() => audioCycleStep());\n\t}\n\treturn player;\n}\n\n/**\n * Removes an audio player from the data store tracking list, if it is present there.\n */\nexport function deleteAudioPlayer(player: AudioPlayer) {\n\tconst index = audioPlayers.indexOf(player);\n\tif (index === -1) return;\n\taudioPlayers.splice(index, 1);\n\tif (audioPlayers.length === 0) {\n\t\tnextTime = -1;\n\t\tif (typeof audioCycleInterval !== 'undefined') clearTimeout(audioCycleInterval);\n\t}\n}\n"]}
|