New web project with Beat Saber tools
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
import {writable} from 'svelte/store';
|
||||
import {tweened} from 'svelte/motion';
|
||||
import {cubicOut} from 'svelte/easing';
|
||||
|
||||
export let songPlayerStore = null;
|
||||
export let currentTimeStore = null;
|
||||
|
||||
const DEFAULT_STATE = {
|
||||
currentHash: null,
|
||||
playing: false,
|
||||
duration: 0,
|
||||
currentTime: 0,
|
||||
volume: 0.3,
|
||||
};
|
||||
|
||||
export default () => {
|
||||
if (songPlayerStore) return songPlayerStore;
|
||||
|
||||
let currentState = {...DEFAULT_STATE};
|
||||
let audio = null;
|
||||
currentTimeStore = tweened(0, {duration: 10, easing: cubicOut});
|
||||
|
||||
const {subscribe, set, update} = writable(currentState);
|
||||
|
||||
function cleanup() {
|
||||
if (audio) {
|
||||
audio.removeEventListener('timeupdate', handleTimeUpdate);
|
||||
audio.removeEventListener('loadedmetadata', handleMetadata);
|
||||
audio.removeEventListener('ended', handleEnded);
|
||||
audio.removeEventListener('pause', handleEnded);
|
||||
audio.pause();
|
||||
audio.currentTime = 0;
|
||||
|
||||
audio = null;
|
||||
}
|
||||
}
|
||||
|
||||
function handleTimeUpdate() {
|
||||
currentTimeStore.set(audio.currentTime);
|
||||
}
|
||||
|
||||
function handleMetadata() {
|
||||
update(state => ({...state, duration: audio.duration}));
|
||||
}
|
||||
|
||||
function handleEnded() {
|
||||
update(state => ({...state, playing: false, currentHash: null}));
|
||||
}
|
||||
|
||||
function togglePlay(hash, local = false) {
|
||||
update(state => {
|
||||
const isPlaying = hash == state.currentHash ? !state.playing : true;
|
||||
|
||||
let url = local ? `https://cdn.songs.beatleader.com/${hash}.mp3` : `https://eu.cdn.beatsaver.com/${hash.toLowerCase()}.mp3`;
|
||||
|
||||
if (hash !== state.currentHash) {
|
||||
cleanup();
|
||||
currentTimeStore.set(0);
|
||||
audio = new Audio(url);
|
||||
audio.volume = state.volume;
|
||||
audio.addEventListener('timeupdate', handleTimeUpdate);
|
||||
audio.addEventListener('loadedmetadata', handleMetadata);
|
||||
audio.addEventListener('ended', handleEnded);
|
||||
audio.addEventListener('pause', handleEnded);
|
||||
} else if (!audio) {
|
||||
audio = new Audio(url);
|
||||
audio.volume = state.volume;
|
||||
audio.addEventListener('timeupdate', handleTimeUpdate);
|
||||
audio.addEventListener('loadedmetadata', handleMetadata);
|
||||
audio.addEventListener('ended', handleEnded);
|
||||
audio.addEventListener('pause', handleEnded);
|
||||
}
|
||||
|
||||
if (isPlaying) {
|
||||
audio?.play();
|
||||
} else {
|
||||
audio?.pause();
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
currentHash: hash,
|
||||
playing: isPlaying,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function setVolume(volume) {
|
||||
update(state => {
|
||||
if (audio) {
|
||||
audio.volume = volume;
|
||||
}
|
||||
return {...state, volume};
|
||||
});
|
||||
}
|
||||
|
||||
const reset = () => {
|
||||
cleanup();
|
||||
set(DEFAULT_STATE);
|
||||
};
|
||||
|
||||
songPlayerStore = {
|
||||
subscribe,
|
||||
togglePlay,
|
||||
setVolume,
|
||||
reset,
|
||||
};
|
||||
|
||||
return songPlayerStore;
|
||||
};
|
||||
Reference in New Issue
Block a user