Created
March 11, 2013 14:35
-
-
Save robrocker7/5134669 to your computer and use it in GitHub Desktop.
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
/* Simple JavaScript Inheritance | |
* By John Resig http://ejohn.org/ | |
* MIT Licensed. | |
*/ | |
// Inspired by base2 and Prototype | |
(function(){ | |
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; | |
// The base Class implementation (does nothing) | |
this.Class = function(){}; | |
// Create a new Class that inherits from this class | |
Class.extend = function(prop) { | |
var _super = this.prototype; | |
// Instantiate a base class (but only create the instance, | |
// don't run the init constructor) | |
initializing = true; | |
var prototype = new this(); | |
initializing = false; | |
// Copy the properties over onto the new prototype | |
for (var name in prop) { | |
// Check if we're overwriting an existing function | |
prototype[name] = typeof prop[name] == "function" && | |
typeof _super[name] == "function" && fnTest.test(prop[name]) ? | |
(function(name, fn){ | |
return function() { | |
var tmp = this._super; | |
// Add a new ._super() method that is the same method | |
// but on the super-class | |
this._super = _super[name]; | |
// The method only need to be bound temporarily, so we | |
// remove it when we're done executing | |
var ret = fn.apply(this, arguments); | |
this._super = tmp; | |
return ret; | |
}; | |
})(name, prop[name]) : | |
prop[name]; | |
} | |
// The dummy class constructor | |
function Class() { | |
// All construction is actually done in the init method | |
if ( !initializing && this.init ) | |
this.init.apply(this, arguments); | |
} | |
// Populate our constructed prototype object | |
Class.prototype = prototype; | |
// Enforce the constructor to be what we expect | |
Class.prototype.constructor = Class; | |
// And make this class extendable | |
Class.extend = arguments.callee; | |
return Class; | |
}; | |
})(); | |
/******************************/ | |
/* Application */ | |
/******************************/ | |
function PlayerApp() { | |
var VERSION = '1.0.0'; | |
var me = this; | |
var template = null; | |
var element = null; | |
/******************************/ | |
/* Models */ | |
/******************************/ | |
// TODO : Write better model functionality | |
var Song = { | |
imageUrl: null, | |
title: null, | |
artist: null, | |
album: null, | |
mediaUrl: null, | |
mediaResource: null, | |
mediaId: null, | |
searchKey: null, | |
liked: false | |
}; | |
var MediaObj = { | |
mediaId: null, | |
mediaName: null, | |
image: null, | |
type: null, | |
url: null, | |
stationId: null | |
}; | |
me.init = function() { | |
// init funciton | |
me.streamController = new StreamController(); | |
me.previewController = new PreviewController(); | |
// initial handlebars template | |
var source = $("#player-template").html(); | |
me.element = $('#player .player-controller'); | |
me.template = Handlebars.compile(source); | |
// load initial song data for default images | |
var song = $(me.Song).clone(); | |
song.imageUrl = '/static/core/img/blank_58x58.jpg'; | |
var media = $(me.MediaObj).clone(); | |
media.image = '/static/core/img/blank_58x58.jpg'; | |
me.streamController.set('currentSong', song); | |
me.streamController.set('currentMedia', media); | |
me._renderHtml(); | |
}; | |
me._renderHtml = function() { | |
me.element.html(me.template(me.streamController)); | |
} | |
me._getTime = function(nMSec) { | |
var nSec = Math.floor(nMSec/1000), | |
min = Math.floor(nSec/60), | |
sec = nSec-(min*60); | |
return min+':'+(sec<10?'0'+sec:sec); | |
}; | |
me._getDurationEstimate = function(oSound) { | |
if (oSound.instanceOptions.isMovieStar) { | |
return (oSound.duration); | |
} else { | |
return (!oSound._data.metadata || !oSound._data.metadata.data.givenDuration ? (oSound.durationEstimate||0) : oSound._data.metadata.data.givenDuration); | |
} | |
}; | |
}; | |
/******************************/ | |
/* Controllers */ | |
/******************************/ | |
var PlayerController = Class.extend({ | |
trackSound: null, | |
volume: 75, | |
songsPlayed: 0, | |
state: 'stopped', | |
currentSong: null, | |
progress_element: null, | |
init: function(){ | |
this._self = this; | |
var _self = this._self; | |
$(document).on('click', '#pause-btn', function(e){ | |
e.preventDefault(); | |
_self.pause(); | |
}); | |
$(document).on('click', '#play-btn', function(e){ | |
e.preventDefault(); | |
_self.play(); | |
}); | |
}, | |
stop: function() { | |
if (!this._self.trackSound) { | |
return false; | |
} | |
this._self.trackSound.stop(); | |
this._self.trackSound.destruct(); | |
this._self.trackSound = null; | |
this._self.set('state', 'stopped'); | |
}, | |
play: function() { | |
if (!this._self.trackSound) { | |
return false; | |
} | |
this._self.trackSound.play(); | |
this._self.trackSound.unmute(); | |
this._self.set('state', 'playing'); | |
}, | |
pause: function() { | |
if (!this._self.trackSound) { | |
return false; | |
} | |
this._self.trackSound.pause() | |
this._self.set('state', 'paused'); | |
}, | |
updateProgress: function(position, duration) { | |
$(this._self.progress_element).find(".prog-position").text(PlayerApp._getTime(position, true)); | |
$(this._self.progress_element).find(".prog-duration").text(PlayerApp._getTime(duration, true)); | |
$(this._self.progress_element).find(".prog-bar").css('width', ((position/PlayerApp._getDurationEstimate(this._self.trackSound))*100)+'%'); | |
}, | |
}); | |
var PreviewController = PlayerController.extend({ | |
init: function(){ | |
this._super(); | |
var _self = this._self; | |
$(document).on('click', '#preview-play-action', function(e){ | |
e.preventDefault(); | |
_self.stop(); | |
}); | |
$(document).on('click', '.headphone-icon', function(e){ | |
e.preventDefault(); | |
var parent = $(this).parent(); | |
media = { | |
type: 'sample', | |
id: parent.attr('data-id'), | |
source: 'msr' | |
}; | |
_self.getSong(media); | |
}); | |
this._self.progress_element = $('#preview-progress'); | |
}, | |
set: function(key, value) { | |
this._self[key] = value; | |
this._self.observer(); | |
}, | |
getSong: function(media) { | |
// had to init this var because we need ot call self in the resolveMedia | |
var _self = this._self; | |
_self.set('state', 'loading'); | |
if (_self.trackSound) { | |
_self.stop(); | |
} | |
//$('#player-loading').fadeIn('slow'); | |
PlayerApp.mediaController.resolveSampleMedia(media, function(song) { | |
if(song) { | |
_self.trackSound = soundManager.createSound({ | |
id: 'S-' + song.mediaId, | |
serverURL: song.mediaUrl, | |
url: song.mediaResource, | |
bufferTime: 6, | |
autoLoad: true, | |
onconnect: function (bSuccess) { | |
if(bSuccess) { | |
_self.play(); | |
_self.updateProgress(this.position, this.duration); | |
} else { | |
// TODO: log and report issue | |
} | |
}, | |
onfinish: function () { | |
_self.stop(); | |
// TODO start playing streamer | |
}, | |
volume: (_self.volume >= 0 ? _self.volume : 75), | |
whileloading: function () { | |
}, | |
whileplaying: function () { | |
_self.updateProgress(this.position, this.duration); | |
} | |
}); | |
_self.set('currentSong', song); | |
} else { | |
// TODO Properly handle no song return | |
} | |
}); | |
}, | |
observer: function() { | |
switch(this._self.state) { | |
case 'stopped': | |
console.log('stopped'); | |
if(PlayerApp.streamController.state == 'paused') { | |
PlayerApp.streamController.play(); | |
} | |
if($('#preview-player').is(":visible")) { | |
$('#preview-player').hide(); | |
} | |
break; | |
case 'playing': | |
console.log('playing'); | |
break; | |
case 'paused': | |
console.log('paused'); | |
break; | |
case 'loading': | |
console.log('loading'); | |
if($('#preview-player').is(":hidden")) { | |
$('#preview-player').show(); | |
} | |
// if the streamer is playing pause it | |
if(PlayerApp.streamController.state == 'playing') { | |
PlayerApp.streamController.pause(); | |
} | |
break; | |
} | |
} | |
}); | |
var StreamController = PlayerController.extend({ | |
currentMedia: null, | |
init: function(){ | |
this._super(); | |
var _self = this._self; | |
$(document).on('click', '#skip-btn', function(e){ | |
e.preventDefault(); | |
_self.skip(); | |
}); | |
$(document).on("click", '.play-me', function(e) { | |
_self.prepareSong(e); | |
}); | |
$(document).on("click", '.play-button span.myx-pause', function(e) { | |
e.preventDefault(); | |
$('#pause-btn').trigger('click'); | |
}); | |
this._self.progress_element = $('#progress'); | |
}, | |
set: function(key, value) { | |
this._self[key] = value; | |
PlayerApp._renderHtml(); | |
this._self.observer(); | |
}, | |
skip: function() { | |
if (!this.trackSound) { | |
return false; | |
} | |
this._self.getSong(null); | |
this._self.set('state', 'loading'); | |
}, | |
changeVolume: function(value) { | |
if (!this._self.trackSound) { | |
return false; | |
} | |
this._self.volume = value; | |
this._self.trackSound.setVolume(value); | |
}, | |
prepareSong: function(e) { | |
var target = $(e.target); | |
var data = e.data; | |
var mediaId = null; | |
var type = null; | |
var meta = null; | |
var name = null; | |
if (data && data.mediaId) { | |
mediaId = data.mediaId; | |
type = data.type; | |
meta = data.meta; | |
name = data.name; | |
} else { | |
mediaId = target.attr('media-id'); | |
type = target.attr('media-type'); | |
meta = target.attr('media-meta'); | |
name = target.attr('media-name'); | |
} | |
// set the station controller ID to make sure the | |
// like/dislike buttons work | |
if (type=='stations' && window.stationController){ | |
window.stationController.stationId = mediaId; | |
} | |
$('.play-me').attr('media-meta',''); | |
// if the same media id is already playing we don't need to ask for another song | |
// should try to play the paused content | |
current_mediaId = null; | |
if(this._self.currentMedia) { | |
current_mediaId = this._self.currentMedia.mediaId; | |
} | |
if(mediaId == current_mediaId){ | |
$('#play-btn').trigger('click'); | |
} else { | |
this._self.getSong({id:mediaId,type:type,meta:meta,name:name}); | |
} | |
}, | |
getSong: function(media) { | |
// had to init this var because we need ot call self in the resolveMedia | |
var _self = this._self; | |
_self.set('state', 'loading'); | |
if (_self.trackSound) { | |
_self.stop(); | |
} | |
$('#player-loading').fadeIn('slow'); | |
PlayerApp.mediaController.resolveMedia(media, function(song, mediaInfo) { | |
if(song) { | |
_self.trackSound = soundManager.createSound({ | |
id: 'S-' + song.mediaId, | |
serverURL: song.mediaUrl, | |
url: song.mediaResource, | |
bufferTime: 6, | |
autoLoad: true, | |
onconnect: function (bSuccess) { | |
if(bSuccess) { | |
_self.play(); | |
_self.set('songsPlayed', _self.songsPlayed + 1); | |
_self.updateProgress(this.position, this.duration); | |
// update personalize state | |
$('.thumbs-up').removeClass('active'); | |
if(song.liked) { | |
$('.thumbs-up').addClass('active'); | |
} | |
} else { | |
// TODO: log and report issue | |
} | |
}, | |
onfinish: function () { | |
_self.stop(); | |
_self.getSong(null); | |
}, | |
volume: (_self.volume >= 0 ? _self.volume : 75), | |
whileloading: function () { | |
}, | |
whileplaying: function () { | |
_self.updateProgress(this.position, this.duration); | |
// if (me.state !== 'paused') { | |
// me.set('state', 'playing'); | |
// } | |
} | |
}); | |
_self.set('currentSong', song); | |
_self.set('currentMedia', mediaInfo); | |
} else { | |
// TODO Properly handle no song return | |
} | |
}); | |
}, | |
observer: function() { | |
switch(this._self.state) { | |
case 'stopped': | |
console.log('stopped'); | |
$('#player-loading').hide(); | |
$('#pause-btn').hide(); | |
$('#play-btn').show(); | |
$('.play-button span').removeClass('myx-pause').addClass('myx-play'); | |
break; | |
case 'playing': | |
console.log('playing'); | |
$('#player-loading').hide(); | |
$('#pause-btn').show(); | |
$('#play-btn').hide(); | |
$('.play-button span').removeClass('myx-pause').addClass('myx-play'); | |
$('.play-button[media-id="'+PlayerApp.streamController.currentMedia.mediaId+'"]' | |
).removeClass('play-me').children('span').removeClass('myx-play').addClass('myx-pause'); | |
break; | |
case 'paused': | |
console.log('paused'); | |
$('#player-loading').hide(); | |
$('#pause-btn').hide(); | |
$('#play-btn').show(); | |
$('.play-button span').removeClass('myx-pause').addClass('myx-play'); | |
$('.play-button[media-id="'+PlayerApp.streamController.currentMedia.mediaId+'"]' | |
).addClass('play-me'); | |
break; | |
case 'loading': | |
console.log('loading'); | |
$('#player-loading').show(); | |
break; | |
} | |
} | |
}); | |
window.PlayerApp = new PlayerApp(); | |
PlayerApp.init(); | |
$(document).ready(function() { | |
$('.button-like').live('click', function(){ | |
$(this).effect('bounce'); | |
$(this).addClass('active'); | |
PlayerApp.streamController.songAction('like'); | |
}); | |
$('.button-dislike').live('click', function(){ | |
$(this).effect('bounce'); | |
PlayerApp.streamController.songAction('dislike'); | |
}); | |
$( "#volume-slider" ).slider({ | |
orientation: "vertical", | |
range: "min", | |
min: 0, | |
max: 100, | |
value: 75, | |
slide: function( event, ui ) { | |
PlayerApp.streamController.changeVolume(ui.value); | |
// TODO: Save volume to cookies | |
} | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment