519 lines
16 KiB
JavaScript
519 lines
16 KiB
JavaScript
|
|
||
|
function HotsPlayer(){
|
||
|
|
||
|
var self = this,
|
||
|
pl = this,
|
||
|
sm = soundManager; // soundManager instance
|
||
|
|
||
|
this.files = [];
|
||
|
this.sounds = [];
|
||
|
this.graphicPaths = {};
|
||
|
this.ready = false;
|
||
|
this.listeners = [];
|
||
|
|
||
|
this.config = {
|
||
|
playerDomID: '#player',
|
||
|
playerWidth: 200,
|
||
|
playerHeight: 100,
|
||
|
canvasHeight:200,
|
||
|
canvasWidth:300,
|
||
|
autoPlay: true,
|
||
|
filesDomID: '#track-list',
|
||
|
buttonHeight: 10,
|
||
|
volume: 80,
|
||
|
random: false,
|
||
|
graphic: {
|
||
|
circleWidth: 20,
|
||
|
waitColor: 'white',
|
||
|
loadedColor: 'red',
|
||
|
playedColor: 'green',
|
||
|
controlsColor: '#333333',
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
this.currentTime = 0;
|
||
|
this.currentDuration = 0;
|
||
|
this.currentBytes = 0;
|
||
|
this.currentTotalBytes = 0;
|
||
|
this.state = 'waiting';
|
||
|
this.currentIndex = -1;
|
||
|
|
||
|
this.events = {
|
||
|
onfinish: function() {
|
||
|
self.playNext();
|
||
|
},
|
||
|
whileplaying: function() {
|
||
|
self.currentTime = this.position;
|
||
|
self.currentDuration = this.durationEstimate;
|
||
|
self.redrawPlay();
|
||
|
},
|
||
|
whileloading: function() {
|
||
|
self.currentBytes = this.bytesLoaded;
|
||
|
self.currentTotalBytes = this.bytesTotal;
|
||
|
self.redrawLoad();
|
||
|
},
|
||
|
};
|
||
|
|
||
|
this.playNext = function() {
|
||
|
var pos = self.currentIndex + 1;
|
||
|
if (pos == self.sounds.length){
|
||
|
pos = 0;
|
||
|
}
|
||
|
if (self.config.random){
|
||
|
pos = Math.floor((Math.random()*(self.sounds.length -1 )) + 0);
|
||
|
}
|
||
|
self.startPlay(pos);
|
||
|
};
|
||
|
|
||
|
this.playPrevious = function() {
|
||
|
var pos = self.currentIndex - 1;
|
||
|
if (pos == -1 ){
|
||
|
pos = self.sounds.length - 1;
|
||
|
}
|
||
|
if (self.config.random){
|
||
|
pos = Math.floor((Math.random()*(self.sounds.length -1 )) + 0);
|
||
|
}
|
||
|
self.startPlay(pos);
|
||
|
};
|
||
|
|
||
|
this.redrawLoad = function() {
|
||
|
var graphics = self.config.graphic;
|
||
|
var path = self.config.graphic.loadingBar;
|
||
|
var radius = self.config.graphic.loadingRadius;
|
||
|
path.remove();
|
||
|
if(self.currentBytes ==self.currentTotalBytes ){
|
||
|
//path = self.drawArc(radius, 100, 100);
|
||
|
}else{
|
||
|
path = self.drawArc(radius, self.currentBytes, self.currentTotalBytes);
|
||
|
path.strokeColor = graphics.loadedColor;
|
||
|
path.strokeWidth = graphics.circleWidth - 5;
|
||
|
path.opacity = 0.6;
|
||
|
self.config.graphic.loadingBar = path;
|
||
|
}
|
||
|
paper.view.draw();
|
||
|
};
|
||
|
|
||
|
|
||
|
this.redrawPlay = function() {
|
||
|
var graphics = self.config.graphic;
|
||
|
var angle = (2 * Math.PI) / self.currentDuration;
|
||
|
var path = self.config.graphic.playingBar;
|
||
|
var radius = self.config.graphic.playingRadius;
|
||
|
path.remove();
|
||
|
paper.view.draw();
|
||
|
path = self.drawArc(radius, self.currentTime, self.currentDuration);
|
||
|
path.strokeColor = graphics.playedColor;
|
||
|
path.strokeWidth = graphics.circleWidth - 5 ;
|
||
|
path.opacity = 0.6;
|
||
|
self.config.graphic.playingBar = path;
|
||
|
paper.view.draw();
|
||
|
};
|
||
|
|
||
|
this.init = function() {
|
||
|
|
||
|
self.loadSongs(self.config.filesDomID);
|
||
|
self.loadSounds();
|
||
|
|
||
|
self.autoStart();
|
||
|
self.ready = true;
|
||
|
};
|
||
|
|
||
|
this.startPlay = function(index){
|
||
|
var song = self.files[index];
|
||
|
self.clearBars();
|
||
|
sm.play(song.id, {volume:self.config.volume});
|
||
|
self.currentIndex = index;
|
||
|
self.state = 'playing';
|
||
|
var uri = song.file;
|
||
|
jQuery('.hotsPlayer-controls-down a', self.config.playerDomID).attr('href', uri);
|
||
|
var evt = {};
|
||
|
evt.target = self.activeFile(song.id);
|
||
|
self.trigger('startPlay', evt);
|
||
|
jQuery('.hotsPlayer-controls-play', self.config.playerDomID).addClass('pause');
|
||
|
};
|
||
|
|
||
|
this.activeFile = function(songID) {
|
||
|
jQuery(self.config.filesDomID + ' a').removeClass('active');
|
||
|
var idRoto = songID.split('_');
|
||
|
var active = jQuery(self.config.filesDomID + ' a[data-id="' + idRoto[1] + '"]');
|
||
|
active.addClass('active');
|
||
|
return active[0];
|
||
|
}
|
||
|
|
||
|
this.clearBars = function() {
|
||
|
var path = self.config.graphic.playingBar;
|
||
|
var loadPath = self.config.graphic.loadingBar;
|
||
|
path.remove();
|
||
|
loadPath.remove();
|
||
|
paper.view.draw();
|
||
|
};
|
||
|
|
||
|
this.starPlayByID = function(songID){
|
||
|
sm.play(songID, {volume:self.config.volume});
|
||
|
var index = self.searchByIndex(songID);
|
||
|
self.clearBars();
|
||
|
self.currentIndex = index;
|
||
|
self.state = 'playing';
|
||
|
var song = self.files[index];
|
||
|
var uri = song.file;
|
||
|
jQuery('.hotsPlayer-controls-down a', self.config.playerDomID).attr('href', uri);
|
||
|
jQuery('.hotsPlayer-controls-play', self.config.playerDomID).addClass('pause');
|
||
|
var evt = {};
|
||
|
evt.target = self.activeFile(song.id);
|
||
|
self.trigger('startPlay', evt);
|
||
|
};
|
||
|
|
||
|
this.searchByIndex = function(id) {
|
||
|
var salir = false;
|
||
|
var pos = 0;
|
||
|
while(!salir && pos < self.files.length){
|
||
|
if (self.files[pos].id == id){
|
||
|
salir = true;
|
||
|
}else{
|
||
|
pos += 1;
|
||
|
}
|
||
|
};
|
||
|
return pos;
|
||
|
};
|
||
|
|
||
|
this.stop = function(){
|
||
|
if (self.state == "playing" || self.state == "paused"){
|
||
|
var song = self.files[self.currentIndex];
|
||
|
sm.stop(song.id);
|
||
|
self.state = 'waiting';
|
||
|
jQuery('.hotsPlayer-controls-play', self.config.playerDomID).removeClass('pause');
|
||
|
}
|
||
|
};
|
||
|
|
||
|
this.handleClick = function(e){
|
||
|
var elemento = e.currentTarget;
|
||
|
var tipoControl = elemento.dataset.controlType;
|
||
|
|
||
|
switch (tipoControl){
|
||
|
case 'play':
|
||
|
e.preventDefault();
|
||
|
if (self.state == 'waiting'){
|
||
|
if (self.currentIndex == -1){
|
||
|
self.startPlay(0);
|
||
|
}else{
|
||
|
self.startPlay(self.currentIndex);
|
||
|
}
|
||
|
}else if (self.state == "playing"){
|
||
|
self.pause();
|
||
|
}else if (self.state == 'paused'){
|
||
|
self.resume();
|
||
|
}
|
||
|
break;
|
||
|
case 'random':
|
||
|
e.preventDefault();
|
||
|
if (self.config.random){
|
||
|
jQuery('.hotsPlayer-controls-random', self.config.playerDomID).removeClass('active');
|
||
|
self.config.random = false;
|
||
|
}else{
|
||
|
jQuery('.hotsPlayer-controls-random', self.config.playerDomID).addClass('active');
|
||
|
self.config.random = true;
|
||
|
}
|
||
|
break;
|
||
|
case 'next':
|
||
|
e.preventDefault();
|
||
|
self.stop();
|
||
|
self.playNext();
|
||
|
break;
|
||
|
case 'prev':
|
||
|
e.preventDefault();
|
||
|
self.stop();
|
||
|
self.playPrevious();
|
||
|
case 'down':
|
||
|
break;
|
||
|
};
|
||
|
};
|
||
|
|
||
|
this.resume = function() {
|
||
|
var song = self.files[self.currentIndex];
|
||
|
sm.resume(song.id);
|
||
|
self.state = 'playing';
|
||
|
jQuery('.hotsPlayer-controls-play', self.config.playerDomID).addClass('pause');
|
||
|
}
|
||
|
|
||
|
this.pause = function() {
|
||
|
var song = self.files[self.currentIndex];
|
||
|
sm.pause(song.id);
|
||
|
self.state = 'paused';
|
||
|
jQuery('.hotsPlayer-controls-play', self.config.playerDomID).removeClass('pause');
|
||
|
};
|
||
|
|
||
|
this.draw = function() {
|
||
|
// Create an empty project and a view for the canvas:
|
||
|
self.insertDomElements();
|
||
|
var t =jQuery('canvas', self.config.playerDomID);
|
||
|
paper.setup(jQuery('canvas', self.config.playerDomID)[0]);
|
||
|
var graphics = self.config.graphic;
|
||
|
var centerX = self.config.canvasWidth / 2;
|
||
|
var centerY = self.config.canvasHeight / 2;
|
||
|
var radius = (((self.config.playerWidth < self.config.playerHeight) ? self.config.playerWidth : self.config.playerHeight ) / 2) - (graphics.circleWidth/2);
|
||
|
graphics.radius = radius;
|
||
|
graphics.centerX = centerX;
|
||
|
graphics.centerY = centerY;
|
||
|
|
||
|
var waitCircle = new paper.Path.Circle(new paper.Point(centerX,centerY), radius);
|
||
|
waitCircle.strokeColor ='white';
|
||
|
waitCircle.strokeWidth = graphics.circleWidth;
|
||
|
|
||
|
//Positioning Controls
|
||
|
|
||
|
var alturaCirculo = (radius * 2) + 24;
|
||
|
var espacio = (alturaCirculo - (self.config.buttonHeight * 4)) / 3;
|
||
|
|
||
|
jQuery(self.config.playerDomID).width(self.config.canvasWidth).height(self.config.canvasHeight).css('position', 'relative');
|
||
|
jQuery('.hotsPlayer-controls').width(self.config.canvasWidth).height(self.config.canvasHeight);
|
||
|
jQuery('.hotsPlayer-controls-play', self.config.playerDomID).css('top', centerY-10).css('left',centerX-10).height(20).width(20);
|
||
|
var top = centerY - radius - self.config.buttonHeight;
|
||
|
var left = centerX + radius + 18;
|
||
|
jQuery('.hotsPlayer-controls-random', self.config.playerDomID).css('top',top).css('left', left - 15);
|
||
|
|
||
|
if (self.config.random){
|
||
|
jQuery('.hotsPlayer-controls-random', self.config.playerDomID).addClass('active');
|
||
|
}
|
||
|
|
||
|
top += espacio + self.config.buttonHeight;
|
||
|
jQuery('.hotsPlayer-controls-next', self.config.playerDomID).css('top',top).css('left', left);
|
||
|
top += espacio + self.config.buttonHeight;
|
||
|
jQuery('.hotsPlayer-controls-prev', self.config.playerDomID).css('top',top).css('left', left);
|
||
|
top += espacio + self.config.buttonHeight;
|
||
|
jQuery('.hotsPlayer-controls-down', self.config.playerDomID).css('top',top).css('left', left - 15);
|
||
|
left = centerX - radius - 18 - self.config.buttonHeight;
|
||
|
top = centerY - radius - 10;
|
||
|
jQuery('.hotsPlayer-controls-vol-up', self.config.playerDomID).css('top',top).css('left', left);
|
||
|
top += espacio * 3 + self.config.buttonHeight * 3;
|
||
|
jQuery('.hotsPlayer-controls-vol-down', self.config.playerDomID).css('top',top).css('left', left);
|
||
|
|
||
|
jQuery('.hotsPlayer-controls>div>a').click(self.handleClick);
|
||
|
|
||
|
var volumenBackBar = new paper.Path.Line(new paper.Point(left + 5, centerY - radius + 10 ), new paper.Point(left + 5,centerY + radius - 10));
|
||
|
|
||
|
volumenBackBar.strokeWidth = 8;
|
||
|
volumenBackBar.strokeColor = 'white';
|
||
|
volumenBackBar.opacity = 0.4;
|
||
|
var distanciaVolumen = (centerY + radius - 10) - (centerY - radius + 10);
|
||
|
var longitudBarra = (distanciaVolumen / 100) * self.config.volume;
|
||
|
var volumenBar = new paper.Path.Line(new paper.Point(left + 5, centerY + radius - 10), new paper.Point(left + 5, centerY + radius - 10 - longitudBarra));
|
||
|
volumenBar.strokeWidth = 8;
|
||
|
volumenBar.strokeColor = 'white';
|
||
|
volumenBar.opacity = 0.6;
|
||
|
|
||
|
var playRadius = radius -10;
|
||
|
var start = new paper.Point(centerX, centerY - playRadius);
|
||
|
|
||
|
var pR = new paper.Path.Arc(start, start, start);
|
||
|
pR.strokeColor = 'red';
|
||
|
pR.strokeWidth = 25;
|
||
|
pR.opacity = 0.6;
|
||
|
|
||
|
graphics.loadingBar = pR;
|
||
|
graphics.loadingRadius = radius - 10;
|
||
|
|
||
|
var sR = radius +5 ;
|
||
|
|
||
|
start = new paper.Point(centerX, centerY - sR);
|
||
|
//end = new paper.Point(centerX, centerY + sR);
|
||
|
//through = new paper.Point(centerX + sR, centerY);
|
||
|
var nn = new paper.Path.Arc(start, start, start);
|
||
|
nn.strokeColor = 'green';
|
||
|
nn.strokeWidth = 15;
|
||
|
nn.opacity = 0.6;
|
||
|
|
||
|
graphics.playingBar = nn;
|
||
|
graphics.playingRadius = radius + 6;
|
||
|
|
||
|
|
||
|
paper.view.draw();
|
||
|
|
||
|
self.autoStart();
|
||
|
self.ready = true;
|
||
|
|
||
|
};
|
||
|
|
||
|
this.drawArc = function(radio, valor, total){
|
||
|
|
||
|
|
||
|
var centerX = self.config.graphic.centerX;
|
||
|
var centerY = self.config.graphic.centerY;
|
||
|
var ratio = (valor % total)/ total;
|
||
|
|
||
|
var angulo =Math.round(360 * ratio);
|
||
|
|
||
|
var vPoint = new paper.Point({length: radio, angle:-90});
|
||
|
var start = new paper.Point(centerX + vPoint.x, centerY + vPoint.y);
|
||
|
var middle = vPoint.rotate(angulo/2);
|
||
|
var end = vPoint.rotate(angulo);
|
||
|
var middlePoint = new paper.Point(centerX + middle.x, centerY + middle.y);
|
||
|
var endPoint = new paper.Point(centerX + end.x, centerY + end.y);
|
||
|
|
||
|
|
||
|
return new paper.Path.Arc(start, middlePoint, endPoint);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
this.autoStart = function() {
|
||
|
if (self.ready && self.config.autoPlay) {
|
||
|
self.startPlay(0);
|
||
|
//window.setInterval(function(){self.currentTime = self.currentTime + 2; self.currentDuration = 50; self.redrawPlay();},1000);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
this.insertDomElements = function() {
|
||
|
|
||
|
var playerDom = jQuery(self.config.playerDomID);
|
||
|
|
||
|
var canvas = document.createElement('canvas');
|
||
|
canvas.height = self.config.canvasHeight;
|
||
|
canvas.width = self.config.canvasWidth;
|
||
|
|
||
|
var controls = document.createElement('div');
|
||
|
controls.className="hotsPlayer-controls";
|
||
|
|
||
|
var controlPlay = document.createElement('div');
|
||
|
controlPlay.className="hotsPlayer-controls-play hotsControl";
|
||
|
var controlPlayLink = document.createElement('a');
|
||
|
controlPlayLink.dataset.controlType = "play";
|
||
|
controlPlayLink.href="#";
|
||
|
controlPlay.appendChild(controlPlayLink);
|
||
|
|
||
|
var controlRandom = document.createElement('div');
|
||
|
controlRandom.className = 'hotsPlayer-controls-random hotsControl';
|
||
|
var controlRandomLink = document.createElement('a');
|
||
|
controlRandomLink.dataset.controlType = "random";
|
||
|
controlRandomLink.href="#";
|
||
|
controlRandom.appendChild(controlRandomLink);
|
||
|
|
||
|
var controlNext = document.createElement('div');
|
||
|
controlNext.className = 'hotsPlayer-controls-next hotsControl'
|
||
|
var controlNextLink = document.createElement('a');
|
||
|
controlNextLink.dataset.controlType = "next";
|
||
|
controlNextLink.href="#";
|
||
|
controlNext.appendChild(controlNextLink);
|
||
|
|
||
|
var controlPrev = document.createElement('div');
|
||
|
controlPrev.className = 'hotsPlayer-controls-prev hotsControl'
|
||
|
var controlPrevLink = document.createElement('a');
|
||
|
controlPrevLink.dataset.controlType = "prev";
|
||
|
controlPrevLink.href="#";
|
||
|
controlPrev.appendChild(controlPrevLink);
|
||
|
|
||
|
var controlDown = document.createElement('div');
|
||
|
controlDown.className = 'hotsPlayer-controls-down hotsControl'
|
||
|
var controlDownLink = document.createElement('a');
|
||
|
controlDownLink.dataset.controlType = "down";
|
||
|
controlDownLink.href="#";
|
||
|
controlDown.appendChild(controlDownLink);
|
||
|
|
||
|
var controlVolDown = document.createElement('div');
|
||
|
controlVolDown.className = 'hotsPlayer-controls-vol-down hotsControl'
|
||
|
var controlVolDownLink = document.createElement('a');
|
||
|
controlVolDownLink.dataset.controlType = "vol-down";
|
||
|
controlVolDownLink.href="#";
|
||
|
controlVolDown.appendChild(controlVolDownLink);
|
||
|
|
||
|
var controlVolUp = document.createElement('div');
|
||
|
controlVolUp.className = 'hotsPlayer-controls-vol-up hotsControl'
|
||
|
var controlVolUpLink = document.createElement('a');
|
||
|
controlVolUpLink.dataset.controlType = "vol-up";
|
||
|
controlVolUpLink.href="#";
|
||
|
controlVolUp.appendChild(controlVolUpLink);
|
||
|
|
||
|
controls.appendChild(controlPlay);
|
||
|
controls.appendChild(controlRandom);
|
||
|
controls.appendChild(controlNext);
|
||
|
controls.appendChild(controlPrev);
|
||
|
controls.appendChild(controlDown);
|
||
|
controls.appendChild(controlVolDown);
|
||
|
controls.appendChild(controlVolUp);
|
||
|
|
||
|
playerDom.append(canvas);
|
||
|
playerDom.append(controls);
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
this.loadSounds = function() {
|
||
|
this.sounds = [];
|
||
|
for(var i in this.files)
|
||
|
{
|
||
|
var song = this.files[i];
|
||
|
this.sounds.push(sm.createSound({
|
||
|
id: song.id,
|
||
|
url: song.file,
|
||
|
volume: self.config.volume,
|
||
|
onfinish: self.events.onfinish,
|
||
|
whileplaying: self.events.whileplaying,
|
||
|
whileloading: self.events.whileloading
|
||
|
}));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
this.handleFileClick = function(e) {
|
||
|
e.preventDefault();
|
||
|
var elemento = e.currentTarget;
|
||
|
var id = elemento.dataset.id;
|
||
|
self.changeSong('hotsPlayer_' + id);
|
||
|
};
|
||
|
|
||
|
this.changeSong = function(songID) {
|
||
|
self.stop();
|
||
|
self.starPlayByID(songID);
|
||
|
};
|
||
|
|
||
|
this.loadSongs = function(filesDomID) {
|
||
|
var files = [];
|
||
|
if(filesDomID == null){
|
||
|
return;
|
||
|
}
|
||
|
jQuery(filesDomID + ' a').click(self.handleFileClick);
|
||
|
|
||
|
jQuery(filesDomID + ' a').each(function (index, Element){
|
||
|
var link = Element.href;
|
||
|
var songID = Element.dataset.id;
|
||
|
self.files.push({
|
||
|
file : link,
|
||
|
id : 'hotsPlayer_' + songID
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
|
||
|
this.registerEvent = function(type, func){
|
||
|
if (func != null) {
|
||
|
var listeners = self.listeners[type];
|
||
|
if (!listeners) {
|
||
|
listeners = [];
|
||
|
self.listeners[type] = listeners;
|
||
|
}
|
||
|
var listener = {func: func};
|
||
|
listeners.push(listener);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
this.trigger = function(type, obj) {
|
||
|
var listeners = self.listeners[type];
|
||
|
if (listeners) {
|
||
|
var callback = listeners[0];
|
||
|
var evt = {};
|
||
|
evt.obj = self;
|
||
|
evt.info = obj;
|
||
|
callback.func.apply(self, [evt]);
|
||
|
}
|
||
|
};
|
||
|
} // Function HostsPlayer
|
||
|
|
||
|
paper.install(window);
|
||
|
|
||
|
var hotsPlayer;
|
||
|
hotsPlayer = new HotsPlayer();
|
||
|
|
||
|
|
||
|
// hook into SM2 init
|
||
|
soundManager.onready(hotsPlayer.init);
|