diff --git a/playlist.html b/2018-playlist.html similarity index 100% rename from playlist.html rename to 2018-playlist.html diff --git a/2019-playlist.html b/2019-playlist.html new file mode 100644 index 0000000..f834db0 --- /dev/null +++ b/2019-playlist.html @@ -0,0 +1,54 @@ + + + + + + 2019 ROF + + + + + + + + +
+
+ +
+ + + + + + +
+ + + + diff --git a/playlist.css b/playlist.css index 348c527..57b397e 100644 --- a/playlist.css +++ b/playlist.css @@ -8,6 +8,10 @@ audio { min-width: 40em; } +#pos { + width: 100%; +} + #currentTime { background-color: #001; float: right; diff --git a/playlist.js b/playlist.js index 209e112..4c2eb0b 100644 --- a/playlist.js +++ b/playlist.js @@ -1,19 +1,22 @@ +// jshint asi:true + // HTML5 Playlist by Neale Pickett // https://github.com/nealey/playlst -var base = "."; + +var base = "." function loadTrack(e) { - let li = e.srcElement; - let audio = document.querySelector("#audio"); - audio.src = base + "/" + li.textContent; - audio.load(); + let li = e.target + let audio = document.querySelector("#audio") + audio.src = base + "/" + li.textContent + audio.load() // Update "current" for (let cur of document.querySelectorAll(".current")) { - cur.classList.remove("current"); + cur.classList.remove("current") } - li.classList.add("current"); + li.classList.add("current") } function clickOn(element) { @@ -21,125 +24,149 @@ function clickOn(element) { view: window, bubbles: true, cancelable: true - }); - element.dispatchEvent(e); + }) + element.dispatchEvent(e) } function prev() { - let cur = document.querySelector(".current"); - let prev = cur.previousElementSibling; + let cur = document.querySelector(".current") + let prev = cur.previousElementSibling if (prev) { - cur = prev; + cur = prev } - clickOn(cur); + clickOn(cur) } function next() { - let cur = document.querySelector(".current"); - let next = cur.nextElementSibling; + let cur = document.querySelector(".current") + let next = cur.nextElementSibling if (next) { - cur = next; + cur = next } - clickOn(cur); + clickOn(cur) } function ended() { - next(); + next() } function mmss(s) { - let mm = Math.floor(s / 60); - let ss = Math.floor(s % 60); + let mm = Math.floor(s / 60) + let ss = Math.floor(s % 60) if (ss < 10) { - ss = "0" + ss; + ss = "0" + ss } - return mm + ":" + ss; + return mm + ":" + ss } function durationchange(e) { - let duration = e.srcElement.duration; + let duration = e.target.duration - document.querySelector("#duration").textContent = mmss(duration); + document.querySelector("#duration").textContent = mmss(duration) + timeupdate(e) +} + +function volumechange(e) { + document.querySelector("#vol").value = e.target.volume } function timeupdate(e) { - let currentTime = e.srcElement.currentTime; - let tgt = document.querySelector("#currentTime"); + let currentTime = e.target.currentTime + let duration = e.target.duration || 1 + let tgt = document.querySelector("#currentTime") + let pos = document.querySelector("#pos") - tgt.textContent = mmss(currentTime); + pos.value = currentTime / duration + + tgt.textContent = mmss(currentTime) if (duration - currentTime < 20) { - tgt.classList.add("fin"); + tgt.classList.add("fin") } else { - tgt.classList.remove("fin"); + tgt.classList.remove("fin") } } +function setPos(e) { + let val = e.target.value + let audio = document.querySelector("#audio") + + audio.currentTime = audio.duration * val +} + +function setGain(e) { + let val = e.target.value + let audio = document.querySelector("#audio") + + audio.volume = val +} + function keydown(e) { - let audio = document.querySelector("#audio"); + let audio = document.querySelector("#audio") switch (event.key) { case " ": // space bar if (audio.paused) { - audio.play(); + audio.play() } else { - audio.pause(); + audio.pause() } - break; + break case "ArrowDown": // Next track - next(); - break; + next() + break case "ArrowUp": // Previous track - prev(); - break; + prev() + break } } function midiMessage(e) { - let audio = document.querySelector("#audio"); - let data = e.data; - let ctrl = data[1]; - let val = data[2]; + let audio = document.querySelector("#audio") + let data = e.data + let ctrl = data[1] + let val = data[2] if ((data[0] == 0xb0) || (data[0] == 0xbf)) { switch (ctrl) { case 0: // master volume slider - audio.volume = val / 127; - break; + audio.volume = val / 127 + document.querySelector("#vol").value = audio.volume + break case 41: // play button if (val == 127) { - audio.play(); + audio.play() } - break; + break case 42: // stop button if (val == 127) { - audio.pause(); + audio.pause() } - break; + break case 58: // prev button if (val == 127) { - prev(); + prev() } - break; + break case 59: // next button if (val == 127) { - next(); + next() } - break; + break } } } function handleMidiAccess(access) { for (let input of access.inputs.values()) { - input.addEventListener("midimessage", midiMessage); + input.addEventListener("midimessage", midiMessage) } for (let output of access.outputs.values()) { if (output.name == "nanoKONTROL2 MIDI 1") { - controller = output; + controller = output output.send([0xf0, 0x42, 0x40, 0x00, 0x01, 0x13, 0x00, 0x00, 0x00, 0x01, 0xf7]); // Native Mode (lets us control LEDs, requires sysex privilege) output.send([0xbf, 0x2a, 0x7f]); // Stop output.send([0xbf, 0x29, 0x7f]); // Play @@ -148,31 +175,36 @@ function handleMidiAccess(access) { } function run() { - let audio = document.querySelector("#audio"); + let audio = document.querySelector("#audio") // Set up events: // - Prev/Next buttons // - ended / timeupdate events on audio // - Track items - document.querySelector("#prev").addEventListener("click", prev); - document.querySelector("#next").addEventListener("click", next); - audio.addEventListener("ended", ended); - audio.addEventListener("timeupdate", timeupdate); - audio.addEventListener("durationchange", durationchange); + document.querySelector("#prev").addEventListener("click", prev) + document.querySelector("#next").addEventListener("click", next) + document.querySelector("#pos").addEventListener("input", setPos) + document.querySelector("#vol").addEventListener("input", setGain) + audio.addEventListener("ended", ended) + audio.addEventListener("timeupdate", timeupdate) + audio.addEventListener("durationchange", durationchange) + audio.addEventListener("volumechange", volumechange) for (let li of document.querySelectorAll("#playlist li")) { - li.addEventListener("click", loadTrack); + li.addEventListener("click", loadTrack) } + document.querySelector("#vol").value = audio.volume + // Bind keypress events // - space: play/pause // - document.addEventListener("keydown", keydown); + document.addEventListener("keydown", keydown) // Load up first track - document.querySelector("#playlist li").classList.add("current"); - prev(); + document.querySelector("#playlist li").classList.add("current") + prev() - navigator.requestMIDIAccess({sysex: true}).then(handleMidiAccess); + navigator.requestMIDIAccess({sysex: true}).then(handleMidiAccess) } -window.addEventListener("load", run); +window.addEventListener("load", run)