182 lines
4.5 KiB
TypeScript
182 lines
4.5 KiB
TypeScript
import { LoopOption, Track } from "./types.js";
|
|
|
|
/**
|
|
* Class of {@link ./player#Player | Player's} queue.
|
|
*
|
|
* @public
|
|
*/
|
|
export default class Queue {
|
|
/**
|
|
* Array of {@link Track | Tracks} - content of queue.
|
|
*/
|
|
private tracks_: Track[] = [];
|
|
public get tracks(): Track[] {
|
|
return this.tracks_;
|
|
}
|
|
|
|
/**
|
|
* Position of current playing track.
|
|
*/
|
|
private position_ = 0;
|
|
public get position(): number {
|
|
return this.position_;
|
|
}
|
|
|
|
/**
|
|
* Defines behavior of queue.
|
|
*
|
|
* @see ./types.ts for more info about values.
|
|
*/
|
|
private loop_: LoopOption = "NONE";
|
|
public get loop(): LoopOption {
|
|
return this.loop_;
|
|
}
|
|
public set loop(x: LoopOption) {
|
|
this.loop_ = x;
|
|
}
|
|
|
|
/**
|
|
* Queue overall duration in seconds.
|
|
*/
|
|
private duration_ = 0;
|
|
public get duration(): number {
|
|
return this.duration_;
|
|
}
|
|
|
|
/**
|
|
* Skips current track.
|
|
*
|
|
* @remarks Behavior depends on loop option.
|
|
*
|
|
* @returns next {@link Track} or undefined if end was reached.
|
|
*/
|
|
public next(): Track | undefined {
|
|
if (this.loop_ === "SONG") {
|
|
return this.current();
|
|
}
|
|
|
|
if (this.loop_ === "AUTO") {
|
|
this.position_ = Math.floor(Math.random() * this.tracks_.length);
|
|
return this.current();
|
|
}
|
|
|
|
if (this.position_ + 1 < this.tracks_.length) {
|
|
this.position_++;
|
|
return this.current();
|
|
} else if (this.loop_ === "LOOP") {
|
|
this.position_ = 0;
|
|
return this.current();
|
|
} else if (this.loop_ === "NONE") {
|
|
this.position_ = 0;
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Shuffles queue by using simple Math.random.
|
|
*/
|
|
public shuffle(): void {
|
|
let currentIndex = this.tracks_.length;
|
|
|
|
while (currentIndex != 0) {
|
|
const randomIndex = Math.floor(Math.random() * currentIndex);
|
|
currentIndex--;
|
|
|
|
[this.tracks_[currentIndex], this.tracks_[randomIndex]] = [
|
|
this.tracks_[randomIndex],
|
|
this.tracks_[currentIndex]
|
|
];
|
|
}
|
|
|
|
this.position_ = 0;
|
|
}
|
|
|
|
/**
|
|
* Inserts tracks from provided array at specific index.
|
|
*
|
|
* @returns first {@link Track} of inserted Tracks.
|
|
*
|
|
* @param tracks - List of Tracks to insert to the queue.
|
|
* @param index - Position at which insertion will be occurred.
|
|
*/
|
|
public push(tracks: Track[], index?: number): Track {
|
|
for (const track of tracks) {
|
|
this.duration_ += track.duration;
|
|
}
|
|
|
|
if (!index || index >= this.tracks_.length) {
|
|
this.tracks_ = this.tracks_.concat(tracks);
|
|
|
|
return this.tracks_[this.tracks_.length - tracks.length];
|
|
}
|
|
|
|
this.tracks_.splice(Math.max(0, index), 0, ...tracks);
|
|
if (this.position_ >= index) {
|
|
this.position_ += tracks.length;
|
|
}
|
|
|
|
return this.tracks_[Math.max(0, index)];
|
|
}
|
|
|
|
/**
|
|
* Removes {@link Track} from the queue at position specified.
|
|
*
|
|
* @returns Track that was deleted or undefined if not.
|
|
*
|
|
* @param query - Index of element that must be deleted.
|
|
*/
|
|
public pop(query: number): Track | undefined {
|
|
if (query >= 0 && query < this.tracks_.length) {
|
|
const track = this.tracks_[query];
|
|
|
|
this.tracks_.splice(query, 1);
|
|
this.position_ = Math.max(0, this.position_ - 1);
|
|
this.duration_ -= track.duration;
|
|
return track;
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
/**
|
|
* Assigns position new value.
|
|
*
|
|
* @returns {@link Track} at position specified or undefined if index out of bounds.
|
|
*/
|
|
public jump(query: number): Track | undefined {
|
|
if (query >= 0 && query < this.tracks_.length) {
|
|
const track = this.tracks_[query];
|
|
this.position_ = query;
|
|
return track;
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
/**
|
|
* Returns current {@link Track} (at position).
|
|
*
|
|
* @returns Track at internal position.
|
|
*/
|
|
public current(): Track {
|
|
return this.tracks_[this.position_];
|
|
}
|
|
|
|
/**
|
|
* Checks if queue is empty.
|
|
*
|
|
* @returns True is queue is empty, False otherwise.
|
|
*/
|
|
public empty(): boolean {
|
|
return this.tracks_.length === 0;
|
|
}
|
|
|
|
/**
|
|
* Clears entire queue and sets position to 0.
|
|
*/
|
|
public clear(): void {
|
|
this.tracks_ = [];
|
|
this.position_ = 0;
|
|
}
|
|
}
|