ws4kp-linhanced/server/scripts/modules/media.mjs

178 lines
4.2 KiB
JavaScript
Raw Normal View History

2025-03-22 15:10:06 +01:00
import { json } from './utils/fetch.mjs';
import Setting from './utils/setting.mjs';
let playlist;
2025-03-23 20:28:04 -05:00
let currentTrack = 0;
let player;
2025-03-22 15:10:06 +01:00
2025-04-08 10:40:36 -05:00
const mediaPlaying = new Setting('mediaPlaying', {
name: 'Media Playing',
type: 'boolean',
defaultValue: false,
sticky: true,
});
2025-03-22 15:10:06 +01:00
document.addEventListener('DOMContentLoaded', () => {
// add the event handler to the page
document.getElementById('ToggleMedia').addEventListener('click', toggleMedia);
// get the playlist
getMedia();
});
const getMedia = async () => {
try {
// fetch the playlist
const rawPlaylist = await json('playlist.json');
// store the playlist
playlist = rawPlaylist;
// enable the media player
enableMediaPlayer();
} catch (e) {
console.error("Couldn't get playlist");
console.error(e);
}
};
const enableMediaPlayer = () => {
// see if files are available
if (playlist?.availableFiles?.length > 0) {
2025-03-23 18:42:48 +01:00
// randomize the list
randomizePlaylist();
2025-03-22 15:10:06 +01:00
// enable the icon
const icon = document.getElementById('ToggleMedia');
icon.classList.add('available');
// set the button type
setIcon();
2025-03-24 21:49:41 -05:00
// if we're already playing (sticky option) then try to start playing
if (mediaPlaying.value === true) {
startMedia();
}
2025-03-22 15:10:06 +01:00
}
};
const setIcon = () => {
// get the icon
const icon = document.getElementById('ToggleMedia');
if (mediaPlaying.value === true) {
icon.classList.add('playing');
} else {
icon.classList.remove('playing');
}
};
const toggleMedia = (forcedState) => {
// handle forcing
if (typeof forcedState === 'boolean') {
mediaPlaying.value = forcedState;
} else {
// toggle the state
mediaPlaying.value = !mediaPlaying.value;
}
// handle the state change
stateChanged();
};
2025-03-24 18:24:49 -05:00
const startMedia = async () => {
2025-03-23 20:28:04 -05:00
// if there's not media player yet, enable it
if (!player) {
initializePlayer();
} else {
2025-03-24 18:24:49 -05:00
try {
await player.play();
setTrackName(playlist.availableFiles[currentTrack]);
2025-03-24 18:24:49 -05:00
} catch (e) {
2025-03-24 21:49:41 -05:00
// report the error
2025-03-24 18:24:49 -05:00
console.error('Couldn\'t play music');
console.error(e);
2025-03-24 21:49:41 -05:00
// set state back to not playing for good UI experience
mediaPlaying.value = false;
stateChanged();
setTrackName('Not playing');
2025-03-24 18:24:49 -05:00
}
2025-03-23 20:28:04 -05:00
}
2025-03-22 15:10:06 +01:00
};
const stopMedia = () => {
2025-03-23 20:28:04 -05:00
if (!player) return;
player.pause();
setTrackName('Not playing');
2025-03-22 15:10:06 +01:00
};
const stateChanged = () => {
// update the icon
setIcon();
// react to the new state
if (mediaPlaying.value) {
startMedia();
} else {
stopMedia();
}
};
2025-03-23 18:42:48 +01:00
const randomizePlaylist = () => {
let availableFiles = [...playlist.availableFiles];
const randomPlaylist = [];
while (availableFiles.length > 0) {
// get a randon item from the available files
const i = Math.floor(Math.random() * availableFiles.length);
// add it to the final list
randomPlaylist.push(availableFiles[i]);
// remove the file from the available files
availableFiles = availableFiles.filter((file, index) => index !== i);
}
playlist.availableFiles = randomPlaylist;
};
2025-03-23 20:28:04 -05:00
const initializePlayer = () => {
// basic sanity checks
if (!playlist.availableFiles || playlist?.availableFiles.length === 0) {
throw new Error('No playlist available');
}
if (player) {
return;
}
// create the player
player = new Audio();
// reset the playlist index
currentTrack = 0;
// add event handlers
player.addEventListener('canplay', playerCanPlay);
player.addEventListener('ended', playerEnded);
2025-03-23 21:17:08 -05:00
// get the first file
player.src = `music/${playlist.availableFiles[currentTrack]}`;
setTrackName(playlist.availableFiles[currentTrack]);
2025-03-23 21:17:08 -05:00
player.type = 'audio/mpeg';
2025-03-23 20:28:04 -05:00
};
2025-03-24 18:24:49 -05:00
const playerCanPlay = async () => {
2025-03-23 20:28:04 -05:00
// check to make sure they user still wants music (protect against slow loading music)
if (!mediaPlaying.value) return;
// start playing
2025-03-24 18:24:49 -05:00
startMedia();
2025-03-23 20:28:04 -05:00
};
const playerEnded = () => {
2025-03-23 21:17:08 -05:00
// next track
currentTrack += 1;
// roll over and re-randomize the tracks
if (currentTrack >= playlist.availableFiles.length) {
2025-03-23 21:17:08 -05:00
randomizePlaylist();
currentTrack = 0;
}
// update the player source
player.src = `music/${playlist.availableFiles[currentTrack]}`;
setTrackName(playlist.availableFiles[currentTrack]);
};
const setTrackName = (fileName) => {
const trackName = fileName.replace(/\.mp3/gi, '').replace(/(_-)/gi, '');
document.getElementById('musicTrack').innerHTML = trackName;
2025-03-23 20:28:04 -05:00
};
2025-03-22 15:10:06 +01:00
export {
// eslint-disable-next-line import/prefer-default-export
toggleMedia,
};