d9c776e1d1
fix repeat added simple keyboard control add preloading tracks add plain view ("api") fix memory leak, add streaming responsive viewport Mobile web capable
158 lines
3.6 KiB
JavaScript
158 lines
3.6 KiB
JavaScript
let gstate = "idle";
|
|
let repeat = false;
|
|
let continuelist = true;
|
|
let queue = [];
|
|
let total = 0;
|
|
let index = 0;
|
|
|
|
let sound = new Howl({
|
|
src: [''],
|
|
format: "mp3",
|
|
html5: true
|
|
});
|
|
|
|
setInterval(function () {
|
|
updateState();
|
|
}, 1000);
|
|
|
|
window.onload = function () {
|
|
initState();
|
|
updateState()
|
|
};
|
|
|
|
document.addEventListener("keypress", function onEvent(event) {
|
|
if (event.key === "p") {
|
|
togglePlayback();
|
|
}
|
|
else if (event.key === "r") {
|
|
toggleRepeat();
|
|
}
|
|
else if (event.key === "c") {
|
|
toggleContinue();
|
|
}
|
|
});
|
|
|
|
|
|
function togglePlayback() {
|
|
if (sound.playing())
|
|
sound.pause();
|
|
else
|
|
sound.play();
|
|
}
|
|
|
|
function setState(state) {
|
|
gstate = state;
|
|
console.log("now in state: " + state);
|
|
updateState();
|
|
}
|
|
|
|
|
|
function playSong(url) {
|
|
if (document.getElementsByClassName("playing").length > 0)
|
|
document.getElementsByClassName("playing")[0].classList.remove("playing");
|
|
index = queue.indexOf(url);
|
|
sound.stop();
|
|
sound.unload();
|
|
sound = null;
|
|
delete sound;
|
|
|
|
sound = new Howl({
|
|
src: [url],
|
|
html5: true
|
|
});
|
|
setState("loading");
|
|
sound.play();
|
|
sound.loop(repeat);
|
|
|
|
document.querySelectorAll('[onclick="playSong(\''+url+'\')"]')[0].classList.add("playing");
|
|
|
|
sound.on("play", function () {
|
|
setState("playing");
|
|
});
|
|
sound.on("loaderror", function () {
|
|
setState("error loading track")
|
|
});
|
|
sound.on("playerror", function () {
|
|
setState("error opening audio device")
|
|
});
|
|
sound.on("end", function () {
|
|
setState("idle");
|
|
nextTrack()
|
|
});
|
|
sound.on("pause", function () {
|
|
setState("paused")
|
|
});
|
|
}
|
|
|
|
function toggleRepeat() {
|
|
repeat = !repeat;
|
|
continuelist = !repeat;
|
|
sound.loop(repeat);
|
|
updateState();
|
|
}
|
|
|
|
function toggleContinue() {
|
|
continuelist = !continuelist;
|
|
updateState();
|
|
}
|
|
|
|
function updateState() {
|
|
document.getElementById("state").setAttribute('onclick', 'togglePlayback()');
|
|
let statestr = "[";
|
|
statestr += gstate;
|
|
if (sound.playing())
|
|
statestr += " " + formatTime(Math.round(sound.seek())) + "/" + formatTime(Math.round(sound.duration()));
|
|
|
|
statestr += "]";
|
|
document.getElementById("state").innerHTML = statestr;
|
|
let flags = "[";
|
|
if (repeat)
|
|
flags += '<a onclick="toggleRepeat()" href="#" style="color:#6b9969">R</a>';
|
|
else
|
|
flags += '<a onclick="toggleRepeat()" href="#">R</a>';
|
|
if (continuelist)
|
|
flags += '<a onclick="toggleContinue()" href="#" style="color:#6b9969">C</a>';
|
|
else
|
|
flags += '<a onclick="toggleContinue()" href="#">C</a>';
|
|
|
|
document.getElementById("flags").innerHTML = flags + "]";
|
|
}
|
|
|
|
function initState() {
|
|
total = queue.length;
|
|
}
|
|
|
|
function nextTrack() {
|
|
if (++index === total)
|
|
index = 0;
|
|
if (continuelist) {
|
|
playSong(queue[index])
|
|
}
|
|
}
|
|
|
|
function formatTime(secs) {
|
|
const minutes = Math.floor(secs / 60) || 0;
|
|
const seconds = (secs - minutes * 60) || 0;
|
|
return minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
|
|
}
|
|
|
|
function download(filename, text) {
|
|
var element = document.createElement('a');
|
|
element.setAttribute('href', 'data:audio/m3u;charset=utf-8,' + encodeURIComponent(text));
|
|
element.setAttribute('download', filename);
|
|
|
|
element.style.display = 'none';
|
|
document.body.appendChild(element);
|
|
|
|
element.click();
|
|
|
|
document.body.removeChild(element);
|
|
}
|
|
|
|
function downloadm3u() {
|
|
let m3utext = "";
|
|
queue.forEach(function(item, index){
|
|
m3utext+=window.location.protocol + "//" + window.location.host + "/" + item + "\n";
|
|
});
|
|
download("play.m3u", m3utext)
|
|
} |