webamp/winamp.js
2014-11-03 22:12:46 -05:00

310 lines
9.7 KiB
JavaScript
Executable File

/* Helpful wrapper for the native <audio> element */
function Media (audioId) {
this.audio = document.getElementById(audioId);
/* Properties */
this.timeElapsed = function() {
return this.audio.currentTime;
}
this.timeRemaining = function() {
return this.audio.duration - this.audio.currentTime;
}
this.timeElapsedObject = function() {
return this._timeObject(this.timeElapsed());
}
this.timeRemainingObject = function() {
return this._timeObject(this.timeRemaining());
}
this.percentComplete = function() {
return (this.audio.currentTime / this.audio.duration) * 100;
}
/* Actions */
this.previous = function() {
this.audio.currentTime = 0;
};
this.play = function() {
this.audio.play();
};
this.pause = function() {
this.audio.pause();
};
this.stop = function() {
this.audio.pause();
this.audio.currentTime = 0;
};
this.next = function() {
this.audio.currentTime = this.audio.duration;
};
this.toggleRepeat = function() {
this.audio.loop = !this.audio.loop;
};
this.toggleShuffle = function() {
// Not implemented
};
/* Actions with arguments */
this.seekToPercentComplete = function(percent) {
this.audio.currentTime = this.audio.duration * (percent/100);
this.audio.play();
};
this.setVolume = function(volume) {
this.audio.volume = volume;
};
this.loadFile = function(file) {
this.audio.setAttribute('src', file);
};
/* Listeners */
this.addEventListener = function(event, callback) {
this.audio.addEventListener(event, callback);
};
/* Helpers */
this._timeObject = function(seconds) {
var minutes = seconds / 60;
var seconds = seconds % 60;
return [
Math.floor(minutes / 10),
Math.floor(minutes % 10),
Math.floor(seconds / 10),
Math.floor(seconds % 10)
];
}
}
function Winamp () {
self = this;
this.media = new Media('player');
this.media.setVolume(.5);
this.nodes = {
'close': document.getElementById('close'),
'position': document.getElementById('position'),
'fileInput': document.getElementById('file-input'),
'time': document.getElementById('time'),
'previous': document.getElementById('previous'),
'play': document.getElementById('play'),
'pause': document.getElementById('pause'),
'stop': document.getElementById('stop'),
'next': document.getElementById('next'),
'eject': document.getElementById('eject'),
'repeat': document.getElementById('repeat'),
'shuffle': document.getElementById('shuffle'),
'volume': document.getElementById('volume'),
'balance': document.getElementById('balance'),
'playPause': document.getElementById('play-pause'),
'winamp': document.getElementById('winamp'),
};
this.nodes.close.onclick = function() {
}
this.media.addEventListener('timeupdate', function() {
self.nodes.position.value = self.media.percentComplete();
self.updateTime();
});
this.media.addEventListener('ended', function() {
self.setStatus('stop');
self.media.previous();
});
this.nodes.time.onclick = function() {
this.classList.toggle('countdown');
self.updateTime();
}
this.nodes.previous.onclick = function() {
self.media.previous();
}
this.nodes.play.onclick = function() {
self.media.play();
self.setStatus('play');
}
this.nodes.pause.onclick = function() {
self.media.pause();
self.setStatus('pause');
}
this.nodes.stop.onclick = function() {
self.media.stop();
self.setStatus('stop');
}
this.nodes.next.onclick = function() {
self.media.next();
}
this.nodes.eject.onclick = function() {
self.nodes.fileInput.click();
}
this.nodes.fileInput.onchange = function(e){
var file = e.target.files[0];
var objectUrl = URL.createObjectURL(file);
self.loadFile(objectUrl, file.name);
self.media.play();
self.setStatus('play');
}
this.nodes.volume.oninput = function() {
setVolume( this.value / 100);
}
this.nodes.position.onmousedown = function() {
self.media.pause();
}
this.nodes.position.onchange = function() {
self.media.seekToPercentComplete(this.value);
}
this.nodes.balance.oninput = function() {
setBalance( this.value / 100);
}
this.nodes.repeat.onclick = function() {
toggleRepeat();
}
this.nodes.shuffle.onclick = function() {
toggleShuffle();
}
this.setStatus = function(className) {
self.nodes.playPause.removeAttribute("class");
self.nodes.playPause.classList.add(className);
}
function setVolume(volume) {
sprite = Math.round(volume * 28);
offset = (sprite - 1) * 15;
self.media.setVolume(volume);
self.nodes.volume.style.backgroundPosition = '0 -' + offset + 'px';
}
function setBalance(balance) {
offset = Math.abs(balance - .5) * 2;
sprite = Math.floor(offset * 28);
offset = (sprite - 1) * 15;
console.log(self.nodes.balance.style);
self.nodes.balance.style.backgroundPosition = '-9px -' + offset + 'px';
}
function toggleRepeat() {
self.media.toggleRepeat();
self.nodes.repeat.classList.toggle('selected');
}
function toggleShuffle() {
self.media.toggleShuffle();
self.nodes.shuffle.classList.toggle('selected');
}
this.updateTime = function() {
if(this.nodes.time.classList.contains('countdown')) {
digits = this.media.timeRemainingObject();
} else {
digits = this.media.timeElapsedObject();
}
html = digitHtml(digits[0]);
document.getElementById('minute-first-digit').innerHTML = '';
document.getElementById('minute-first-digit').appendChild(html);
html = digitHtml(digits[1]);
document.getElementById('minute-second-digit').innerHTML = '';
document.getElementById('minute-second-digit').appendChild(html);
html = digitHtml(digits[2]);
document.getElementById('second-first-digit').innerHTML = '';
document.getElementById('second-first-digit').appendChild(html);
html = digitHtml(digits[3]);
document.getElementById('second-second-digit').innerHTML = '';
document.getElementById('second-second-digit').appendChild(html);
}
this.loadFile = function(file, fileName) {
this.media.loadFile(file);
html = fontHtml(fileName);
document.getElementById('song-title').innerHTML = '';
document.getElementById('song-title').appendChild(html);
html = fontHtml("128");
document.getElementById('kbps').innerHTML = '';
document.getElementById('kbps').appendChild(html);
html = fontHtml("44");
document.getElementById('khz').innerHTML = '';
document.getElementById('khz').appendChild(html);
this.updateTime();
}
function digitHtml(digit) {
horizontalOffset = digit * 9;
div = document.createElement('div');
div.classList.add('digit');
div.style.backgroundPosition = '-' + horizontalOffset + 'px 0';
div.innerHTML = digit;
return div;
}
function fontHtml(string) {
parentDiv = document.createElement('div');
for (var i = 0, len = string.length; i < len; i++) {
char = string[i].toLowerCase();
parentDiv.appendChild(charHtml(char));
}
return parentDiv;
}
function charHtml(char) {
position = charPosition(char);
row = position[0];
column = position[1];
verticalOffset = row * 6;
horizontalOffset = column * 5;
div = document.createElement('div');
div.classList.add('character');
x = '-' + horizontalOffset + 'px';
y = '-' + verticalOffset + 'px'
div.style.backgroundPosition = x + ' ' + y;
div.innerHTML = char;
return div;
}
function charPosition(char) {
position = fontLookup[char];
if(!position) {
return fontLookup[' '];
}
return position;
}
/* XXX There are too many " " and "_" characters */
var fontLookup = {
"a": [0,0], "b": [0,1], "c": [0,2], "d": [0,3], "e": [0,4], "f": [0,5],
"g": [0,6], "h": [0,7], "i": [0,8], "j": [0,9], "k": [0,10],
"l": [0,11], "m": [0,12], "n": [0,13], "o": [0,14], "p": [0,15],
"q": [0,16], "r": [0,17], "s": [0,18], "t": [0,19], "u": [0,20],
"v": [0,21], "w": [0,22], "x": [0,23], "y": [0,24], "z": [0,25],
"\"": [0,26], "@": [0,27], " ": [0,29], "0": [1,0], "1": [1,1],
"2": [1,2], "3": [1,3], "4": [1,4], "5": [1,5], "6": [1,6], "7": [1,7],
"8": [1,8], "9": [1,9], " ": [1,10], "_": [1,11], ":": [1,12],
"(": [1,13], ")": [1,14], "-": [1,15], "'": [1,16], "!": [1,17],
"_": [1,18], "+": [1,19], "\\": [1,20], "/": [1,21], "[": [1,22],
"]": [1,23], "^": [1,24], "&": [1,25], "%": [1,26], ".": [1,27],
"=": [1,28], "$": [1,29], "#": [1,30], "Å": [2,0], "Ö": [2,1],
"Ä": [2,2], "?": [2,3], "*": [2,4], " ": [2,5]
};
}
keylog = [];
trigger = [78,85,76,27,76,27,83,79,70,84];
// Easter Egg
document.onkeyup = function(e){
keylog.push(e.which);
keylog = keylog.slice(-10);
if(keylog.toString() == trigger.toString()) {
document.getElementById('winamp').classList.toggle('llama');
}
}
winamp = new Winamp();
winamp.loadFile('http://jordaneldredge.com/projects/winamp2-js/llama.mp3', 'llama.mp3');