@students-dev/audify-js 1.0.0 → 1.0.2
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 +21 -0
- package/README.md +93 -310
- package/dist/AudioEngine.js +232 -0
- package/dist/cjs/index.js +1497 -1392
- package/dist/cjs/index.js.map +1 -1
- package/dist/constants/index.js +35 -0
- package/dist/engine/Filters.js +137 -0
- package/dist/engine/MockAudioContext.js +53 -0
- package/dist/engine/Player.js +209 -0
- package/dist/esm/index.js +1490 -1389
- package/dist/esm/index.js.map +1 -1
- package/dist/events/EventBus.js +61 -0
- package/dist/index.js +18 -0
- package/dist/interfaces/index.js +1 -0
- package/dist/plugins/Plugin.js +27 -0
- package/dist/plugins/PluginManager.js +106 -0
- package/dist/providers/LavalinkProvider.js +81 -0
- package/dist/providers/LocalProvider.js +70 -0
- package/dist/providers/ProviderRegistry.js +20 -0
- package/dist/providers/SpotifyProvider.js +59 -0
- package/dist/providers/YouTubeProvider.js +48 -0
- package/dist/queue/Queue.js +186 -0
- package/dist/queue/Track.js +54 -0
- package/dist/types/AudioEngine.d.ts +107 -0
- package/dist/types/constants/index.d.ts +39 -0
- package/dist/types/engine/AudioEngine.d.ts +44 -1
- package/dist/types/engine/Filters.d.ts +25 -24
- package/dist/types/engine/MockAudioContext.d.ts +43 -0
- package/dist/types/engine/Player.d.ts +25 -21
- package/dist/types/events/EventBus.d.ts +17 -15
- package/dist/types/index.d.ts +17 -13
- package/dist/types/interfaces/index.d.ts +31 -0
- package/dist/types/plugins/Plugin.d.ts +11 -43
- package/dist/types/plugins/PluginManager.d.ts +19 -19
- package/dist/types/providers/LavalinkProvider.d.ts +17 -0
- package/dist/types/providers/LocalProvider.d.ts +11 -22
- package/dist/types/providers/ProviderRegistry.d.ts +10 -0
- package/dist/types/providers/SpotifyProvider.d.ts +14 -0
- package/dist/types/providers/YouTubeProvider.d.ts +11 -28
- package/dist/types/queue/Queue.d.ts +28 -22
- package/dist/types/queue/Track.d.ts +18 -16
- package/dist/types/utils/Logger.d.ts +12 -16
- package/dist/types/utils/Metadata.d.ts +16 -15
- package/dist/types/utils/Probe.d.ts +7 -7
- package/dist/types/utils/Time.d.ts +9 -9
- package/dist/utils/Logger.js +59 -0
- package/dist/utils/Metadata.js +90 -0
- package/dist/utils/Probe.js +59 -0
- package/dist/utils/Time.js +54 -0
- package/package.json +19 -9
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { Player } from './engine/Player';
|
|
2
|
+
import { Filters } from './engine/Filters';
|
|
3
|
+
import { Queue } from './queue/Queue';
|
|
4
|
+
import { Track } from './queue/Track';
|
|
5
|
+
import { EventBus } from './events/EventBus';
|
|
6
|
+
import { ProviderRegistry } from './providers/ProviderRegistry';
|
|
7
|
+
import { LocalProvider } from './providers/LocalProvider';
|
|
8
|
+
import { YouTubeProvider } from './providers/YouTubeProvider';
|
|
9
|
+
import { SpotifyProvider } from './providers/SpotifyProvider';
|
|
10
|
+
import { LavalinkProvider } from './providers/LavalinkProvider';
|
|
11
|
+
import { PluginManager } from './plugins/PluginManager';
|
|
12
|
+
import { EVENTS } from './constants';
|
|
13
|
+
/**
|
|
14
|
+
* Main audio engine class
|
|
15
|
+
*/
|
|
16
|
+
export class AudioEngine {
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
this.options = options;
|
|
19
|
+
this.queue = new Queue();
|
|
20
|
+
this.eventBus = new EventBus();
|
|
21
|
+
this.providers = new ProviderRegistry();
|
|
22
|
+
this.isReady = false;
|
|
23
|
+
this.player = new Player(this);
|
|
24
|
+
// @ts-ignore - Accessing private audioContext from player for filters
|
|
25
|
+
this.filters = new Filters(this.player.audioContext);
|
|
26
|
+
this.plugins = new PluginManager(this);
|
|
27
|
+
this.initialize();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Initialize the audio engine
|
|
31
|
+
*/
|
|
32
|
+
async initialize() {
|
|
33
|
+
try {
|
|
34
|
+
// Connect event buses
|
|
35
|
+
this.queue.eventBus.on(EVENTS.TRACK_ADD, (track) => this.eventBus.emit(EVENTS.TRACK_ADD, track));
|
|
36
|
+
this.queue.eventBus.on(EVENTS.TRACK_REMOVE, (track) => this.eventBus.emit(EVENTS.TRACK_REMOVE, track));
|
|
37
|
+
this.queue.eventBus.on(EVENTS.QUEUE_UPDATE, (tracks) => {
|
|
38
|
+
this.eventBus.emit(EVENTS.QUEUE_UPDATE, tracks);
|
|
39
|
+
this.plugins.callHook('queueUpdate', this.queue);
|
|
40
|
+
});
|
|
41
|
+
this.player.eventBus.on(EVENTS.PLAY, (data) => this.eventBus.emit(EVENTS.PLAY, data));
|
|
42
|
+
this.player.eventBus.on(EVENTS.PAUSE, () => this.eventBus.emit(EVENTS.PAUSE));
|
|
43
|
+
this.player.eventBus.on(EVENTS.STOP, () => this.eventBus.emit(EVENTS.STOP));
|
|
44
|
+
this.player.eventBus.on(EVENTS.ERROR, (error) => this.eventBus.emit(EVENTS.ERROR, error));
|
|
45
|
+
this.player.eventBus.on(EVENTS.TRACK_START, (track) => {
|
|
46
|
+
this.eventBus.emit(EVENTS.TRACK_START, track);
|
|
47
|
+
this.plugins.callHook('afterPlay', track); // afterPlay usually means playback started
|
|
48
|
+
});
|
|
49
|
+
this.player.eventBus.on(EVENTS.TRACK_END, (track) => {
|
|
50
|
+
this.eventBus.emit(EVENTS.TRACK_END, track);
|
|
51
|
+
this.plugins.callHook('trackEnd', track);
|
|
52
|
+
});
|
|
53
|
+
// Register default providers
|
|
54
|
+
await this.registerProvider(new LocalProvider());
|
|
55
|
+
await this.registerProvider(new YouTubeProvider());
|
|
56
|
+
if (this.options.spotify) {
|
|
57
|
+
await this.registerProvider(new SpotifyProvider(this.options.spotify));
|
|
58
|
+
}
|
|
59
|
+
if (this.options.lavalink) {
|
|
60
|
+
await this.registerProvider(new LavalinkProvider(this.options.lavalink));
|
|
61
|
+
}
|
|
62
|
+
this.isReady = true;
|
|
63
|
+
this.eventBus.emit(EVENTS.READY);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
this.eventBus.emit(EVENTS.ERROR, error);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async registerProvider(provider) {
|
|
70
|
+
await provider.initialize(this);
|
|
71
|
+
this.providers.register(provider);
|
|
72
|
+
}
|
|
73
|
+
getProvider(name) {
|
|
74
|
+
return this.providers.get(name);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Play track or resume playback
|
|
78
|
+
* @param track - Track to play or track identifier
|
|
79
|
+
*/
|
|
80
|
+
async play(track) {
|
|
81
|
+
if (!this.isReady)
|
|
82
|
+
return;
|
|
83
|
+
if (track) {
|
|
84
|
+
let trackObj = null;
|
|
85
|
+
if (typeof track === 'string') {
|
|
86
|
+
trackObj = new Track(track);
|
|
87
|
+
this.queue.add(trackObj);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
trackObj = track;
|
|
91
|
+
}
|
|
92
|
+
this.plugins.callHook('beforePlay', trackObj);
|
|
93
|
+
await this.player.play(trackObj);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
this.player.resume();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Pause playback
|
|
101
|
+
*/
|
|
102
|
+
pause() {
|
|
103
|
+
this.player.pause();
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Stop playback
|
|
107
|
+
*/
|
|
108
|
+
stop() {
|
|
109
|
+
this.player.stop();
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Seek to position
|
|
113
|
+
* @param time - Time in seconds
|
|
114
|
+
*/
|
|
115
|
+
seek(time) {
|
|
116
|
+
this.player.seek(time);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Set volume
|
|
120
|
+
* @param volume - Volume level (0-1)
|
|
121
|
+
*/
|
|
122
|
+
setVolume(volume) {
|
|
123
|
+
this.player.setVolume(volume);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Add track(s) to queue
|
|
127
|
+
* @param tracks - Track(s) to add
|
|
128
|
+
*/
|
|
129
|
+
add(tracks) {
|
|
130
|
+
this.queue.add(tracks);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Remove track from queue
|
|
134
|
+
* @param identifier - Track index or ID
|
|
135
|
+
*/
|
|
136
|
+
remove(identifier) {
|
|
137
|
+
return this.queue.remove(identifier);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Skip to next track
|
|
141
|
+
*/
|
|
142
|
+
next() {
|
|
143
|
+
const nextTrack = this.queue.next(false);
|
|
144
|
+
if (nextTrack) {
|
|
145
|
+
this.play(nextTrack);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
this.stop();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Go to previous track
|
|
153
|
+
*/
|
|
154
|
+
previous() {
|
|
155
|
+
const prevTrack = this.queue.previous(false);
|
|
156
|
+
if (prevTrack) {
|
|
157
|
+
this.play(prevTrack);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Shuffle queue
|
|
162
|
+
*/
|
|
163
|
+
shuffle() {
|
|
164
|
+
this.queue.shuffle();
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Clear queue
|
|
168
|
+
*/
|
|
169
|
+
clear() {
|
|
170
|
+
this.queue.clear();
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Jump to track in queue
|
|
174
|
+
* @param index - Track index
|
|
175
|
+
*/
|
|
176
|
+
jump(index) {
|
|
177
|
+
const track = this.queue.jump(index);
|
|
178
|
+
if (track) {
|
|
179
|
+
this.play(track);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Apply audio filter
|
|
184
|
+
* @param type - Filter type
|
|
185
|
+
* @param options - Filter options
|
|
186
|
+
*/
|
|
187
|
+
applyFilter(type, options) {
|
|
188
|
+
this.filters.apply(type, options);
|
|
189
|
+
this.eventBus.emit(EVENTS.FILTER_APPLIED, { type, options });
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Remove audio filter
|
|
193
|
+
* @param type - Filter type
|
|
194
|
+
*/
|
|
195
|
+
removeFilter(type) {
|
|
196
|
+
this.filters.remove(type);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Set loop mode
|
|
200
|
+
* @param mode - Loop mode
|
|
201
|
+
*/
|
|
202
|
+
setLoopMode(mode) {
|
|
203
|
+
this.player.setLoopMode(mode);
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Get current state
|
|
207
|
+
* @returns Engine state
|
|
208
|
+
*/
|
|
209
|
+
getState() {
|
|
210
|
+
return {
|
|
211
|
+
isReady: this.isReady,
|
|
212
|
+
...this.player.getState(),
|
|
213
|
+
currentTrack: this.queue.getCurrent(),
|
|
214
|
+
queue: this.queue.getTracks(),
|
|
215
|
+
filters: this.filters.getEnabled()
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Destroy the engine
|
|
220
|
+
*/
|
|
221
|
+
destroy() {
|
|
222
|
+
this.filters.clear();
|
|
223
|
+
this.player.stop();
|
|
224
|
+
this.providers.getAll().forEach(p => p.destroy());
|
|
225
|
+
this.plugins.getAll().forEach(p => p.onUnload());
|
|
226
|
+
// @ts-ignore
|
|
227
|
+
if (this.player.audioContext && this.player.audioContext.state !== 'closed') {
|
|
228
|
+
// @ts-ignore
|
|
229
|
+
this.player.audioContext.close();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|