let mediaDir = "media/";
let mainContainerEl = document.getElementById("mainContainer");
let playerEl = document.getElementById("player");
let tracksEl = document.getElementById("tracks");
let descriptionEl = document.getElementById("description");
let bigButtonEl = document.getElementById("bigButton");
let controlsEl = document.getElementById("controls");
let scrubberTrackContainerEl = document.getElementById(
"scrubberTrackContainer"
);
let scrubberTrackPreviewEl = document.getElementById("scrubberTrackPreview");
let scrubberTrackEl = document.getElementById("scrubberTrack");
let scrubberFillEl = document.getElementById("scrubberFill");
let scrubberEl = document.getElementById("scrubber");
let nextTrackEl = document.getElementById("nextTrack");
let prevTrackEl = document.getElementById("prevTrack");
let loopSwitchEl = document.getElementById("loopSwitch");
let titleEl = document.getElementById("title");
let titleContainerEl = document.getElementById("titleContainer");
let mediaColumnEl = document.getElementById("mediaColumn");
let mediaContainerEl = document.getElementById("mediaContainer");
let mediaInfoEl = document.getElementById("mediaInfo");
let mediaImageEl = document.getElementById("mediaImage");
let mediaVideoEl = document.getElementById("mediaVideo");
let volumeContainerEl = document.getElementById("volumeContainer");
let volumeTrackContainerEl = document.getElementById("volumeTrackContainer");
let volumeTrackEl = document.getElementById("volumeTrack");
let volumeFillEl = document.getElementById("volumeFill");
let volumeIconEl = document.getElementById("volumeIcon");
let currentEntry = {};
let media = [];
let scrubPosition = 0;
let volumeIcons = ["icon-volume-none", "icon-volume-low", "icon-volume-high"];
let volume = 0.8;
let muted = false;
let loadedFirst = false;
let autoPlay = false;
let loopMode = "none";
let config = {};
function init() {
fetch("config.json")
.then((res) => res.json())
.then((data) => {
update(data);
})
.catch(console.error);
}
init();
function updateTheme(theme) {
config.theme = theme;
let rootEl = document.documentElement;
if (theme.primaryColor)
rootEl.style.setProperty("--primaryColor", theme.primaryColor);
if (theme.primaryAltColor)
rootEl.style.setProperty("--primaryAltColor", theme.primaryAltColor);
if (theme.primaryTextColor)
rootEl.style.setProperty("--primaryTextColor", theme.primaryTextColor);
if (theme.primaryAltTextColor)
rootEl.style.setProperty(
"--primaryAltTextColor",
theme.primaryAltTextColor
);
if (theme.secondaryColor)
rootEl.style.setProperty("--secondaryColor", theme.secondaryColor);
if (theme.highlightColor)
rootEl.style.setProperty("--highlightColor", theme.highlightColor);
if (theme.backgroundColor)
rootEl.style.setProperty("--backgroundColor", theme.backgroundColor);
if (theme.previewStripeColor1)
rootEl.style.setProperty(
"--previewStripeColor1",
theme.previewStripeColor1
);
if (theme.previewStripeColor2)
rootEl.style.setProperty(
"--previewStripeColor2",
theme.previewStripeColor2
);
if (theme.linkColor) rootEl.style.setProperty("--linkColor", theme.linkColor);
if (theme.overlayTextColor)
rootEl.style.setProperty("--overlayTextColor", theme.overlayTextColor);
if (theme.overlayBackgroundColor)
rootEl.style.setProperty(
"--overlayBackgroundColor",
theme.overlayBackgroundColor
);
if (theme.layoutStyle) {
mainContainerEl.classList.remove("vertical", "horizontal");
mainContainerEl.classList.add(theme.layoutStyle);
}
if (theme.infoStyle) {
mainContainerEl.classList.remove(
"info-none",
"info-overlaid",
"info-below",
"info-overlaid-toggle"
);
mainContainerEl.classList.add("info-" + theme.infoStyle);
}
if (theme.titleStyle) {
mainContainerEl.classList.remove("title-none", "title-span");
mainContainerEl.classList.add("title-" + theme.titleStyle);
}
if (theme.contentWidth)
document.getElementById("contentContainer").style.maxWidth =
theme.contentWidth + "px";
if (theme.nativePlayer) {
document.getElementById("audio").classList.add("native");
mediaVideoEl.setAttribute("controls", "");
} else {
document.getElementById("audio").classList.remove("native");
mediaVideoEl.removeAttribute("controls");
}
if (theme.hideInfoDropdown) {
mainContainerEl.classList.add("hide-info");
} else {
mainContainerEl.classList.remove("hide-info");
}
mediaContainerEl.style.maxWidth = theme.coverSize + "px";
mediaContainerEl.style.maxHeight = theme.coverSize + "px";
mediaColumnEl.style.maxWidth = theme.coverSize + "px";
if (theme.customCSS !== undefined) {
document.querySelectorAll("#customCSS").forEach((el) => el.remove());
let styleEl = document.createElement("style");
styleEl.setAttribute("id", "customCSS");
styleEl.innerText = theme.customCSS;
document.head.appendChild(styleEl);
}
}
function loadContent(data) {
loadCover(data.cover);
mediaImageEl.style.width = config.theme.coverSize + "px";
mediaImageEl.style.height = config.theme.coverSize + "px";
if (data.media) loadMedia(data.media);
}
function updateTitle(title) {
if (title) {
titleContainerEl.classList.add("active");
config.title = title;
titleEl.innerHTML = title;
} else {
titleContainerEl.classList.remove("active");
}
}
function updateDescription(description) {
if (description === undefined || description === "") {
descriptionEl.classList.remove("active");
} else {
descriptionEl.classList.add("active");
config.description = description;
descriptionEl.innerHTML = description;
}
}
function updateLoopMode(mode) {
if (mode === undefined || mode === "") {
config.loopModeDefault = "none";
} else {
config.loopModeDefault = mode;
}
loopSwitch(config.loopModeDefault);
}
function localStorageSet(key, value) {
try {
localStorage.setItem(key, value);
} catch {}
}
function localStorageGet(key) {
let value;
try {
value = localStorage.getItem(key);
} catch {
return undefined;
}
return value;
}
function update(data) {
if (!data) {
data = config;
}
if (!data.theme) {
data.theme = {};
}
let title = data.title;
let theme = data.theme;
let description = data.description;
config = data;
loadContent(data);
updateTitle(title);
updateDescription(description);
updateLoopMode(data.loopModeDefault);
updateTheme(theme);
updateTrackPreview();
document.title = titleEl.textContent;
volume = parseFloat(localStorageGet("volume"));
muted = parseInt(localStorageGet("muted"));
if (volume && typeof volume === "number") {
setVolume(volume, muted);
} else {
volume = 0.8;
muted = false;
localStorageSet("volume", volume);
}
}
function loadMedia(list) {
if (list.length === 0) {
return;
}
loadedFirst = false;
autoPlay = false;
bigButtonEl.classList.remove("pause");
media = list.map((entry) => {
//return {file: entry.file, title: entry.title};
if (!/:\/\//.test(entry.file)) {
//if not a url
entry.file = mediaDir + entry.file;
}
entry.title = entry.title || entry.file;
return entry;
});
let featureIndex = 0;
tracksEl.textContent = "";
media.forEach((entry, i) => {
tracksEl.insertAdjacentHTML(
"beforeend",
`
${i + 1}.
${entry.title}
${
entry.info
? `
`
: ""
}
${
entry.info
? `
`
: ""
}
`
);
let trackEl = tracksEl.lastChild;
entry.trackEl = trackEl;
let buttonEl = trackEl.querySelector("button");
if (entry.feature) {
featureIndex = i;
}
if (entry.locked && featureIndex === i) {
featureIndex++;
}
if (entry.info) {
let infoContainerEl = trackEl.querySelector(".infoContainer");
trackEl.querySelector(".toggleInfo").addEventListener("click", (e) => {
infoContainerEl.style.height =
trackEl.querySelector(".info").clientHeight + "px";
entry.infoToggled = infoContainerEl.classList.toggle("active");
if (entry.info && entry.infoToggled) {
infoContainerEl.removeAttribute("inert");
} else {
infoContainerEl.setAttribute("inert", "");
}
if (config.theme.infoStyle === "overlaid-toggle") {
if (entry.info && entry.infoToggled) {
mediaInfoEl.innerHTML = entry.info;
mediaInfoContainer.classList.add("active");
} else {
mediaInfoEl.innerHTML = "";
mediaInfoContainer.classList.remove("active");
}
}
});
}
if (!entry.previewFade && entry.previewFade !== false) {
entry.previewFade = true; //default true
}
if (typeof entry.loopCount === "number" && entry.loopCount > 0) {
entry.remainingLoops = entry.loopCount;
trackEl.classList.add("looped");
buttonEl.setAttribute("title", "loop count");
updateLoops(entry);
}
if (!entry.locked) {
buttonEl.onclick = () => {
loadedFirst = true;
autoPlay = true;
playEntry(entry);
};
let loaderEl;
if (entry.type === "video") {
loaderEl = document.createElement("video");
} else {
loaderEl = document.createElement("audio");
}
if (entry.previewStart || entry.previewEnd) {
entry.preview = true;
}
let needsPreviewEnd = false;
if (!entry.previewEnd) {
needsPreviewEnd = true;
}
entry.originalDuration =
(entry.originalDuration && fromHMS(entry.originalDuration)) || 1;
entry.previewStart =
(entry.previewStart && fromHMS(entry.previewStart)) || 0;
entry.previewEnd =
(entry.previewEnd && fromHMS(entry.previewEnd)) ||
entry.originalDuration;
entry.previewDuration = entry.previewEnd - entry.previewStart;
loaderEl.addEventListener("loadedmetadata", (e) => {
entry.duration = e.target.duration;
entry.needsDuration = false;
entry.previewStart = entry.previewStart || 0;
if (needsPreviewEnd) {
entry.previewEnd = entry.duration;
}
entry.originalDuration = Math.max(
entry.originalDuration,
entry.duration,
entry.previewEnd
);
entry.previewDuration = entry.previewEnd - entry.previewStart;
//make assumptions about the audio start points
if (entry.duration < entry.previewDuration) {
//smaller than given preview duration
//left align to preview
entry.audioStart = entry.previewStart;
} else if (
entry.duration <
entry.originalDuration - entry.previewStart
) {
//else, smaller than region between preview start and original end
//left align to preview
entry.audioStart = entry.previewStart;
} else if (entry.duration < entry.originalDuration) {
//else, smaller than original duration
//right align to original
entry.audioStart = entry.originalDuration - entry.duration;
} else {
//larger than original duration
//left align to original
entry.audioStart = 0;
}
entry.audioEnd = entry.audioStart + entry.duration;
let durationText = toHMS(entry.duration);
if (entry.preview) {
durationText += " (preview)";
}
trackEl.querySelector(".duration").textContent = durationText;
if (entry === currentEntry) {
updateTrackPreview();
// updateScrubPosition(entry.previewStart / entry.originalDuration);
updateScrubPosition(0);
updatePreviewVolume(0);
}
});
loaderEl.addEventListener("error", (e) => {
entry.error = true;
entry.errorMessage = e.target.error;
removeLoading(entry, true);
buttonEl.classList.add("error", "icon-warning");
buttonEl.setAttribute("title", "error loading file");
});
loaderEl.addEventListener("canplay", (e) => {
removeLoading(entry, true);
if (entry.feature && entry.autoplay) {
playerEl.play();
}
});
loaderEl.volume = 0;
loaderEl.src = entry.file;
entry.started = false;
entry.loading = true;
entry.loaderEl = loaderEl;
}
});
loadEntry(media[mod(featureIndex, media.length)]);
}
function loadCover(cover) {
if (cover) {
let src = cover;
if (mediaImageEl.src == src) {
return; //already loaded
}
if (!/:\/\//.test(src)) {
//if not a url
src = mediaDir + src;
}
mediaImageEl.src = src;
mediaImageEl.classList.add("active");
mediaImageEl.style.visibility = "visible";
} else {
mediaImageEl.style.visibility = "hidden";
}
}
function setCover(cover, size) {
if (cover) {
config.cover = cover;
size && (config.coverSize = size);
loadCover(cover);
}
}
playerEl.addEventListener("canplay", (e) => {
removeLoading(currentEntry);
if (currentEntry.needsDuration) {
currentEntry.duration = playerEl.duration;
currentEntry.needsDuration = false;
}
if (autoPlay && !currentEntry.started) {
currentEntry.started = true;
if (!currentEntry.needsDuration) {
playerEl.currentTime =
currentEntry.previewStart - currentEntry.audioStart;
}
playerEl.play();
}
if (!loadedFirst) {
autoPlay = true;
}
});
playerEl.addEventListener("waiting", (e) => {
setLoading(currentEntry, 0);
});
playerEl.addEventListener("play", (e) => {
if (
currentEntry.preview &&
playerEl.currentTime < currentEntry.previewStart - currentEntry.audioStart
) {
playerEl.currentTime = currentEntry.previewStart - currentEntry.audioStart;
}
bigButtonEl.classList.add("pause");
currentEntry.started = true;
currentEntry.trackEl.querySelector("button").classList.add("pause");
if (currentEntry.type === "video") {
mediaVideoEl.play();
}
});
playerEl.addEventListener("pause", (e) => {
bigButtonEl.classList.remove("pause");
currentEntry.trackEl.querySelector("button").classList.remove("pause");
if (currentEntry.type === "video") {
mediaVideoEl.pause();
}
});
playerEl.addEventListener("volumechange", (e) => {
if (config.theme.nativePlayer) {
volume = e.target.volume;
localStorageSet("volume", volume);
}
if (currentEntry.type === "video") {
if (config.theme.nativePlayer) {
mediaVideoEl.volume = e.target.volume;
} else {
mediaVideoEl.volume = 0;
}
}
});
mediaVideoEl.addEventListener("volumechange", (e) => {
if (currentEntry.type === "video" && config.theme.nativePlayer) {
volume = e.target.volume;
localStorageSet("volume", volume);
}
});
playerEl.addEventListener("timeupdate", (e) => {
let buffer = 0.18;
if (!scrubberDragged) {
if (currentEntry.duration && !currentEntry.needsDuration) {
if (currentEntry.started) {
let time = e.target.currentTime;
if (time > currentEntry.previewEnd - currentEntry.audioStart - buffer) {
nextTrack(false);
} else {
let t = time / currentEntry.duration;
updatePreviewVolume(t);
updateScrubPosition(t);
}
} else {
}
} else {
let time = e.target.currentTime;
if (time > e.target.duration - buffer) {
nextTrack(false);
}
}
}
});
playerEl.addEventListener("ended", (e) => {
if (!scrubberDragged) {
nextTrack(false);
}
});
mediaVideoEl.addEventListener("ended", (e) => {
if (currentEntry.type === "video" && config.theme.nativePlayer) {
nextTrack(false);
}
});
bigButtonEl.addEventListener("click", (e) => {
playEntry(currentEntry);
});
volumeIconEl.addEventListener("click", (e) => {
toggleMute();
});
let volumeDragged = false;
volumeTrackContainerEl.addEventListener("mousedown", (e) => {
volumeDragged = true;
scrubVolume(e.clientX);
});
let volumeHovered = false;
volumeContainerEl.addEventListener("mouseenter", (e) => {
if (!scrubberDragged) {
volumeHovered = true;
volumeContainerEl.classList.add("hover");
}
});
volumeContainerEl.addEventListener("mouseleave", (e) => {
volumeHovered = false;
if (!volumeDragged) {
volumeContainerEl.classList.remove("hover");
}
});
function toggleMute() {
muted = !muted;
setVolume(volume, muted);
}
function scrubVolume(x) {
if (volumeDragged) {
let trackX = volumeTrackEl.getBoundingClientRect().x;
x -= trackX;
let scrubberWidth = 6;
let trackWidth = volumeTrackEl.clientWidth;
let t =
1 -
Math.max(
0,
Math.min(1, (x - scrubberWidth / 2) / (trackWidth - scrubberWidth))
);
setVolume(t);
}
}
function endVolumeScrub() {
if (!volumeHovered) {
volumeContainerEl.classList.remove("hover");
}
}
function setVolume(vol, mute = false) {
volume = vol;
localStorageSet("volume", volume);
localStorageSet("muted", mute ? 1 : 0);
vol = mute ? 0 : vol;
if (currentEntry.type === "video") {
if (config.theme.nativePlayer) {
mediaVideoEl.volume = volume;
playerEl.volume = 0;
} else {
mediaVideoEl.volume = 0;
playerEl.volume = vol;
}
} else {
playerEl.volume = vol;
}
let scrubberWidth = 6;
let trackWidth = volumeTrackEl.clientWidth;
volumeFillEl.style.left = (1 - vol) * (trackWidth - scrubberWidth) + "px";
volumeIconEl.classList.remove(...volumeIcons);
if (vol <= 0) {
volumeIconEl.classList.add(volumeIcons[0]);
} else if (vol <= 0.5) {
volumeIconEl.classList.add(volumeIcons[1]);
} else {
volumeIconEl.classList.add(volumeIcons[2]);
}
}
document.addEventListener("keydown", (e) => {
if (e.key === " " && e.target === document.body) {
playEntry(currentEntry);
e.preventDefault();
}
});
let scrubberDragged = false;
scrubberTrackContainerEl.addEventListener("pointerdown", (e) => {
scrubberDragged = true;
currentEntry.started = true;
scrub(e.clientX);
});
document.addEventListener("pointerup", (e) => {
if (scrubberDragged) {
scrubberDragged = false;
endScrub();
}
if (volumeDragged) {
volumeDragged = false;
endVolumeScrub();
}
});
document.addEventListener("pointermove", (e) => {
scrub(e.clientX);
scrubVolume(e.clientX);
});
document.addEventListener("pointercancel", (e) => {
console.log(e);
});
nextTrackEl.addEventListener("click", (e) => {
nextTrack();
});
prevTrackEl.addEventListener("click", (e) => {
prevTrack();
});
loopSwitchEl.addEventListener("click", (e) => {
loopSwitch();
});
function updateTrackPreview() {
if (currentEntry.needsDuration) {
return;
}
//reset to prevent compounding width calculation issues
scrubberTrackPreviewEl.style.removeProperty("margin-left");
scrubberTrackPreviewEl.style.removeProperty("width");
scrubberEl.style.removeProperty("left");
scrubberFillEl.style.removeProperty("width");
if (currentEntry.preview) {
let fullWidth = scrubberEl.parentElement.parentElement.clientWidth;
scrubberTrackPreviewEl.style.marginLeft =
(currentEntry.previewStart / currentEntry.originalDuration) * 100 + "%";
scrubberTrackPreviewEl.style.width =
((currentEntry.previewEnd - currentEntry.previewStart) /
currentEntry.originalDuration) *
100 +
"%";
}
}
function updatePreviewVolume(t) {
if (currentEntry.preview && currentEntry.previewFade && !muted) {
if (currentEntry.needsDuration) {
playEntry.volume = 0;
} else {
//rebase t to full (assumed) duration
t = currentEntry.audioStart + t * currentEntry.duration;
//clip to preview
t = Math.max(
currentEntry.previewStart,
Math.min(currentEntry.previewEnd, t)
);
let inTime = t - currentEntry.previewStart;
let outTime = currentEntry.previewEnd - t;
playerEl.volume =
volume * Math.max(0, Math.min(1, inTime / 1, outTime / 1)); //1 second fade in/out
}
}
}
//t: 0-1 value in relation to the actual audio start/end
function updateScrubPosition(t) {
if (currentEntry.needsDuration) {
return;
}
//rebase t to full (assumed) duration
t = currentEntry.audioStart + t * currentEntry.duration;
//clip to preview
t = Math.max(currentEntry.previewStart, Math.min(currentEntry.previewEnd, t));
scrubPosition = (t - currentEntry.audioStart) / currentEntry.duration;
let time = t;
//rebase
t = t / currentEntry.originalDuration;
//relative to preview region
let scrubberT =
(t * currentEntry.originalDuration - currentEntry.previewStart) /
currentEntry.previewDuration;
let scrubberWidth = scrubberEl.clientWidth;
let trackWidth = scrubberEl.parentElement.clientWidth;
scrubberEl.style.left =
((scrubberT * (trackWidth - scrubberWidth)) / trackWidth) * 100 + "%";
scrubberFillEl.style.width = scrubberT * 100 + "%";
//let time = timePosition * currentEntry.duration;
let timeText = "";
if (currentEntry.preview) {
timeText += "(preview)
";
}
timeText += `${toHMS(time)} / ${
currentEntry.originalDuration
? toHMS(currentEntry.originalDuration)
: "0:00"
}`;
controlsEl.querySelector(".time").innerHTML = timeText;
}
function scrub(x) {
if (scrubberDragged) {
let trackX = scrubberTrackEl.getBoundingClientRect().x;
x -= trackX;
let scrubberWidth = scrubberEl.clientWidth;
let trackWidth = scrubberEl.parentElement.clientWidth;
let t = Math.max(
0,
Math.min(1, (x - scrubberWidth / 2) / (trackWidth - scrubberWidth))
);
if (currentEntry.preview) {
//rebase t from preview to audio start/end
t =
(t * currentEntry.previewDuration +
(currentEntry.previewStart - currentEntry.audioStart)) /
currentEntry.duration;
}
updateScrubPosition(t);
}
}
function endScrub() {
if (currentEntry.loading) {
return;
}
playerEl.currentTime = scrubPosition * playerEl.duration;
if (currentEntry.type === "video") {
mediaVideoEl.currentTime = scrubPosition * playerEl.duration;
}
}
function canPlay(entry) {
return !entry.error && !entry.locked;
}
function nextTrack(manual = true) {
if (!manual && loopMode === "track") {
loadEntry(currentEntry);
} else if (!manual && currentEntry.remainingLoops > 0) {
currentEntry.remainingLoops--;
updateLoops(currentEntry);
loadEntry(currentEntry);
} else {
let loop = manual || loopMode === "playlist";
let idx = media.indexOf(currentEntry) + 1;
if (!loop && idx >= media.length) {
return;
}
let entry = media[mod(idx, media.length)];
let i = 0;
while (!canPlay(entry) && i < media.length) {
i++;
idx++;
if (!loop && idx >= media.length) {
return;
}
entry = media[mod(idx, media.length)];
}
loadEntry(entry);
}
}
function prevTrack() {
if (
playerEl.currentTime >
currentEntry.previewStart - currentEntry.audioStart + 5
) {
playerEl.currentTime = currentEntry.previewStart - currentEntry.audioStart;
} else {
let idx = media.indexOf(currentEntry) - 1;
let entry = media[mod(idx, media.length)];
let i = 0;
while (!canPlay(entry) && i < media.length) {
i++;
idx--;
entry = media[mod(idx, media.length)];
}
loadEntry(entry);
}
}
function loopSwitch(mode) {
loopSwitchEl.classList.remove("icon-loop", "icon-loop-1");
loopSwitchEl.style.opacity = 1;
if (mode) {
loopMode = mode;
} else {
if (loopMode === "none") {
loopMode = "playlist";
} else if (loopMode === "playlist") {
loopMode = "track";
} else {
loopMode = "none";
}
}
if (loopMode === "none") {
loopSwitchEl.classList.add("icon-loop");
loopSwitchEl.style.opacity = 0.5;
loopSwitchEl.setAttribute("title", "loop off");
} else if (loopMode === "playlist") {
loopSwitchEl.classList.add("icon-loop");
loopSwitchEl.setAttribute("title", "loop playlist");
} else {
loopSwitchEl.classList.add("icon-loop-1");
loopSwitchEl.setAttribute("title", "loop track");
}
}
function setLoading(entry, delay = 150) {
if (entry.loading) {
delay = 0;
}
if (entry === currentEntry) {
bigButtonEl.classList.add("preloading");
setTimeout(() => {
if (bigButtonEl.classList.contains("preloading")) {
bigButtonEl.classList.remove("preloading");
bigButtonEl.classList.add("loading");
}
}, delay);
}
entry.loading = true;
}
function removeLoading(entry, track = false) {
if (entry === currentEntry) {
bigButtonEl.classList.remove("loading", "preloading");
}
if (track) {
entry.trackEl
.querySelector("button")
.classList.remove("loading", "preloading");
}
entry.loading = false;
}
function updateLoops(entry) {
if (entry.loopCount > 0) {
let buttonEl = entry.trackEl.querySelector("button");
buttonEl.setAttribute("loopcount", entry.remainingLoops);
// buttonEl.setAttribute('title', 'loop count');
}
if (entry === currentEntry) {
if (entry.loopCount > 0) {
bigButtonEl.setAttribute("loopcount", entry.remainingLoops);
} else {
bigButtonEl.removeAttribute("loopcount");
}
}
}
function resetLoops(entry) {
entry.remainingLoops = entry.loopCount;
updateLoops(entry);
}
function loadEntry(entry) {
if (entry.error) {
return;
}
if (entry.locked) {
return;
}
if (entry === currentEntry) {
if (entry.type === "video") {
mediaVideoEl.currentTime = 0;
} else {
}
playerEl.currentTime = 0;
playerEl.play();
return;
}
currentEntry = entry;
media.forEach((thisEntry) => {
thisEntry.trackEl.classList.remove("active");
thisEntry.trackEl.querySelector("button").classList.remove("pause");
if (thisEntry !== entry) {
resetLoops(thisEntry);
}
updateLoops(entry);
});
if (!currentEntry.duration) {
currentEntry.duration = 999;
currentEntry.needsDuration = true;
}
updateTrackPreview();
if (entry.preview) {
scrubberTrackContainerEl.classList.add("preview");
updatePreviewVolume(0);
} else {
scrubberTrackContainerEl.classList.remove("preview");
}
if (entry.loopCount > 0) {
bigButtonEl.classList.add("looped");
} else {
bigButtonEl.classList.remove("looped");
}
Array.from(mediaContainerEl.children).forEach((el) => {
el.classList.remove("active");
});
if (entry.type === "video") {
mediaVideoEl.src = entry.file;
mediaVideoEl.classList.add("active");
mediaImageEl.style.visibility = "hidden";
playerEl.classList.add("video");
if (config.theme.nativePlayer) {
mediaVideoEl.volume = volume;
playerEl.volume = 0;
} else {
mediaVideoEl.volume = 0;
playerEl.volume = volume;
}
} else {
mediaImageEl.classList.add("active");
playerEl.classList.remove("video");
playerEl.volume = volume;
mediaVideoEl.pause();
mediaVideoEl.removeAttribute("src");
mediaVideoEl.load();
if (entry.cover) {
loadCover(entry.cover);
} else {
loadCover(config.cover);
}
}
playerEl.src = entry.file;
entry.started = false;
setLoading(currentEntry);
entry.trackEl.classList.add("active");
controlsEl.querySelector(".title").innerHTML = entry.title;
if (
entry.info &&
(config.theme.infoStyle !== "overlaid-toggle" || entry.infoToggled)
) {
mediaInfoEl.innerHTML = entry.info;
mediaInfoContainer.classList.add("active");
} else {
mediaInfoEl.innerHTML = "";
mediaInfoContainer.classList.remove("active");
}
}
function playEntry(entry) {
if (currentEntry === entry) {
if (entry.loading) {
return;
}
if (playerEl.paused) {
playerEl.play();
entry.trackEl.querySelector("button").classList.add("pause");
} else {
playerEl.pause();
}
} else {
loadEntry(entry);
}
}
function toHMS(secs) {
if (isNaN(secs)) {
return "00:00";
}
let sec_num = Math.max(0, Math.round(secs)); //flooring is more correct, but rounding gives nicer results due to playback event buffering
let hours = Math.floor(sec_num / 3600);
let minutes = Math.floor(sec_num / 60) % 60;
let seconds = sec_num % 60;
return [hours, minutes, seconds]
.map((v) => (v < 10 ? "0" + v : v))
.filter((v, i) => v !== "00" || i > 0)
.join(":");
}
function fromHMS(hms) {
if (!hms) {
return 0;
}
let groups = ("" + hms).split(":");
if (groups.length < 1) {
return 0;
}
for (let i = 0; i < groups.length; i++) {
if (groups[i] === "") {
groups[i] = "0";
continue;
}
if (isNaN(groups[i])) {
return 0;
}
}
let seconds = 0;
let minutes = 0;
let hours = 0;
seconds = parseFloat(groups[groups.length - 1]);
if (groups.length >= 2) {
minutes = parseFloat(groups[groups.length - 2]);
}
if (groups.length >= 3) {
hours = parseFloat(groups[groups.length - 3]);
}
return (hours * 60 + minutes) * 60 + seconds;
}
function mod(x, n) {
return ((x % n) + n) % n;
}