mirror of
https://github.com/ivuorinen/rss-audio-player.git
synced 2026-02-19 17:53:23 +00:00
RSSAudioPlayer 1.0
Quick system to play your (currently my) favourite podcast feeds and stuff.
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
/vendor/*
|
||||||
|
!/vendor/.gitkeep
|
||||||
|
/cache/*
|
||||||
|
!/cache/.gitkeep
|
||||||
|
composer.lock
|
||||||
9
.htaccess
Normal file
9
.htaccess
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<IfModule mod_rewrite.c>
|
||||||
|
RewriteEngine On
|
||||||
|
RewriteBase /rss-audio-player/
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-f
|
||||||
|
RewriteCond %{REQUEST_FILENAME} !-d
|
||||||
|
RewriteRule ^([^/]*)$ ./index.php [QSA]
|
||||||
|
RewriteRule ^list/([^/]*)$ ./index.php?page=list [QSA]
|
||||||
|
RewriteRule ^show/([^/]*)$ ./index.php?page=show&feed=$1 [QSA,L]
|
||||||
|
</IfModule>
|
||||||
19
assets/audiojs/LICENSE
Normal file
19
assets/audiojs/LICENSE
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
Copyright (c) 2010 Anthony Kolber (http://aestheticallyloyal.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
24
assets/audiojs/audio.min.js
vendored
Normal file
24
assets/audiojs/audio.min.js
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
(function(h,o,g){var p=function(){for(var b=/audio(.min)?.js.*/,a=document.getElementsByTagName("script"),c=0,d=a.length;c<d;c++){var e=a[c].getAttribute("src");if(b.test(e))return e.replace(b,"")}}();g[h]={instanceCount:0,instances:{},flashSource:' <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="$1" width="1" height="1" name="$1" style="position: absolute; left: -1px;"> <param name="movie" value="$2?playerInstance='+h+'.instances[\'$1\']&datetime=$3"> <param name="allowscriptaccess" value="always"> <embed name="$1" src="$2?playerInstance='+
|
||||||
|
h+'.instances[\'$1\']&datetime=$3" width="1" height="1" allowscriptaccess="always"> </object>',settings:{autoplay:false,loop:false,preload:true,imageLocation:p+"player-graphics.gif",swfLocation:p+"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:' <div class="play-pause"> <p class="play"></p> <p class="pause"></p> <p class="loading"></p> <p class="error"></p> </div> <div class="scrubber"> <div class="progress"></div> <div class="loaded"></div> </div> <div class="time"> <em class="played">00:00</em>/<strong class="duration">00:00</strong> </div> <div class="error-message"></div>',
|
||||||
|
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=j(b.errorMessageClass,this.wrapper),c='Missing <a href="http://get.adobe.com/flashplayer/">flash player</a> plugin.';if(this.mp3)c+=' <a href="'+this.mp3+'">Download audio file</a>.';g[h].helpers.removeClass(this.wrapper,b.loadingClass);g[h].helpers.addClass(this.wrapper,b.errorClass);a.innerHTML=c},loadError:function(){var b=this.settings.createPlayer,a=j(b.errorMessageClass,this.wrapper);g[h].helpers.removeClass(this.wrapper,
|
||||||
|
b.loadingClass);g[h].helpers.addClass(this.wrapper,b.errorClass);a.innerHTML='Error loading: "'+this.mp3+'"'},init:function(){g[h].helpers.addClass(this.wrapper,this.settings.createPlayer.loadingClass)},loadStarted:function(){var b=this.settings.createPlayer,a=j(b.durationClass,this.wrapper),c=Math.floor(this.duration/60),d=Math.floor(this.duration%60);g[h].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=j(a.scrubberClass,this.wrapper);j(a.loaderClass,this.wrapper).style.width=c.offsetWidth*b+"px"},playPause:function(){this.playing?this.settings.play():this.settings.pause()},play:function(){g[h].helpers.addClass(this.wrapper,this.settings.createPlayer.playingClass)},pause:function(){g[h].helpers.removeClass(this.wrapper,this.settings.createPlayer.playingClass)},updatePlayhead:function(b){var a=this.settings.createPlayer,c=j(a.scrubberClass,this.wrapper);j(a.progressClass,this.wrapper).style.width=
|
||||||
|
c.offsetWidth*b+"px";a=j(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,i=c.length;e<i;e++)d.push(this.newInstance(c[e],b));return d},newInstance:function(b,a){var c=this.helpers.clone(this.settings),d="audiojs"+this.instanceCount,
|
||||||
|
e="audiojs_wrapper"+this.instanceCount;this.instanceCount++;if(b.getAttribute("autoplay")!=null)c.autoplay=true;if(b.getAttribute("loop")!=null)c.loop=true;if(b.getAttribute("preload")=="none")c.preload=false;a&&this.helpers.merge(c,a);if(c.createPlayer.markup)b=this.createPlayer(b,c.createPlayer,e);else b.parentNode.setAttribute("id",e);e=new g[o](b,c);c.css&&this.helpers.injectCss(e,c.css);if(c.useFlash&&c.hasFlash){this.injectFlash(e,d);this.attachFlashEvents(e.wrapper,e)}else c.useFlash&&!c.hasFlash&&
|
||||||
|
this.settings.flashError.apply(e);if(!c.useFlash||c.useFlash&&c.hasFlash)this.attachEvents(e.wrapper,e);return this.instances[d]=e},createPlayer:function(b,a,c){var d=document.createElement("div"),e=b.cloneNode(true);d.setAttribute("class","audiojs");d.setAttribute("className","audiojs");d.setAttribute("id",c);if(e.outerHTML&&!document.createElement("audio").canPlayType){e=this.helpers.cloneHtml5Node(b);d.innerHTML=a.markup;d.appendChild(e);b.outerHTML=d.outerHTML;d=document.getElementById(c)}else{d.appendChild(e);
|
||||||
|
d.innerHTML+=a.markup;b.parentNode.replaceChild(d,b)}return d.getElementsByTagName("audio")[0]},attachEvents:function(b,a){if(a.settings.createPlayer){var c=a.settings.createPlayer,d=j(c.playPauseClass,b),e=j(c.scrubberClass,b);g[h].events.addListener(d,"click",function(){a.playPause.apply(a)});g[h].events.addListener(e,"click",function(i){i=i.clientX;var f=this,k=0;if(f.offsetParent){do k+=f.offsetLeft;while(f=f.offsetParent)}a.skipTo((i-k)/e.offsetWidth)});if(!a.settings.useFlash){g[h].events.trackLoadProgress(a);
|
||||||
|
g[h].events.addListener(a.element,"timeupdate",function(){a.updatePlayhead.apply(a)});g[h].events.addListener(a.element,"ended",function(){a.trackEnded.apply(a)});g[h].events.addListener(a.source,"error",function(){clearInterval(a.readyTimer);clearInterval(a.loadTimer);a.settings.loadError.apply(a)})}}},attachFlashEvents:function(b,a){a.swfReady=false;a.load=function(c){a.mp3=c;a.swfReady&&a.element.load(c)};a.loadProgress=function(c,d){a.loadedPercent=c;a.duration=d;a.settings.loadStarted.apply(a);
|
||||||
|
a.settings.loadProgress.apply(a,[c])};a.skipTo=function(c){if(!(c>a.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.setVolume=function(c){a.element.setVolume(c)};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),i=0,f=d.length;i<f;i++){var k=d[i].getAttribute("title");if(k&&~k.indexOf("audiojs")){f=
|
||||||
|
d[i];if(f.innerHTML===e)return;c=f.innerHTML;break}}d=document.getElementsByTagName("head")[0];i=d.firstChild;f=document.createElement("style");if(d){f.setAttribute("type","text/css");f.setAttribute("title","audiojs");if(f.styleSheet)f.styleSheet.cssText=c+e;else f.appendChild(document.createTextNode(c+e));i?d.insertBefore(f,i):d.appendChild(styleElement)}},cloneHtml5Node:function(b){var a=document.createDocumentFragment(),c=a.createElement?a:document;c.createElement("audio");c=c.createElement("div");
|
||||||
|
a.appendChild(c);c.innerHTML=b.outerHTML;return c.firstChild},getSwf:function(b){b=document[b]||window[b];return b.length>1?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(){if(this.listeners)for(var d=0,e=this.listeners.length;d<e;d++)g[h].events.purge(this.listeners[d])});this.memoryLeaking=true}b.attachEvent("on"+
|
||||||
|
a,function(){c.call(b,window.event)})}},trackLoadProgress:function(b){if(b.settings.preload){var a,c;b=b;var d=/(ipod|iphone|ipad)/i.test(navigator.userAgent);a=setInterval(function(){if(b.element.readyState>-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;c<a.length;c+=
|
||||||
|
1)if(typeof b[a[c].name]==="function")b[a[c].name]=null;if(a=b.childNodes)for(c=0;c<a.length;c+=1)purge(b.childNodes[c])},ready:function(){return function(b){var a=window,c=false,d=true,e=a.document,i=e.documentElement,f=e.addEventListener?"addEventListener":"attachEvent",k=e.addEventListener?"removeEventListener":"detachEvent",n=e.addEventListener?"":"on",m=function(l){if(!(l.type=="readystatechange"&&e.readyState!="complete")){(l.type=="load"?a:e)[k](n+l.type,m,false);if(!c&&(c=true))b.call(a,l.type||
|
||||||
|
l)}},q=function(){try{i.doScroll("left")}catch(l){setTimeout(q,50);return}m("poll")};if(e.readyState=="complete")b.call(a,"lazy");else{if(e.createEventObject&&i.doScroll){try{d=!a.frameElement}catch(r){}d&&q()}e[f](n+"DOMContentLoaded",m,false);e[f](n+"readystatechange",m,false);a[f](n+"load",m,false)}}}()}};g[o]=function(b,a){this.element=b;this.wrapper=b.parentNode;this.source=b.getElementsByTagName("source")[0]||b;this.mp3=function(c){var d=c.getElementsByTagName("source")[0];return c.getAttribute("src")||
|
||||||
|
(d?d.getAttribute("src"):null)}(b);this.settings=a;this.loadStartedCalled=false;this.loadedPercent=0;this.duration=1;this.playing=false};g[o].prototype={updatePlayhead:function(){this.settings.updatePlayhead.apply(this,[this.element.currentTime/this.duration])},skipTo:function(b){if(!(b>this.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;g[h].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");g[h].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)},
|
||||||
|
setVolume:function(b){this.element.volume=b},trackEnded:function(){this.skipTo.apply(this,[0]);this.settings.loop||this.pause.apply(this);this.settings.trackEnded.apply(this)}};var j=function(b,a){var c=[];a=a||document;if(a.getElementsByClassName)c=a.getElementsByClassName(b);else{var d,e,i=a.getElementsByTagName("*"),f=RegExp("(^|\\s)"+b+"(\\s|$)");d=0;for(e=i.length;d<e;d++)f.test(i[d].className)&&c.push(i[d])}return c.length>1?c:c[0]}})("audiojs","audiojsInstance",this);
|
||||||
BIN
assets/audiojs/audiojs.swf
Normal file
BIN
assets/audiojs/audiojs.swf
Normal file
Binary file not shown.
BIN
assets/audiojs/player-graphics.gif
Normal file
BIN
assets/audiojs/player-graphics.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
51
assets/scripts.js
Normal file
51
assets/scripts.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
$(document).foundation();
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
// Setup the player to autoplay the next track
|
||||||
|
var a = audiojs.createAll({
|
||||||
|
trackEnded: function() {
|
||||||
|
var next = $('ol li.playing').next();
|
||||||
|
if (!next.length) next = $('ol li').first();
|
||||||
|
next.addClass('playing').siblings().removeClass('playing');
|
||||||
|
audio.load($('a', next).attr('data-src'));
|
||||||
|
audio.play();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load in the first track
|
||||||
|
var audio = a[0];
|
||||||
|
first = $('ol a').attr('data-src');
|
||||||
|
$('ol li').first().addClass('playing');
|
||||||
|
audio.load(first);
|
||||||
|
|
||||||
|
// Load in a track on click
|
||||||
|
$('ol li').click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$(this).addClass('playing').siblings().removeClass('playing');
|
||||||
|
audio.load($('a', this).attr('data-src'));
|
||||||
|
audio.play();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Keyboard shortcuts
|
||||||
|
$(document).keydown(function(e) {
|
||||||
|
var unicode = e.charCode ? e.charCode : e.keyCode;
|
||||||
|
|
||||||
|
// right arrow
|
||||||
|
if (unicode == 39) {
|
||||||
|
var next = $('li.playing').next();
|
||||||
|
if (!next.length) next = $('ol li').first();
|
||||||
|
next.click();
|
||||||
|
|
||||||
|
// back arrow
|
||||||
|
} else if (unicode == 37) {
|
||||||
|
|
||||||
|
var prev = $('li.playing').prev();
|
||||||
|
|
||||||
|
if (!prev.length) prev = $('ol li').last();
|
||||||
|
prev.click();
|
||||||
|
// spacebar
|
||||||
|
} else if (unicode == 32) {
|
||||||
|
audio.playPause();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
66
assets/style.css
Normal file
66
assets/style.css
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
.audiojs {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
ol {
|
||||||
|
display: block;
|
||||||
|
padding: 0px; margin: 0px 20px; list-style: decimal-leading-zero inside;
|
||||||
|
color: #ccc; border-top: 1px solid #ccc; font-size: 0.9em;
|
||||||
|
}
|
||||||
|
.play-pause {
|
||||||
|
width: 38px !important;
|
||||||
|
}
|
||||||
|
.scrubber {
|
||||||
|
width: 80% !important;
|
||||||
|
}
|
||||||
|
ol li { position: relative; margin: 0px; padding: 9px 5px 10px; border-bottom: 1px solid #ccc; cursor: pointer; }
|
||||||
|
ol li:hover { background: #fff; }
|
||||||
|
ol li a { display: block; text-indent: -3.3ex; padding: 0px 0px 0px 20px; }
|
||||||
|
li.playing { color: #aaa; text-shadow: 1px 1px 0px rgba(255, 255, 255, 0.3); }
|
||||||
|
li.playing a { color: #000; }
|
||||||
|
li.playing:before {
|
||||||
|
content: '♬'; width: 14px; height: 14px; padding: 3px; line-height: 14px;
|
||||||
|
margin: 0px; position: absolute; left: -24px; top: 9px; color: #000;
|
||||||
|
font-size: 13px; text-shadow: 1px 1px 0px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
.feeds-list ul {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px 20px;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
.feeds-list li {
|
||||||
|
width: 25%;
|
||||||
|
text-align: center;
|
||||||
|
padding: 5px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bottom p,
|
||||||
|
#bottom li {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-size: 13px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#shortcuts {
|
||||||
|
position: fixed; bottom: 0px; width: 100%; color: #666; font-size: 0.9em;
|
||||||
|
margin: 60px 0px 0px; padding: 20px 20px 15px;
|
||||||
|
background: #f3f3f3; background: rgba(240, 240, 240, 0.7);
|
||||||
|
}
|
||||||
|
#shortcuts div { width: 90%; margin: 0px auto; }
|
||||||
|
#shortcuts h1 { margin: 0px 0px 6px; }
|
||||||
|
#shortcuts p { margin: 0px 0px 18px; }
|
||||||
|
#shortcuts em {
|
||||||
|
font-style: normal; background: #d3d3d3; padding: 3px 9px;
|
||||||
|
position: relative; left: -3px;
|
||||||
|
-webkit-border-radius: 4px;
|
||||||
|
-moz-border-radius: 4px;
|
||||||
|
-o-border-radius: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
-webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
-moz-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
-o-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
8
composer.json
Normal file
8
composer.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "ivuorinen/rss-audio-player",
|
||||||
|
"description": "Web based RSS Audio Player",
|
||||||
|
"license": "MIT",
|
||||||
|
"require": {
|
||||||
|
"simplepie/simplepie": "*"
|
||||||
|
}
|
||||||
|
}
|
||||||
5
feeds.json
Normal file
5
feeds.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"5by5master": "http://feeds.5by5.tv/master",
|
||||||
|
"Alas": "http://alas.kschzt.com/rss.xml",
|
||||||
|
"AlasAmbient": "http://alasambient.kschzt.com/rss.xml"
|
||||||
|
}
|
||||||
133
inc/rss-audio-player.php
Normal file
133
inc/rss-audio-player.php
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* RSS Audio Player class
|
||||||
|
*/
|
||||||
|
namespace ivuorinen;
|
||||||
|
|
||||||
|
class RSSAudioPlayer
|
||||||
|
{
|
||||||
|
public $basepath;
|
||||||
|
public $baseurl;
|
||||||
|
public $feeds;
|
||||||
|
public $feedslist;
|
||||||
|
public $templatepath;
|
||||||
|
|
||||||
|
protected $version;
|
||||||
|
protected $build;
|
||||||
|
|
||||||
|
public function __construct($config = null)
|
||||||
|
{
|
||||||
|
$this->version = "1.0";
|
||||||
|
$this->build = "20130725";
|
||||||
|
|
||||||
|
self::setDefaults();
|
||||||
|
self::setConfig($config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function translateFeed($feed = null)
|
||||||
|
{
|
||||||
|
$data = $this->feedslist;
|
||||||
|
if (is_readable($data)) {
|
||||||
|
$data = json_decode(file_get_contents($data));
|
||||||
|
$this->feeds = $data;
|
||||||
|
} else {
|
||||||
|
return $this->feed_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->feeds->$feed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildPage($page = 'list', $feed = null)
|
||||||
|
{
|
||||||
|
// Set our template path to shorthand
|
||||||
|
$tpl = $this->templatepath;
|
||||||
|
require_once $tpl . '/header.php';
|
||||||
|
|
||||||
|
$feed = $this->translateFeed($feed);
|
||||||
|
|
||||||
|
$simplepie = new \SimplePie();
|
||||||
|
$simplepie->set_feed_url($feed);
|
||||||
|
$simplepie->init();
|
||||||
|
$simplepie->handle_content_type();
|
||||||
|
|
||||||
|
$data['this'] = $this;
|
||||||
|
|
||||||
|
switch ($page) {
|
||||||
|
case 'show':
|
||||||
|
$data['feed'] = $simplepie;
|
||||||
|
break;
|
||||||
|
case 'list':
|
||||||
|
default:
|
||||||
|
$data['feeds'] = $this->feedslist;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_readable($tpl . DIRECTORY_SEPARATOR . $page . '.php')) {
|
||||||
|
require_once $tpl . DIRECTORY_SEPARATOR . $page . '.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once $tpl . '/footer.php';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFeedTitle($feed = null)
|
||||||
|
{
|
||||||
|
if (empty($feed)) {
|
||||||
|
return 'Feed "'.$feed.'" not known.';
|
||||||
|
} else {
|
||||||
|
$feed = $this->translateFeed($feed);
|
||||||
|
|
||||||
|
$simplepie = new \SimplePie();
|
||||||
|
$simplepie->set_feed_url($feed);
|
||||||
|
$simplepie->init();
|
||||||
|
$simplepie->handle_content_type();
|
||||||
|
|
||||||
|
return $simplepie->get_title();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function lnk($link = null, $text = '')
|
||||||
|
{
|
||||||
|
return '<a href="' . $link . '">' . $text . '</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function lst($text = null)
|
||||||
|
{
|
||||||
|
return '<li>' . $text . '</li>';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function currentDir()
|
||||||
|
{
|
||||||
|
$path = dirname($_SERVER["PHP_SELF"]);
|
||||||
|
$position = strrpos($path, '/') + 1;
|
||||||
|
return '/' . substr($path, $position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDefaults()
|
||||||
|
{
|
||||||
|
$path = pathinfo(__FILE__);
|
||||||
|
$this->basepath = dirname($path['dirname']) . DIRECTORY_SEPARATOR;
|
||||||
|
$this->cache_location = $this->basepath . 'cache';
|
||||||
|
$this->feed_url = 'http://feeds.5by5.tv/master';
|
||||||
|
$this->useragent = 'RSSAudioPlayer/'. $this->version
|
||||||
|
.' (Feed Parser; http://github.com/ivuorinen/rss-audio-player; '
|
||||||
|
.'Allow like Gecko) Build/'. $this->build;
|
||||||
|
$this->templatepath = $this->basepath . 'templates';
|
||||||
|
$this->feedslist = $this->basepath . 'feeds.json';
|
||||||
|
$this->baseurl = $this->currentDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setConfig($config = null)
|
||||||
|
{
|
||||||
|
if (empty($config)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($config as $key => $value) {
|
||||||
|
$this->$key = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
44
index.php
Normal file
44
index.php
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* MIT License
|
||||||
|
* ===========
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Ismo Vuorinen <ivuorinen@me.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @category Default
|
||||||
|
* @package ivuorinen\RSS_Audio_Player
|
||||||
|
* @author Ismo Vuorinen <ivuorinen@me.com>
|
||||||
|
* @copyright 2012 Ismo Vuorinen.
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||||
|
* @version 1.0
|
||||||
|
* @link http://github.com/ivuorinen/rss-audio-player
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once 'vendor/simplepie/simplepie/autoloader.php';
|
||||||
|
require_once 'inc/rss-audio-player.php';
|
||||||
|
|
||||||
|
$page = (empty($_GET['page'])) ? 'list' : $_GET['page'];
|
||||||
|
$feed = (empty($_GET['feed'])) ? '5by5master' : $_GET['feed'];
|
||||||
|
|
||||||
|
$rap = new \ivuorinen\RSSAudioPlayer();
|
||||||
|
|
||||||
|
$rap->buildPage($page, $feed);
|
||||||
34
templates/footer.php
Normal file
34
templates/footer.php
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
<footer id="bottom" class="row">
|
||||||
|
<div class="large-12 columns">
|
||||||
|
<hr />
|
||||||
|
<div class="row">
|
||||||
|
<div class="large-3 columns">
|
||||||
|
<p>RSSAudioPlayer <?php echo $this->version; ?></p>
|
||||||
|
</div>
|
||||||
|
<div class="large-7 columns">
|
||||||
|
<ul class="inline-list right">
|
||||||
|
<li>Components used in making this</li>
|
||||||
|
<li><a href="http://foundation.zurb.com">ZURB's Foundation Framework</a></li>
|
||||||
|
<li><a href="http://simplepie.org">SimplePIE</a></li>
|
||||||
|
<li><a href="http://kolber.github.io/audiojs/">audio.js</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="<?php echo $this->baseurl; ?>/assets/audiojs/audio.min.js"></script>
|
||||||
|
<script>
|
||||||
|
document.write(
|
||||||
|
'<script src=//cdnjs.cloudflare.com/ajax/libs'
|
||||||
|
+ '/foundation/4.1.6/js/vendor/'
|
||||||
|
+ ('__proto__' in {} ? 'zepto' : 'jquery')
|
||||||
|
+ '.js><\/script>'
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/4.1.6/js/foundation.min.js"></script>
|
||||||
|
<script src="<?php echo $this->baseurl; ?>/assets/scripts.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
23
templates/header.php
Normal file
23
templates/header.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!--[if IE 8]><html class="no-js lt-ie9" lang="en"><![endif]-->
|
||||||
|
<!--[if gt IE 8]><html class="no-js" lang="en"><![endif]-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
|
||||||
|
<!-- Set the viewport width to device width for mobile -->
|
||||||
|
<meta name="viewport" content="width=device-width" />
|
||||||
|
<title>RSS Audio Player</title>
|
||||||
|
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/foundation/4.1.6/css/normalize.min.css">
|
||||||
|
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/foundation/4.1.6/css/foundation.min.css">
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/4.1.6/js/vendor/custom.modernizr.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="<?php echo $this->baseurl; ?>/assets/style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="large-12 columns">
|
||||||
|
<div class="panel">
|
||||||
|
<h1><a href="<?php echo $this->baseurl; ?>">RSS Audio Player</a></h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
26
templates/list.php
Normal file
26
templates/list.php
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="large-12 columns">
|
||||||
|
<div class="panel">
|
||||||
|
|
||||||
|
<h2>Our known feeds</h2>
|
||||||
|
<ul class="inline-list feeds-list">
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
foreach ($this->feeds as $key => $url) {
|
||||||
|
$title = $this->getFeedTitle($key);
|
||||||
|
echo "\t\t\t\t" . $this->lst(
|
||||||
|
$this->lnk(
|
||||||
|
$this->baseurl . '/show/' . $key, // Our link
|
||||||
|
$title
|
||||||
|
)
|
||||||
|
). "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
48
templates/show.php
Normal file
48
templates/show.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="large-12 columns">
|
||||||
|
<div class="panel">
|
||||||
|
|
||||||
|
<h2><a title="<?php
|
||||||
|
echo $data['feed']->get_link();
|
||||||
|
?>" href="<?php
|
||||||
|
echo $data['feed']->get_link();
|
||||||
|
?>" target="_blank"><?php
|
||||||
|
echo $data['feed']->get_title();
|
||||||
|
?></a></h2>
|
||||||
|
<header>
|
||||||
|
<p><?php echo $data['feed']->get_description(); ?></p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
$items = $data['feed']->get_items();
|
||||||
|
|
||||||
|
if (! empty($items)) {
|
||||||
|
|
||||||
|
echo '<audio></audio>'."\n";
|
||||||
|
echo '<ol>' . "\n";
|
||||||
|
|
||||||
|
foreach ($items as $item) {
|
||||||
|
|
||||||
|
if (($enclosure = $item->get_enclosure())) {
|
||||||
|
$link = $enclosure->get_link();
|
||||||
|
} else {
|
||||||
|
$link = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\t\t\t\t<li>"
|
||||||
|
. '<a href="'. $item->get_permalink() .'" '
|
||||||
|
. ' data-src="'. $link .'"'
|
||||||
|
. '>'
|
||||||
|
. $item->get_title()
|
||||||
|
. '</a>'
|
||||||
|
."</li>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '</ol>' . "\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
0
vendor/.gitkeep
vendored
Normal file
0
vendor/.gitkeep
vendored
Normal file
Reference in New Issue
Block a user