2019 updates

This commit is contained in:
Neale Pickett 2019-03-16 10:34:15 -06:00
parent 5134fb14d3
commit 22e82ac561
4 changed files with 155 additions and 65 deletions

54
2019-playlist.html Normal file
View File

@ -0,0 +1,54 @@
<!DOCTYPE html>
<!-- HTML5 Playlist by Neale Pickett -->
<!-- https://github.com/nealey/playlist -->
<html>
<head>
<title>2019 ROF</title>
<meta name="viewport" content="width=device-width">
<link href="playlist.css" rel="stylesheet">
<script src="playlist.js"></script>
</head>
<body>
<audio preload id="audio">
Your browser does not support HTML5 Audio!
</audio>
<input type="range" min="0" max="1" step="any" id="pos">
<div id="currentTime"></div>
<div id="duration"></div>
<div id="controls">
<a id="prev"></a>
<a id="next"></a>
<input type="range" min="0.0" max="1.0" list="tickmarks" step="any" id="vol">
<datalist id="tickmarks">
<option value="0.0" label="0%">
<option value="0.5" label="50%">
<option value="1.0" label="100%">
</datalist>
</div>
<ul id="playlist">
<li>0-0 God.mp3</li>
<li>1 - 1 - Summer Set 1.mp3</li>
<li>1 - 1 - Summer Set 2.mp3</li>
<li>1 - 2 - Live Set</li>
<li>1 - 3 - Ole Irlanda.mp3</li>
<li>1 - 4 - Slip Jig.mp3</li>
<li>1 - 5 - El Son de la Negra.m4a</li>
<li>1 - 6 - Gweebarra.wav</li>
<li>----- Intermission -----</li>
<li>2 - 1 - Adventure of a Lifetime.m4a</li>
<li>2 - 2 - El Portorico de los Machetes.mp3</li>
<li>2 - 3 - Orange Rouge.wav</li>
<li>2 - 4 - Live Set</li>
<li>2 - 5 - Live Set</li>
<li>2 - 6 - Pink Panther.mp3</li>
<li>2 - 7 - Alegrias.wav</li>
<li>2 - 8 - Rock n Rince.mp3</li>
<li>2 - 9 - Finale 1.m4a</li>
<li>2 - 9 - Finale 2.mp3</li>
</ul>
</body>
</html>

View File

@ -8,6 +8,10 @@ audio {
min-width: 40em; min-width: 40em;
} }
#pos {
width: 100%;
}
#currentTime { #currentTime {
background-color: #001; background-color: #001;
float: right; float: right;

View File

@ -1,19 +1,22 @@
// jshint asi:true
// HTML5 Playlist by Neale Pickett // HTML5 Playlist by Neale Pickett
// https://github.com/nealey/playlst // https://github.com/nealey/playlst
var base = ".";
var base = "."
function loadTrack(e) { function loadTrack(e) {
let li = e.srcElement; let li = e.target
let audio = document.querySelector("#audio"); let audio = document.querySelector("#audio")
audio.src = base + "/" + li.textContent; audio.src = base + "/" + li.textContent
audio.load(); audio.load()
// Update "current" // Update "current"
for (let cur of document.querySelectorAll(".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) { function clickOn(element) {
@ -21,125 +24,149 @@ function clickOn(element) {
view: window, view: window,
bubbles: true, bubbles: true,
cancelable: true cancelable: true
}); })
element.dispatchEvent(e); element.dispatchEvent(e)
} }
function prev() { function prev() {
let cur = document.querySelector(".current"); let cur = document.querySelector(".current")
let prev = cur.previousElementSibling; let prev = cur.previousElementSibling
if (prev) { if (prev) {
cur = prev; cur = prev
} }
clickOn(cur); clickOn(cur)
} }
function next() { function next() {
let cur = document.querySelector(".current"); let cur = document.querySelector(".current")
let next = cur.nextElementSibling; let next = cur.nextElementSibling
if (next) { if (next) {
cur = next; cur = next
} }
clickOn(cur); clickOn(cur)
} }
function ended() { function ended() {
next(); next()
} }
function mmss(s) { function mmss(s) {
let mm = Math.floor(s / 60); let mm = Math.floor(s / 60)
let ss = Math.floor(s % 60); let ss = Math.floor(s % 60)
if (ss < 10) { if (ss < 10) {
ss = "0" + ss; ss = "0" + ss
} }
return mm + ":" + ss; return mm + ":" + ss
} }
function durationchange(e) { 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) { function timeupdate(e) {
let currentTime = e.srcElement.currentTime; let currentTime = e.target.currentTime
let tgt = document.querySelector("#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) { if (duration - currentTime < 20) {
tgt.classList.add("fin"); tgt.classList.add("fin")
} else { } 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) { function keydown(e) {
let audio = document.querySelector("#audio"); let audio = document.querySelector("#audio")
switch (event.key) { switch (event.key) {
case " ": // space bar case " ": // space bar
if (audio.paused) { if (audio.paused) {
audio.play(); audio.play()
} else { } else {
audio.pause(); audio.pause()
} }
break; break
case "ArrowDown": // Next track case "ArrowDown": // Next track
next(); next()
break; break
case "ArrowUp": // Previous track case "ArrowUp": // Previous track
prev(); prev()
break; break
} }
} }
function midiMessage(e) { function midiMessage(e) {
let audio = document.querySelector("#audio"); let audio = document.querySelector("#audio")
let data = e.data; let data = e.data
let ctrl = data[1]; let ctrl = data[1]
let val = data[2]; let val = data[2]
if ((data[0] == 0xb0) || (data[0] == 0xbf)) { if ((data[0] == 0xb0) || (data[0] == 0xbf)) {
switch (ctrl) { switch (ctrl) {
case 0: // master volume slider case 0: // master volume slider
audio.volume = val / 127; audio.volume = val / 127
break; document.querySelector("#vol").value = audio.volume
break
case 41: // play button case 41: // play button
if (val == 127) { if (val == 127) {
audio.play(); audio.play()
} }
break; break
case 42: // stop button case 42: // stop button
if (val == 127) { if (val == 127) {
audio.pause(); audio.pause()
} }
break; break
case 58: // prev button case 58: // prev button
if (val == 127) { if (val == 127) {
prev(); prev()
} }
break; break
case 59: // next button case 59: // next button
if (val == 127) { if (val == 127) {
next(); next()
} }
break; break
} }
} }
} }
function handleMidiAccess(access) { function handleMidiAccess(access) {
for (let input of access.inputs.values()) { for (let input of access.inputs.values()) {
input.addEventListener("midimessage", midiMessage); input.addEventListener("midimessage", midiMessage)
} }
for (let output of access.outputs.values()) { for (let output of access.outputs.values()) {
if (output.name == "nanoKONTROL2 MIDI 1") { 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([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, 0x2a, 0x7f]); // Stop
output.send([0xbf, 0x29, 0x7f]); // Play output.send([0xbf, 0x29, 0x7f]); // Play
@ -148,31 +175,36 @@ function handleMidiAccess(access) {
} }
function run() { function run() {
let audio = document.querySelector("#audio"); let audio = document.querySelector("#audio")
// Set up events: // Set up events:
// - Prev/Next buttons // - Prev/Next buttons
// - ended / timeupdate events on audio // - ended / timeupdate events on audio
// - Track items // - Track items
document.querySelector("#prev").addEventListener("click", prev); document.querySelector("#prev").addEventListener("click", prev)
document.querySelector("#next").addEventListener("click", next); document.querySelector("#next").addEventListener("click", next)
audio.addEventListener("ended", ended); document.querySelector("#pos").addEventListener("input", setPos)
audio.addEventListener("timeupdate", timeupdate); document.querySelector("#vol").addEventListener("input", setGain)
audio.addEventListener("durationchange", durationchange); audio.addEventListener("ended", ended)
audio.addEventListener("timeupdate", timeupdate)
audio.addEventListener("durationchange", durationchange)
audio.addEventListener("volumechange", volumechange)
for (let li of document.querySelectorAll("#playlist li")) { 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 // Bind keypress events
// - space: play/pause // - space: play/pause
// //
document.addEventListener("keydown", keydown); document.addEventListener("keydown", keydown)
// Load up first track // Load up first track
document.querySelector("#playlist li").classList.add("current"); document.querySelector("#playlist li").classList.add("current")
prev(); prev()
navigator.requestMIDIAccess({sysex: true}).then(handleMidiAccess); navigator.requestMIDIAccess({sysex: true}).then(handleMidiAccess)
} }
window.addEventListener("load", run); window.addEventListener("load", run)