react-native-audio-player-hooks
Version:
Audio player hooks & Utility Classes to play audio files, using libraries react-native-video, rxjs, with playlist handling, player controls.
152 lines (151 loc) • 5.05 kB
JavaScript
import { BehaviorSubject } from "rxjs";
class PlayerController {
ref = undefined;
currentAudio$ = new BehaviorSubject(undefined);
playList$ = new BehaviorSubject([]);
playListMap = {};
unshuffledPlayList = [];
paused$ = new BehaviorSubject(true);
buffering$ = new BehaviorSubject(false);
shuffled$ = new BehaviorSubject(false);
repeat$ = new BehaviorSubject("none");
progress$ = new BehaviorSubject({
currentTime: 0,
playableDuration: 0,
seekableDuration: 0,
});
constructor() { }
createRef = (ref) => {
this.ref = ref;
};
play = (id, currentPlaylist = []) => {
const currentAudio = this.currentAudio$.getValue();
if (id === currentAudio?.id) {
this.paused$.next(!this.paused$.getValue());
}
else {
const audio = this.playListMap[id];
if (audio) {
this.currentAudio$.next(audio);
this.paused$.next(false);
this.seek(0);
}
else {
if (currentPlaylist.length > 0) {
this.load(currentPlaylist);
const _audio = this.playListMap[id];
this.currentAudio$.next(_audio);
this.paused$.next(false);
}
}
}
};
pause = () => {
this.paused$.next(true);
};
seek = (seconds) => {
this.ref?.seek(seconds);
};
toggle = () => {
const isPaused = this.paused$.getValue();
this.paused$.next(!isPaused);
};
next = () => {
const currentAudio = this.currentAudio$.getValue();
if (currentAudio) {
const playList = this.playList$.getValue();
const repeat = this.repeat$.getValue();
if (repeat !== "single") {
const currentAudioIndex = this.playListMap[currentAudio.id].index;
const nextAudioIndex = currentAudioIndex + 1;
if (nextAudioIndex <= playList.length - 1) {
this.play(playList[nextAudioIndex].id);
}
else if (repeat === "all") {
this.play(playList[0].id);
}
else {
this.stop();
}
}
else {
this.seek(0);
}
}
};
prev = () => {
const currentAudio = this.currentAudio$.getValue();
if (currentAudio) {
const playList = this.playList$.getValue();
const repeat = this.repeat$.getValue();
if (repeat !== "single") {
const currentAudioIndex = this.playListMap[currentAudio.id].index;
const prevAudioIndex = currentAudioIndex - 1;
if (prevAudioIndex >= 0) {
this.play(playList[prevAudioIndex].id);
}
else if (repeat === "all") {
this.play(playList[playList.length - 1].id);
}
}
}
else {
this.seek(0);
}
};
repeat = () => {
const repeat = this.repeat$.getValue();
switch (repeat) {
case "all":
this.repeat$.next("none");
break;
case "none":
this.repeat$.next("single");
break;
case "single":
this.repeat$.next("all");
break;
}
};
shuffle = () => {
if (this.shuffled$.getValue()) {
this.shuffled$.next(false);
this.load(this.unshuffledPlayList);
}
else {
this.shuffled$.next(true);
this.unshuffledPlayList = JSON.parse(JSON.stringify(this.playList$.getValue()));
const newPlaylist = this._getShuffledArr(this.unshuffledPlayList);
this.load(newPlaylist);
}
};
_getShuffledArr = (arr) => {
const newArr = arr.slice();
for (let i = newArr.length - 1; i > 0; i--) {
const rand = Math.floor(Math.random() * (i + 1));
[newArr[i], newArr[rand]] = [newArr[rand], newArr[i]];
}
return newArr;
};
load = (playlist) => {
playlist.forEach((audio, index) => {
this.playListMap[audio.id] = { ...audio, index };
});
this.playList$.next(playlist);
};
stop = () => {
this.playList$.next(JSON.parse(JSON.stringify([])));
this.playListMap = JSON.parse(JSON.stringify({}));
this.currentAudio$.next(undefined);
};
stopAudio = () => {
this.currentAudio$.next(undefined);
};
formatTimePlayer = (seconds) => {
return `${this._addZeroToNumber(new Date(seconds * 1000).getUTCMinutes())} : ${this._addZeroToNumber(new Date(seconds * 1000).getUTCSeconds())}`;
};
_addZeroToNumber = (num) => {
return num < 10 ? `0${num}` : num;
};
}
export default PlayerController;