Skip to content

Instantly share code, notes, and snippets.

@killroy42
Last active December 27, 2015 13:33
Show Gist options
  • Save killroy42/c8b8a77df979cd2e0433 to your computer and use it in GitHub Desktop.
Save killroy42/c8b8a77df979cd2e0433 to your computer and use it in GitHub Desktop.
Music player for streaming
<html>
<link href="style.css" rel="stylesheet">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/howler/1.1.28/howler.min.js"></script>
<script src="script.js"></script>
<body>
<div id="display">
<span id="label">Drop songs here</span>
<span id="time"></span>
<span id="song"></span>
</div>
<div id="help" class="display flash">
<p>[Scroll Up/Down]: Volume</p>
<p>[m]: Mute/un-mute</p>
<p>[s]: Skip to next song</p>
<p>[r]: Toggle randomize</p>
</div>
<div id="info" class="display"></div>
</body>
</html>
var d = document, url = window.URL;
var toArray = [].slice.apply.bind([].slice);
var KEYCODE_H = 104;
var KEYCODE_M = 109;
var KEYCODE_P = 112;
var KEYCODE_R = 114;
var KEYCODE_S = 115;
var FADE_TIME = 3000;
var currentVolume = 0.1;
var randomize = false;
function createSound(name, url) {
return new Promise(function(resolve, reject) {
var sound = new Howl({
urls: [url],
format: 'mp3',
buffer: true,
rate: 1.0,
onload: function() { resolve(sound); },
onloaderror: reject,
});
sound.name = name;
});
}
function flashElement(elem) {
elem = $(elem);
elem.addClass('flash');
setTimeout(function() {
elem.removeClass('flash');
}, 500);
}
function flashMessage(msg) {
$('#info').text(msg);
flashElement($('#info'));
}
function setVolume(volume) {
volume = Math.max(0, Math.min(1, volume));
var volumeVal = Math.pow(volume, 1.3);
flashMessage('vol: '+Math.round(volumeVal*100)+'%');
Howler.volume(volumeVal);
}
var main = function() {
console.clear();
var curSong, nextSong, timerInterval, fadeTimeout, files, soundUrls;
var i = -1;
function startSong(name, url) {
createSound(name, url)
.then(function(song) {
if(nextSong) nextSong.unload();
nextSong = song;
nextSong.startTime = Date.now();
nextSong.play();
nextSong.fade(0, 1, FADE_TIME, function() {
if(curSong) curSong.unload();
curSong = nextSong;
});
if(curSong) curSong.fade(1, 0, FADE_TIME);
var fadeNext = (nextSong._duration*1000)-FADE_TIME;
clearTimeout(fadeTimeout);
fadeTimeout = setTimeout(startNextSong, fadeNext);
});
}
function startNextSong() {
if(files === undefined || files.length === 0) return;
i++;
if(i >= files.length) i = 0;
if(randomize) {
var ii = Math.floor(Math.random() * files.length);
startSong(files[ii].name, soundUrls[ii]);
} else {
startSong(files[i].name, soundUrls[i]);
}
}
function updateSongTimer() {
var song = nextSong || curSong;
if(song === undefined) return;
var progress = Math.round((Date.now()-song.startTime)/1000);
var dur = [Math.round(song._duration / 60), Math.round(song._duration % 60)];
var cur = [Math.round(progress / 60), Math.round(progress % 60)];
$('#display #label').text('Now playing ');
$('#display #song').text('"'+song.name.replace(/\.mp3$/, '')+'"');
$('#display #time').html(
'('+
[cur[0]]+':'+('0'+cur[1]).slice(-2)+' / '+
[dur[0]]+':'+('0'+dur[1]).slice(-2)+
'):'
);
}
setVolume(currentVolume);
d.addEventListener('dragenter', cancel);
d.addEventListener('dragover', cancel);
d.addEventListener('keypress', function(e) {
switch(e.keyCode) {
case KEYCODE_H:
flashElement($('#help'));
break;
case KEYCODE_M:
if(Howler._muted) {
flashMessage('unmute');
Howler.unmute();
} else {
flashMessage('mute');
Howler.mute();
}
break;
case KEYCODE_S:
flashMessage('skip to next song');
startNextSong();
break;
case KEYCODE_R:
randomize = !randomize;
if(randomize) {
flashMessage('Randomize');
} else {
flashMessage('Play in sequence');
}
break;
default: console.log(e.keyCode);
}
});
d.addEventListener('wheel', function(e) {
currentVolume += Math.sign(e.wheelDelta) * 1/20;
setVolume(currentVolume);
});
d.addEventListener('drop', function(e) {
cancel(e);
files = [].slice.apply.call([].slice, e.dataTransfer.files);
soundUrls = files.map(url.createObjectURL.bind(url));
$('#help').removeClass('flash');
clearInterval(timerInterval);
timerInterval = setInterval(updateSongTimer, 500);
startNextSong();
});
}
var cancel = function(e) {e.stopPropagation(); e.preventDefault(); }
window.addEventListener('DOMContentLoaded', main);
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/howler/1.1.28/howler.min.js"></script>
body {
background: #000; margin: 0;
font-size: 1.5rem;
font-weight: normal;
font-family: sans-serif;
color: #fff;
text-shadow:
0 0 3px #000, 0 0 3px #000, 0 0 3px #000,
0 0 3px #000, 0 0 3px #000, 0 0 3px #000;
}
#display {
position: absolute;
bottom: 0;
left: 0;
padding: 0.5rem;
margin: 1rem;
}
#help, #info {
position: absolute;
top: 0;
left: 0;
padding: 0.5rem;
margin: 1rem;
font-size: 1rem;
}
.display {
transition: opacity 1s ease-in;
opacity: 0;
}
.flash {
transition: opacity 0.1s ease-out;
opacity: 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment