initial commit
This commit is contained in:
34
src/build.sh
Normal file
34
src/build.sh
Normal file
@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
# MyPlayer - Copyright 2014 tilt@linuxfoo.de GPLv3
|
||||
# Build Script; recompiles the MyPlayer JavaScript from source.
|
||||
|
||||
cd $(dirname $0)
|
||||
|
||||
echo '/*
|
||||
jQuery
|
||||
Copyright 2014 jQuery Foundation and other contributors
|
||||
http://jquery.com/
|
||||
MediaElement.js
|
||||
Copyright 2010-2013, John Dyer (http://j.hn)
|
||||
MediaElement Playlist Feature (plugin) -
|
||||
Andrew Berezovsky <andrew.berezovsky@gmail.com>
|
||||
and Junaid Qadir Baloch <shekhanzai.baloch@gmail.com>
|
||||
JavaScript-ID3-Reader
|
||||
Copyright (c) 2008 Jacob Seidelin, http://blog.nihilogic.dk/ BSD License
|
||||
Copyright (c) 2009 Opera Software ASA BSD License
|
||||
Copyright (c) 2010 António Afonso BSD License
|
||||
Copyright (c) 2010 Joshua Kifer BSD License
|
||||
MyPlayer
|
||||
Copyright (c) 2014 tilt@linuxfoo.de MIT License
|
||||
*/' > ../js/myplayer.min.js
|
||||
|
||||
# https://developers.google.com/closure/compiler/
|
||||
java \
|
||||
-jar /usr/local/lib/closure-compiler/compiler.jar \
|
||||
--js mediaelement-and-player.min.js \
|
||||
--js mep-feature-playlist.js \
|
||||
--js id3-minimized.js \
|
||||
--js player.js \
|
||||
>> ../js/myplayer.min.js
|
||||
|
||||
echo "Done: Javascript source has compiled into ../js/myplayer.min.js"
|
23
src/id3-minimized.js
Normal file
23
src/id3-minimized.js
Normal file
@ -0,0 +1,23 @@
|
||||
function A(h,g,b){var e=g||0,c=0;"string"==typeof h?(c=b||h.length,this.a=function(a){return h.charCodeAt(a+e)&255}):"unknown"==typeof h&&(c=b||IEBinary_getLength(h),this.a=function(a){return IEBinary_getByteAt(h,a+e)});this.l=function(a,f){for(var v=Array(f),b=0;b<f;b++)v[b]=this.a(a+b);return v};this.h=function(){return c};this.d=function(a,f){return 0!=(this.a(a)&1<<f)};this.w=function(a){a=(this.a(a+1)<<8)+this.a(a);0>a&&(a+=65536);return a};this.i=function(a){var f=this.a(a),b=this.a(a+1),c=
|
||||
this.a(a+2);a=this.a(a+3);f=(((f<<8)+b<<8)+c<<8)+a;0>f&&(f+=4294967296);return f};this.o=function(a){var f=this.a(a),b=this.a(a+1);a=this.a(a+2);f=((f<<8)+b<<8)+a;0>f&&(f+=16777216);return f};this.c=function(a,f){for(var b=[],c=a,d=0;c<a+f;c++,d++)b[d]=String.fromCharCode(this.a(c));return b.join("")};this.e=function(a,b,c){a=this.l(a,b);switch(c.toLowerCase()){case "utf-16":case "utf-16le":case "utf-16be":b=c;var k,d=0,e=1;c=0;k=Math.min(k||a.length,a.length);254==a[0]&&255==a[1]?(b=!0,d=2):255==
|
||||
a[0]&&254==a[1]&&(b=!1,d=2);b&&(e=0,c=1);b=[];for(var m=0;d<k;m++){var g=a[d+e],l=(g<<8)+a[d+c],d=d+2;if(0==l)break;else 216>g||224<=g?b[m]=String.fromCharCode(l):(g=(a[d+e]<<8)+a[d+c],d+=2,b[m]=String.fromCharCode(l,g))}a=new String(b.join(""));a.g=d;break;case "utf-8":k=0;d=Math.min(d||a.length,a.length);239==a[0]&&187==a[1]&&191==a[2]&&(k=3);e=[];for(c=0;k<d&&(b=a[k++],0!=b);c++)128>b?e[c]=String.fromCharCode(b):194<=b&&224>b?(m=a[k++],e[c]=String.fromCharCode(((b&31)<<6)+(m&63))):224<=b&&240>
|
||||
b?(m=a[k++],l=a[k++],e[c]=String.fromCharCode(((b&255)<<12)+((m&63)<<6)+(l&63))):240<=b&&245>b&&(m=a[k++],l=a[k++],g=a[k++],b=((b&7)<<18)+((m&63)<<12)+((l&63)<<6)+(g&63)-65536,e[c]=String.fromCharCode((b>>10)+55296,(b&1023)+56320));a=new String(e.join(""));a.g=k;break;default:d=[];e=e||a.length;for(k=0;k<e;){c=a[k++];if(0==c)break;d[k-1]=String.fromCharCode(c)}a=new String(d.join(""));a.g=k}return a};this.f=function(a,b){b()}}document.write("<script type='text/vbscript'>\r\nFunction IEBinary_getByteAt(strBinary, iOffset)\r\n\tIEBinary_getByteAt = AscB(MidB(strBinary,iOffset+1,1))\r\nEnd Function\r\nFunction IEBinary_getLength(strBinary)\r\n\tIEBinary_getLength = LenB(strBinary)\r\nEnd Function\r\n\x3c/script>\r\n");function B(h,g,b){function e(a,b,d,e,f,g){var l=c();l?("undefined"===typeof g&&(g=!0),b&&("undefined"!=typeof l.onload?l.onload=function(){"200"==l.status||"206"==l.status?(l.fileSize=f||l.getResponseHeader("Content-Length"),b(l)):d&&d();l=null}:l.onreadystatechange=function(){4==l.readyState&&("200"==l.status||"206"==l.status?(l.fileSize=f||l.getResponseHeader("Content-Length"),b(l)):d&&d(),l=null)}),l.open("GET",a,g),l.overrideMimeType&&l.overrideMimeType("text/plain; charset=x-user-defined"),e&&
|
||||
l.setRequestHeader("Range","bytes="+e[0]+"-"+e[1]),l.setRequestHeader("If-Modified-Since","Sat, 1 Jan 1970 00:00:00 GMT"),l.send(null)):d&&d()}function c(){var a=null;window.XMLHttpRequest?a=new XMLHttpRequest:window.ActiveXObject&&(a=new ActiveXObject("Microsoft.XMLHTTP"));return a}function a(a,b){var d=c();d&&(b&&("undefined"!=typeof d.onload?d.onload=function(){"200"==d.status&&b(this);d=null}:d.onreadystatechange=function(){4==d.readyState&&("200"==d.status&&b(this),d=null)}),d.open("HEAD",a,
|
||||
!0),d.send(null))}function f(a,c){var d,f;function g(a){var b=~~(a[0]/d)-f;a=~~(a[1]/d)+1+f;0>b&&(b=0);a>=blockTotal&&(a=blockTotal-1);return[b,a]}function h(f,g){for(;n[f[0]];)if(f[0]++,f[0]>f[1]){g&&g();return}for(;n[f[1]];)if(f[1]--,f[0]>f[1]){g&&g();return}var m=[f[0]*d,(f[1]+1)*d-1];e(a,function(a){parseInt(a.getResponseHeader("Content-Length"),10)==c&&(f[0]=0,f[1]=blockTotal-1,m[0]=0,m[1]=c-1);a={data:a.N||a.responseText,offset:m[0]};for(var b=f[0];b<=f[1];b++)n[b]=a;g&&g()},b,m,l,!!g)}var l,
|
||||
r=new A("",0,c),n=[];d=d||2048;f="undefined"===typeof f?0:f;blockTotal=~~((c-1)/d)+1;for(var q in r)r.hasOwnProperty(q)&&"function"===typeof r[q]&&(this[q]=r[q]);this.a=function(a){var b;h(g([a,a]));b=n[~~(a/d)];if("string"==typeof b.data)return b.data.charCodeAt(a-b.offset)&255;if("unknown"==typeof b.data)return IEBinary_getByteAt(b.data,a-b.offset)};this.f=function(a,b){h(g(a),b)}}(function(){a(h,function(a){a=parseInt(a.getResponseHeader("Content-Length"),10)||-1;g(new f(h,a))})})()};(function(h){h.FileAPIReader=function(g,b){return function(e,c){var a=b||new FileReader;a.onload=function(a){c(new A(a.target.result))};a.readAsBinaryString(g)}}})(this);(function(h){var g=h.p={},b={},e=[0,7];g.t=function(c){delete b[c]};g.s=function(){b={}};g.B=function(c,a,f){f=f||{};(f.dataReader||B)(c,function(g){g.f(e,function(){var e="ftypM4A"==g.c(4,7)?ID4:"ID3"==g.c(0,3)?ID3v2:ID3v1;e.m(g,function(){var d=f.tags,h=e.n(g,d),d=b[c]||{},m;for(m in h)h.hasOwnProperty(m)&&(d[m]=h[m]);b[c]=d;a&&a()})})})};g.v=function(c){if(!b[c])return null;var a={},f;for(f in b[c])b[c].hasOwnProperty(f)&&(a[f]=b[c][f]);return a};g.A=function(c,a){return b[c]?b[c][a]:null};h.ID3=
|
||||
h.p;g.loadTags=g.B;g.getAllTags=g.v;g.getTag=g.A;g.clearTags=g.t;g.clearAll=g.s})(this);(function(h){var g=h.q={},b="Blues;Classic Rock;Country;Dance;Disco;Funk;Grunge;Hip-Hop;Jazz;Metal;New Age;Oldies;Other;Pop;R&B;Rap;Reggae;Rock;Techno;Industrial;Alternative;Ska;Death Metal;Pranks;Soundtrack;Euro-Techno;Ambient;Trip-Hop;Vocal;Jazz+Funk;Fusion;Trance;Classical;Instrumental;Acid;House;Game;Sound Clip;Gospel;Noise;AlternRock;Bass;Soul;Punk;Space;Meditative;Instrumental Pop;Instrumental Rock;Ethnic;Gothic;Darkwave;Techno-Industrial;Electronic;Pop-Folk;Eurodance;Dream;Southern Rock;Comedy;Cult;Gangsta;Top 40;Christian Rap;Pop/Funk;Jungle;Native American;Cabaret;New Wave;Psychadelic;Rave;Showtunes;Trailer;Lo-Fi;Tribal;Acid Punk;Acid Jazz;Polka;Retro;Musical;Rock & Roll;Hard Rock;Folk;Folk-Rock;National Folk;Swing;Fast Fusion;Bebob;Latin;Revival;Celtic;Bluegrass;Avantgarde;Gothic Rock;Progressive Rock;Psychedelic Rock;Symphonic Rock;Slow Rock;Big Band;Chorus;Easy Listening;Acoustic;Humour;Speech;Chanson;Opera;Chamber Music;Sonata;Symphony;Booty Bass;Primus;Porn Groove;Satire;Slow Jam;Club;Tango;Samba;Folklore;Ballad;Power Ballad;Rhythmic Soul;Freestyle;Duet;Punk Rock;Drum Solo;Acapella;Euro-House;Dance Hall".split(";");
|
||||
g.m=function(b,c){var a=b.h();b.f([a-128-1,a],c)};g.n=function(e){var c=e.h()-128;if("TAG"==e.c(c,3)){var a=e.c(c+3,30).replace(/\0/g,""),f=e.c(c+33,30).replace(/\0/g,""),g=e.c(c+63,30).replace(/\0/g,""),k=e.c(c+93,4).replace(/\0/g,"");if(0==e.a(c+97+28))var d=e.c(c+97,28).replace(/\0/g,""),h=e.a(c+97+29);else d="",h=0;e=e.a(c+97+30);return{version:"1.1",title:a,artist:f,album:g,year:k,comment:d,track:h,genre:255>e?b[e]:""}}return{}};h.ID3v1=h.q})(this);(function(h){function g(a,b){var c=b.a(a),e=b.a(a+1),d=b.a(a+2);return b.a(a+3)&127|(d&127)<<7|(e&127)<<14|(c&127)<<21}var b=h.D={};b.b={};b.frames={BUF:"Recommended buffer size",CNT:"Play counter",COM:"Comments",CRA:"Audio encryption",CRM:"Encrypted meta frame",ETC:"Event timing codes",EQU:"Equalization",GEO:"General encapsulated object",IPL:"Involved people list",LNK:"Linked information",MCI:"Music CD Identifier",MLL:"MPEG location lookup table",PIC:"Attached picture",POP:"Popularimeter",REV:"Reverb",
|
||||
RVA:"Relative volume adjustment",SLT:"Synchronized lyric/text",STC:"Synced tempo codes",TAL:"Album/Movie/Show title",TBP:"BPM (Beats Per Minute)",TCM:"Composer",TCO:"Content type",TCR:"Copyright message",TDA:"Date",TDY:"Playlist delay",TEN:"Encoded by",TFT:"File type",TIM:"Time",TKE:"Initial key",TLA:"Language(s)",TLE:"Length",TMT:"Media type",TOA:"Original artist(s)/performer(s)",TOF:"Original filename",TOL:"Original Lyricist(s)/text writer(s)",TOR:"Original release year",TOT:"Original album/Movie/Show title",
|
||||
TP1:"Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group",TP2:"Band/Orchestra/Accompaniment",TP3:"Conductor/Performer refinement",TP4:"Interpreted, remixed, or otherwise modified by",TPA:"Part of a set",TPB:"Publisher",TRC:"ISRC (International Standard Recording Code)",TRD:"Recording dates",TRK:"Track number/Position in set",TSI:"Size",TSS:"Software/hardware and settings used for encoding",TT1:"Content group description",TT2:"Title/Songname/Content description",TT3:"Subtitle/Description refinement",
|
||||
TXT:"Lyricist/text writer",TXX:"User defined text information frame",TYE:"Year",UFI:"Unique file identifier",ULT:"Unsychronized lyric/text transcription",WAF:"Official audio file webpage",WAR:"Official artist/performer webpage",WAS:"Official audio source webpage",WCM:"Commercial information",WCP:"Copyright/Legal information",WPB:"Publishers official webpage",WXX:"User defined URL link frame",AENC:"Audio encryption",APIC:"Attached picture",COMM:"Comments",COMR:"Commercial frame",ENCR:"Encryption method registration",
|
||||
EQUA:"Equalization",ETCO:"Event timing codes",GEOB:"General encapsulated object",GRID:"Group identification registration",IPLS:"Involved people list",LINK:"Linked information",MCDI:"Music CD identifier",MLLT:"MPEG location lookup table",OWNE:"Ownership frame",PRIV:"Private frame",PCNT:"Play counter",POPM:"Popularimeter",POSS:"Position synchronisation frame",RBUF:"Recommended buffer size",RVAD:"Relative volume adjustment",RVRB:"Reverb",SYLT:"Synchronized lyric/text",SYTC:"Synchronized tempo codes",
|
||||
TALB:"Album/Movie/Show title",TBPM:"BPM (beats per minute)",TCOM:"Composer",TCON:"Content type",TCOP:"Copyright message",TDAT:"Date",TDLY:"Playlist delay",TENC:"Encoded by",TEXT:"Lyricist/Text writer",TFLT:"File type",TIME:"Time",TIT1:"Content group description",TIT2:"Title/songname/content description",TIT3:"Subtitle/Description refinement",TKEY:"Initial key",TLAN:"Language(s)",TLEN:"Length",TMED:"Media type",TOAL:"Original album/movie/show title",TOFN:"Original filename",TOLY:"Original lyricist(s)/text writer(s)",
|
||||
TOPE:"Original artist(s)/performer(s)",TORY:"Original release year",TOWN:"File owner/licensee",TPE1:"Lead performer(s)/Soloist(s)",TPE2:"Band/orchestra/accompaniment",TPE3:"Conductor/performer refinement",TPE4:"Interpreted, remixed, or otherwise modified by",TPOS:"Part of a set",TPUB:"Publisher",TRCK:"Track number/Position in set",TRDA:"Recording dates",TRSN:"Internet radio station name",TRSO:"Internet radio station owner",TSIZ:"Size",TSRC:"ISRC (international standard recording code)",TSSE:"Software/Hardware and settings used for encoding",
|
||||
TYER:"Year",TXXX:"User defined text information frame",UFID:"Unique file identifier",USER:"Terms of use",USLT:"Unsychronized lyric/text transcription",WCOM:"Commercial information",WCOP:"Copyright/Legal information",WOAF:"Official audio file webpage",WOAR:"Official artist/performer webpage",WOAS:"Official audio source webpage",WORS:"Official internet radio station homepage",WPAY:"Payment",WPUB:"Publishers official webpage",WXXX:"User defined URL link frame"};var e={title:["TIT2","TT2"],artist:["TPE1",
|
||||
"TP1"],album:["TALB","TAL"],year:["TYER","TYE"],comment:["COMM","COM"],track:["TRCK","TRK"],genre:["TCON","TCO"],picture:["APIC","PIC"],lyrics:["USLT","ULT"]},c=["title","artist","album","track"];b.m=function(a,b){a.f([0,g(6,a)],b)};b.n=function(a,f){var h=0,k=a.a(h+3);if(4<k)return{version:">2.4"};var d=a.a(h+4),t=a.d(h+5,7),m=a.d(h+5,6),u=a.d(h+5,5),l=g(h+6,a),h=h+10;if(m)var r=a.i(h),h=h+(r+4);var k={version:"2."+k+"."+d,major:k,revision:d,flags:{unsynchronisation:t,extended_header:m,experimental_indicator:u},
|
||||
size:l},n;if(t)n={};else{for(var l=l-10,t=a,d=f,m={},u=k.major,r=[],q=0,p;p=(d||c)[q];q++)r=r.concat(e[p]||[p]);for(d=r;h<l;){r=null;q=t;p=h;var x=null;switch(u){case 2:n=q.c(p,3);var s=q.o(p+3),w=6;break;case 3:n=q.c(p,4);s=q.i(p+4);w=10;break;case 4:n=q.c(p,4),s=g(p+4,q),w=10}if(""==n)break;h+=w+s;0>d.indexOf(n)||(2<u&&(x={message:{P:q.d(p+8,6),I:q.d(p+8,5),M:q.d(p+8,4)},k:{K:q.d(p+8+1,7),F:q.d(p+8+1,3),H:q.d(p+8+1,2),C:q.d(p+8+1,1),u:q.d(p+8+1,0)}}),p+=w,x&&x.k.u&&(g(p,q),p+=4,s-=4),x&&x.k.C||
|
||||
(n in b.b?r=b.b[n]:"T"==n[0]&&(r=b.b["T*"]),r=r?r(p,s,q,x):void 0,r={id:n,size:s,description:n in b.frames?b.frames[n]:"Unknown",data:r},n in m?(m[n].id&&(m[n]=[m[n]]),m[n].push(r)):m[n]=r))}n=m}for(var y in e)if(e.hasOwnProperty(y)){a:{s=e[y];"string"==typeof s&&(s=[s]);w=0;for(h=void 0;h=s[w];w++)if(h in n){a=n[h].data;break a}a=void 0}a&&(k[y]=a)}for(var z in n)n.hasOwnProperty(z)&&(k[z]=n[z]);return k};h.ID3v2=b})(this);(function(){function h(b){var e;switch(b){case 0:e="iso-8859-1";break;case 1:e="utf-16";break;case 2:e="utf-16be";break;case 3:e="utf-8"}return e}var g="32x32 pixels 'file icon' (PNG only);Other file icon;Cover (front);Cover (back);Leaflet page;Media (e.g. lable side of CD);Lead artist/lead performer/soloist;Artist/performer;Conductor;Band/Orchestra;Composer;Lyricist/text writer;Recording Location;During recording;During performance;Movie/video screen capture;A bright coloured fish;Illustration;Band/artist logotype;Publisher/Studio logotype".split(";");
|
||||
ID3v2.b.APIC=function(b,e,c,a,f){f=f||"3";a=b;var v=h(c.a(b));switch(f){case "2":var k=c.c(b+1,3);b+=4;break;case "3":case "4":k=c.e(b+1,e-(b-a),v),b+=1+k.g}f=c.a(b,1);f=g[f];v=c.e(b+1,e-(b-a),v);b+=1+v.g;return{format:k.toString(),type:f,description:v.toString(),data:c.l(b,a+e-b)}};ID3v2.b.COMM=function(b,e,c){var a=b,f=h(c.a(b)),g=c.c(b+1,3),k=c.e(b+4,e-4,f);b+=4+k.g;b=c.e(b,a+e-b,f);return{language:g,O:k.toString(),text:b.toString()}};ID3v2.b.COM=ID3v2.b.COMM;ID3v2.b.PIC=function(b,e,c,a){return ID3v2.b.APIC(b,
|
||||
e,c,a,"2")};ID3v2.b.PCNT=function(b,e,c){return c.J(b)};ID3v2.b.CNT=ID3v2.b.PCNT;ID3v2.b["T*"]=function(b,e,c){var a=h(c.a(b));return c.e(b+1,e-1,a).toString()};ID3v2.b.TCON=function(b,e,c){return ID3v2.b["T*"].apply(this,arguments).replace(/^\(\d+\)/,"")};ID3v2.b.TCO=ID3v2.b.TCON;ID3v2.b.USLT=function(b,e,c){var a=b,f=h(c.a(b)),g=c.c(b+1,3),k=c.e(b+4,e-4,f);b+=4+k.g;b=c.e(b,a+e-b,f);return{language:g,G:k.toString(),L:b.toString()}};ID3v2.b.ULT=ID3v2.b.USLT})();(function(h){function g(b,a,f,h){var k=b.i(a);if(0==k)h();else{var d=b.c(a+4,4);-1<["moov","udta","meta","ilst"].indexOf(d)?("meta"==d&&(a+=4),b.f([a+8,a+8+8],function(){g(b,a+8,k-8,h)})):b.f([a+(d in e.j?0:k),a+k+8],function(){g(b,a+k,f,h)})}}function b(c,a,f,g,h){h=void 0===h?"":h+" ";for(var d=f;d<f+g;){var t=a.i(d);if(0==t)break;var m=a.c(d+4,4);if(-1<["moov","udta","meta","ilst"].indexOf(m)){"meta"==m&&(d+=4);b(c,a,d+8,t-8,h);break}if(e.j[m]){var u=a.o(d+16+1),l=e.j[m],u=e.types[u];if("trkn"==
|
||||
m)c[l[0]]=a.a(d+16+11),c.count=a.a(d+16+13);else{var m=d+16+4+4,r=t-16-4-4,n;switch(u){case "text":n=a.e(m,r,"UTF-8");break;case "uint8":n=a.w(m);break;case "jpeg":case "png":n={k:"image/"+u,data:a.l(m,r)}}c[l[0]]="comment"===l[0]?{text:n}:n}}d+=t}}var e=h.r={};e.types={0:"uint8",1:"text",13:"jpeg",14:"png",21:"uint8"};e.j={"\u00a9alb":["album"],"\u00a9art":["artist"],"\u00a9ART":["artist"],aART:["artist"],"\u00a9day":["year"],"\u00a9nam":["title"],"\u00a9gen":["genre"],trkn:["track"],"\u00a9wrt":["composer"],
|
||||
"\u00a9too":["encoder"],cprt:["copyright"],covr:["picture"],"\u00a9grp":["grouping"],keyw:["keyword"],"\u00a9lyr":["lyrics"],"\u00a9cmt":["comment"],tmpo:["tempo"],cpil:["compilation"],disk:["disc"]};e.m=function(b,a){b.f([0,7],function(){g(b,0,b.h(),a)})};e.n=function(c){var a={};b(a,c,0,c.h());return a};h.ID4=h.r})(this);
|
28
src/mediaelement-and-player.min.js
vendored
Normal file
28
src/mediaelement-and-player.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
268
src/mep-feature-playlist.js
Normal file
268
src/mep-feature-playlist.js
Normal file
@ -0,0 +1,268 @@
|
||||
/**
|
||||
* @file MediaElement Playlist Feature (plugin).
|
||||
* @author Andrew Berezovsky <andrew.berezovsky@gmail.com>
|
||||
* Twitter handle: duozersk
|
||||
* @author Original author: Junaid Qadir Baloch <shekhanzai.baloch@gmail.com>
|
||||
* Twitter handle: jeykeu
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
$.extend(mejs.MepDefaults, {
|
||||
loopText: 'Repeat On/Off',
|
||||
shuffleText: 'Shuffle On/Off',
|
||||
nextText: 'Next Track',
|
||||
prevText: 'Previous Track',
|
||||
playlistText: 'Show/Hide Playlist'
|
||||
});
|
||||
|
||||
$.extend(MediaElementPlayer.prototype, {
|
||||
// LOOP TOGGLE
|
||||
buildloop: function(player, controls, layers, media) {
|
||||
var t = this;
|
||||
|
||||
var loop = $('<div class="mejs-button mejs-loop-button ' + ((player.options.loop) ? 'mejs-loop-on' : 'mejs-loop-off') + '">' +
|
||||
'<button type="button" aria-controls="' + player.id + '" title="' + player.options.loopText + '"></button>' +
|
||||
'</div>')
|
||||
// append it to the toolbar
|
||||
.appendTo(controls)
|
||||
// add a click toggle event
|
||||
.click(function(e) {
|
||||
player.options.loop = !player.options.loop;
|
||||
$(media).trigger('mep-looptoggle', [player.options.loop]);
|
||||
if (player.options.loop) {
|
||||
loop.removeClass('mejs-loop-off').addClass('mejs-loop-on');
|
||||
//media.setAttribute('loop', 'loop');
|
||||
}
|
||||
else {
|
||||
loop.removeClass('mejs-loop-on').addClass('mejs-loop-off');
|
||||
//media.removeAttribute('loop');
|
||||
}
|
||||
});
|
||||
|
||||
t.loopToggle = t.controls.find('.mejs-loop-button');
|
||||
},
|
||||
loopToggleClick: function() {
|
||||
var t = this;
|
||||
t.loopToggle.trigger('click');
|
||||
},
|
||||
// SHUFFLE TOGGLE
|
||||
buildshuffle: function(player, controls, layers, media) {
|
||||
var t = this;
|
||||
|
||||
var shuffle = $('<div class="mejs-button mejs-shuffle-button ' + ((player.options.shuffle) ? 'mejs-shuffle-on' : 'mejs-shuffle-off') + '">' +
|
||||
'<button type="button" aria-controls="' + player.id + '" title="' + player.options.shuffleText + '"></button>' +
|
||||
'</div>')
|
||||
// append it to the toolbar
|
||||
.appendTo(controls)
|
||||
// add a click toggle event
|
||||
.click(function(e) {
|
||||
player.options.shuffle = !player.options.shuffle;
|
||||
$(media).trigger('mep-shuffletoggle', [player.options.shuffle]);
|
||||
if (player.options.shuffle) {
|
||||
shuffle.removeClass('mejs-shuffle-off').addClass('mejs-shuffle-on');
|
||||
}
|
||||
else {
|
||||
shuffle.removeClass('mejs-shuffle-on').addClass('mejs-shuffle-off');
|
||||
}
|
||||
});
|
||||
|
||||
t.shuffleToggle = t.controls.find('.mejs-shuffle-button');
|
||||
},
|
||||
shuffleToggleClick: function() {
|
||||
var t = this;
|
||||
t.shuffleToggle.trigger('click');
|
||||
},
|
||||
// PREVIOUS TRACK BUTTON
|
||||
buildprevtrack: function(player, controls, layers, media) {
|
||||
var t = this;
|
||||
|
||||
var prevTrack = $('<div class="mejs-button mejs-prevtrack-button mejs-prevtrack">' +
|
||||
'<button type="button" aria-controls="' + player.id + '" title="' + player.options.prevText + '"></button>' +
|
||||
'</div>')
|
||||
.appendTo(controls)
|
||||
.click(function(e){
|
||||
$(media).trigger('mep-playprevtrack');
|
||||
player.playPrevTrack();
|
||||
});
|
||||
|
||||
t.prevTrack = t.controls.find('.mejs-prevtrack-button');
|
||||
},
|
||||
prevTrackClick: function() {
|
||||
var t = this;
|
||||
t.prevTrack.trigger('click');
|
||||
},
|
||||
// NEXT TRACK BUTTON
|
||||
buildnexttrack: function(player, controls, layers, media) {
|
||||
var t = this;
|
||||
|
||||
var nextTrack = $('<div class="mejs-button mejs-nexttrack-button mejs-nexttrack">' +
|
||||
'<button type="button" aria-controls="' + player.id + '" title="' + player.options.nextText + '"></button>' +
|
||||
'</div>')
|
||||
.appendTo(controls)
|
||||
.click(function(e){
|
||||
$(media).trigger('mep-playnexttrack');
|
||||
player.playNextTrack();
|
||||
});
|
||||
|
||||
t.nextTrack = t.controls.find('.mejs-nexttrack-button');
|
||||
},
|
||||
nextTrackClick: function() {
|
||||
var t = this;
|
||||
t.nextTrack.trigger('click');
|
||||
},
|
||||
// PLAYLIST TOGGLE
|
||||
buildplaylist: function(player, controls, layers, media) {
|
||||
var t = this;
|
||||
|
||||
var playlistToggle = $('<div class="mejs-button mejs-playlist-button ' + ((player.options.playlist) ? 'mejs-hide-playlist' : 'mejs-show-playlist') + '">' +
|
||||
'<button type="button" aria-controls="' + player.id + '" title="' + player.options.playlistText + '"></button>' +
|
||||
'</div>')
|
||||
.appendTo(controls)
|
||||
.click(function(e) {
|
||||
player.options.playlist = !player.options.playlist;
|
||||
$(media).trigger('mep-playlisttoggle', [player.options.playlist]);
|
||||
if (player.options.playlist) {
|
||||
layers.children('.mejs-playlist').show();
|
||||
playlistToggle.removeClass('mejs-show-playlist').addClass('mejs-hide-playlist');
|
||||
}
|
||||
else {
|
||||
layers.children('.mejs-playlist').hide();
|
||||
playlistToggle.removeClass('mejs-hide-playlist').addClass('mejs-show-playlist');
|
||||
}
|
||||
});
|
||||
|
||||
t.playlistToggle = t.controls.find('.mejs-playlist-button');
|
||||
},
|
||||
playlistToggleClick: function() {
|
||||
var t = this;
|
||||
t.playlistToggle.trigger('click');
|
||||
},
|
||||
// PLAYLIST WINDOW
|
||||
buildplaylistfeature: function(player, controls, layers, media) {
|
||||
var playlist = $('<div class="mejs-playlist mejs-layer">' +
|
||||
'<ul class="mejs"></ul>' +
|
||||
'</div>')
|
||||
.appendTo(layers);
|
||||
if (!player.options.playlist) {
|
||||
playlist.hide();
|
||||
}
|
||||
if (player.options.playlistposition == 'bottom') {
|
||||
playlist.css('top', player.options.audioHeight + 'px');
|
||||
}
|
||||
else {
|
||||
playlist.css('bottom', player.options.audioHeight + 'px');
|
||||
}
|
||||
var getTrackName = function(trackUrl) {
|
||||
var trackUrlParts = trackUrl.split("/");
|
||||
if (trackUrlParts.length > 0) {
|
||||
return decodeURIComponent(trackUrlParts[trackUrlParts.length-1]);
|
||||
}
|
||||
else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
// calculate tracks and build playlist
|
||||
var tracks = [];
|
||||
//$(media).children('source').each(function(index, element) { // doesn't work in Opera 12.12
|
||||
$('#'+player.id).find('.mejs-mediaelement source').each(function(index, element) {
|
||||
if ($.trim(this.src) != '') {
|
||||
var track = {};
|
||||
track.source = $.trim(this.src);
|
||||
if ($.trim(this.title) != '') {
|
||||
track.name = $.trim(this.title);
|
||||
}
|
||||
else {
|
||||
track.name = getTrackName(track.source);
|
||||
}
|
||||
tracks.push(track);
|
||||
}
|
||||
});
|
||||
for (var track in tracks) {
|
||||
layers.find('.mejs-playlist > ul').append('<li data-url="' + tracks[track].source + '" title="' + tracks[track].name + '">' + tracks[track].name + '</li>');
|
||||
}
|
||||
|
||||
// set the first track as current
|
||||
layers.find('li:first').addClass('current played');
|
||||
// play track from playlist when clicking it
|
||||
layers.find('.mejs-playlist > ul li').click(function(e) {
|
||||
if (!$(this).hasClass('current')) {
|
||||
$(this).addClass('played');
|
||||
player.playTrack($(this));
|
||||
}
|
||||
else {
|
||||
player.play();
|
||||
}
|
||||
});
|
||||
|
||||
// when current track ends - play the next one
|
||||
media.addEventListener('ended', function(e) {
|
||||
player.playNextTrack();
|
||||
}, false);
|
||||
},
|
||||
playNextTrack: function() {
|
||||
var t = this;
|
||||
var tracks = t.layers.find('.mejs-playlist > ul > li');
|
||||
var current = tracks.filter('.current');
|
||||
var notplayed = tracks.not('.played');
|
||||
if (notplayed.length < 1) {
|
||||
current.removeClass('played').siblings().removeClass('played');
|
||||
notplayed = tracks.not('.current');
|
||||
}
|
||||
if (t.options.shuffle) {
|
||||
var random = Math.floor(Math.random()*notplayed.length);
|
||||
var nxt = notplayed.eq(random);
|
||||
}
|
||||
else {
|
||||
var nxt = current.next();
|
||||
if (nxt.length < 1 && t.options.loop) {
|
||||
nxt = current.siblings().first();
|
||||
}
|
||||
}
|
||||
if (nxt.length == 1) {
|
||||
nxt.addClass('played');
|
||||
t.playTrack(nxt);
|
||||
}
|
||||
},
|
||||
playPrevTrack: function() {
|
||||
var t = this;
|
||||
var tracks = t.layers.find('.mejs-playlist > ul > li');
|
||||
var current = tracks.filter('.current');
|
||||
var played = tracks.filter('.played').not('.current');
|
||||
if (played.length < 1) {
|
||||
current.removeClass('played');
|
||||
played = tracks.not('.current');
|
||||
}
|
||||
if (t.options.shuffle) {
|
||||
var random = Math.floor(Math.random()*played.length);
|
||||
var prev = played.eq(random);
|
||||
}
|
||||
else {
|
||||
var prev = current.prev();
|
||||
if (prev.length < 1 && t.options.loop) {
|
||||
prev = current.siblings().last();
|
||||
}
|
||||
}
|
||||
if (prev.length == 1) {
|
||||
current.removeClass('played');
|
||||
t.playTrack(prev);
|
||||
}
|
||||
},
|
||||
playTrack: function(track) {
|
||||
var t = this;
|
||||
t.pause();
|
||||
t.setSrc(track.attr('data-url'));
|
||||
t.load();
|
||||
t.play();
|
||||
track.addClass('current').siblings().removeClass('current');
|
||||
},
|
||||
playTrackURL: function(url) {
|
||||
var t = this;
|
||||
var tracks = t.layers.find('.mejs-playlist > ul > li');
|
||||
var track = tracks.filter('[data-url="'+url+'"]');
|
||||
t.playTrack(track);
|
||||
}
|
||||
});
|
||||
|
||||
})(mejs.$);
|
332
src/player.js
Normal file
332
src/player.js
Normal file
@ -0,0 +1,332 @@
|
||||
/* Copyright (C) 2013, 2014 Tilman Kranz <tilt@linuxfoo.de>
|
||||
*
|
||||
* 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 */
|
||||
|
||||
var MyPlayer = function(_args) {
|
||||
var failed = false;
|
||||
var detached = false;
|
||||
var player = null;
|
||||
|
||||
var defaultArgs = {
|
||||
detachable: true,
|
||||
element: 'body',
|
||||
id3: false,
|
||||
mode: 'mp3url',
|
||||
waveform: false,
|
||||
autoplay: false,
|
||||
loop: true,
|
||||
shuffle: false,
|
||||
list: []
|
||||
};
|
||||
|
||||
var args = (typeof(_args)==='undefined')
|
||||
? defaultArgs
|
||||
: $.extend({}, defaultArgs, _args);
|
||||
|
||||
var createAudio = function() {
|
||||
var autoplay = args.autoplay ? 'autoplay="true"' : '';
|
||||
|
||||
$(args.element).append(
|
||||
'<audio controls="controls" ' + autoplay + '>'+
|
||||
'<p>'+
|
||||
'Your browser does not understand '+
|
||||
'the <audio> tag. '+
|
||||
'</p>'+
|
||||
'</audio>'
|
||||
);
|
||||
|
||||
args.audio = args.element + ' audio';
|
||||
}
|
||||
|
||||
var readId3 = function() {
|
||||
$(args.element).find('ul.mejs li').each(function(i, track){
|
||||
var url = $(track).attr('data-url');
|
||||
|
||||
$(track).prepend('<span class="ajaxLoader"> </span> ');
|
||||
|
||||
ID3.loadTags(url, function() {
|
||||
var tags = ID3.getAllTags(url);
|
||||
|
||||
if(typeof(tags.title)!='undefined') {
|
||||
var track_title = tags.title;
|
||||
|
||||
if(typeof(tags.artist)!='undefined')
|
||||
track_title = tags.artist + ' - ' + track_title;
|
||||
|
||||
$(args.element).find('ul.mejs li').each(function(j, _track){
|
||||
if(i==j)
|
||||
$(_track).html(track_title);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var playerCreated = function() {
|
||||
restoreParams();
|
||||
|
||||
if(args.id3)
|
||||
readId3();
|
||||
}
|
||||
|
||||
var createPlayer = function() {
|
||||
player = new MediaElementPlayer(
|
||||
$(args.audio), {
|
||||
success: playerCreated,
|
||||
loop: args.loop,
|
||||
shuffle: args.shuffle,
|
||||
playlist: true,
|
||||
audioHeight: 32,
|
||||
playlistposition: 'bottom',
|
||||
features: ['playlistfeature', 'prevtrack', 'playpause',
|
||||
'nexttrack', 'loop', 'shuffle', 'current', 'progress',
|
||||
'duration', 'volume'],
|
||||
pluginPath: mejs.Utility.getScriptPath(['myplayer.min.js'])+'../plugins/'
|
||||
});
|
||||
|
||||
$(args.element).append(
|
||||
'<p class="playerDetached" style="display: none;">'+
|
||||
'The player is currently detached.'+
|
||||
'</p>'
|
||||
);
|
||||
}
|
||||
|
||||
var param = function(name) {
|
||||
var query = window.location.search.substring(1);
|
||||
var vars = query.split("&");
|
||||
|
||||
for(var i=0; i<vars.length; i++) {
|
||||
var pair = vars[i].split("=");
|
||||
|
||||
if(pair[0] == name)
|
||||
return pair[1];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var setupDetach = function() {
|
||||
if(!args.detachable)
|
||||
return;
|
||||
|
||||
var popup = function(url) {
|
||||
player.pause();
|
||||
$('.mejs-audio').hide();
|
||||
$('.playerDetached').show();
|
||||
|
||||
var playerWindow = window.open(
|
||||
url, 'myplayer',
|
||||
'height='+ Math.max($(args.element).height(), 298)+','+
|
||||
'width='+408+','+
|
||||
'resizable=false'
|
||||
);
|
||||
|
||||
if(window.focus)
|
||||
playerWindow.focus();
|
||||
|
||||
$("iframe",top.document).height(20);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(param('popup')==false) {
|
||||
$('.mejs-controls').append(
|
||||
'<div id="popupButton" '+
|
||||
'class="popupButton">'+
|
||||
'<button '+
|
||||
'title="Open in separate window" '+
|
||||
'type="button">'+
|
||||
'</button>'+
|
||||
'</div>'
|
||||
);
|
||||
|
||||
$('.popupButton button').click(function(){
|
||||
var currentTime = player.getCurrentTime();
|
||||
var volume = player.getVolume();
|
||||
var paused = player.media.paused;
|
||||
var trackNo = 0;
|
||||
|
||||
$(args.element).find('ul.mejs li').each(function(i){
|
||||
if($(this).hasClass('current'))
|
||||
trackNo = i;
|
||||
});
|
||||
|
||||
popup(
|
||||
$(location).attr('href')+'?'+
|
||||
'popup&'+
|
||||
'paused='+paused+'&'+
|
||||
'currentTime='+currentTime+'&'+
|
||||
'volume='+volume+'&'+
|
||||
'trackNo='+trackNo
|
||||
)
|
||||
});
|
||||
}
|
||||
else {
|
||||
var windowHeight = $(window).height();
|
||||
|
||||
window.onbeforeunload = function(){
|
||||
$("iframe", opener.top.document).height(windowHeight);
|
||||
$('.mejs-audio', opener.document).show();
|
||||
$('.playerDetached', opener.document).hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var restoreParams = function() {
|
||||
if(!detached)
|
||||
return;
|
||||
|
||||
var paused = (param('paused') && param('paused')=='true');
|
||||
var currentTime = param('currentTime') ? parseFloat(param('currentTime')) : 0.0;
|
||||
var volume = param('volume') ? parseFloat(param('volume')) : 1.0;
|
||||
var trackNo = param('trackNo') ? parseInt(param('trackNo')) : 0;
|
||||
|
||||
player.setVolume(volume);
|
||||
|
||||
$(args.element).find('ul.mejs li').each(function(i){
|
||||
if(i==trackNo) {
|
||||
player.playTrack($(this));
|
||||
player.setCurrentTime(currentTime);
|
||||
}
|
||||
});
|
||||
|
||||
if(paused)
|
||||
player.pause();
|
||||
}
|
||||
|
||||
if(param('popup')!==false) {
|
||||
detached = true;
|
||||
|
||||
$('body').html(
|
||||
'<div '+
|
||||
'id="myplayer" '+
|
||||
'style="'+
|
||||
'width: '+$(args.element).width()+'px; '+
|
||||
'height: '+$(args.element).height()+' px;'+
|
||||
'"></div>'
|
||||
);
|
||||
|
||||
args.element = '#myplayer';
|
||||
}
|
||||
|
||||
if(args.mode=='mp3url') {
|
||||
var mp3url = (typeof args.mp3url === "undefined")
|
||||
? $(location).attr('href').replace(/\?.*/, '').replace(/\/[^\/]+\/?$/, '')
|
||||
: args.mp3url;
|
||||
|
||||
$.ajax({
|
||||
url: mp3url,
|
||||
type: 'GET',
|
||||
success: function(res) {
|
||||
createAudio();
|
||||
|
||||
var doc = document.createElement('html');
|
||||
doc.innerHTML = res;
|
||||
|
||||
var head = $(doc).find('a').each(function(idx,item) {
|
||||
var src = $(item).attr('href');
|
||||
|
||||
if(src.match(/\.mp3$/)) {
|
||||
var url = mp3url+'/'+src;
|
||||
var title = item.innerHTML;
|
||||
|
||||
$(args.audio).append('<source src="'+url+'" title="'+title+'"/>');
|
||||
}
|
||||
});
|
||||
|
||||
createPlayer();
|
||||
setupDetach();
|
||||
}
|
||||
});
|
||||
}
|
||||
else if(args.mode=='m3u') {
|
||||
var m3u = (typeof args.m3u === "undefined")
|
||||
? $(location).attr('href').replace(/\?.*/, '').replace(/\/[^\/]+\/?$/, '/play.m3u')
|
||||
: args.m3u;
|
||||
|
||||
createAudio();
|
||||
|
||||
$.get(m3u, function(txt){
|
||||
var lines = txt.split("\n");
|
||||
|
||||
for(var i = 0, len = lines.length; i < len; i++)
|
||||
if(!lines[i].match(/^[ \t]*#/) && lines[i].match(/\.mp3$/)) {
|
||||
var mp3 = lines[i];
|
||||
var title = unescape(mp3.split('/').pop());
|
||||
|
||||
$(args.audio).append('<source src="'+mp3+'" title="'+title+'"/>');
|
||||
}
|
||||
|
||||
createPlayer();
|
||||
setupDetach();
|
||||
});
|
||||
}
|
||||
else if(args.mode=='list') {
|
||||
createAudio();
|
||||
|
||||
for(var i = 0, len = args.list.length; i < len; i++) {
|
||||
var item = args.list[i];
|
||||
var type = typeof item;
|
||||
var src = '';
|
||||
var title = '';
|
||||
|
||||
if(item !== null && type === 'object') {
|
||||
if(item.url)
|
||||
src = item.url;
|
||||
else {
|
||||
alert(
|
||||
'MyPlayer: item[' + i + ']: '+
|
||||
'property "url" is missing.'
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(item.title)
|
||||
title = item.title;
|
||||
else
|
||||
title = url.replace(/(.*\/)?([^\/]+)/, '$2');
|
||||
}
|
||||
else if(type === 'string') {
|
||||
src = item;
|
||||
title = src;
|
||||
}
|
||||
else {
|
||||
alert(
|
||||
'MyPlayer: item [' + i + ']: '+
|
||||
'unsupported type "' + type + '"'
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$(args.audio).append('<source src="'+src+'" title="'+title+'"/>');
|
||||
}
|
||||
|
||||
createPlayer();
|
||||
setupDetach();
|
||||
}
|
||||
else {
|
||||
$(args.element).append('<p>Unsupported mode "'+args.mode+'"</p>');
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user