commit b63a78798133187724e2c7e09c95ab54af597dfd Author: GM-Script-Writer-62850 Date: Sun Jun 1 13:32:48 2014 -0400 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..afc0e18 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +This is a basic HTML5 music player +This was made to have the basic features in a music player as well as have a mobile friendly layout + +Setup: +1. Add the index.html, player,js, player,css, and playlist.php files to a folder on your web server +2. Create a folder called library in that folder, this folder should contain your music +this folder can be a symlink to your main music folder + +Any files/folders starting with a "." will be ignored +Cover images should be named cover (not case sensitive), they should be in png, jpg/jpeg, or gif format, basically anything a web browser can display +Cover images are optional +Any file not called cover will be treated as a audio file +All files should have a file extension (eg .png, .mp3, .ogg, etc) +This uses 3 icons from the apache web server, if you are using a different web service, grab these icons and save them as the following: +/icons/open.folder.png +/icons/folder.png +/icons/sound2.png diff --git a/index.html b/index.html new file mode 100644 index 0000000..378ed98 --- /dev/null +++ b/index.html @@ -0,0 +1,26 @@ + + + + + Music Player + + + + + + +
+
+

+ + + Shuffle:
+ Repeat: +

+
+
+ +

+
+ + diff --git a/overview.png b/overview.png new file mode 100644 index 0000000..fb80868 Binary files /dev/null and b/overview.png differ diff --git a/player.css b/player.css new file mode 100644 index 0000000..fc60bd5 --- /dev/null +++ b/player.css @@ -0,0 +1,118 @@ +html,body{ + margin:0; + padding:0; +} +body{ + background:#383838; + color:white; + font-size:16px; + font-family:'open sans' sans serif; + font-weight:400; + font-variant:normal; + font-style:normal; + text-align:center; +} +body > div{ + border:1px solid white; + border-radius:5px; + display:inline-block; +} +#player{ + padding:10px; + text-align:right; + margin:10px 0; + width:300px; +} +#player > div{ + width:195px; + display:inline-block; + text-align:right; + float:right; +} +#player #cover{ + width:100px; + height:100px; + background:white; + border-radius:5px; + margin-bottom:5px; + float:left; +} +#player #title{ + margin:0; + display:inline-block; + text-align:center; + width:195px; + word-wrap:break-word; +} +#player #back, +#player #next{ + float:left; + margin:9px 5px 0 0; + font-family:Arial; + height:25px; + width:47px; +} +#player #error{ + margin:0; + font-style:italic; + color:red; + font-size:small; + text-align:center; + display:none; +} +#player #error.open{ + display:block; +} +#player audio{ + width:100%; + max-height:30px; + display:inline-block; + font-size:small; + text-align:center; +} +#playlist{ + min-height:300px; + overflow:auto; + text-align:left; + margin-bottom:6px; + width:320px; +} +#playlist ul{ + list-style:none; + padding-left:0; +} +#playlist > ul{ + margin:9px 0 9px 9px; +} +#playlist > ul ul{ + height:0; + transition: max-height 1s; + overflow:hidden; +} +#playlist li{ + background-repeat:no-repeat; + padding-left:25px; + line-height:25px; +} +#playlist li:hover > ul, +#playlist li.open > ul{ + height:auto; +} +#playlist .folder{ + background-image:url(/icons/folder.png); +} +#playlist .folder.open{ + background-image:url(/icons/folder.open.png); +} +#playlist .song{ + background-image:url(/icons/sound2.png); + cursor:pointer; +} +#playlist li{ + font-style:italic; + color:lime; +} +#playlist li:not(.playing){ + font-style:normal; + color:white; +} diff --git a/player.js b/player.js new file mode 100644 index 0000000..fa22a09 --- /dev/null +++ b/player.js @@ -0,0 +1,198 @@ +var music=Array(), + track,audio,pic,title,shuffle,repeat,err,playlist,offset; +function getId(id){ + return document.getElementById(id); +} +function randInt(min,max){ + var rand=Math.round(Math.random()*(max-min+1)+min); + if(rand==max+1){ + return min; + } + return rand; +} +function sendEvt(element,event){ + evt = document.createEvent("HTMLEvents"); + evt.initEvent(event, true, true ); + return !element.dispatchEvent(evt); +} +function extToMime(ext){ + switch(ext){ + case "mp3":return "audio/mpeg"; + case "ogg":return "audio/ogg"; + case "aac":return "audio/aac"; + case "wav":return "audio/wave"; + default: "audio/"+ext; + } +} +function wait4It(fn){// Dirty trick + try{ + fn(); + } + catch(e){ + setTimeout(function(){ + wait4It(fn); + },7); + } +} +function populateList(arr,e,dir){ + var li,i,x,cover; + for(i in arr){ + if(i!="/"){ + li=document.createElement('li'); + li.className="folder"; + li.textContent=i; + e.appendChild(li); + li.addEventListener('click',function(event){ + event.stopPropagation(); + if(this.className.indexOf("open")==-1){ + this.className="open "+this.className; + } + else{ + this.className=this.className.substr(5); + } + },false); + li.appendChild(document.createElement('ul')) + populateList(arr[i],li.childNodes[1],dir+i+'/'); + } + else{ + cover=false; + for(x in arr[i]){ + if(arr[i][x].slice(0,arr[i][x].lastIndexOf('.')).toLowerCase()=="cover"){ + cover=arr[i][x]; + arr[i].splice(x,1); + break; + } + } + for(x in arr[i]){ + li=document.createElement('li'); + li.id=music.length; + li.className="song"; + li.textContent=arr[i][x].substr(0,arr[i][x].lastIndexOf('.')); + li.setAttribute('file',dir+arr[i][x]); + li.setAttribute('cover',cover?dir+cover:'/icons/sound2.png'); + li.addEventListener('click',function(event){ + event.stopPropagation(); + var file=this.getAttribute('file'), + cover=this.getAttribute('cover'), + s=document.createElement('source'), + mime=extToMime(file.substr(-3)), + last=music[track]; + if(last.className.indexOf('playing')>-1){ + while(last.id!='playlist'){ + last.className=last.className.slice(0,-8); + last=last.parentNode.parentNode; + } + } + pic.src=cover; + title.textContent=this.textContent; + if(!audio.canPlayType(mime)){ + err.textContent="This browser does not support "+mime.substr(mime.indexOf('/')+1).toUpperCase()+" audio." + err.className='open'; + } + else{ + err.removeAttribute('class'); + } + s.type=mime; + s.src=file; + audio.appendChild(s); + if(audio.childNodes.length>1){ + audio.removeChild(audio.childNodes[0]); + } + audio.load(); + audio.play(); + track=parseInt(this.id); + last=music[track]; + while(last.id!='playlist'){ + last.className+=' playing'; + last=last.parentNode.parentNode; + } + },false); + e.appendChild(li); + music.push(li); + } + } + } +} +function init(){ + var ul=document.createElement('ul'), + config=localStorage.getItem("config"); + audio=getId('audio'); + title=getId('title'); + pic=getId('cover'); + shuffle=getId('shuffle'); + repeat=getId('repeat'); + err=getId('error'); + offset=getId('player').offsetHeight+32; + playlist=getId('playlist'); + playlist.appendChild(ul); + populateList(libary,ul,'library/');// Folder containing music + config=config!=null?JSON.parse(config):{// Default player settings + "volume":.25, + "track":0, + "state":false, + "time":0, + "shuffle":true, + "repeat":false + }; + audio.addEventListener("ended",function(){ + var next=track; + if(!repeat.checked){ + if(shuffle.checked){ + next=randInt(0,music.length-1); + } + else if(track+1 < music.length){ + next++; + } + else{ + next=0; + } + } + + sendEvt(music[next],'click'); + },false); + getId('next').addEventListener("click",function(){ + if(track==music.length-1){ + track=-1; + } + sendEvt(music[track+1],'click'); + },false); + getId('back').addEventListener("click",function(){ + if(track==0){ + track=music.length; + } + sendEvt(music[track-1],'click'); + },false); + shuffle.checked=config["shuffle"]; + repeat.checked=config["repeat"]; + track=config["track"]; + if(config['time']==0&&track==0){ + sendEvt(audio,'ended'); + } + else{ + sendEvt(music[track],'click'); + audio.pause(); + wait4It(function(){ + audio.currentTime=config["time"]; + if(config["state"]===false){ + audio.play(); + } + }); + } + audio.volume=config["volume"]; + window.onunload=function(){ + if( isNaN(track) || isNaN(audio.currentTime) || isNaN(audio.volume) ){ + return; + } + localStorage.setItem("config",JSON.stringify({ + "volume":audio.volume, + "track":track, + "state":audio.paused===true, + "time":audio.currentTime, + "shuffle":shuffle.checked===true, + "repeat":repeat.checked===true + })); + } +} +window.onresize=function(){ + playlist.style.maxHeight=window.innerHeight-offset+'px'; +} diff --git a/playlist.php b/playlist.php new file mode 100644 index 0000000..8028d99 --- /dev/null +++ b/playlist.php @@ -0,0 +1,29 @@ + +var libary={$f}=tree("$dir/$f",$depth+1); + } + else{ + $json->{$f}=array("Error: Too Deep"=>array("Infinite loop prevention"=>array())); + } + } + else{ + array_push($files,$f); + } + } + if(count($files)>0){ + $json->{"/"}=$files; + } + return $json; + } + echo json_encode(tree('library',0)); +?>