Created
October 10, 2013 16:45
-
-
Save pwwilson/6921611 to your computer and use it in GitHub Desktop.
code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* -------------------------------------------------------- | |
* | |
* Global Audio Player | |
* Base class | |
* | |
* -------------------------------------------------------- | |
*/ | |
define(['jquery', 'backbone', 'moment'], | |
function ($, Backbone, moment) { | |
'use strict'; | |
var $this; | |
var PlayerView = Backbone.View.extend({ | |
template: HBS.player, | |
eventTypes: { start: 'mousedown', move: 'mousemove', end: 'mouseup', select: 'click' }, | |
isPhoneGap: false, | |
delegate: null, | |
mediaTimer: null, | |
audioPlayer: null, | |
audioElem: null, | |
isDragging: false, | |
isPaused: true, | |
wasPausedBeforeScrub: false, | |
liveTime: 0, | |
farthestBuffer: 0, | |
scrubIsDirty: false, | |
dragPercX: 0, | |
isLive: true, | |
cues: [], | |
cueIndx: 0, | |
handle: null, | |
_date: null, | |
timeLapsed: 0, | |
intervalTime: 150, | |
initialize: function () { | |
// Override // tODO: Can implement Backbone super() | |
// $this = this; | |
}, | |
render: function () { | |
$this = this; | |
$this.$el.html(this.template(this.model)); | |
$this.transitionIn(); // TODO: call externally instead | |
App.EventDispatcher.on('app:render', $this.onAppReady); // Dispatching more than once? | |
console.log("*** RENDER", moment(), this.model); | |
$this.reset(); | |
return this; | |
}, | |
onAppReady: function() { | |
App.EventDispatcher.off('app:render', $this.onAppReady); | |
$this.cues = $this.model.cues; | |
$this.setUpPlayer(); // Mobile will be overwritten | |
$this.setUpBindings(); | |
console.log("### ON APP READY ###"); | |
//// $this.playAudio(); | |
}, | |
setUpPlayer: function() { | |
$this.audioPlayer = new Audio(); | |
$this.audioPlayer.src = "../audio/test.mp3"; | |
$this.$el.append($this.audioPlayer); | |
$this.audioElem = document.getElementsByTagName("audio")[0]; | |
$this.audioPlayer.addEventListener('loadedmetadata', this.onMetaData, true); | |
}, | |
setUpBindings: function(){ | |
$('#player .icon-btn').bind($this.eventTypes.select, function(e){ | |
var classes = $(e.currentTarget).attr('class'); | |
switch ( true ) { | |
case classes.indexOf("RegularPlay01") != -1: | |
$this.playAudio(); | |
$(e.currentTarget).addClass('RegularPause').removeClass('RegularPlay01'); | |
break; | |
case classes.indexOf("RegularPause") != -1: | |
$this.pauseAudio(); | |
$(e.currentTarget).addClass('RegularPlay01').removeClass('RegularPause'); | |
break; | |
case classes.indexOf("control-skip") != -1: | |
// | |
break; | |
case classes.indexOf("RegularPrev") != -1: | |
var newTime; | |
if ( $this.getCurrentTime() < 15) { | |
newTime = 0; | |
} else { | |
newTime = $this.getCurrentTime() - 15; | |
} | |
$this.setCurrentTime(newTime); | |
break; | |
case classes.indexOf("RegularNext") != -1: | |
// | |
$this.setCurrentTime(20); | |
// | |
break; | |
default: | |
console.log("### Button has no class", $(e.currentTarget).attr('class')); | |
} | |
}); | |
$('.progress-bar-progress').css({width: 0}); | |
$this.mediaTimer = setInterval(function () { | |
if ( $this.getDuration() <= 0 ) return; | |
if ( $this.isDragging ) { | |
if ( $this.scrubIsDirty ) { | |
$this.playAudio(); | |
$this.scrubIsDirty = false; | |
} else { | |
$this.pauseAudio(); | |
} | |
$this.setCurrentTime($this.dragPercX * $this.getDuration()); | |
} | |
$('#player .time-readout').html(moment({seconds: moment($this.getCurrentTime())}).format('mm:ss')+"/"+moment({seconds: moment($this.getDuration())}).format('mm:ss')); | |
var perComplete = (($this.getCurrentTime()/$this.getDuration())*100).toFixed(2)+'%'; | |
$('.progress-bar-progress').css({width: perComplete}); | |
if ( ($this.timeLapsed/1000)/$this.getDuration() < 1 ) { | |
var elapsedPerComplete = ((($this.timeLapsed/1000)/$this.getDuration())*100).toFixed(2)+'%'; | |
$('.progress-bar-buffer').css({width: elapsedPerComplete}); | |
} | |
$this.handle.css({left: perComplete}); | |
// TODO: Error check | |
if ( $this.getCurrentTime() >= $this.cues[$this.cueIndx].time ) { | |
$this[$this.cues[$this.cueIndx].action].apply($this); | |
$this.cueIndx++; | |
} | |
$this.timeLapsed += $this.intervalTime; | |
}, $this.intervalTime); | |
$this.setUpDragging(); | |
}, | |
setUpDragging: function(){ | |
$this.handle = $('.drag-handle'); | |
$this.handle.bind($this.eventTypes.start, function(e) { | |
e.preventDefault(); | |
$this.isDragging = true; | |
$this.wasPausedBeforeScrub = $this.isPaused; | |
$this.zoomInMode(); | |
$this.bindMovingDragger(); | |
}); | |
}, | |
bindMovingDragger: function() { | |
$(document).bind($this.eventTypes.move, $this.onMove); | |
$(document).bind($this.eventTypes.end, $this.onEnd); | |
}, | |
unbindMovingDragger: function() { | |
$(document).unbind($this.eventTypes.move, $this.onMove); | |
$(document).unbind($this.eventTypes.end, $this.onEnd); | |
}, | |
onMove: function(e) { | |
e.preventDefault(); | |
if ( $this.isDragging ) { | |
var xPos; | |
if ( e.originalEvent.touches && e.originalEvent.touches.length ) { | |
xPos = e.originalEvent.touches[0].pageX; | |
} else if( e.originalEvent.changedTouches && e.originalEvent.changedTouches.length ) { | |
xPos = e.originalEvent.changedTouches[0]; | |
} else { | |
xPos = e.pageX; | |
} | |
// Check that we haven't passed live point | |
if ( xPos > parseInt($('.progress-bar-buffer').css('width')) ) { | |
$this.isLive = true; | |
// console.log("### Live", xPos, parseInt($('.progress-bar-buffer').css('width'))); | |
} else { | |
$this.isLive = false; | |
$this.dragPercX = Math.max(0, xPos / parseInt($('.controls-container').css('width'), 10)); | |
$this.scrubIsDirty = true; | |
} | |
} | |
}, | |
onEnd: function(e) { | |
e.preventDefault(); | |
if ( $this.isDragging ) { | |
// $this.handle.css('background', '#808'); | |
$this.isDragging = false; | |
if ( $this.wasPausedBeforeScrub ) { | |
$this.pauseAudio(); | |
} else { | |
$this.playAudio(); | |
} | |
$this.zoomOutMode(); | |
$this.unbindMovingDragger(); | |
} | |
}, | |
// tODO: Refactor zoom related into mobile-only class once built. Empty implementation in this class. | |
// tODO: Fix tick mark layering bug | |
zoomInMode: function() { | |
$('.drag-handle-circle').transition({ scale: 3.0 }); | |
$('.progress-bar').transition({ scale: 2.8 }); | |
$('.player .full').hide(); | |
$('.player .mini').show(); | |
}, | |
zoomOutMode: function() { | |
$('.drag-handle-circle').transition({ scale: 1.0 }); | |
$('.progress-bar').transition({ scale: 1.0 }); | |
$('.player .full').show(); | |
$('.player .mini').hide(); | |
}, | |
drawCues: function() { | |
_.each($this.cues, function(cue, indx){ | |
var tick = $('.progress-bar-background').append("<div class='progress-bar-tick'></div>"); | |
var perc = (cue.time/$this.getDuration())*100; | |
$('.progress-bar-tick:last').css({'left': perc+'%'}); | |
if ( cue.visible != true ) { | |
$('.progress-bar-tick:last').hide(); | |
} | |
}); | |
}, | |
setData: function() { | |
// Populate with new model here... | |
}, | |
onMetaData: function() { | |
if ( $this.cues.length > 0 ) { | |
$this.drawCues(); | |
} | |
}, | |
reset: function() { | |
// Use before feeding in new data | |
// tODO: zero out progress bar buffer | |
// tODO: redraw cues | |
// | |
$this.timeLapsed = 0; | |
}, | |
destroy: function() { | |
// TODO: destroy all and kill interval | |
}, | |
transitionIn: function(){ | |
//// TweenMax.from(this.container, .5, {delay: 1, top: -120, ease: Back.easeOut}); | |
}, | |
transitionOut: function(){ | |
//// TweenMax.to(this.container, .4, {delay: 1, top: -120, ease: Back.easeIn}); | |
}, | |
// Audio api Methods | |
playAudio: function() { | |
$this.isPaused = false; | |
$this.audioPlayer.play(); | |
}, | |
pauseAudio: function() { | |
$this.isPaused = true; | |
$this.audioPlayer.pause(); | |
}, | |
getCurrentTime: function() { | |
return $this.audioElem.currentTime; | |
}, | |
setCurrentTime: function(tm) { | |
$this.audioElem.currentTime = tm; | |
}, | |
getDuration: function() { | |
return $this.audioElem.duration; | |
}, | |
// Cue Point Methods | |
callTestMethodOne: function(){ | |
console.log("### CALLED ###"); | |
}, | |
callTestMethodTwo: function(){ | |
console.log("### CALLED 2 ###"); | |
} | |
}); | |
return PlayerView; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment