From b6ac0e4d360b2082f787962129d8bb370561ebf7 Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Mon, 8 Aug 2011 15:11:49 -0700 Subject: [PATCH] replace audio.js with a hand-rolled player --- beetsplug/web/static/audiojs/audio.js | 24 --- beetsplug/web/static/audiojs/audiojs.swf | Bin 1644 -> 0 bytes .../web/static/audiojs/player-graphics.gif | Bin 4499 -> 0 bytes beetsplug/web/static/beets.css | 32 ++-- beetsplug/web/static/beets.js | 139 ++++++++++++++++-- beetsplug/web/templates/index.html | 11 +- 6 files changed, 156 insertions(+), 50 deletions(-) delete mode 100644 beetsplug/web/static/audiojs/audio.js delete mode 100644 beetsplug/web/static/audiojs/audiojs.swf delete mode 100644 beetsplug/web/static/audiojs/player-graphics.gif diff --git a/beetsplug/web/static/audiojs/audio.js b/beetsplug/web/static/audiojs/audio.js deleted file mode 100644 index d675b9371..000000000 --- a/beetsplug/web/static/audiojs/audio.js +++ /dev/null @@ -1,24 +0,0 @@ -(function(g,r,f){var s=function(){for(var b=/audio(.min)?.js.*/,a=document.getElementsByTagName("script"),c=0,d=a.length;c ',settings:{autoplay:false,loop:false,preload:true,imageLocation:s+"player-graphics.gif",swfLocation:s+"audiojs.swf",useFlash:function(){var b=document.createElement("audio");return!(b.canPlayType&&b.canPlayType("audio/mpeg;").replace(/no/,""))}(),hasFlash:function(){if(navigator.plugins&&navigator.plugins.length&&navigator.plugins["Shockwave Flash"])return true;else if(navigator.mimeTypes&&navigator.mimeTypes.length){var b= -navigator.mimeTypes["application/x-shockwave-flash"];return b&&b.enabledPlugin}else try{new ActiveXObject("ShockwaveFlash.ShockwaveFlash");return true}catch(a){}return false}(),createPlayer:{markup:'

00:00/00:00
', -playPauseClass:"play-pause",scrubberClass:"scrubber",progressClass:"progress",loaderClass:"loaded",timeClass:"time",durationClass:"duration",playedClass:"played",errorMessageClass:"error-message",playingClass:"playing",loadingClass:"loading",errorClass:"error"},css:' .audiojs audio { position: absolute; left: -1px; } .audiojs { width: 460px; height: 36px; background: #404040; overflow: hidden; font-family: monospace; font-size: 12px; background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #444), color-stop(0.5, #555), color-stop(0.51, #444), color-stop(1, #444)); background-image: -moz-linear-gradient(center top, #444 0%, #555 50%, #444 51%, #444 100%); -webkit-box-shadow: 1px 1px 8px rgba(0, 0, 0, 0.3); -moz-box-shadow: 1px 1px 8px rgba(0, 0, 0, 0.3); -o-box-shadow: 1px 1px 8px rgba(0, 0, 0, 0.3); box-shadow: 1px 1px 8px rgba(0, 0, 0, 0.3); } .audiojs .play-pause { width: 25px; height: 40px; padding: 4px 6px; margin: 0px; float: left; overflow: hidden; border-right: 1px solid #000; } .audiojs p { display: none; width: 25px; height: 40px; margin: 0px; cursor: pointer; } .audiojs .play { display: block; } .audiojs .scrubber { position: relative; float: left; width: 280px; background: #5a5a5a; height: 14px; margin: 10px; border-top: 1px solid #3f3f3f; border-left: 0px; border-bottom: 0px; overflow: hidden; } .audiojs .progress { position: absolute; top: 0px; left: 0px; height: 14px; width: 0px; background: #ccc; z-index: 1; background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #ccc), color-stop(0.5, #ddd), color-stop(0.51, #ccc), color-stop(1, #ccc)); background-image: -moz-linear-gradient(center top, #ccc 0%, #ddd 50%, #ccc 51%, #ccc 100%); } .audiojs .loaded { position: absolute; top: 0px; left: 0px; height: 14px; width: 0px; background: #000; background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #222), color-stop(0.5, #333), color-stop(0.51, #222), color-stop(1, #222)); background-image: -moz-linear-gradient(center top, #222 0%, #333 50%, #222 51%, #222 100%); } .audiojs .time { float: left; height: 36px; line-height: 36px; margin: 0px 0px 0px 6px; padding: 0px 6px 0px 12px; border-left: 1px solid #000; color: #ddd; text-shadow: 1px 1px 0px rgba(0, 0, 0, 0.5); } .audiojs .time em { padding: 0px 2px 0px 0px; color: #f9f9f9; font-style: normal; } .audiojs .time strong { padding: 0px 0px 0px 2px; font-weight: normal; } .audiojs .error-message { float: left; display: none; margin: 0px 10px; height: 36px; width: 400px; overflow: hidden; line-height: 36px; white-space: nowrap; color: #fff; text-overflow: ellipsis; -o-text-overflow: ellipsis; -icab-text-overflow: ellipsis; -khtml-text-overflow: ellipsis; -moz-text-overflow: ellipsis; -webkit-text-overflow: ellipsis; } .audiojs .error-message a { color: #eee; text-decoration: none; padding-bottom: 1px; border-bottom: 1px solid #999; white-space: wrap; } .audiojs .play { background: url("$1") -2px -1px no-repeat; } .audiojs .loading { background: url("$1") -2px -31px no-repeat; } .audiojs .error { background: url("$1") -2px -61px no-repeat; } .audiojs .pause { background: url("$1") -2px -91px no-repeat; } .playing .play, .playing .loading, .playing .error { display: none; } .playing .pause { display: block; } .loading .play, .loading .pause, .loading .error { display: none; } .loading .loading { display: block; } .error .time, .error .play, .error .pause, .error .scrubber, .error .loading { display: none; } .error .error { display: block; } .error .play-pause p { cursor: auto; } .error .error-message { display: block; }', -trackEnded:function(){},flashError:function(){var b=this.settings.createPlayer,a=m(b.errorMessageClass,this.wrapper),c='Missing flash player plugin.';if(this.mp3)c+=' Download audio file.';f[g].helpers.removeClass(this.wrapper,b.loadingClass);f[g].helpers.addClass(this.wrapper,b.errorClass);a.innerHTML=c},loadError:function(){var b=this.settings.createPlayer,a=m(b.errorMessageClass,this.wrapper);f[g].helpers.removeClass(this.wrapper, -b.loadingClass);f[g].helpers.addClass(this.wrapper,b.errorClass);a.innerHTML='Error loading: "'+this.mp3+'"'},init:function(){f[g].helpers.addClass(this.wrapper,this.settings.createPlayer.loadingClass)},loadStarted:function(){var b=this.settings.createPlayer,a=m(b.durationClass,this.wrapper),c=Math.floor(this.duration/60),d=Math.floor(this.duration%60);f[g].helpers.removeClass(this.wrapper,b.loadingClass);a.innerHTML=(c<10?"0":"")+c+":"+(d<10?"0":"")+d},loadProgress:function(b){var a=this.settings.createPlayer, -c=m(a.scrubberClass,this.wrapper);m(a.loaderClass,this.wrapper).style.width=c.offsetWidth*b+"px"},playPause:function(){this.playing?this.settings.play():this.settings.pause()},play:function(){f[g].helpers.addClass(this.wrapper,this.settings.createPlayer.playingClass)},pause:function(){f[g].helpers.removeClass(this.wrapper,this.settings.createPlayer.playingClass)},updatePlayhead:function(b){var a=this.settings.createPlayer,c=m(a.scrubberClass,this.wrapper);m(a.progressClass,this.wrapper).style.width= -c.offsetWidth*b+"px";a=m(a.playedClass,this.wrapper);c=this.duration*b;b=Math.floor(c/60);c=Math.floor(c%60);a.innerHTML=(b<10?"0":"")+b+":"+(c<10?"0":"")+c}},create:function(b,a){a=a||{};return b.length?this.createAll(a,b):this.newInstance(b,a)},createAll:function(b,a){var c=a||document.getElementsByTagName("audio"),d=[];b=b||{};for(var e=0,k=c.length;ea.loadedPercent)){a.updatePlayhead.call(a,[c]);a.element.skipTo(c)}};a.updatePlayhead=function(c){a.settings.updatePlayhead.apply(a,[c])};a.play=function(){if(!a.settings.preload){a.settings.preload=true;a.element.init(a.mp3)}a.playing=true;a.element.pplay();a.settings.play.apply(a)};a.pause=function(){a.playing=false;a.element.ppause();a.settings.pause.apply(a)};a.loadStarted=function(){a.swfReady=true;a.settings.preload&&a.element.init(a.mp3); -a.settings.autoplay&&a.play.apply(a)}},injectFlash:function(b,a){var c=this.flashSource.replace(/\$1/g,a);c=c.replace(/\$2/g,b.settings.swfLocation);c=c.replace(/\$3/g,+new Date+Math.random());var d=b.wrapper.innerHTML,e=document.createElement("div");e.innerHTML=c+d;b.wrapper.innerHTML=e.innerHTML;b.element=this.helpers.getSwf(a)},helpers:{merge:function(b,a){for(attr in a)if(b.hasOwnProperty(attr)||a.hasOwnProperty(attr))b[attr]=a[attr]},clone:function(b){if(b==null||typeof b!=="object")return b; -var a=new b.constructor,c;for(c in b)a[c]=arguments.callee(b[c]);return a},addClass:function(b,a){RegExp("(\\s|^)"+a+"(\\s|$)").test(b.className)||(b.className+=" "+a)},removeClass:function(b,a){b.className=b.className.replace(RegExp("(\\s|^)"+a+"(\\s|$)")," ")},injectCss:function(b,a){for(var c="",d=document.getElementsByTagName("style"),e=a.replace(/\$1/g,b.settings.imageLocation),k=0,h=d.length;k1?b[b.length-1]:b}},events:{memoryLeaking:false,listeners:[],addListener:function(b,a,c){if(b.addEventListener)b.addEventListener(a,c,false);else if(b.attachEvent){this.listeners.push(b);if(!this.memoryLeaking){window.attachEvent("onunload",function(){for(var d=0,e=this.listeners.length;d-1)d||b.init.apply(b);if(b.element.readyState>1){b.settings.autoplay&&b.play.apply(b);clearInterval(a);c=setInterval(function(){b.loadProgress.apply(b);b.loadedPercent>=1&&clearInterval(c)})}},10);b.readyTimer=a;b.loadTimer=c}},purge:function(b){var a=b.attributes,c;if(a)for(c=0;cthis.loadedPercent)){this.element.currentTime=this.duration*b;this.updatePlayhead()}},load:function(b){this.loadStartedCalled=false;this.source.setAttribute("src",b);this.element.load();this.mp3=b;f[g].events.trackLoadProgress(this)},loadError:function(){this.settings.loadError.apply(this)},init:function(){this.settings.init.apply(this)}, -loadStarted:function(){if(!this.element.duration)return false;this.duration=this.element.duration;this.updatePlayhead();this.settings.loadStarted.apply(this)},loadProgress:function(){if(this.element.buffered!=null&&this.element.buffered.length){if(!this.loadStartedCalled)this.loadStartedCalled=this.loadStarted();this.loadedPercent=this.element.buffered.end(this.element.buffered.length-1)/this.duration;this.settings.loadProgress.apply(this,[this.loadedPercent])}},playPause:function(){this.playing? -this.pause():this.play()},play:function(){/(ipod|iphone|ipad)/i.test(navigator.userAgent)&&this.element.readyState==0&&this.init.apply(this);if(!this.settings.preload){this.settings.preload=true;this.element.setAttribute("preload","auto");f[g].events.trackLoadProgress(this)}this.playing=true;this.element.play();this.settings.play.apply(this)},pause:function(){this.playing=false;this.element.pause();this.settings.pause.apply(this)},trackEnded:function(){this.skipTo.apply(this,[0]);this.settings.loop|| -this.pause.apply(this);this.settings.trackEnded.apply(this)}};var m=function(b,a,c){var d=[];if(document.getElementsByClassName)d=a.getElementsByClassName(b);else{a=a||document;c=c||"*";a=a.getElementsByTagName(c);b=RegExp("(^|\\s)"+b+"(\\s|$)");j=i=0;for(l=a.length;i1?d:d[0]}})("audiojs","audiojsInstance",this); diff --git a/beetsplug/web/static/audiojs/audiojs.swf b/beetsplug/web/static/audiojs/audiojs.swf deleted file mode 100644 index 483599fc8273d0ccaaa935aa115a65e05ffe27ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1644 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 KA7@~Jh5rN$ej 1.0) { + ratio = 1.0; + } + return (Math.round(ratio * 10000) / 100) + '%'; + } + + // Event helpers. + var dbg = function(msg) { + if (debug) + console.log(msg); + } + var showState = function() { + if (audio.duration == undefined || isNaN(audio.duration)) { + playBtn.hide(); + pauseBtn.hide(); + disabledInd.show(); + timesEl.hide(); + } else if (audio.paused) { + playBtn.show(); + pauseBtn.hide(); + disabledInd.hide(); + timesEl.show(); + } else { + playBtn.hide(); + pauseBtn.show(); + disabledInd.hide(); + timesEl.show(); + } + } + var showTimes = function() { + curTimeEl.text(timeFormat(audio.currentTime)); + totalTimeEl.text(timeFormat(audio.duration)); + + sliderPlayedEl.css('width', + timePercent(audio.currentTime, audio.duration)); + + // last time buffered + var bufferEnd = 0; + for (var i = 0; i < audio.buffered.length; ++i) { + if (audio.buffered.end(i) > bufferEnd) + bufferEnd = audio.buffered.end(i); + } + sliderLoadedEl.css('width', + timePercent(bufferEnd, audio.duration)); + } + + // Initialize controls. + showState(); + showTimes(); + + // Bind events. + $('audio', this).bind({ + playing: function() { + dbg('playing'); + showState(); + }, + pause: function() { + dbg('pause'); + showState(); + }, + ended: function() { + dbg('ended'); + showState(); + }, + progress: function() { + dbg('progress ' + audio.buffered); + }, + timeupdate: function() { + dbg('timeupdate ' + audio.currentTime); + showTimes(); + }, + durationchange: function() { + dbg('durationchange ' + audio.duration); + showState(); + showTimes(); + }, + loadeddata: function() { + dbg('loadeddata'); + }, + loadedmetadata: function() { + dbg('loadedmetadata'); + } + }); +} + // Simple selection disable for jQuery. // Cut-and-paste from: // http://stackoverflow.com/questions/2700000 @@ -98,9 +225,8 @@ var AppView = Backbone.View.extend({ }, playItem: function(item) { var url = '/item/' + item.get('id') + '/file'; - $(audio.wrapper).removeClass('unloaded'); - audio.load(url); - audio.play(); + $('#player audio').attr('src', url); + $('#player audio').get(0).play(); } }); var app = new AppView(); @@ -113,11 +239,6 @@ $('#entities ul').disableSelection(); $('#header').disableSelection(); // Audio player setup. -var audio; -audiojs.events.ready(function() { - var as = audiojs.createAll(); - audio = as[0]; - $(audio.wrapper).addClass('unloaded'); -}); +$('#player').player(); }); diff --git a/beetsplug/web/templates/index.html b/beetsplug/web/templates/index.html index caa4f2900..4906f0ce3 100644 --- a/beetsplug/web/templates/index.html +++ b/beetsplug/web/templates/index.html @@ -10,8 +10,6 @@ - @@ -19,6 +17,15 @@

beets

+ + + + + + + + +