diff --git a/dashboard-ui/bower_components/cryptojslib/.bower.json b/dashboard-ui/bower_components/cryptojslib/.bower.json index a2b26693e..a0eafda50 100644 --- a/dashboard-ui/bower_components/cryptojslib/.bower.json +++ b/dashboard-ui/bower_components/cryptojslib/.bower.json @@ -15,8 +15,7 @@ "tag": "v3.1.2", "commit": "79faa50ca65a0bc302ff93518215c015b4d3004c" }, - "_source": "git://github.com/sytelus/CryptoJS.git", - "_target": "~3.1.2", - "_originalSource": "cryptojslib", - "_direct": true + "_source": "https://github.com/sytelus/CryptoJS.git", + "_target": "^3.1.2", + "_originalSource": "cryptojslib" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/cryptojslib/rollups/aes.js b/dashboard-ui/bower_components/cryptojslib/rollups/aes.js deleted file mode 100644 index 827503cbd..000000000 --- a/dashboard-ui/bower_components/cryptojslib/rollups/aes.js +++ /dev/null @@ -1,35 +0,0 @@ -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -var CryptoJS=CryptoJS||function(u,p){var d={},l=d.lib={},s=function(){},t=l.Base={extend:function(a){s.prototype=this;var c=new s;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, -r=l.WordArray=t.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=p?c:4*a.length},toString:function(a){return(a||v).stringify(this)},concat:function(a){var c=this.words,e=a.words,j=this.sigBytes;a=a.sigBytes;this.clamp();if(j%4)for(var k=0;k>>2]|=(e[k>>>2]>>>24-8*(k%4)&255)<<24-8*((j+k)%4);else if(65535>>2]=e[k>>>2];else c.push.apply(c,e);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< -32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],e=0;e>>2]>>>24-8*(j%4)&255;e.push((k>>>4).toString(16));e.push((k&15).toString(16))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>3]|=parseInt(a.substr(j, -2),16)<<24-4*(j%8);return new r.init(e,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j>>2]>>>24-8*(j%4)&255));return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new r.init(e,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}}, -q=l.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=x.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,e=c.words,j=c.sigBytes,k=this.blockSize,b=j/(4*k),b=a?u.ceil(b):u.max((b|0)-this._minBufferSize,0);a=b*k;j=u.min(4*a,j);if(a){for(var q=0;q>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join("")},parse:function(d){var l=d.length,s=this._map,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w< -l;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})(); -(function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])}, -_doProcessBlock:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this._hash.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]), -f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f, -m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m, -E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},_doFinalize:function(){var b=this._data,n=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/ -4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this._process();b=this._hash;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});t.MD5=v._createHelper(r);t.HmacMD5=v._createHmacHelper(r)})(Math); -(function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a, -this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684, -1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})}, -decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d, -b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this._parse(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}(); -(function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8, -16,32,64,128,27,54],d=d.AES=p.extend({_doReset:function(){for(var a=this._key,c=a.words,d=a.sigBytes/4,a=4*((this._nRounds=d+6)+1),e=this._keySchedule=[],j=0;j>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this._invKeySchedule=[];for(d=0;dd||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>> -8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this._doCryptBlock(a,b,this._keySchedule,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this._doCryptBlock(a,c,this._invKeySchedule,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},_doCryptBlock:function(a,b,c,d,e,j,l,f){for(var m=this._nRounds,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t= -d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p._createHelper(d)})(); diff --git a/dashboard-ui/bower_components/cryptojslib/rollups/hmac-md5.js b/dashboard-ui/bower_components/cryptojslib/rollups/hmac-md5.js deleted file mode 100644 index 085eb4a1f..000000000 --- a/dashboard-ui/bower_components/cryptojslib/rollups/hmac-md5.js +++ /dev/null @@ -1,21 +0,0 @@ -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -var CryptoJS=CryptoJS||function(q,r){var k={},g=k.lib={},p=function(){},t=g.Base={extend:function(b){p.prototype=this;var j=new p;b&&j.mixIn(b);j.hasOwnProperty("init")||(j.init=function(){j.$super.init.apply(this,arguments)});j.init.prototype=j;j.$super=this;return j},create:function(){var b=this.extend();b.init.apply(b,arguments);return b},init:function(){},mixIn:function(b){for(var j in b)b.hasOwnProperty(j)&&(this[j]=b[j]);b.hasOwnProperty("toString")&&(this.toString=b.toString)},clone:function(){return this.init.prototype.extend(this)}}, -n=g.WordArray=t.extend({init:function(b,j){b=this.words=b||[];this.sigBytes=j!=r?j:4*b.length},toString:function(b){return(b||u).stringify(this)},concat:function(b){var j=this.words,a=b.words,l=this.sigBytes;b=b.sigBytes;this.clamp();if(l%4)for(var h=0;h>>2]|=(a[h>>>2]>>>24-8*(h%4)&255)<<24-8*((l+h)%4);else if(65535>>2]=a[h>>>2];else j.push.apply(j,a);this.sigBytes+=b;return this},clamp:function(){var b=this.words,j=this.sigBytes;b[j>>>2]&=4294967295<< -32-8*(j%4);b.length=q.ceil(j/4)},clone:function(){var b=t.clone.call(this);b.words=this.words.slice(0);return b},random:function(b){for(var j=[],a=0;a>>2]>>>24-8*(l%4)&255;h.push((m>>>4).toString(16));h.push((m&15).toString(16))}return h.join("")},parse:function(b){for(var a=b.length,h=[],l=0;l>>3]|=parseInt(b.substr(l, -2),16)<<24-4*(l%8);return new n.init(h,a/2)}},a=v.Latin1={stringify:function(b){var a=b.words;b=b.sigBytes;for(var h=[],l=0;l>>2]>>>24-8*(l%4)&255));return h.join("")},parse:function(b){for(var a=b.length,h=[],l=0;l>>2]|=(b.charCodeAt(l)&255)<<24-8*(l%4);return new n.init(h,a)}},s=v.Utf8={stringify:function(b){try{return decodeURIComponent(escape(a.stringify(b)))}catch(h){throw Error("Malformed UTF-8 data");}},parse:function(b){return a.parse(unescape(encodeURIComponent(b)))}}, -h=g.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new n.init;this._nDataBytes=0},_append:function(b){"string"==typeof b&&(b=s.parse(b));this._data.concat(b);this._nDataBytes+=b.sigBytes},_process:function(b){var a=this._data,h=a.words,l=a.sigBytes,m=this.blockSize,k=l/(4*m),k=b?q.ceil(k):q.max((k|0)-this._minBufferSize,0);b=k*m;l=q.min(4*b,l);if(b){for(var g=0;g>>32-l)+m}function k(a,m,b,j,g,l,k){a=a+(m&j|b&~j)+g+k;return(a<>>32-l)+m}function g(a,m,b,j,g,l,k){a=a+(m^b^j)+g+k;return(a<>>32-l)+m}function p(a,g,b,j,k,l,p){a=a+(b^(g|~j))+k+p;return(a<>>32-l)+g}for(var t=CryptoJS,n=t.lib,v=n.WordArray,u=n.Hasher,n=t.algo,a=[],s=0;64>s;s++)a[s]=4294967296*q.abs(q.sin(s+1))|0;n=n.MD5=u.extend({_doReset:function(){this._hash=new v.init([1732584193,4023233417,2562383102,271733878])}, -_doProcessBlock:function(h,m){for(var b=0;16>b;b++){var j=m+b,n=h[j];h[j]=(n<<8|n>>>24)&16711935|(n<<24|n>>>8)&4278255360}var b=this._hash.words,j=h[m+0],n=h[m+1],l=h[m+2],q=h[m+3],t=h[m+4],s=h[m+5],u=h[m+6],v=h[m+7],w=h[m+8],x=h[m+9],y=h[m+10],z=h[m+11],A=h[m+12],B=h[m+13],C=h[m+14],D=h[m+15],c=b[0],d=b[1],e=b[2],f=b[3],c=r(c,d,e,f,j,7,a[0]),f=r(f,c,d,e,n,12,a[1]),e=r(e,f,c,d,l,17,a[2]),d=r(d,e,f,c,q,22,a[3]),c=r(c,d,e,f,t,7,a[4]),f=r(f,c,d,e,s,12,a[5]),e=r(e,f,c,d,u,17,a[6]),d=r(d,e,f,c,v,22,a[7]), -c=r(c,d,e,f,w,7,a[8]),f=r(f,c,d,e,x,12,a[9]),e=r(e,f,c,d,y,17,a[10]),d=r(d,e,f,c,z,22,a[11]),c=r(c,d,e,f,A,7,a[12]),f=r(f,c,d,e,B,12,a[13]),e=r(e,f,c,d,C,17,a[14]),d=r(d,e,f,c,D,22,a[15]),c=k(c,d,e,f,n,5,a[16]),f=k(f,c,d,e,u,9,a[17]),e=k(e,f,c,d,z,14,a[18]),d=k(d,e,f,c,j,20,a[19]),c=k(c,d,e,f,s,5,a[20]),f=k(f,c,d,e,y,9,a[21]),e=k(e,f,c,d,D,14,a[22]),d=k(d,e,f,c,t,20,a[23]),c=k(c,d,e,f,x,5,a[24]),f=k(f,c,d,e,C,9,a[25]),e=k(e,f,c,d,q,14,a[26]),d=k(d,e,f,c,w,20,a[27]),c=k(c,d,e,f,B,5,a[28]),f=k(f,c, -d,e,l,9,a[29]),e=k(e,f,c,d,v,14,a[30]),d=k(d,e,f,c,A,20,a[31]),c=g(c,d,e,f,s,4,a[32]),f=g(f,c,d,e,w,11,a[33]),e=g(e,f,c,d,z,16,a[34]),d=g(d,e,f,c,C,23,a[35]),c=g(c,d,e,f,n,4,a[36]),f=g(f,c,d,e,t,11,a[37]),e=g(e,f,c,d,v,16,a[38]),d=g(d,e,f,c,y,23,a[39]),c=g(c,d,e,f,B,4,a[40]),f=g(f,c,d,e,j,11,a[41]),e=g(e,f,c,d,q,16,a[42]),d=g(d,e,f,c,u,23,a[43]),c=g(c,d,e,f,x,4,a[44]),f=g(f,c,d,e,A,11,a[45]),e=g(e,f,c,d,D,16,a[46]),d=g(d,e,f,c,l,23,a[47]),c=p(c,d,e,f,j,6,a[48]),f=p(f,c,d,e,v,10,a[49]),e=p(e,f,c,d, -C,15,a[50]),d=p(d,e,f,c,s,21,a[51]),c=p(c,d,e,f,A,6,a[52]),f=p(f,c,d,e,q,10,a[53]),e=p(e,f,c,d,y,15,a[54]),d=p(d,e,f,c,n,21,a[55]),c=p(c,d,e,f,w,6,a[56]),f=p(f,c,d,e,D,10,a[57]),e=p(e,f,c,d,u,15,a[58]),d=p(d,e,f,c,B,21,a[59]),c=p(c,d,e,f,t,6,a[60]),f=p(f,c,d,e,z,10,a[61]),e=p(e,f,c,d,l,15,a[62]),d=p(d,e,f,c,x,21,a[63]);b[0]=b[0]+c|0;b[1]=b[1]+d|0;b[2]=b[2]+e|0;b[3]=b[3]+f|0},_doFinalize:function(){var a=this._data,g=a.words,b=8*this._nDataBytes,j=8*a.sigBytes;g[j>>>5]|=128<<24-j%32;var k=q.floor(b/ -4294967296);g[(j+64>>>9<<4)+15]=(k<<8|k>>>24)&16711935|(k<<24|k>>>8)&4278255360;g[(j+64>>>9<<4)+14]=(b<<8|b>>>24)&16711935|(b<<24|b>>>8)&4278255360;a.sigBytes=4*(g.length+1);this._process();a=this._hash;g=a.words;for(b=0;4>b;b++)j=g[b],g[b]=(j<<8|j>>>24)&16711935|(j<<24|j>>>8)&4278255360;return a},clone:function(){var a=u.clone.call(this);a._hash=this._hash.clone();return a}});t.MD5=u._createHelper(n);t.HmacMD5=u._createHmacHelper(n)})(Math); -(function(){var q=CryptoJS,r=q.enc.Utf8;q.algo.HMAC=q.lib.Base.extend({init:function(k,g){k=this._hasher=new k.init;"string"==typeof g&&(g=r.parse(g));var p=k.blockSize,q=4*p;g.sigBytes>q&&(g=k.finalize(g));g.clamp();for(var n=this._oKey=g.clone(),v=this._iKey=g.clone(),u=n.words,a=v.words,s=0;s>>2]|=(B[b>>>2]>>>24-8*(b%4)&255)<<24-8*((f+b)%4);else if(65535>>2]=B[b>>>2];else d.push.apply(d,B);this.sigBytes+=a;return this},clamp:function(){var a=this.words,d=this.sigBytes;a[d>>>2]&=4294967295<< -32-8*(d%4);a.length=h.ceil(d/4)},clone:function(){var a=l.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var d=[],b=0;b>>2]>>>24-8*(f%4)&255;b.push((c>>>4).toString(16));b.push((c&15).toString(16))}return b.join("")},parse:function(a){for(var d=a.length,b=[],f=0;f>>3]|=parseInt(a.substr(f, -2),16)<<24-4*(f%8);return new m.init(b,d/2)}},w=v.Latin1={stringify:function(a){var d=a.words;a=a.sigBytes;for(var b=[],f=0;f>>2]>>>24-8*(f%4)&255));return b.join("")},parse:function(a){for(var b=a.length,c=[],f=0;f>>2]|=(a.charCodeAt(f)&255)<<24-8*(f%4);return new m.init(c,b)}},k=v.Utf8={stringify:function(a){try{return decodeURIComponent(escape(w.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return w.parse(unescape(encodeURIComponent(a)))}}, -u=e.BufferedBlockAlgorithm=l.extend({reset:function(){this._data=new m.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=k.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var b=this._data,c=b.words,f=b.sigBytes,e=this.blockSize,k=f/(4*e),k=a?h.ceil(k):h.max((k|0)-this._minBufferSize,0);a=k*e;f=h.min(4*a,f);if(a){for(var u=0;ub;b++){var a=e+b,d=c[a];c[a]=(d<<8|d>>>24)&16711935|(d<<24|d>>>8)&4278255360}var a=this._hash.words,d=x.words,h=w.words,f=A.words,j=l.words,E=m.words,F=v.words,C,n,p,q,y,D,r,s,t,z;D=C=a[0];r=n=a[1];s=p=a[2];t=q=a[3];z=y=a[4];for(var g,b=0;80>b;b+=1)g=C+c[e+f[b]]|0,g=16>b?g+((n^p^q)+d[0]):32>b?g+((n&p|~n&q)+d[1]):48>b? -g+(((n|~p)^q)+d[2]):64>b?g+((n&q|p&~q)+d[3]):g+((n^(p|~q))+d[4]),g|=0,g=g<>>32-E[b],g=g+y|0,C=y,y=q,q=p<<10|p>>>22,p=n,n=g,g=D+c[e+j[b]]|0,g=16>b?g+((r^(s|~t))+h[0]):32>b?g+((r&t|s&~t)+h[1]):48>b?g+(((r|~s)^t)+h[2]):64>b?g+((r&s|~r&t)+h[3]):g+((r^s^t)+h[4]),g|=0,g=g<>>32-F[b],g=g+z|0,D=z,z=t,t=s<<10|s>>>22,s=r,r=g;g=a[1]+p+t|0;a[1]=a[2]+q+z|0;a[2]=a[3]+y+D|0;a[3]=a[4]+C+r|0;a[4]=a[0]+n+s|0;a[0]=g},_doFinalize:function(){var c=this._data,e=c.words,b=8*this._nDataBytes,a=8*c.sigBytes; -e[a>>>5]|=128<<24-a%32;e[(a+64>>>9<<4)+14]=(b<<8|b>>>24)&16711935|(b<<24|b>>>8)&4278255360;c.sigBytes=4*(e.length+1);this._process();c=this._hash;e=c.words;for(b=0;5>b;b++)a=e[b],e[b]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;return c},clone:function(){var c=e.clone.call(this);c._hash=this._hash.clone();return c}});h.RIPEMD160=e._createHelper(j);h.HmacRIPEMD160=e._createHmacHelper(j)})(Math); -(function(){var h=CryptoJS,j=h.enc.Utf8;h.algo.HMAC=h.lib.Base.extend({init:function(c,e){c=this._hasher=new c.init;"string"==typeof e&&(e=j.parse(e));var h=c.blockSize,l=4*h;e.sigBytes>l&&(e=c.finalize(e));e.clamp();for(var m=this._oKey=e.clone(),v=this._iKey=e.clone(),x=m.words,w=v.words,k=0;k>>2]|=(q[b>>>2]>>>24-8*(b%4)&255)<<24-8*((f+b)%4);else if(65535>>2]=q[b>>>2];else c.push.apply(c,q);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< -32-8*(c%4);a.length=g.ceil(c/4)},clone:function(){var a=k.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],b=0;b>>2]>>>24-8*(f%4)&255;b.push((d>>>4).toString(16));b.push((d&15).toString(16))}return b.join("")},parse:function(a){for(var c=a.length,b=[],f=0;f>>3]|=parseInt(a.substr(f, -2),16)<<24-4*(f%8);return new p.init(b,c/2)}},j=b.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],f=0;f>>2]>>>24-8*(f%4)&255));return b.join("")},parse:function(a){for(var c=a.length,b=[],f=0;f>>2]|=(a.charCodeAt(f)&255)<<24-8*(f%4);return new p.init(b,c)}},h=b.Utf8={stringify:function(a){try{return decodeURIComponent(escape(j.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return j.parse(unescape(encodeURIComponent(a)))}}, -r=d.BufferedBlockAlgorithm=k.extend({reset:function(){this._data=new p.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=h.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,b=c.words,f=c.sigBytes,d=this.blockSize,e=f/(4*d),e=a?g.ceil(e):g.max((e|0)-this._minBufferSize,0);a=e*d;f=g.min(4*a,f);if(a){for(var k=0;ka;a++){if(16>a)m[a]=d[e+a]|0;else{var c=m[a-3]^m[a-8]^m[a-14]^m[a-16];m[a]=c<<1|c>>>31}c=(n<<5|n>>>27)+l+m[a];c=20>a?c+((j&h|~j&g)+1518500249):40>a?c+((j^h^g)+1859775393):60>a?c+((j&h|j&g|h&g)-1894007588):c+((j^h^ -g)-899497514);l=g;g=h;h=j<<30|j>>>2;j=n;n=c}b[0]=b[0]+n|0;b[1]=b[1]+j|0;b[2]=b[2]+h|0;b[3]=b[3]+g|0;b[4]=b[4]+l|0},_doFinalize:function(){var d=this._data,e=d.words,b=8*this._nDataBytes,g=8*d.sigBytes;e[g>>>5]|=128<<24-g%32;e[(g+64>>>9<<4)+14]=Math.floor(b/4294967296);e[(g+64>>>9<<4)+15]=b;d.sigBytes=4*e.length;this._process();return this._hash},clone:function(){var e=d.clone.call(this);e._hash=this._hash.clone();return e}});g.SHA1=d._createHelper(l);g.HmacSHA1=d._createHmacHelper(l)})(); -(function(){var g=CryptoJS,l=g.enc.Utf8;g.algo.HMAC=g.lib.Base.extend({init:function(e,d){e=this._hasher=new e.init;"string"==typeof d&&(d=l.parse(d));var g=e.blockSize,k=4*g;d.sigBytes>k&&(d=e.finalize(d));d.clamp();for(var p=this._oKey=d.clone(),b=this._iKey=d.clone(),n=p.words,j=b.words,h=0;h>>2]|=(f[g>>>2]>>>24-8*(g%4)&255)<<24-8*((b+g)%4);else if(65535>>2]=f[g>>>2];else d.push.apply(d,f);this.sigBytes+=a;return this},clamp:function(){var a=this.words,d=this.sigBytes;a[d>>>2]&=4294967295<< -32-8*(d%4);a.length=j.ceil(d/4)},clone:function(){var a=m.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var d=[],f=0;f>>2]>>>24-8*(b%4)&255;f.push((g>>>4).toString(16));f.push((g&15).toString(16))}return f.join("")},parse:function(a){for(var d=a.length,f=[],b=0;b>>3]|=parseInt(a.substr(b, -2),16)<<24-4*(b%8);return new r.init(f,d/2)}},n=s.Latin1={stringify:function(a){var d=a.words;a=a.sigBytes;for(var f=[],b=0;b>>2]>>>24-8*(b%4)&255));return f.join("")},parse:function(a){for(var d=a.length,f=[],b=0;b>>2]|=(a.charCodeAt(b)&255)<<24-8*(b%4);return new r.init(f,d)}},h=s.Utf8={stringify:function(a){try{return decodeURIComponent(escape(n.stringify(a)))}catch(d){throw Error("Malformed UTF-8 data");}},parse:function(a){return n.parse(unescape(encodeURIComponent(a)))}}, -u=e.BufferedBlockAlgorithm=m.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=h.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var d=this._data,f=d.words,b=d.sigBytes,g=this.blockSize,c=b/(4*g),c=a?j.ceil(c):j.max((c|0)-this._minBufferSize,0);a=c*g;b=j.min(4*a,b);if(a){for(var e=0;en;){var h;a:{h=l;for(var u=j.sqrt(h),t=2;t<=u;t++)if(!(h%t)){h=!1;break a}h=!0}h&&(8>n&&(m[n]=s(j.pow(l,0.5))),r[n]=s(j.pow(l,1/3)),n++);l++}var a=[],c=c.SHA256=p.extend({_doReset:function(){this._hash=new e.init(m.slice(0))},_doProcessBlock:function(d,f){for(var b=this._hash.words,g=b[0],c=b[1],e=b[2],j=b[3],h=b[4],p=b[5],m=b[6],n=b[7],q=0;64>q;q++){if(16>q)a[q]= -d[f+q]|0;else{var k=a[q-15],l=a[q-2];a[q]=((k<<25|k>>>7)^(k<<14|k>>>18)^k>>>3)+a[q-7]+((l<<15|l>>>17)^(l<<13|l>>>19)^l>>>10)+a[q-16]}k=n+((h<<26|h>>>6)^(h<<21|h>>>11)^(h<<7|h>>>25))+(h&p^~h&m)+r[q]+a[q];l=((g<<30|g>>>2)^(g<<19|g>>>13)^(g<<10|g>>>22))+(g&c^g&e^c&e);n=m;m=p;p=h;h=j+k|0;j=e;e=c;c=g;g=k+l|0}b[0]=b[0]+g|0;b[1]=b[1]+c|0;b[2]=b[2]+e|0;b[3]=b[3]+j|0;b[4]=b[4]+h|0;b[5]=b[5]+p|0;b[6]=b[6]+m|0;b[7]=b[7]+n|0},_doFinalize:function(){var a=this._data,c=a.words,b=8*this._nDataBytes,e=8*a.sigBytes; -c[e>>>5]|=128<<24-e%32;c[(e+64>>>9<<4)+14]=j.floor(b/4294967296);c[(e+64>>>9<<4)+15]=b;a.sigBytes=4*c.length;this._process();return this._hash},clone:function(){var a=p.clone.call(this);a._hash=this._hash.clone();return a}});k.SHA256=p._createHelper(c);k.HmacSHA256=p._createHmacHelper(c)})(Math); -(function(){var j=CryptoJS,k=j.lib.WordArray,c=j.algo,e=c.SHA256,c=c.SHA224=e.extend({_doReset:function(){this._hash=new k.init([3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428])},_doFinalize:function(){var c=e._doFinalize.call(this);c.sigBytes-=4;return c}});j.SHA224=e._createHelper(c);j.HmacSHA224=e._createHmacHelper(c)})(); -(function(){var j=CryptoJS,k=j.enc.Utf8;j.algo.HMAC=j.lib.Base.extend({init:function(c,e){c=this._hasher=new c.init;"string"==typeof e&&(e=k.parse(e));var j=c.blockSize,m=4*j;e.sigBytes>m&&(e=c.finalize(e));e.clamp();for(var r=this._oKey=e.clone(),s=this._iKey=e.clone(),l=r.words,n=s.words,h=0;h>>2]|=(d[e>>>2]>>>24-8*(e%4)&255)<<24-8*((b+e)%4);else if(65535>>2]=d[e>>>2];else c.push.apply(c,d);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< -32-8*(c%4);a.length=h.ceil(c/4)},clone:function(){var a=m.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],d=0;d>>2]>>>24-8*(b%4)&255;d.push((e>>>4).toString(16));d.push((e&15).toString(16))}return d.join("")},parse:function(a){for(var c=a.length,d=[],b=0;b>>3]|=parseInt(a.substr(b, -2),16)<<24-4*(b%8);return new r.init(d,c/2)}},n=l.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var d=[],b=0;b>>2]>>>24-8*(b%4)&255));return d.join("")},parse:function(a){for(var c=a.length,d=[],b=0;b>>2]|=(a.charCodeAt(b)&255)<<24-8*(b%4);return new r.init(d,c)}},j=l.Utf8={stringify:function(a){try{return decodeURIComponent(escape(n.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return n.parse(unescape(encodeURIComponent(a)))}}, -u=g.BufferedBlockAlgorithm=m.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=j.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,d=c.words,b=c.sigBytes,e=this.blockSize,f=b/(4*e),f=a?h.ceil(f):h.max((f|0)-this._minBufferSize,0);a=f*e;b=h.min(4*a,b);if(a){for(var g=0;gn;){var j;a:{j=k;for(var u=h.sqrt(j),t=2;t<=u;t++)if(!(j%t)){j=!1;break a}j=!0}j&&(8>n&&(m[n]=l(h.pow(k,0.5))),r[n]=l(h.pow(k,1/3)),n++);k++}var a=[],f=f.SHA256=q.extend({_doReset:function(){this._hash=new g.init(m.slice(0))},_doProcessBlock:function(c,d){for(var b=this._hash.words,e=b[0],f=b[1],g=b[2],j=b[3],h=b[4],m=b[5],n=b[6],q=b[7],p=0;64>p;p++){if(16>p)a[p]= -c[d+p]|0;else{var k=a[p-15],l=a[p-2];a[p]=((k<<25|k>>>7)^(k<<14|k>>>18)^k>>>3)+a[p-7]+((l<<15|l>>>17)^(l<<13|l>>>19)^l>>>10)+a[p-16]}k=q+((h<<26|h>>>6)^(h<<21|h>>>11)^(h<<7|h>>>25))+(h&m^~h&n)+r[p]+a[p];l=((e<<30|e>>>2)^(e<<19|e>>>13)^(e<<10|e>>>22))+(e&f^e&g^f&g);q=n;n=m;m=h;h=j+k|0;j=g;g=f;f=e;e=k+l|0}b[0]=b[0]+e|0;b[1]=b[1]+f|0;b[2]=b[2]+g|0;b[3]=b[3]+j|0;b[4]=b[4]+h|0;b[5]=b[5]+m|0;b[6]=b[6]+n|0;b[7]=b[7]+q|0},_doFinalize:function(){var a=this._data,d=a.words,b=8*this._nDataBytes,e=8*a.sigBytes; -d[e>>>5]|=128<<24-e%32;d[(e+64>>>9<<4)+14]=h.floor(b/4294967296);d[(e+64>>>9<<4)+15]=b;a.sigBytes=4*d.length;this._process();return this._hash},clone:function(){var a=q.clone.call(this);a._hash=this._hash.clone();return a}});s.SHA256=q._createHelper(f);s.HmacSHA256=q._createHmacHelper(f)})(Math); -(function(){var h=CryptoJS,s=h.enc.Utf8;h.algo.HMAC=h.lib.Base.extend({init:function(f,g){f=this._hasher=new f.init;"string"==typeof g&&(g=s.parse(g));var h=f.blockSize,m=4*h;g.sigBytes>m&&(g=f.finalize(g));g.clamp();for(var r=this._oKey=g.clone(),l=this._iKey=g.clone(),k=r.words,n=l.words,j=0;j>>2]|=(e[p>>>2]>>>24-8*(p%4)&255)<<24-8*((j+p)%4);else if(65535>>2]=e[p>>>2];else b.push.apply(b,e);this.sigBytes+=a;return this},clamp:function(){var a=this.words,b=this.sigBytes;a[b>>>2]&=4294967295<< -32-8*(b%4);a.length=q.ceil(b/4)},clone:function(){var a=s.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var b=[],e=0;e>>2]>>>24-8*(j%4)&255;e.push((p>>>4).toString(16));e.push((p&15).toString(16))}return e.join("")},parse:function(a){for(var b=a.length,e=[],j=0;j>>3]|=parseInt(a.substr(j, -2),16)<<24-4*(j%8);return new t.init(e,b/2)}},g=w.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var e=[],j=0;j>>2]>>>24-8*(j%4)&255));return e.join("")},parse:function(a){for(var b=a.length,e=[],j=0;j>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new t.init(e,b)}},n=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(g.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return g.parse(unescape(encodeURIComponent(a)))}}, -u=d.BufferedBlockAlgorithm=s.extend({reset:function(){this._data=new t.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=n.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var b=this._data,e=b.words,j=b.sigBytes,p=this.blockSize,c=j/(4*p),c=a?q.ceil(c):q.max((c|0)-this._minBufferSize,0);a=c*p;j=q.min(4*a,j);if(a){for(var g=0;gu;u++){t[g+5*n]=(u+1)*(u+2)/2%64;var x=(2*g+3*n)%5,g=n%5,n=x}for(g=0;5>g;g++)for(n=0;5>n;n++)w[g+5*n]=n+5*((2*g+3*n)%5);g=1;for(n=0;24>n;n++){for(var a=x=u=0;7>a;a++){if(g&1){var b=(1<b?x^=1<g;g++)e[g]=s.create();c=c.SHA3=v.extend({cfg:v.cfg.extend({outputLength:512}),_doReset:function(){for(var a=this._state= -[],b=0;25>b;b++)a[b]=new s.init;this.blockSize=(1600-2*this.cfg.outputLength)/32},_doProcessBlock:function(a,b){for(var c=this._state,g=this.blockSize/2,k=0;k>>24)&16711935|(d<<24|d>>>8)&4278255360,l=(l<<8|l>>>24)&16711935|(l<<24|l>>>8)&4278255360,h=c[k];h.high^=l;h.low^=d}for(g=0;24>g;g++){for(k=0;5>k;k++){for(var f=d=0,m=0;5>m;m++)h=c[k+5*m],d^=h.high,f^=h.low;h=e[k];h.high=d;h.low=f}for(k=0;5>k;k++){h=e[(k+4)%5];d=e[(k+1)%5];l=d.high;m=d.low;d=h.high^ -(l<<1|m>>>31);f=h.low^(m<<1|l>>>31);for(m=0;5>m;m++)h=c[k+5*m],h.high^=d,h.low^=f}for(l=1;25>l;l++)h=c[l],k=h.high,h=h.low,m=t[l],32>m?(d=k<>>32-m,f=h<>>32-m):(d=h<>>64-m,f=k<>>64-m),h=e[w[l]],h.high=d,h.low=f;h=e[0];k=c[0];h.high=k.high;h.low=k.low;for(k=0;5>k;k++)for(m=0;5>m;m++)l=k+5*m,h=c[l],d=e[l],l=e[(k+1)%5+5*m],f=e[(k+2)%5+5*m],h.high=d.high^~l.high&f.high,h.low=d.low^~l.low&f.low;h=c[0];k=r[g];h.high^=k.high;h.low^=k.low}},_doFinalize:function(){var a=this._data, -b=a.words,c=8*a.sigBytes,e=32*this.blockSize;b[c>>>5]|=1<<24-c%32;b[(q.ceil((c+1)/e)*e>>>5)-1]|=128;a.sigBytes=4*b.length;this._process();for(var a=this._state,b=this.cfg.outputLength/8,c=b/8,e=[],g=0;g>>24)&16711935|(l<<24|l>>>8)&4278255360,f=(f<<8|f>>>24)&16711935|(f<<24|f>>>8)&4278255360;e.push(f);e.push(l)}return new d.init(e,b)},clone:function(){for(var a=v.clone.call(this),b=a._state=this._state.slice(0),c=0;25>c;c++)b[c]=b[c].clone();return a}}); -f.SHA3=v._createHelper(c);f.HmacSHA3=v._createHmacHelper(c)})(Math); -(function(){var q=CryptoJS,f=q.enc.Utf8;q.algo.HMAC=q.lib.Base.extend({init:function(c,d){c=this._hasher=new c.init;"string"==typeof d&&(d=f.parse(d));var q=c.blockSize,s=4*q;d.sigBytes>s&&(d=c.finalize(d));d.clamp();for(var t=this._oKey=d.clone(),w=this._iKey=d.clone(),r=t.words,g=w.words,n=0;n>>2]|=(c[b>>>2]>>>24-8*(b%4)&255)<<24-8*((e+b)%4);else if(65535>>2]=c[b>>>2];else g.push.apply(g,c);this.sigBytes+=a;return this},clamp:function(){var C=this.words,g=this.sigBytes;C[g>>>2]&=4294967295<< -32-8*(g%4);C.length=a.ceil(g/4)},clone:function(){var a=l.clone.call(this);a.words=this.words.slice(0);return a},random:function(C){for(var g=[],b=0;b>>2]>>>24-8*(e%4)&255;b.push((c>>>4).toString(16));b.push((c&15).toString(16))}return b.join("")},parse:function(a){for(var b=a.length,c=[],e=0;e>>3]|=parseInt(a.substr(e, -2),16)<<24-4*(e%8);return new u.init(c,b/2)}},x=k.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var c=[],e=0;e>>2]>>>24-8*(e%4)&255));return c.join("")},parse:function(a){for(var b=a.length,c=[],e=0;e>>2]|=(a.charCodeAt(e)&255)<<24-8*(e%4);return new u.init(c,b)}},y=k.Utf8={stringify:function(a){try{return decodeURIComponent(escape(x.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return x.parse(unescape(encodeURIComponent(a)))}}, -$=b.BufferedBlockAlgorithm=l.extend({reset:function(){this._data=new u.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=y.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(b){var c=this._data,l=c.words,e=c.sigBytes,d=this.blockSize,f=e/(4*d),f=b?a.ceil(f):a.max((f|0)-this._minBufferSize,0);b=f*d;e=a.min(4*b,e);if(b){for(var k=0;km;m++)k[m]=a();b=b.SHA512=c.extend({_doReset:function(){this._hash=new l.init([new f.init(1779033703,4089235720),new f.init(3144134277,2227873595),new f.init(1013904242,4271175723),new f.init(2773480762,1595750129),new f.init(1359893119,2917565137),new f.init(2600822924,725511199),new f.init(528734635,4215389547),new f.init(1541459225,327033209)])},_doProcessBlock:function(a,b){for(var c=this._hash.words, -d=c[0],f=c[1],g=c[2],l=c[3],e=c[4],m=c[5],L=c[6],c=c[7],Z=d.high,M=d.low,aa=f.high,N=f.low,ba=g.high,O=g.low,ca=l.high,P=l.low,da=e.high,Q=e.low,ea=m.high,R=m.low,fa=L.high,S=L.low,ga=c.high,T=c.low,r=Z,n=M,F=aa,D=N,G=ba,E=O,W=ca,H=P,s=da,p=Q,U=ea,I=R,V=fa,J=S,X=ga,K=T,t=0;80>t;t++){var z=k[t];if(16>t)var q=z.high=a[b+2*t]|0,h=z.low=a[b+2*t+1]|0;else{var q=k[t-15],h=q.high,v=q.low,q=(h>>>1|v<<31)^(h>>>8|v<<24)^h>>>7,v=(v>>>1|h<<31)^(v>>>8|h<<24)^(v>>>7|h<<25),B=k[t-2],h=B.high,j=B.low,B=(h>>>19|j<< -13)^(h<<3|j>>>29)^h>>>6,j=(j>>>19|h<<13)^(j<<3|h>>>29)^(j>>>6|h<<26),h=k[t-7],Y=h.high,A=k[t-16],w=A.high,A=A.low,h=v+h.low,q=q+Y+(h>>>0>>0?1:0),h=h+j,q=q+B+(h>>>0>>0?1:0),h=h+A,q=q+w+(h>>>0>>0?1:0);z.high=q;z.low=h}var Y=s&U^~s&V,A=p&I^~p&J,z=r&F^r&G^F&G,ja=n&D^n&E^D&E,v=(r>>>28|n<<4)^(r<<30|n>>>2)^(r<<25|n>>>7),B=(n>>>28|r<<4)^(n<<30|r>>>2)^(n<<25|r>>>7),j=u[t],ka=j.high,ha=j.low,j=K+((p>>>14|s<<18)^(p>>>18|s<<14)^(p<<23|s>>>9)),w=X+((s>>>14|p<<18)^(s>>>18|p<<14)^(s<<23|p>>>9))+(j>>>0< -K>>>0?1:0),j=j+A,w=w+Y+(j>>>0>>0?1:0),j=j+ha,w=w+ka+(j>>>0>>0?1:0),j=j+h,w=w+q+(j>>>0>>0?1:0),h=B+ja,z=v+z+(h>>>0>>0?1:0),X=V,K=J,V=U,J=I,U=s,I=p,p=H+j|0,s=W+w+(p>>>0>>0?1:0)|0,W=G,H=E,G=F,E=D,F=r,D=n,n=j+h|0,r=w+z+(n>>>0>>0?1:0)|0}M=d.low=M+n;d.high=Z+r+(M>>>0>>0?1:0);N=f.low=N+D;f.high=aa+F+(N>>>0>>0?1:0);O=g.low=O+E;g.high=ba+G+(O>>>0>>0?1:0);P=l.low=P+H;l.high=ca+W+(P>>>0>>0?1:0);Q=e.low=Q+p;e.high=da+s+(Q>>>0

>>0?1:0);R=m.low=R+I;m.high=ea+U+(R>>>0>>0?1:0); -S=L.low=S+J;L.high=fa+V+(S>>>0>>0?1:0);T=c.low=T+K;c.high=ga+X+(T>>>0>>0?1:0)},_doFinalize:function(){var a=this._data,c=a.words,b=8*this._nDataBytes,d=8*a.sigBytes;c[d>>>5]|=128<<24-d%32;c[(d+128>>>10<<5)+30]=Math.floor(b/4294967296);c[(d+128>>>10<<5)+31]=b;a.sigBytes=4*c.length;this._process();return this._hash.toX32()},clone:function(){var a=c.clone.call(this);a._hash=this._hash.clone();return a},blockSize:32});d.SHA512=c._createHelper(b);d.HmacSHA512=c._createHmacHelper(b)})(); -(function(){var a=CryptoJS,d=a.x64,c=d.Word,b=d.WordArray,d=a.algo,f=d.SHA512,d=d.SHA384=f.extend({_doReset:function(){this._hash=new b.init([new c.init(3418070365,3238371032),new c.init(1654270250,914150663),new c.init(2438529370,812702999),new c.init(355462360,4144912697),new c.init(1731405415,4290775857),new c.init(2394180231,1750603025),new c.init(3675008525,1694076839),new c.init(1203062813,3204075428)])},_doFinalize:function(){var a=f._doFinalize.call(this);a.sigBytes-=16;return a}});a.SHA384= -f._createHelper(d);a.HmacSHA384=f._createHmacHelper(d)})(); -(function(){var a=CryptoJS,d=a.enc.Utf8;a.algo.HMAC=a.lib.Base.extend({init:function(a,b){a=this._hasher=new a.init;"string"==typeof b&&(b=d.parse(b));var f=a.blockSize,l=4*f;b.sigBytes>l&&(b=a.finalize(b));b.clamp();for(var u=this._oKey=b.clone(),k=this._iKey=b.clone(),m=u.words,x=k.words,y=0;y>>2]|=(M[b>>>2]>>>24-8*(b%4)&255)<<24-8*((e+b)%4);else if(65535>>2]=M[b>>>2];else d.push.apply(d,M);this.sigBytes+=a;return this},clamp:function(){var D=this.words,d=this.sigBytes;D[d>>>2]&=4294967295<< -32-8*(d%4);D.length=a.ceil(d/4)},clone:function(){var a=l.clone.call(this);a.words=this.words.slice(0);return a},random:function(D){for(var d=[],b=0;b>>2]>>>24-8*(e%4)&255;b.push((c>>>4).toString(16));b.push((c&15).toString(16))}return b.join("")},parse:function(a){for(var d=a.length,b=[],e=0;e>>3]|=parseInt(a.substr(e, -2),16)<<24-4*(e%8);return new u.init(b,d/2)}},y=k.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var c=[],e=0;e>>2]>>>24-8*(e%4)&255));return c.join("")},parse:function(a){for(var b=a.length,c=[],e=0;e>>2]|=(a.charCodeAt(e)&255)<<24-8*(e%4);return new u.init(c,b)}},z=k.Utf8={stringify:function(a){try{return decodeURIComponent(escape(y.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return y.parse(unescape(encodeURIComponent(a)))}}, -x=b.BufferedBlockAlgorithm=l.extend({reset:function(){this._data=new u.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=z.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(b){var d=this._data,c=d.words,e=d.sigBytes,l=this.blockSize,k=e/(4*l),k=b?a.ceil(k):a.max((k|0)-this._minBufferSize,0);b=k*l;e=a.min(4*b,e);if(b){for(var x=0;xm;m++)k[m]=a();b=b.SHA512=c.extend({_doReset:function(){this._hash=new l.init([new f.init(1779033703,4089235720),new f.init(3144134277,2227873595),new f.init(1013904242,4271175723),new f.init(2773480762,1595750129),new f.init(1359893119,2917565137),new f.init(2600822924,725511199),new f.init(528734635,4215389547),new f.init(1541459225,327033209)])},_doProcessBlock:function(a,b){for(var c=this._hash.words, -f=c[0],j=c[1],d=c[2],l=c[3],e=c[4],m=c[5],N=c[6],c=c[7],aa=f.high,O=f.low,ba=j.high,P=j.low,ca=d.high,Q=d.low,da=l.high,R=l.low,ea=e.high,S=e.low,fa=m.high,T=m.low,ga=N.high,U=N.low,ha=c.high,V=c.low,r=aa,n=O,G=ba,E=P,H=ca,F=Q,Y=da,I=R,s=ea,p=S,W=fa,J=T,X=ga,K=U,Z=ha,L=V,t=0;80>t;t++){var A=k[t];if(16>t)var q=A.high=a[b+2*t]|0,g=A.low=a[b+2*t+1]|0;else{var q=k[t-15],g=q.high,v=q.low,q=(g>>>1|v<<31)^(g>>>8|v<<24)^g>>>7,v=(v>>>1|g<<31)^(v>>>8|g<<24)^(v>>>7|g<<25),C=k[t-2],g=C.high,h=C.low,C=(g>>>19| -h<<13)^(g<<3|h>>>29)^g>>>6,h=(h>>>19|g<<13)^(h<<3|g>>>29)^(h>>>6|g<<26),g=k[t-7],$=g.high,B=k[t-16],w=B.high,B=B.low,g=v+g.low,q=q+$+(g>>>0>>0?1:0),g=g+h,q=q+C+(g>>>0>>0?1:0),g=g+B,q=q+w+(g>>>0>>0?1:0);A.high=q;A.low=g}var $=s&W^~s&X,B=p&J^~p&K,A=r&G^r&H^G&H,ka=n&E^n&F^E&F,v=(r>>>28|n<<4)^(r<<30|n>>>2)^(r<<25|n>>>7),C=(n>>>28|r<<4)^(n<<30|r>>>2)^(n<<25|r>>>7),h=u[t],la=h.high,ia=h.low,h=L+((p>>>14|s<<18)^(p>>>18|s<<14)^(p<<23|s>>>9)),w=Z+((s>>>14|p<<18)^(s>>>18|p<<14)^(s<<23|p>>>9))+(h>>> -0>>0?1:0),h=h+B,w=w+$+(h>>>0>>0?1:0),h=h+ia,w=w+la+(h>>>0>>0?1:0),h=h+g,w=w+q+(h>>>0>>0?1:0),g=C+ka,A=v+A+(g>>>0>>0?1:0),Z=X,L=K,X=W,K=J,W=s,J=p,p=I+h|0,s=Y+w+(p>>>0>>0?1:0)|0,Y=H,I=F,H=G,F=E,G=r,E=n,n=h+g|0,r=w+A+(n>>>0>>0?1:0)|0}O=f.low=O+n;f.high=aa+r+(O>>>0>>0?1:0);P=j.low=P+E;j.high=ba+G+(P>>>0>>0?1:0);Q=d.low=Q+F;d.high=ca+H+(Q>>>0>>0?1:0);R=l.low=R+I;l.high=da+Y+(R>>>0>>0?1:0);S=e.low=S+p;e.high=ea+s+(S>>>0

>>0?1:0);N=j.low=N+D;j.high=$+G+(N>>>0>>0?1:0);O=b.low=O+E;b.high=aa+H+(O>>>0>>0?1:0);P=g.low=P+I;g.high=ba+W+(P>>>0>>0?1:0);Q=e.low=Q+q;e.high=ca+t+(Q>>>0>>0?1:0);R=k.low=R+J;k.high=da+U+(R>>>0>>0?1:0); -S=m.low=S+K;m.high=ea+V+(S>>>0>>0?1:0);T=d.low=T+L;d.high=fa+X+(T>>>0>>0?1:0)},_doFinalize:function(){var a=this._data,c=a.words,d=8*this._nDataBytes,f=8*a.sigBytes;c[f>>>5]|=128<<24-f%32;c[(f+128>>>10<<5)+30]=Math.floor(d/4294967296);c[(f+128>>>10<<5)+31]=d;a.sigBytes=4*c.length;this._process();return this._hash.toX32()},clone:function(){var a=d.clone.call(this);a._hash=this._hash.clone();return a},blockSize:32});c.SHA512=d._createHelper(j);c.HmacSHA512=d._createHmacHelper(j)})(); -(function(){var a=CryptoJS,c=a.x64,d=c.Word,j=c.WordArray,c=a.algo,f=c.SHA512,c=c.SHA384=f.extend({_doReset:function(){this._hash=new j.init([new d.init(3418070365,3238371032),new d.init(1654270250,914150663),new d.init(2438529370,812702999),new d.init(355462360,4144912697),new d.init(1731405415,4290775857),new d.init(2394180231,1750603025),new d.init(3675008525,1694076839),new d.init(1203062813,3204075428)])},_doFinalize:function(){var a=f._doFinalize.call(this);a.sigBytes-=16;return a}});a.SHA384= -f._createHelper(c);a.HmacSHA384=f._createHmacHelper(c)})(); diff --git a/dashboard-ui/bower_components/cryptojslib/rollups/sha512.js b/dashboard-ui/bower_components/cryptojslib/rollups/sha512.js deleted file mode 100644 index ecbffee76..000000000 --- a/dashboard-ui/bower_components/cryptojslib/rollups/sha512.js +++ /dev/null @@ -1,23 +0,0 @@ -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -var CryptoJS=CryptoJS||function(a,m){var r={},f=r.lib={},g=function(){},l=f.Base={extend:function(a){g.prototype=this;var b=new g;a&&b.mixIn(a);b.hasOwnProperty("init")||(b.init=function(){b.$super.init.apply(this,arguments)});b.init.prototype=b;b.$super=this;return b},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, -p=f.WordArray=l.extend({init:function(a,b){a=this.words=a||[];this.sigBytes=b!=m?b:4*a.length},toString:function(a){return(a||q).stringify(this)},concat:function(a){var b=this.words,d=a.words,c=this.sigBytes;a=a.sigBytes;this.clamp();if(c%4)for(var j=0;j>>2]|=(d[j>>>2]>>>24-8*(j%4)&255)<<24-8*((c+j)%4);else if(65535>>2]=d[j>>>2];else b.push.apply(b,d);this.sigBytes+=a;return this},clamp:function(){var n=this.words,b=this.sigBytes;n[b>>>2]&=4294967295<< -32-8*(b%4);n.length=a.ceil(b/4)},clone:function(){var a=l.clone.call(this);a.words=this.words.slice(0);return a},random:function(n){for(var b=[],d=0;d>>2]>>>24-8*(c%4)&255;d.push((j>>>4).toString(16));d.push((j&15).toString(16))}return d.join("")},parse:function(a){for(var b=a.length,d=[],c=0;c>>3]|=parseInt(a.substr(c, -2),16)<<24-4*(c%8);return new p.init(d,b/2)}},G=y.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var d=[],c=0;c>>2]>>>24-8*(c%4)&255));return d.join("")},parse:function(a){for(var b=a.length,d=[],c=0;c>>2]|=(a.charCodeAt(c)&255)<<24-8*(c%4);return new p.init(d,b)}},fa=y.Utf8={stringify:function(a){try{return decodeURIComponent(escape(G.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return G.parse(unescape(encodeURIComponent(a)))}}, -h=f.BufferedBlockAlgorithm=l.extend({reset:function(){this._data=new p.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=fa.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(n){var b=this._data,d=b.words,c=b.sigBytes,j=this.blockSize,l=c/(4*j),l=n?a.ceil(l):a.max((l|0)-this._minBufferSize,0);n=l*j;c=a.min(4*n,c);if(n){for(var h=0;hq;q++)y[q]=a();f=f.SHA512=r.extend({_doReset:function(){this._hash=new l.init([new g.init(1779033703,4089235720),new g.init(3144134277,2227873595),new g.init(1013904242,4271175723),new g.init(2773480762,1595750129),new g.init(1359893119,2917565137),new g.init(2600822924,725511199),new g.init(528734635,4215389547),new g.init(1541459225,327033209)])},_doProcessBlock:function(a,f){for(var h=this._hash.words, -g=h[0],n=h[1],b=h[2],d=h[3],c=h[4],j=h[5],l=h[6],h=h[7],q=g.high,m=g.low,r=n.high,N=n.low,Z=b.high,O=b.low,$=d.high,P=d.low,aa=c.high,Q=c.low,ba=j.high,R=j.low,ca=l.high,S=l.low,da=h.high,T=h.low,v=q,s=m,H=r,E=N,I=Z,F=O,W=$,J=P,w=aa,t=Q,U=ba,K=R,V=ca,L=S,X=da,M=T,x=0;80>x;x++){var B=y[x];if(16>x)var u=B.high=a[f+2*x]|0,e=B.low=a[f+2*x+1]|0;else{var u=y[x-15],e=u.high,z=u.low,u=(e>>>1|z<<31)^(e>>>8|z<<24)^e>>>7,z=(z>>>1|e<<31)^(z>>>8|e<<24)^(z>>>7|e<<25),D=y[x-2],e=D.high,k=D.low,D=(e>>>19|k<<13)^ -(e<<3|k>>>29)^e>>>6,k=(k>>>19|e<<13)^(k<<3|e>>>29)^(k>>>6|e<<26),e=y[x-7],Y=e.high,C=y[x-16],A=C.high,C=C.low,e=z+e.low,u=u+Y+(e>>>0>>0?1:0),e=e+k,u=u+D+(e>>>0>>0?1:0),e=e+C,u=u+A+(e>>>0>>0?1:0);B.high=u;B.low=e}var Y=w&U^~w&V,C=t&K^~t&L,B=v&H^v&I^H&I,ha=s&E^s&F^E&F,z=(v>>>28|s<<4)^(v<<30|s>>>2)^(v<<25|s>>>7),D=(s>>>28|v<<4)^(s<<30|v>>>2)^(s<<25|v>>>7),k=p[x],ia=k.high,ea=k.low,k=M+((t>>>14|w<<18)^(t>>>18|w<<14)^(t<<23|w>>>9)),A=X+((w>>>14|t<<18)^(w>>>18|t<<14)^(w<<23|t>>>9))+(k>>>0>> -0?1:0),k=k+C,A=A+Y+(k>>>0>>0?1:0),k=k+ea,A=A+ia+(k>>>0>>0?1:0),k=k+e,A=A+u+(k>>>0>>0?1:0),e=D+ha,B=z+B+(e>>>0>>0?1:0),X=V,M=L,V=U,L=K,U=w,K=t,t=J+k|0,w=W+A+(t>>>0>>0?1:0)|0,W=I,J=F,I=H,F=E,H=v,E=s,s=k+e|0,v=A+B+(s>>>0>>0?1:0)|0}m=g.low=m+s;g.high=q+v+(m>>>0>>0?1:0);N=n.low=N+E;n.high=r+H+(N>>>0>>0?1:0);O=b.low=O+F;b.high=Z+I+(O>>>0>>0?1:0);P=d.low=P+J;d.high=$+W+(P>>>0>>0?1:0);Q=c.low=Q+t;c.high=aa+w+(Q>>>0>>0?1:0);R=j.low=R+K;j.high=ba+U+(R>>>0>>0?1:0);S=l.low= -S+L;l.high=ca+V+(S>>>0>>0?1:0);T=h.low=T+M;h.high=da+X+(T>>>0>>0?1:0)},_doFinalize:function(){var a=this._data,f=a.words,h=8*this._nDataBytes,g=8*a.sigBytes;f[g>>>5]|=128<<24-g%32;f[(g+128>>>10<<5)+30]=Math.floor(h/4294967296);f[(g+128>>>10<<5)+31]=h;a.sigBytes=4*f.length;this._process();return this._hash.toX32()},clone:function(){var a=r.clone.call(this);a._hash=this._hash.clone();return a},blockSize:32});m.SHA512=r._createHelper(f);m.HmacSHA512=r._createHmacHelper(f)})(); diff --git a/dashboard-ui/bower_components/cryptojslib/rollups/tripledes.js b/dashboard-ui/bower_components/cryptojslib/rollups/tripledes.js deleted file mode 100644 index ba24108e7..000000000 --- a/dashboard-ui/bower_components/cryptojslib/rollups/tripledes.js +++ /dev/null @@ -1,51 +0,0 @@ -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -var CryptoJS=CryptoJS||function(u,l){var d={},n=d.lib={},p=function(){},s=n.Base={extend:function(a){p.prototype=this;var c=new p;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, -q=n.WordArray=s.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=l?c:4*a.length},toString:function(a){return(a||v).stringify(this)},concat:function(a){var c=this.words,m=a.words,f=this.sigBytes;a=a.sigBytes;this.clamp();if(f%4)for(var t=0;t>>2]|=(m[t>>>2]>>>24-8*(t%4)&255)<<24-8*((f+t)%4);else if(65535>>2]=m[t>>>2];else c.push.apply(c,m);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< -32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=s.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],m=0;m>>2]>>>24-8*(f%4)&255;m.push((t>>>4).toString(16));m.push((t&15).toString(16))}return m.join("")},parse:function(a){for(var c=a.length,m=[],f=0;f>>3]|=parseInt(a.substr(f, -2),16)<<24-4*(f%8);return new q.init(m,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var m=[],f=0;f>>2]>>>24-8*(f%4)&255));return m.join("")},parse:function(a){for(var c=a.length,m=[],f=0;f>>2]|=(a.charCodeAt(f)&255)<<24-8*(f%4);return new q.init(m,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}}, -r=n.BufferedBlockAlgorithm=s.extend({reset:function(){this._data=new q.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=x.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,m=c.words,f=c.sigBytes,t=this.blockSize,b=f/(4*t),b=a?u.ceil(b):u.max((b|0)-this._minBufferSize,0);a=b*t;f=u.min(4*a,f);if(a){for(var e=0;e>>2]>>>24-8*(q%4)&255)<<16|(n[q+1>>>2]>>>24-8*((q+1)%4)&255)<<8|n[q+2>>>2]>>>24-8*((q+2)%4)&255,v=0;4>v&&q+0.75*v>>6*(3-v)&63));if(n=s.charAt(64))for(;d.length%4;)d.push(n);return d.join("")},parse:function(d){var n=d.length,p=this._map,s=p.charAt(64);s&&(s=d.indexOf(s),-1!=s&&(n=s));for(var s=[],q=0,w=0;w< -n;w++)if(w%4){var v=p.indexOf(d.charAt(w-1))<<2*(w%4),b=p.indexOf(d.charAt(w))>>>6-2*(w%4);s[q>>>2]|=(v|b)<<24-8*(q%4);q++}return l.create(s,q)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})(); -(function(u){function l(b,e,a,c,m,f,t){b=b+(e&a|~e&c)+m+t;return(b<>>32-f)+e}function d(b,e,a,c,m,f,t){b=b+(e&c|a&~c)+m+t;return(b<>>32-f)+e}function n(b,e,a,c,m,f,t){b=b+(e^a^c)+m+t;return(b<>>32-f)+e}function p(b,e,a,c,m,f,t){b=b+(a^(e|~c))+m+t;return(b<>>32-f)+e}for(var s=CryptoJS,q=s.lib,w=q.WordArray,v=q.Hasher,q=s.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;q=q.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])}, -_doProcessBlock:function(r,e){for(var a=0;16>a;a++){var c=e+a,m=r[c];r[c]=(m<<8|m>>>24)&16711935|(m<<24|m>>>8)&4278255360}var a=this._hash.words,c=r[e+0],m=r[e+1],f=r[e+2],t=r[e+3],y=r[e+4],q=r[e+5],s=r[e+6],w=r[e+7],v=r[e+8],u=r[e+9],x=r[e+10],z=r[e+11],A=r[e+12],B=r[e+13],C=r[e+14],D=r[e+15],g=a[0],h=a[1],j=a[2],k=a[3],g=l(g,h,j,k,c,7,b[0]),k=l(k,g,h,j,m,12,b[1]),j=l(j,k,g,h,f,17,b[2]),h=l(h,j,k,g,t,22,b[3]),g=l(g,h,j,k,y,7,b[4]),k=l(k,g,h,j,q,12,b[5]),j=l(j,k,g,h,s,17,b[6]),h=l(h,j,k,g,w,22,b[7]), -g=l(g,h,j,k,v,7,b[8]),k=l(k,g,h,j,u,12,b[9]),j=l(j,k,g,h,x,17,b[10]),h=l(h,j,k,g,z,22,b[11]),g=l(g,h,j,k,A,7,b[12]),k=l(k,g,h,j,B,12,b[13]),j=l(j,k,g,h,C,17,b[14]),h=l(h,j,k,g,D,22,b[15]),g=d(g,h,j,k,m,5,b[16]),k=d(k,g,h,j,s,9,b[17]),j=d(j,k,g,h,z,14,b[18]),h=d(h,j,k,g,c,20,b[19]),g=d(g,h,j,k,q,5,b[20]),k=d(k,g,h,j,x,9,b[21]),j=d(j,k,g,h,D,14,b[22]),h=d(h,j,k,g,y,20,b[23]),g=d(g,h,j,k,u,5,b[24]),k=d(k,g,h,j,C,9,b[25]),j=d(j,k,g,h,t,14,b[26]),h=d(h,j,k,g,v,20,b[27]),g=d(g,h,j,k,B,5,b[28]),k=d(k,g, -h,j,f,9,b[29]),j=d(j,k,g,h,w,14,b[30]),h=d(h,j,k,g,A,20,b[31]),g=n(g,h,j,k,q,4,b[32]),k=n(k,g,h,j,v,11,b[33]),j=n(j,k,g,h,z,16,b[34]),h=n(h,j,k,g,C,23,b[35]),g=n(g,h,j,k,m,4,b[36]),k=n(k,g,h,j,y,11,b[37]),j=n(j,k,g,h,w,16,b[38]),h=n(h,j,k,g,x,23,b[39]),g=n(g,h,j,k,B,4,b[40]),k=n(k,g,h,j,c,11,b[41]),j=n(j,k,g,h,t,16,b[42]),h=n(h,j,k,g,s,23,b[43]),g=n(g,h,j,k,u,4,b[44]),k=n(k,g,h,j,A,11,b[45]),j=n(j,k,g,h,D,16,b[46]),h=n(h,j,k,g,f,23,b[47]),g=p(g,h,j,k,c,6,b[48]),k=p(k,g,h,j,w,10,b[49]),j=p(j,k,g,h, -C,15,b[50]),h=p(h,j,k,g,q,21,b[51]),g=p(g,h,j,k,A,6,b[52]),k=p(k,g,h,j,t,10,b[53]),j=p(j,k,g,h,x,15,b[54]),h=p(h,j,k,g,m,21,b[55]),g=p(g,h,j,k,v,6,b[56]),k=p(k,g,h,j,D,10,b[57]),j=p(j,k,g,h,s,15,b[58]),h=p(h,j,k,g,B,21,b[59]),g=p(g,h,j,k,y,6,b[60]),k=p(k,g,h,j,z,10,b[61]),j=p(j,k,g,h,f,15,b[62]),h=p(h,j,k,g,u,21,b[63]);a[0]=a[0]+g|0;a[1]=a[1]+h|0;a[2]=a[2]+j|0;a[3]=a[3]+k|0},_doFinalize:function(){var b=this._data,e=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;e[c>>>5]|=128<<24-c%32;var m=u.floor(a/ -4294967296);e[(c+64>>>9<<4)+15]=(m<<8|m>>>24)&16711935|(m<<24|m>>>8)&4278255360;e[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(e.length+1);this._process();b=this._hash;e=b.words;for(a=0;4>a;a++)c=e[a],e[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});s.MD5=v._createHelper(q);s.HmacMD5=v._createHmacHelper(q)})(Math); -(function(){var u=CryptoJS,l=u.lib,d=l.Base,n=l.WordArray,l=u.algo,p=l.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:l.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,l){for(var p=this.cfg,v=p.hasher.create(),b=n.create(),u=b.words,r=p.keySize,p=p.iterations;u.length>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:r}),reset:function(){v.reset.call(this);var a=this.cfg,c=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var b=a.createEncryptor;else b=a.createDecryptor,this._minBufferSize=1;this._mode=b.call(a, -this,c&&c.words)},_doProcessBlock:function(a,c){this._mode.processBlock(a,c)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var c=this._process(!0)}else c=this._process(!0),a.unpad(c);return c},blockSize:4});var e=d.CipherParams=n.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(l.format={}).OpenSSL={stringify:function(a){var c=a.ciphertext;a=a.salt;return(a?p.create([1398893684, -1701076831]).concat(a).concat(c):c).toString(q)},parse:function(a){a=q.parse(a);var c=a.words;if(1398893684==c[0]&&1701076831==c[1]){var b=p.create(c.slice(2,4));c.splice(0,4);a.sigBytes-=16}return e.create({ciphertext:a,salt:b})}},a=d.SerializableCipher=n.extend({cfg:n.extend({format:b}),encrypt:function(a,c,b,d){d=this.cfg.extend(d);var l=a.createEncryptor(b,d);c=l.finalize(c);l=l.cfg;return e.create({ciphertext:c,key:b,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})}, -decrypt:function(a,c,b,e){e=this.cfg.extend(e);c=this._parse(c,e.format);return a.createDecryptor(b,e).finalize(c.ciphertext)},_parse:function(a,c){return"string"==typeof a?c.parse(a,this):a}}),l=(l.kdf={}).OpenSSL={execute:function(a,c,b,d){d||(d=p.random(8));a=w.create({keySize:c+b}).compute(a,d);b=p.create(a.words.slice(c),4*b);a.sigBytes=4*c;return e.create({key:a,iv:b,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:l}),encrypt:function(c,b,e,d){d=this.cfg.extend(d);e=d.kdf.execute(e, -c.keySize,c.ivSize);d.iv=e.iv;c=a.encrypt.call(this,c,b,e.key,d);c.mixIn(e);return c},decrypt:function(c,b,e,d){d=this.cfg.extend(d);b=this._parse(b,d.format);e=d.kdf.execute(e,c.keySize,c.ivSize,b.salt);d.iv=e.iv;return a.decrypt.call(this,c,b,e.key,d)}})}(); -(function(){function u(b,a){var c=(this._lBlock>>>b^this._rBlock)&a;this._rBlock^=c;this._lBlock^=c<>>b^this._lBlock)&a;this._lBlock^=c;this._rBlock^=c<c;c++){var d=q[c]-1;a[c]=b[d>>>5]>>>31-d%32&1}b=this._subKeys=[];for(d=0;16>d;d++){for(var f=b[d]=[],l=v[d],c=0;24>c;c++)f[c/6|0]|=a[(w[c]-1+l)%28]<<31-c%6,f[4+(c/6|0)]|=a[28+(w[c+24]-1+l)%28]<<31-c%6;f[0]=f[0]<<1|f[0]>>>31;for(c=1;7>c;c++)f[c]>>>= -4*(c-1)+3;f[7]=f[7]<<5|f[7]>>>27}a=this._invSubKeys=[];for(c=0;16>c;c++)a[c]=b[15-c]},encryptBlock:function(b,a){this._doCryptBlock(b,a,this._subKeys)},decryptBlock:function(b,a){this._doCryptBlock(b,a,this._invSubKeys)},_doCryptBlock:function(e,a,c){this._lBlock=e[a];this._rBlock=e[a+1];u.call(this,4,252645135);u.call(this,16,65535);l.call(this,2,858993459);l.call(this,8,16711935);u.call(this,1,1431655765);for(var d=0;16>d;d++){for(var f=c[d],n=this._lBlock,p=this._rBlock,q=0,r=0;8>r;r++)q|=b[r][((p^ -f[r])&x[r])>>>0];this._lBlock=p;this._rBlock=n^q}c=this._lBlock;this._lBlock=this._rBlock;this._rBlock=c;u.call(this,1,1431655765);l.call(this,8,16711935);l.call(this,2,858993459);u.call(this,16,65535);u.call(this,4,252645135);e[a]=this._lBlock;e[a+1]=this._rBlock},keySize:2,ivSize:2,blockSize:2});d.DES=n._createHelper(r);s=s.TripleDES=n.extend({_doReset:function(){var b=this._key.words;this._des1=r.createEncryptor(p.create(b.slice(0,2)));this._des2=r.createEncryptor(p.create(b.slice(2,4)));this._des3= -r.createEncryptor(p.create(b.slice(4,6)))},encryptBlock:function(b,a){this._des1.encryptBlock(b,a);this._des2.decryptBlock(b,a);this._des3.encryptBlock(b,a)},decryptBlock:function(b,a){this._des3.decryptBlock(b,a);this._des2.encryptBlock(b,a);this._des1.decryptBlock(b,a)},keySize:6,ivSize:2,blockSize:2});d.TripleDES=n._createHelper(s)})(); diff --git a/dashboard-ui/bower_components/fetch/.bower.json b/dashboard-ui/bower_components/fetch/.bower.json index 96d72ad5c..4a0490aa1 100644 --- a/dashboard-ui/bower_components/fetch/.bower.json +++ b/dashboard-ui/bower_components/fetch/.bower.json @@ -14,15 +14,14 @@ "test/" ], "homepage": "https://github.com/github/fetch", - "version": "0.10.1", - "_release": "0.10.1", + "version": "0.11.1", + "_release": "0.11.1", "_resolution": { "type": "version", - "tag": "v0.10.1", - "commit": "f4f8ca8d0ba6c7d11e5317a84189913cefe55809" + "tag": "v0.11.1", + "commit": "7d9a11deec5c0ea2d453390be647ba52695166f8" }, - "_source": "git://github.com/github/fetch.git", - "_target": "~0.10.1", - "_originalSource": "fetch", - "_direct": true + "_source": "https://github.com/github/fetch.git", + "_target": "^0.11.0", + "_originalSource": "fetch" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/fetch/LICENSE b/dashboard-ui/bower_components/fetch/LICENSE index ef00ba265..0e319d55d 100644 --- a/dashboard-ui/bower_components/fetch/LICENSE +++ b/dashboard-ui/bower_components/fetch/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2015 GitHub, Inc. +Copyright (c) 2014-2016 GitHub, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/dashboard-ui/bower_components/fetch/fetch.js b/dashboard-ui/bower_components/fetch/fetch.js index f89f27a66..01aa5d063 100644 --- a/dashboard-ui/bower_components/fetch/fetch.js +++ b/dashboard-ui/bower_components/fetch/fetch.js @@ -1,4 +1,4 @@ -(function() { +(function(self) { 'use strict'; if (self.fetch) { @@ -110,7 +110,7 @@ var support = { blob: 'FileReader' in self && 'Blob' in self && (function() { try { - new Blob(); + new Blob() return true } catch(e) { return false @@ -140,6 +140,14 @@ } else { throw new Error('unsupported BodyInit type') } + + if (!this.headers.get('content-type')) { + if (typeof body === 'string') { + this.headers.set('content-type', 'text/plain;charset=UTF-8') + } else if (this._bodyBlob && this._bodyBlob.type) { + this.headers.set('content-type', this._bodyBlob.type) + } + } } if (support.blob) { @@ -259,7 +267,7 @@ function headers(xhr) { var head = new Headers() - var pairs = xhr.getAllResponseHeaders().trim().split('\n') + var pairs = (xhr.getAllResponseHeaders() || '').trim().split('\n') pairs.forEach(function(header) { var split = header.trim().split(':') var key = split.shift().trim() @@ -276,13 +284,13 @@ options = {} } - this._initBody(bodyInit) this.type = 'default' this.status = options.status this.ok = this.status >= 200 && this.status < 300 this.statusText = options.statusText this.headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers) this.url = options.url || '' + this._initBody(bodyInit) } Body.call(Response.prototype) @@ -312,9 +320,9 @@ return new Response(null, {status: status, headers: {location: url}}) } - self.Headers = Headers; - self.Request = Request; - self.Response = Response; + self.Headers = Headers + self.Request = Request + self.Response = Response self.fetch = function(input, init) { return new Promise(function(resolve, reject) { @@ -337,7 +345,7 @@ return xhr.getResponseHeader('X-Request-URL') } - return; + return } xhr.onload = function() { @@ -352,7 +360,7 @@ headers: headers(xhr), url: responseURL() } - var body = 'response' in xhr ? xhr.response : xhr.responseText; + var body = 'response' in xhr ? xhr.response : xhr.responseText resolve(new Response(body, options)) } @@ -360,6 +368,10 @@ reject(new TypeError('Network request failed')) } + xhr.ontimeout = function() { + reject(new TypeError('Network request failed')) + } + xhr.open(request.method, request.url, true) if (request.credentials === 'include') { @@ -378,4 +390,4 @@ }) } self.fetch.polyfill = true -})(); +})(typeof self !== 'undefined' ? self : this); diff --git a/dashboard-ui/bower_components/fingerprintjs2/.bower.json b/dashboard-ui/bower_components/fingerprintjs2/.bower.json index dc61d5d90..4ac638717 100644 --- a/dashboard-ui/bower_components/fingerprintjs2/.bower.json +++ b/dashboard-ui/bower_components/fingerprintjs2/.bower.json @@ -23,14 +23,14 @@ "spec" ], "homepage": "https://github.com/Valve/fingerprintjs2", - "version": "1.4.0", - "_release": "1.4.0", + "version": "1.1.4", + "_release": "1.1.4", "_resolution": { "type": "version", - "tag": "1.4.0", - "commit": "75cbd474158f8ecce43e00f198c76e486b896937" + "tag": "1.1.4", + "commit": "ae5719db3d942a1a84ab43b707d4d1c34138934e" }, "_source": "https://github.com/Valve/fingerprintjs2.git", - "_target": "^1.1.3", + "_target": "~1.1.2", "_originalSource": "fingerprintjs2" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/fingerprintjs2/CONTRIBUTING.md b/dashboard-ui/bower_components/fingerprintjs2/CONTRIBUTING.md index 7b4835504..33049a165 100644 --- a/dashboard-ui/bower_components/fingerprintjs2/CONTRIBUTING.md +++ b/dashboard-ui/bower_components/fingerprintjs2/CONTRIBUTING.md @@ -13,7 +13,7 @@ Include in the issue: * Include library call code (I need all options you used when calling the library function) ## Want to add a feature / contribute? -* Make sure the issue/suggestion does not exist by searching existing issues + * Fork the project and make the required changes in it (don't forget to add specs) * PRs w/out specs will not be accepted * Run `gulp` to catch stylistic errors and produce the minified version. diff --git a/dashboard-ui/bower_components/fingerprintjs2/dist/fingerprint2.min.js b/dashboard-ui/bower_components/fingerprintjs2/dist/fingerprint2.min.js index 3d5aafd2e..c2a5d2c02 100644 --- a/dashboard-ui/bower_components/fingerprintjs2/dist/fingerprint2.min.js +++ b/dashboard-ui/bower_components/fingerprintjs2/dist/fingerprint2.min.js @@ -1,2 +1,2 @@ -!function(e,t,i){"use strict";"undefined"!=typeof module&&module.exports?module.exports=i():"function"==typeof define&&define.amd?define(i):t[e]=i()}("Fingerprint2",this,function(){"use strict";Array.prototype.indexOf||(Array.prototype.indexOf=function(e,t){var i;if(null==this)throw new TypeError("'this' is null or undefined");var a=Object(this),r=a.length>>>0;if(0===r)return-1;var n=+t||0;if(Math.abs(n)===1/0&&(n=0),n>=r)return-1;for(i=Math.max(n>=0?n:r-Math.abs(n),0);r>i;){if(i in a&&a[i]===e)return i;i++}return-1});var e=function(e){var t={swfContainerId:"fingerprintjs2",swfPath:"flash/compiled/FontList.swf",detectScreenOrientation:!0,sortPluginsFor:[/palemoon/i]};this.options=this.extend(e,t),this.nativeForEach=Array.prototype.forEach,this.nativeMap=Array.prototype.map};return e.prototype={extend:function(e,t){if(null==e)return t;for(var i in e)null!=e[i]&&t[i]!==e[i]&&(t[i]=e[i]);return t},log:function(e){window.console&&console.log(e)},get:function(e){var t=[];t=this.userAgentKey(t),t=this.languageKey(t),t=this.colorDepthKey(t),t=this.pixelRatioKey(t),t=this.screenResolutionKey(t),t=this.availableScreenResolutionKey(t),t=this.timezoneOffsetKey(t),t=this.sessionStorageKey(t),t=this.localStorageKey(t),t=this.indexedDbKey(t),t=this.addBehaviorKey(t),t=this.openDatabaseKey(t),t=this.cpuClassKey(t),t=this.platformKey(t),t=this.doNotTrackKey(t),t=this.pluginsKey(t),t=this.canvasKey(t),t=this.webglKey(t),t=this.adBlockKey(t),t=this.hasLiedLanguagesKey(t),t=this.hasLiedResolutionKey(t),t=this.hasLiedOsKey(t),t=this.hasLiedBrowserKey(t),t=this.touchSupportKey(t);var i=this;this.fontsKey(t,function(t){var a=[];i.each(t,function(e){var t=e.value;"undefined"!=typeof e.value.join&&(t=e.value.join(";")),a.push(t)});var r=i.x64hash128(a.join("~~~"),31);return e(r,t)})},userAgentKey:function(e){return this.options.excludeUserAgent||e.push({key:"user_agent",value:this.getUserAgent()}),e},getUserAgent:function(){return navigator.userAgent},languageKey:function(e){return this.options.excludeLanguage||e.push({key:"language",value:navigator.language||navigator.userLanguage||navigator.browserLanguage||navigator.systemLanguage||""}),e},colorDepthKey:function(e){return this.options.excludeColorDepth||e.push({key:"color_depth",value:screen.colorDepth}),e},pixelRatioKey:function(e){return this.options.excludePixelRatio||e.push({key:"pixel_ratio",value:this.getPixelRatio()}),e},getPixelRatio:function(){return window.devicePixelRatio||""},screenResolutionKey:function(e){return this.options.excludeScreenResolution?e:this.getScreenResolution(e)},getScreenResolution:function(e){var t;return t=this.options.detectScreenOrientation&&screen.height>screen.width?[screen.height,screen.width]:[screen.width,screen.height],"undefined"!=typeof t&&e.push({key:"resolution",value:t}),e},availableScreenResolutionKey:function(e){return this.options.excludeAvailableScreenResolution?e:this.getAvailableScreenResolution(e)},getAvailableScreenResolution:function(e){var t;return screen.availWidth&&screen.availHeight&&(t=this.options.detectScreenOrientation?screen.availHeight>screen.availWidth?[screen.availHeight,screen.availWidth]:[screen.availWidth,screen.availHeight]:[screen.availHeight,screen.availWidth]),"undefined"!=typeof t&&e.push({key:"available_resolution",value:t}),e},timezoneOffsetKey:function(e){return this.options.excludeTimezoneOffset||e.push({key:"timezone_offset",value:(new Date).getTimezoneOffset()}),e},sessionStorageKey:function(e){return!this.options.excludeSessionStorage&&this.hasSessionStorage()&&e.push({key:"session_storage",value:1}),e},localStorageKey:function(e){return!this.options.excludeSessionStorage&&this.hasLocalStorage()&&e.push({key:"local_storage",value:1}),e},indexedDbKey:function(e){return!this.options.excludeIndexedDB&&this.hasIndexedDB()&&e.push({key:"indexed_db",value:1}),e},addBehaviorKey:function(e){return document.body&&!this.options.excludeAddBehavior&&document.body.addBehavior&&e.push({key:"add_behavior",value:1}),e},openDatabaseKey:function(e){return!this.options.excludeOpenDatabase&&window.openDatabase&&e.push({key:"open_database",value:1}),e},cpuClassKey:function(e){return this.options.excludeCpuClass||e.push({key:"cpu_class",value:this.getNavigatorCpuClass()}),e},platformKey:function(e){return this.options.excludePlatform||e.push({key:"navigator_platform",value:this.getNavigatorPlatform()}),e},doNotTrackKey:function(e){return this.options.excludeDoNotTrack||e.push({key:"do_not_track",value:this.getDoNotTrack()}),e},canvasKey:function(e){return!this.options.excludeCanvas&&this.isCanvasSupported()&&e.push({key:"canvas",value:this.getCanvasFp()}),e},webglKey:function(e){return this.options.excludeWebGL?e:this.isWebGlSupported()?(e.push({key:"webgl",value:this.getWebglFp()}),e):e},adBlockKey:function(e){return this.options.excludeAdBlock||e.push({key:"adblock",value:this.getAdBlock()}),e},hasLiedLanguagesKey:function(e){return this.options.excludeHasLiedLanguages||e.push({key:"has_lied_languages",value:this.getHasLiedLanguages()}),e},hasLiedResolutionKey:function(e){return this.options.excludeHasLiedResolution||e.push({key:"has_lied_resolution",value:this.getHasLiedResolution()}),e},hasLiedOsKey:function(e){return this.options.excludeHasLiedOs||e.push({key:"has_lied_os",value:this.getHasLiedOs()}),e},hasLiedBrowserKey:function(e){return this.options.excludeHasLiedBrowser||e.push({key:"has_lied_browser",value:this.getHasLiedBrowser()}),e},fontsKey:function(e,t){return this.options.excludeJsFonts?this.flashFontsKey(e,t):this.jsFontsKey(e,t)},flashFontsKey:function(e,t){return this.options.excludeFlashFonts?t(e):this.hasSwfObjectLoaded()&&this.hasMinFlashInstalled()?"undefined"==typeof this.options.swfPath?t(e):void this.loadSwfAndDetectFonts(function(i){e.push({key:"swf_fonts",value:i.join(";")}),t(e)}):t(e)},jsFontsKey:function(e,t){var i=this;return setTimeout(function(){var a=["monospace","sans-serif","serif"],r=["Andale Mono","Arial","Arial Black","Arial Hebrew","Arial MT","Arial Narrow","Arial Rounded MT Bold","Arial Unicode MS","Bitstream Vera Sans Mono","Book Antiqua","Bookman Old Style","Calibri","Cambria","Cambria Math","Century","Century Gothic","Century Schoolbook","Comic Sans","Comic Sans MS","Consolas","Courier","Courier New","Garamond","Geneva","Georgia","Helvetica","Helvetica Neue","Impact","Lucida Bright","Lucida Calligraphy","Lucida Console","Lucida Fax","LUCIDA GRANDE","Lucida Handwriting","Lucida Sans","Lucida Sans Typewriter","Lucida Sans Unicode","Microsoft Sans Serif","Monaco","Monotype Corsiva","MS Gothic","MS Outlook","MS PGothic","MS Reference Sans Serif","MS Sans Serif","MS Serif","MYRIAD","MYRIAD PRO","Palatino","Palatino Linotype","Segoe Print","Segoe Script","Segoe UI","Segoe UI Light","Segoe UI Semibold","Segoe UI Symbol","Tahoma","Times","Times New Roman","Times New Roman PS","Trebuchet MS","Verdana","Wingdings","Wingdings 2","Wingdings 3"],n=["Abadi MT Condensed Light","Academy Engraved LET","ADOBE CASLON PRO","Adobe Garamond","ADOBE GARAMOND PRO","Agency FB","Aharoni","Albertus Extra Bold","Albertus Medium","Algerian","Amazone BT","American Typewriter","American Typewriter Condensed","AmerType Md BT","Andalus","Angsana New","AngsanaUPC","Antique Olive","Aparajita","Apple Chancery","Apple Color Emoji","Apple SD Gothic Neo","Arabic Typesetting","ARCHER","ARNO PRO","Arrus BT","Aurora Cn BT","AvantGarde Bk BT","AvantGarde Md BT","AVENIR","Ayuthaya","Bandy","Bangla Sangam MN","Bank Gothic","BankGothic Md BT","Baskerville","Baskerville Old Face","Batang","BatangChe","Bauer Bodoni","Bauhaus 93","Bazooka","Bell MT","Bembo","Benguiat Bk BT","Berlin Sans FB","Berlin Sans FB Demi","Bernard MT Condensed","BernhardFashion BT","BernhardMod BT","Big Caslon","BinnerD","Blackadder ITC","BlairMdITC TT","Bodoni 72","Bodoni 72 Oldstyle","Bodoni 72 Smallcaps","Bodoni MT","Bodoni MT Black","Bodoni MT Condensed","Bodoni MT Poster Compressed","Bookshelf Symbol 7","Boulder","Bradley Hand","Bradley Hand ITC","Bremen Bd BT","Britannic Bold","Broadway","Browallia New","BrowalliaUPC","Brush Script MT","Californian FB","Calisto MT","Calligrapher","Candara","CaslonOpnface BT","Castellar","Centaur","Cezanne","CG Omega","CG Times","Chalkboard","Chalkboard SE","Chalkduster","Charlesworth","Charter Bd BT","Charter BT","Chaucer","ChelthmITC Bk BT","Chiller","Clarendon","Clarendon Condensed","CloisterBlack BT","Cochin","Colonna MT","Constantia","Cooper Black","Copperplate","Copperplate Gothic","Copperplate Gothic Bold","Copperplate Gothic Light","CopperplGoth Bd BT","Corbel","Cordia New","CordiaUPC","Cornerstone","Coronet","Cuckoo","Curlz MT","DaunPenh","Dauphin","David","DB LCD Temp","DELICIOUS","Denmark","DFKai-SB","Didot","DilleniaUPC","DIN","DokChampa","Dotum","DotumChe","Ebrima","Edwardian Script ITC","Elephant","English 111 Vivace BT","Engravers MT","EngraversGothic BT","Eras Bold ITC","Eras Demi ITC","Eras Light ITC","Eras Medium ITC","EucrosiaUPC","Euphemia","Euphemia UCAS","EUROSTILE","Exotc350 Bd BT","FangSong","Felix Titling","Fixedsys","FONTIN","Footlight MT Light","Forte","FrankRuehl","Fransiscan","Freefrm721 Blk BT","FreesiaUPC","Freestyle Script","French Script MT","FrnkGothITC Bk BT","Fruitger","FRUTIGER","Futura","Futura Bk BT","Futura Lt BT","Futura Md BT","Futura ZBlk BT","FuturaBlack BT","Gabriola","Galliard BT","Gautami","Geeza Pro","Geometr231 BT","Geometr231 Hv BT","Geometr231 Lt BT","GeoSlab 703 Lt BT","GeoSlab 703 XBd BT","Gigi","Gill Sans","Gill Sans MT","Gill Sans MT Condensed","Gill Sans MT Ext Condensed Bold","Gill Sans Ultra Bold","Gill Sans Ultra Bold Condensed","Gisha","Gloucester MT Extra Condensed","GOTHAM","GOTHAM BOLD","Goudy Old Style","Goudy Stout","GoudyHandtooled BT","GoudyOLSt BT","Gujarati Sangam MN","Gulim","GulimChe","Gungsuh","GungsuhChe","Gurmukhi MN","Haettenschweiler","Harlow Solid Italic","Harrington","Heather","Heiti SC","Heiti TC","HELV","Herald","High Tower Text","Hiragino Kaku Gothic ProN","Hiragino Mincho ProN","Hoefler Text","Humanst 521 Cn BT","Humanst521 BT","Humanst521 Lt BT","Imprint MT Shadow","Incised901 Bd BT","Incised901 BT","Incised901 Lt BT","INCONSOLATA","Informal Roman","Informal011 BT","INTERSTATE","IrisUPC","Iskoola Pota","JasmineUPC","Jazz LET","Jenson","Jester","Jokerman","Juice ITC","Kabel Bk BT","Kabel Ult BT","Kailasa","KaiTi","Kalinga","Kannada Sangam MN","Kartika","Kaufmann Bd BT","Kaufmann BT","Khmer UI","KodchiangUPC","Kokila","Korinna BT","Kristen ITC","Krungthep","Kunstler Script","Lao UI","Latha","Leelawadee","Letter Gothic","Levenim MT","LilyUPC","Lithograph","Lithograph Light","Long Island","Lydian BT","Magneto","Maiandra GD","Malayalam Sangam MN","Malgun Gothic","Mangal","Marigold","Marion","Marker Felt","Market","Marlett","Matisse ITC","Matura MT Script Capitals","Meiryo","Meiryo UI","Microsoft Himalaya","Microsoft JhengHei","Microsoft New Tai Lue","Microsoft PhagsPa","Microsoft Tai Le","Microsoft Uighur","Microsoft YaHei","Microsoft Yi Baiti","MingLiU","MingLiU_HKSCS","MingLiU_HKSCS-ExtB","MingLiU-ExtB","Minion","Minion Pro","Miriam","Miriam Fixed","Mistral","Modern","Modern No. 20","Mona Lisa Solid ITC TT","Mongolian Baiti","MONO","MoolBoran","Mrs Eaves","MS LineDraw","MS Mincho","MS PMincho","MS Reference Specialty","MS UI Gothic","MT Extra","MUSEO","MV Boli","Nadeem","Narkisim","NEVIS","News Gothic","News GothicMT","NewsGoth BT","Niagara Engraved","Niagara Solid","Noteworthy","NSimSun","Nyala","OCR A Extended","Old Century","Old English Text MT","Onyx","Onyx BT","OPTIMA","Oriya Sangam MN","OSAKA","OzHandicraft BT","Palace Script MT","Papyrus","Parchment","Party LET","Pegasus","Perpetua","Perpetua Titling MT","PetitaBold","Pickwick","Plantagenet Cherokee","Playbill","PMingLiU","PMingLiU-ExtB","Poor Richard","Poster","PosterBodoni BT","PRINCETOWN LET","Pristina","PTBarnum BT","Pythagoras","Raavi","Rage Italic","Ravie","Ribbon131 Bd BT","Rockwell","Rockwell Condensed","Rockwell Extra Bold","Rod","Roman","Sakkal Majalla","Santa Fe LET","Savoye LET","Sceptre","Script","Script MT Bold","SCRIPTINA","Serifa","Serifa BT","Serifa Th BT","ShelleyVolante BT","Sherwood","Shonar Bangla","Showcard Gothic","Shruti","Signboard","SILKSCREEN","SimHei","Simplified Arabic","Simplified Arabic Fixed","SimSun","SimSun-ExtB","Sinhala Sangam MN","Sketch Rockwell","Skia","Small Fonts","Snap ITC","Snell Roundhand","Socket","Souvenir Lt BT","Staccato222 BT","Steamer","Stencil","Storybook","Styllo","Subway","Swis721 BlkEx BT","Swiss911 XCm BT","Sylfaen","Synchro LET","System","Tamil Sangam MN","Technical","Teletype","Telugu Sangam MN","Tempus Sans ITC","Terminal","Thonburi","Traditional Arabic","Trajan","TRAJAN PRO","Tristan","Tubular","Tunga","Tw Cen MT","Tw Cen MT Condensed","Tw Cen MT Condensed Extra Bold","TypoUpright BT","Unicorn","Univers","Univers CE 55 Medium","Univers Condensed","Utsaah","Vagabond","Vani","Vijaya","Viner Hand ITC","VisualUI","Vivaldi","Vladimir Script","Vrinda","Westminster","WHITNEY","Wide Latin","ZapfEllipt BT","ZapfHumnst BT","ZapfHumnst Dm BT","Zapfino","Zurich BlkEx BT","Zurich Ex BT","ZWAdobeF"];i.options.extendedJsFonts&&(r=r.concat(n));var o="mmmmmmmmmmlli",s="72px",l=document.getElementsByTagName("body")[0],h=document.createElement("div"),u=document.createElement("div"),d={},c={},g=function(){var e=document.createElement("span");return e.style.position="absolute",e.style.left="-9999px",e.style.fontSize=s,e.innerHTML=o,e},p=function(e,t){var i=g();return i.style.fontFamily="'"+e+"',"+t,i},f=function(){for(var e=[],t=0,i=a.length;i>t;t++){var r=g();r.style.fontFamily=a[t],h.appendChild(r),e.push(r)}return e},m=function(){for(var e={},t=0,i=r.length;i>t;t++){for(var n=[],o=0,s=a.length;s>o;o++){var l=p(r[t],a[o]);u.appendChild(l),n.push(l)}e[r[t]]=n}return e},S=function(e){for(var t=!1,i=0;ix;x++)d[a[x]]=T[x].offsetWidth,c[a[x]]=T[x].offsetHeight;var M=m();l.appendChild(u);for(var A=[],E=0,y=r.length;y>E;E++)S(M[r[E]])&&A.push(r[E]);l.removeChild(u),l.removeChild(h),e.push({key:"js_fonts",value:A}),t(e)},1)},pluginsKey:function(e){return this.options.excludePlugins||(this.isIE()?this.options.excludeIEPlugins||e.push({key:"ie_plugins",value:this.getIEPlugins()}):e.push({key:"regular_plugins",value:this.getRegularPlugins()})),e},getRegularPlugins:function(){for(var e=[],t=0,i=navigator.plugins.length;i>t;t++)e.push(navigator.plugins[t]);return this.pluginsShouldBeSorted()&&(e=e.sort(function(e,t){return e.name>t.name?1:e.namet;t++){var a=this.options.sortPluginsFor[t];if(navigator.userAgent.match(a)){e=!0;break}}return e},touchSupportKey:function(e){return this.options.excludeTouchSupport||e.push({key:"touch_support",value:this.getTouchSupport()}),e},hasSessionStorage:function(){try{return!!window.sessionStorage}catch(e){return!0}},hasLocalStorage:function(){try{return!!window.localStorage}catch(e){return!0}},hasIndexedDB:function(){return!!window.indexedDB},getNavigatorCpuClass:function(){return navigator.cpuClass?navigator.cpuClass:"unknown"},getNavigatorPlatform:function(){return navigator.platform?navigator.platform:"unknown"},getDoNotTrack:function(){return navigator.doNotTrack?navigator.doNotTrack:"unknown"},getTouchSupport:function(){var e=0,t=!1;"undefined"!=typeof navigator.maxTouchPoints?e=navigator.maxTouchPoints:"undefined"!=typeof navigator.msMaxTouchPoints&&(e=navigator.msMaxTouchPoints);try{document.createEvent("TouchEvent"),t=!0}catch(i){}var a="ontouchstart"in window;return[e,t,a]},getCanvasFp:function(){var e=[],t=document.createElement("canvas");t.width=2e3,t.height=200,t.style.display="inline";var i=t.getContext("2d");return i.rect(0,0,10,10),i.rect(2,2,6,6),e.push("canvas winding:"+(i.isPointInPath(5,5,"evenodd")===!1?"yes":"no")),i.textBaseline="alphabetic",i.fillStyle="#f60",i.fillRect(125,1,62,20),i.fillStyle="#069",this.options.dontUseFakeFontInCanvas?i.font="11pt Arial":i.font="11pt no-real-font-123",i.fillText("Cwm fjordbank glyphs vext quiz, 😃",2,15),i.fillStyle="rgba(102, 204, 0, 0.2)",i.font="18pt Arial",i.fillText("Cwm fjordbank glyphs vext quiz, 😃",4,45),i.globalCompositeOperation="multiply",i.fillStyle="rgb(255,0,255)",i.beginPath(),i.arc(50,50,50,0,2*Math.PI,!0),i.closePath(),i.fill(),i.fillStyle="rgb(0,255,255)",i.beginPath(),i.arc(100,50,50,0,2*Math.PI,!0),i.closePath(),i.fill(),i.fillStyle="rgb(255,255,0)",i.beginPath(),i.arc(75,100,50,0,2*Math.PI,!0),i.closePath(),i.fill(),i.fillStyle="rgb(255,0,255)",i.arc(75,75,75,0,2*Math.PI,!0),i.arc(75,75,25,0,2*Math.PI,!0),i.fill("evenodd"),e.push("canvas fp:"+t.toDataURL()),e.join("~")},getWebglFp:function(){var e,t=function(t){return e.clearColor(0,0,0,1),e.enable(e.DEPTH_TEST),e.depthFunc(e.LEQUAL),e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT),"["+t[0]+", "+t[1]+"]"},i=function(e){var t,i=e.getExtension("EXT_texture_filter_anisotropic")||e.getExtension("WEBKIT_EXT_texture_filter_anisotropic")||e.getExtension("MOZ_EXT_texture_filter_anisotropic");return i?(t=e.getParameter(i.MAX_TEXTURE_MAX_ANISOTROPY_EXT),0===t&&(t=2),t):null};if(e=this.getWebglCanvas(),!e)return null;var a=[],r="attribute vec2 attrVertex;varying vec2 varyinTexCoordinate;uniform vec2 uniformOffset;void main(){varyinTexCoordinate=attrVertex+uniformOffset;gl_Position=vec4(attrVertex,0,1);}",n="precision mediump float;varying vec2 varyinTexCoordinate;void main() {gl_FragColor=vec4(varyinTexCoordinate,0,1);}",o=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,o);var s=new Float32Array([-.2,-.9,0,.4,-.26,0,0,.732134444,0]);e.bufferData(e.ARRAY_BUFFER,s,e.STATIC_DRAW),o.itemSize=3,o.numItems=3;var l=e.createProgram(),h=e.createShader(e.VERTEX_SHADER);e.shaderSource(h,r),e.compileShader(h);var u=e.createShader(e.FRAGMENT_SHADER);return e.shaderSource(u,n),e.compileShader(u),e.attachShader(l,h),e.attachShader(l,u),e.linkProgram(l),e.useProgram(l),l.vertexPosAttrib=e.getAttribLocation(l,"attrVertex"),l.offsetUniform=e.getUniformLocation(l,"uniformOffset"),e.enableVertexAttribArray(l.vertexPosArray),e.vertexAttribPointer(l.vertexPosAttrib,o.itemSize,e.FLOAT,!1,0,0),e.uniform2f(l.offsetUniform,1,1),e.drawArrays(e.TRIANGLE_STRIP,0,o.numItems),null!=e.canvas&&a.push(e.canvas.toDataURL()),a.push("extensions:"+e.getSupportedExtensions().join(";")),a.push("webgl aliased line width range:"+t(e.getParameter(e.ALIASED_LINE_WIDTH_RANGE))),a.push("webgl aliased point size range:"+t(e.getParameter(e.ALIASED_POINT_SIZE_RANGE))),a.push("webgl alpha bits:"+e.getParameter(e.ALPHA_BITS)),a.push("webgl antialiasing:"+(e.getContextAttributes().antialias?"yes":"no")),a.push("webgl blue bits:"+e.getParameter(e.BLUE_BITS)),a.push("webgl depth bits:"+e.getParameter(e.DEPTH_BITS)),a.push("webgl green bits:"+e.getParameter(e.GREEN_BITS)),a.push("webgl max anisotropy:"+i(e)),a.push("webgl max combined texture image units:"+e.getParameter(e.MAX_COMBINED_TEXTURE_IMAGE_UNITS)),a.push("webgl max cube map texture size:"+e.getParameter(e.MAX_CUBE_MAP_TEXTURE_SIZE)),a.push("webgl max fragment uniform vectors:"+e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS)),a.push("webgl max render buffer size:"+e.getParameter(e.MAX_RENDERBUFFER_SIZE)),a.push("webgl max texture image units:"+e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS)),a.push("webgl max texture size:"+e.getParameter(e.MAX_TEXTURE_SIZE)),a.push("webgl max varying vectors:"+e.getParameter(e.MAX_VARYING_VECTORS)),a.push("webgl max vertex attribs:"+e.getParameter(e.MAX_VERTEX_ATTRIBS)),a.push("webgl max vertex texture image units:"+e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS)),a.push("webgl max vertex uniform vectors:"+e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS)),a.push("webgl max viewport dims:"+t(e.getParameter(e.MAX_VIEWPORT_DIMS))),a.push("webgl red bits:"+e.getParameter(e.RED_BITS)),a.push("webgl renderer:"+e.getParameter(e.RENDERER)),a.push("webgl shading language version:"+e.getParameter(e.SHADING_LANGUAGE_VERSION)),a.push("webgl stencil bits:"+e.getParameter(e.STENCIL_BITS)),a.push("webgl vendor:"+e.getParameter(e.VENDOR)),a.push("webgl version:"+e.getParameter(e.VERSION)),e.getShaderPrecisionFormat?(a.push("webgl vertex shader high float precision:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.HIGH_FLOAT).precision),a.push("webgl vertex shader high float precision rangeMin:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.HIGH_FLOAT).rangeMin),a.push("webgl vertex shader high float precision rangeMax:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.HIGH_FLOAT).rangeMax),a.push("webgl vertex shader medium float precision:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).precision),a.push("webgl vertex shader medium float precision rangeMin:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).rangeMin),a.push("webgl vertex shader medium float precision rangeMax:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).rangeMax),a.push("webgl vertex shader low float precision:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.LOW_FLOAT).precision),a.push("webgl vertex shader low float precision rangeMin:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.LOW_FLOAT).rangeMin),a.push("webgl vertex shader low float precision rangeMax:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.LOW_FLOAT).rangeMax),a.push("webgl fragment shader high float precision:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).precision),a.push("webgl fragment shader high float precision rangeMin:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).rangeMin),a.push("webgl fragment shader high float precision rangeMax:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).rangeMax),a.push("webgl fragment shader medium float precision:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).precision),a.push("webgl fragment shader medium float precision rangeMin:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).rangeMin),a.push("webgl fragment shader medium float precision rangeMax:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).rangeMax),a.push("webgl fragment shader low float precision:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_FLOAT).precision),a.push("webgl fragment shader low float precision rangeMin:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_FLOAT).rangeMin),a.push("webgl fragment shader low float precision rangeMax:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_FLOAT).rangeMax),a.push("webgl vertex shader high int precision:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.HIGH_INT).precision),a.push("webgl vertex shader high int precision rangeMin:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.HIGH_INT).rangeMin),a.push("webgl vertex shader high int precision rangeMax:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.HIGH_INT).rangeMax),a.push("webgl vertex shader medium int precision:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_INT).precision),a.push("webgl vertex shader medium int precision rangeMin:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_INT).rangeMin),a.push("webgl vertex shader medium int precision rangeMax:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_INT).rangeMax),a.push("webgl vertex shader low int precision:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.LOW_INT).precision),a.push("webgl vertex shader low int precision rangeMin:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.LOW_INT).rangeMin),a.push("webgl vertex shader low int precision rangeMax:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.LOW_INT).rangeMax),a.push("webgl fragment shader high int precision:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT).precision),a.push("webgl fragment shader high int precision rangeMin:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT).rangeMin),a.push("webgl fragment shader high int precision rangeMax:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT).rangeMax),a.push("webgl fragment shader medium int precision:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_INT).precision),a.push("webgl fragment shader medium int precision rangeMin:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_INT).rangeMin),a.push("webgl fragment shader medium int precision rangeMax:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_INT).rangeMax),a.push("webgl fragment shader low int precision:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_INT).precision),a.push("webgl fragment shader low int precision rangeMin:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_INT).rangeMin),a.push("webgl fragment shader low int precision rangeMax:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_INT).rangeMax),a.join("~")):a.join("~")},getAdBlock:function(){var e=document.createElement("div");e.innerHTML=" ",e.className="adsbox";var t=!1;try{document.body.appendChild(e),t=0===document.getElementsByClassName("adsbox")[0].offsetHeight,document.body.removeChild(e)}catch(i){t=!1}return t},getHasLiedLanguages:function(){if("undefined"!=typeof navigator.languages)try{var e=navigator.languages[0].substr(0,2);if(e!==navigator.language.substr(0,2))return!0}catch(t){return!0}return!1},getHasLiedResolution:function(){return screen.width=0?"Windows Phone":t.indexOf("win")>=0?"Windows":t.indexOf("android")>=0?"Android":t.indexOf("linux")>=0?"Linux":t.indexOf("iphone")>=0||t.indexOf("ipad")>=0?"iOS":t.indexOf("mac")>=0?"Mac":"Other";var r;if(r="ontouchstart"in window||navigator.maxTouchPoints>0||navigator.msMaxTouchPoints>0,r&&"Windows Phone"!==e&&"Android"!==e&&"iOS"!==e&&"Other"!==e)return!0;if("undefined"!=typeof i){if(i=i.toLowerCase(),i.indexOf("win")>=0&&"Windows"!==e&&"Windows Phone"!==e)return!0;if(i.indexOf("linux")>=0&&"Linux"!==e&&"Android"!==e)return!0;if(i.indexOf("mac")>=0&&"Mac"!==e&&"iOS"!==e)return!0;if(0===i.indexOf("win")&&0===i.indexOf("linux")&&i.indexOf("mac")>=0&&"other"!==e)return!0}return a.indexOf("win")>=0&&"Windows"!==e&&"Windows Phone"!==e?!0:(a.indexOf("linux")>=0||a.indexOf("android")>=0||a.indexOf("pike")>=0)&&"Linux"!==e&&"Android"!==e?!0:(a.indexOf("mac")>=0||a.indexOf("ipad")>=0||a.indexOf("ipod")>=0||a.indexOf("iphone")>=0)&&"Mac"!==e&&"iOS"!==e?!0:0===a.indexOf("win")&&0===a.indexOf("linux")&&a.indexOf("mac")>=0&&"other"!==e?!0:"undefined"==typeof navigator.plugins&&"Windows"!==e&&"Windows Phone"!==e},getHasLiedBrowser:function(){var e,t=navigator.userAgent.toLowerCase(),i=navigator.productSub;if(e=t.indexOf("firefox")>=0?"Firefox":t.indexOf("opera")>=0||t.indexOf("opr")>=0?"Opera":t.indexOf("chrome")>=0?"Chrome":t.indexOf("safari")>=0?"Safari":t.indexOf("trident")>=0?"Internet Explorer":"Other",("Chrome"===e||"Safari"===e||"Opera"===e)&&"20030107"!==i)return!0;var a=eval.toString().length;if(37===a&&"Safari"!==e&&"Firefox"!==e&&"Other"!==e)return!0;if(39===a&&"Internet Explorer"!==e&&"Other"!==e)return!0;if(33===a&&"Chrome"!==e&&"Opera"!==e&&"Other"!==e)return!0;var r;try{throw"a"}catch(n){try{n.toSource(),r=!0}catch(o){r=!1}}return!(!r||"Firefox"===e||"Other"===e)},isCanvasSupported:function(){var e=document.createElement("canvas");return!(!e.getContext||!e.getContext("2d"))},isWebGlSupported:function(){if(!this.isCanvasSupported())return!1;var e,t=document.createElement("canvas");try{e=t.getContext&&(t.getContext("webgl")||t.getContext("experimental-webgl"))}catch(i){e=!1}return!!window.WebGLRenderingContext&&!!e},isIE:function(){return"Microsoft Internet Explorer"===navigator.appName?!0:!("Netscape"!==navigator.appName||!/Trident/.test(navigator.userAgent))},hasSwfObjectLoaded:function(){return"undefined"!=typeof window.swfobject},hasMinFlashInstalled:function(){return swfobject.hasFlashPlayerVersion("9.0.0")},addFlashDivNode:function(){var e=document.createElement("div");e.setAttribute("id",this.options.swfContainerId),document.body.appendChild(e)},loadSwfAndDetectFonts:function(e){var t="___fp_swf_loaded";window[t]=function(t){e(t)};var i=this.options.swfContainerId;this.addFlashDivNode();var a={onReady:t},r={allowScriptAccess:"always",menu:"false"};swfobject.embedSWF(this.options.swfPath,i,"1","1","9.0.0",!1,a,r,{})},getWebglCanvas:function(){var e=document.createElement("canvas"),t=null;try{t=e.getContext("webgl")||e.getContext("experimental-webgl")}catch(i){}return t||(t=null),t},each:function(e,t,i){if(null!==e)if(this.nativeForEach&&e.forEach===this.nativeForEach)e.forEach(t,i);else if(e.length===+e.length){for(var a=0,r=e.length;r>a;a++)if(t.call(i,e[a],a,e)==={})return}else for(var n in e)if(e.hasOwnProperty(n)&&t.call(i,e[n],n,e)==={})return},map:function(e,t,i){var a=[];return null==e?a:this.nativeMap&&e.map===this.nativeMap?e.map(t,i):(this.each(e,function(e,r,n){a[a.length]=t.call(i,e,r,n)}),a)},x64Add:function(e,t){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],t=[t[0]>>>16,65535&t[0],t[1]>>>16,65535&t[1]];var i=[0,0,0,0];return i[3]+=e[3]+t[3],i[2]+=i[3]>>>16,i[3]&=65535,i[2]+=e[2]+t[2],i[1]+=i[2]>>>16,i[2]&=65535,i[1]+=e[1]+t[1],i[0]+=i[1]>>>16,i[1]&=65535,i[0]+=e[0]+t[0],i[0]&=65535,[i[0]<<16|i[1],i[2]<<16|i[3]]},x64Multiply:function(e,t){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],t=[t[0]>>>16,65535&t[0],t[1]>>>16,65535&t[1]];var i=[0,0,0,0];return i[3]+=e[3]*t[3],i[2]+=i[3]>>>16,i[3]&=65535,i[2]+=e[2]*t[3],i[1]+=i[2]>>>16,i[2]&=65535,i[2]+=e[3]*t[2],i[1]+=i[2]>>>16,i[2]&=65535,i[1]+=e[1]*t[3],i[0]+=i[1]>>>16,i[1]&=65535,i[1]+=e[2]*t[2],i[0]+=i[1]>>>16,i[1]&=65535,i[1]+=e[3]*t[1],i[0]+=i[1]>>>16,i[1]&=65535,i[0]+=e[0]*t[3]+e[1]*t[2]+e[2]*t[1]+e[3]*t[0],i[0]&=65535,[i[0]<<16|i[1],i[2]<<16|i[3]]},x64Rotl:function(e,t){return t%=64,32===t?[e[1],e[0]]:32>t?[e[0]<>>32-t,e[1]<>>32-t]:(t-=32,[e[1]<>>32-t,e[0]<>>32-t])},x64LeftShift:function(e,t){return t%=64,0===t?e:32>t?[e[0]<>>32-t,e[1]<>>1]),e=this.x64Multiply(e,[4283543511,3981806797]),e=this.x64Xor(e,[0,e[0]>>>1]),e=this.x64Multiply(e,[3301882366,444984403]),e=this.x64Xor(e,[0,e[0]>>>1])},x64hash128:function(e,t){e=e||"",t=t||0;for(var i=e.length%16,a=e.length-i,r=[0,t],n=[0,t],o=[0,0],s=[0,0],l=[2277735313,289559509],h=[1291169091,658871167],u=0;a>u;u+=16)o=[255&e.charCodeAt(u+4)|(255&e.charCodeAt(u+5))<<8|(255&e.charCodeAt(u+6))<<16|(255&e.charCodeAt(u+7))<<24,255&e.charCodeAt(u)|(255&e.charCodeAt(u+1))<<8|(255&e.charCodeAt(u+2))<<16|(255&e.charCodeAt(u+3))<<24],s=[255&e.charCodeAt(u+12)|(255&e.charCodeAt(u+13))<<8|(255&e.charCodeAt(u+14))<<16|(255&e.charCodeAt(u+15))<<24,255&e.charCodeAt(u+8)|(255&e.charCodeAt(u+9))<<8|(255&e.charCodeAt(u+10))<<16|(255&e.charCodeAt(u+11))<<24],o=this.x64Multiply(o,l),o=this.x64Rotl(o,31),o=this.x64Multiply(o,h),r=this.x64Xor(r,o),r=this.x64Rotl(r,27),r=this.x64Add(r,n),r=this.x64Add(this.x64Multiply(r,[0,5]),[0,1390208809]), -s=this.x64Multiply(s,h),s=this.x64Rotl(s,33),s=this.x64Multiply(s,l),n=this.x64Xor(n,s),n=this.x64Rotl(n,31),n=this.x64Add(n,r),n=this.x64Add(this.x64Multiply(n,[0,5]),[0,944331445]);switch(o=[0,0],s=[0,0],i){case 15:s=this.x64Xor(s,this.x64LeftShift([0,e.charCodeAt(u+14)],48));case 14:s=this.x64Xor(s,this.x64LeftShift([0,e.charCodeAt(u+13)],40));case 13:s=this.x64Xor(s,this.x64LeftShift([0,e.charCodeAt(u+12)],32));case 12:s=this.x64Xor(s,this.x64LeftShift([0,e.charCodeAt(u+11)],24));case 11:s=this.x64Xor(s,this.x64LeftShift([0,e.charCodeAt(u+10)],16));case 10:s=this.x64Xor(s,this.x64LeftShift([0,e.charCodeAt(u+9)],8));case 9:s=this.x64Xor(s,[0,e.charCodeAt(u+8)]),s=this.x64Multiply(s,h),s=this.x64Rotl(s,33),s=this.x64Multiply(s,l),n=this.x64Xor(n,s);case 8:o=this.x64Xor(o,this.x64LeftShift([0,e.charCodeAt(u+7)],56));case 7:o=this.x64Xor(o,this.x64LeftShift([0,e.charCodeAt(u+6)],48));case 6:o=this.x64Xor(o,this.x64LeftShift([0,e.charCodeAt(u+5)],40));case 5:o=this.x64Xor(o,this.x64LeftShift([0,e.charCodeAt(u+4)],32));case 4:o=this.x64Xor(o,this.x64LeftShift([0,e.charCodeAt(u+3)],24));case 3:o=this.x64Xor(o,this.x64LeftShift([0,e.charCodeAt(u+2)],16));case 2:o=this.x64Xor(o,this.x64LeftShift([0,e.charCodeAt(u+1)],8));case 1:o=this.x64Xor(o,[0,e.charCodeAt(u)]),o=this.x64Multiply(o,l),o=this.x64Rotl(o,31),o=this.x64Multiply(o,h),r=this.x64Xor(r,o)}return r=this.x64Xor(r,[0,e.length]),n=this.x64Xor(n,[0,e.length]),r=this.x64Add(r,n),n=this.x64Add(n,r),r=this.x64Fmix(r),n=this.x64Fmix(n),r=this.x64Add(r,n),n=this.x64Add(n,r),("00000000"+(r[0]>>>0).toString(16)).slice(-8)+("00000000"+(r[1]>>>0).toString(16)).slice(-8)+("00000000"+(n[0]>>>0).toString(16)).slice(-8)+("00000000"+(n[1]>>>0).toString(16)).slice(-8)}},e.VERSION="1.4.0",e}); \ No newline at end of file +!function(e,t,i){"use strict";"undefined"!=typeof module&&module.exports?module.exports=i():"function"==typeof define&&define.amd?define(i):t[e]=i()}("Fingerprint2",this,function(){"use strict";Array.prototype.indexOf||(Array.prototype.indexOf=function(e,t){var i;if(null==this)throw new TypeError("'this' is null or undefined");var a=Object(this),r=a.length>>>0;if(0===r)return-1;var n=+t||0;if(Math.abs(n)===1/0&&(n=0),n>=r)return-1;for(i=Math.max(n>=0?n:r-Math.abs(n),0);r>i;){if(i in a&&a[i]===e)return i;i++}return-1});var e=function(e){var t={swfContainerId:"fingerprintjs2",swfPath:"flash/compiled/FontList.swf",detectScreenOrientation:!0,sortPluginsFor:[/palemoon/i]};this.options=this.extend(e,t),this.nativeForEach=Array.prototype.forEach,this.nativeMap=Array.prototype.map};return e.prototype={extend:function(e,t){if(null==e)return t;for(var i in e)null!=e[i]&&t[i]!==e[i]&&(t[i]=e[i]);return t},log:function(e){window.console&&console.log(e)},get:function(e){var t=[];t=this.userAgentKey(t),t=this.languageKey(t),t=this.colorDepthKey(t),t=this.screenResolutionKey(t),t=this.availableScreenResolutionKey(t),t=this.timezoneOffsetKey(t),t=this.sessionStorageKey(t),t=this.localStorageKey(t),t=this.indexedDbKey(t),t=this.addBehaviorKey(t),t=this.openDatabaseKey(t),t=this.cpuClassKey(t),t=this.platformKey(t),t=this.doNotTrackKey(t),t=this.pluginsKey(t),t=this.canvasKey(t),t=this.webglKey(t),t=this.adBlockKey(t),t=this.hasLiedLanguagesKey(t),t=this.hasLiedResolutionKey(t),t=this.hasLiedOsKey(t),t=this.hasLiedBrowserKey(t),t=this.touchSupportKey(t);var i=this;this.fontsKey(t,function(t){var a=[];i.each(t,function(e){var t=e.value;"undefined"!=typeof e.value.join&&(t=e.value.join(";")),a.push(t)});var r=i.x64hash128(a.join("~~~"),31);return e(r,t)})},userAgentKey:function(e){return this.options.excludeUserAgent||e.push({key:"user_agent",value:this.getUserAgent()}),e},getUserAgent:function(){return navigator.userAgent},languageKey:function(e){return this.options.excludeLanguage||e.push({key:"language",value:navigator.language||navigator.userLanguage||navigator.browserLanguage||navigator.systemLanguage||""}),e},colorDepthKey:function(e){return this.options.excludeColorDepth||e.push({key:"color_depth",value:screen.colorDepth}),e},screenResolutionKey:function(e){return this.options.excludeScreenResolution?e:this.getScreenResolution(e)},getScreenResolution:function(e){var t;return t=this.options.detectScreenOrientation&&screen.height>screen.width?[screen.height,screen.width]:[screen.width,screen.height],"undefined"!=typeof t&&e.push({key:"resolution",value:t}),e},availableScreenResolutionKey:function(e){return this.options.excludeAvailableScreenResolution?e:this.getAvailableScreenResolution(e)},getAvailableScreenResolution:function(e){var t;return screen.availWidth&&screen.availHeight&&(t=this.options.detectScreenOrientation?screen.availHeight>screen.availWidth?[screen.availHeight,screen.availWidth]:[screen.availWidth,screen.availHeight]:[screen.availHeight,screen.availWidth]),"undefined"!=typeof t&&e.push({key:"available_resolution",value:t}),e},timezoneOffsetKey:function(e){return this.options.excludeTimezoneOffset||e.push({key:"timezone_offset",value:(new Date).getTimezoneOffset()}),e},sessionStorageKey:function(e){return!this.options.excludeSessionStorage&&this.hasSessionStorage()&&e.push({key:"session_storage",value:1}),e},localStorageKey:function(e){return!this.options.excludeSessionStorage&&this.hasLocalStorage()&&e.push({key:"local_storage",value:1}),e},indexedDbKey:function(e){return!this.options.excludeIndexedDB&&this.hasIndexedDB()&&e.push({key:"indexed_db",value:1}),e},addBehaviorKey:function(e){return document.body&&!this.options.excludeAddBehavior&&document.body.addBehavior&&e.push({key:"add_behavior",value:1}),e},openDatabaseKey:function(e){return!this.options.excludeOpenDatabase&&window.openDatabase&&e.push({key:"open_database",value:1}),e},cpuClassKey:function(e){return this.options.excludeCpuClass||e.push({key:"cpu_class",value:this.getNavigatorCpuClass()}),e},platformKey:function(e){return this.options.excludePlatform||e.push({key:"navigator_platform",value:this.getNavigatorPlatform()}),e},doNotTrackKey:function(e){return this.options.excludeDoNotTrack||e.push({key:"do_not_track",value:this.getDoNotTrack()}),e},canvasKey:function(e){return!this.options.excludeCanvas&&this.isCanvasSupported()&&e.push({key:"canvas",value:this.getCanvasFp()}),e},webglKey:function(e){return this.options.excludeWebGL?e:this.isWebGlSupported()?(e.push({key:"webgl",value:this.getWebglFp()}),e):e},adBlockKey:function(e){return this.options.excludeAdBlock||e.push({key:"adblock",value:this.getAdBlock()}),e},hasLiedLanguagesKey:function(e){return this.options.excludeHasLiedLanguages||e.push({key:"has_lied_languages",value:this.getHasLiedLanguages()}),e},hasLiedResolutionKey:function(e){return this.options.excludeHasLiedResolution||e.push({key:"has_lied_resolution",value:this.getHasLiedResolution()}),e},hasLiedOsKey:function(e){return this.options.excludeHasLiedOs||e.push({key:"has_lied_os",value:this.getHasLiedOs()}),e},hasLiedBrowserKey:function(e){return this.options.excludeHasLiedBrowser||e.push({key:"has_lied_browser",value:this.getHasLiedBrowser()}),e},fontsKey:function(e,t){return this.options.excludeJsFonts?this.flashFontsKey(e,t):this.jsFontsKey(e,t)},flashFontsKey:function(e,t){return this.options.excludeFlashFonts?t(e):this.hasSwfObjectLoaded()&&this.hasMinFlashInstalled()?"undefined"==typeof this.options.swfPath?t(e):void this.loadSwfAndDetectFonts(function(i){e.push({key:"swf_fonts",value:i.join(";")}),t(e)}):t(e)},jsFontsKey:function(e,t){var i=this;return setTimeout(function(){var a=["monospace","sans-serif","serif"],r="mmmmmmmmmmlli",n="72px",o=document.getElementsByTagName("body")[0],s=document.createElement("span");s.style.position="absolute",s.style.left="-9999px",s.style.fontSize=n,s.innerHTML=r;for(var l={},h={},u=0,d=a.length;d>u;u++)s.style.fontFamily=a[u],o.appendChild(s),l[a[u]]=s.offsetWidth,h[a[u]]=s.offsetHeight,o.removeChild(s);var c=function(e){for(var t=!1,i=0,r=a.length;r>i;i++){s.style.fontFamily=e+","+a[i],o.appendChild(s);var n=s.offsetWidth!==l[a[i]]||s.offsetHeight!==h[a[i]];o.removeChild(s),t=t||n}return t},g=["Andale Mono","Arial","Arial Black","Arial Hebrew","Arial MT","Arial Narrow","Arial Rounded MT Bold","Arial Unicode MS","Bitstream Vera Sans Mono","Book Antiqua","Bookman Old Style","Calibri","Cambria","Cambria Math","Century","Century Gothic","Century Schoolbook","Comic Sans","Comic Sans MS","Consolas","Courier","Courier New","Garamond","Geneva","Georgia","Helvetica","Helvetica Neue","Impact","Lucida Bright","Lucida Calligraphy","Lucida Console","Lucida Fax","LUCIDA GRANDE","Lucida Handwriting","Lucida Sans","Lucida Sans Typewriter","Lucida Sans Unicode","Microsoft Sans Serif","Monaco","Monotype Corsiva","MS Gothic","MS Outlook","MS PGothic","MS Reference Sans Serif","MS Sans Serif","MS Serif","MYRIAD","MYRIAD PRO","Palatino","Palatino Linotype","Segoe Print","Segoe Script","Segoe UI","Segoe UI Light","Segoe UI Semibold","Segoe UI Symbol","Tahoma","Times","Times New Roman","Times New Roman PS","Trebuchet MS","Verdana","Wingdings","Wingdings 2","Wingdings 3"],p=["Abadi MT Condensed Light","Academy Engraved LET","ADOBE CASLON PRO","Adobe Garamond","ADOBE GARAMOND PRO","Agency FB","Aharoni","Albertus Extra Bold","Albertus Medium","Algerian","Amazone BT","American Typewriter","American Typewriter Condensed","AmerType Md BT","Andalus","Angsana New","AngsanaUPC","Antique Olive","Aparajita","Apple Chancery","Apple Color Emoji","Apple SD Gothic Neo","Arabic Typesetting","ARCHER","ARNO PRO","Arrus BT","Aurora Cn BT","AvantGarde Bk BT","AvantGarde Md BT","AVENIR","Ayuthaya","Bandy","Bangla Sangam MN","Bank Gothic","BankGothic Md BT","Baskerville","Baskerville Old Face","Batang","BatangChe","Bauer Bodoni","Bauhaus 93","Bazooka","Bell MT","Bembo","Benguiat Bk BT","Berlin Sans FB","Berlin Sans FB Demi","Bernard MT Condensed","BernhardFashion BT","BernhardMod BT","Big Caslon","BinnerD","Blackadder ITC","BlairMdITC TT","Bodoni 72","Bodoni 72 Oldstyle","Bodoni 72 Smallcaps","Bodoni MT","Bodoni MT Black","Bodoni MT Condensed","Bodoni MT Poster Compressed","Bookshelf Symbol 7","Boulder","Bradley Hand","Bradley Hand ITC","Bremen Bd BT","Britannic Bold","Broadway","Browallia New","BrowalliaUPC","Brush Script MT","Californian FB","Calisto MT","Calligrapher","Candara","CaslonOpnface BT","Castellar","Centaur","Cezanne","CG Omega","CG Times","Chalkboard","Chalkboard SE","Chalkduster","Charlesworth","Charter Bd BT","Charter BT","Chaucer","ChelthmITC Bk BT","Chiller","Clarendon","Clarendon Condensed","CloisterBlack BT","Cochin","Colonna MT","Constantia","Cooper Black","Copperplate","Copperplate Gothic","Copperplate Gothic Bold","Copperplate Gothic Light","CopperplGoth Bd BT","Corbel","Cordia New","CordiaUPC","Cornerstone","Coronet","Cuckoo","Curlz MT","DaunPenh","Dauphin","David","DB LCD Temp","DELICIOUS","Denmark","DFKai-SB","Didot","DilleniaUPC","DIN","DokChampa","Dotum","DotumChe","Ebrima","Edwardian Script ITC","Elephant","English 111 Vivace BT","Engravers MT","EngraversGothic BT","Eras Bold ITC","Eras Demi ITC","Eras Light ITC","Eras Medium ITC","EucrosiaUPC","Euphemia","Euphemia UCAS","EUROSTILE","Exotc350 Bd BT","FangSong","Felix Titling","Fixedsys","FONTIN","Footlight MT Light","Forte","FrankRuehl","Fransiscan","Freefrm721 Blk BT","FreesiaUPC","Freestyle Script","French Script MT","FrnkGothITC Bk BT","Fruitger","FRUTIGER","Futura","Futura Bk BT","Futura Lt BT","Futura Md BT","Futura ZBlk BT","FuturaBlack BT","Gabriola","Galliard BT","Gautami","Geeza Pro","Geometr231 BT","Geometr231 Hv BT","Geometr231 Lt BT","GeoSlab 703 Lt BT","GeoSlab 703 XBd BT","Gigi","Gill Sans","Gill Sans MT","Gill Sans MT Condensed","Gill Sans MT Ext Condensed Bold","Gill Sans Ultra Bold","Gill Sans Ultra Bold Condensed","Gisha","Gloucester MT Extra Condensed","GOTHAM","GOTHAM BOLD","Goudy Old Style","Goudy Stout","GoudyHandtooled BT","GoudyOLSt BT","Gujarati Sangam MN","Gulim","GulimChe","Gungsuh","GungsuhChe","Gurmukhi MN","Haettenschweiler","Harlow Solid Italic","Harrington","Heather","Heiti SC","Heiti TC","HELV","Herald","High Tower Text","Hiragino Kaku Gothic ProN","Hiragino Mincho ProN","Hoefler Text","Humanst 521 Cn BT","Humanst521 BT","Humanst521 Lt BT","Imprint MT Shadow","Incised901 Bd BT","Incised901 BT","Incised901 Lt BT","INCONSOLATA","Informal Roman","Informal011 BT","INTERSTATE","IrisUPC","Iskoola Pota","JasmineUPC","Jazz LET","Jenson","Jester","Jokerman","Juice ITC","Kabel Bk BT","Kabel Ult BT","Kailasa","KaiTi","Kalinga","Kannada Sangam MN","Kartika","Kaufmann Bd BT","Kaufmann BT","Khmer UI","KodchiangUPC","Kokila","Korinna BT","Kristen ITC","Krungthep","Kunstler Script","Lao UI","Latha","Leelawadee","Letter Gothic","Levenim MT","LilyUPC","Lithograph","Lithograph Light","Long Island","Lydian BT","Magneto","Maiandra GD","Malayalam Sangam MN","Malgun Gothic","Mangal","Marigold","Marion","Marker Felt","Market","Marlett","Matisse ITC","Matura MT Script Capitals","Meiryo","Meiryo UI","Microsoft Himalaya","Microsoft JhengHei","Microsoft New Tai Lue","Microsoft PhagsPa","Microsoft Tai Le","Microsoft Uighur","Microsoft YaHei","Microsoft Yi Baiti","MingLiU","MingLiU_HKSCS","MingLiU_HKSCS-ExtB","MingLiU-ExtB","Minion","Minion Pro","Miriam","Miriam Fixed","Mistral","Modern","Modern No. 20","Mona Lisa Solid ITC TT","Mongolian Baiti","MONO","MoolBoran","Mrs Eaves","MS LineDraw","MS Mincho","MS PMincho","MS Reference Specialty","MS UI Gothic","MT Extra","MUSEO","MV Boli","Nadeem","Narkisim","NEVIS","News Gothic","News GothicMT","NewsGoth BT","Niagara Engraved","Niagara Solid","Noteworthy","NSimSun","Nyala","OCR A Extended","Old Century","Old English Text MT","Onyx","Onyx BT","OPTIMA","Oriya Sangam MN","OSAKA","OzHandicraft BT","Palace Script MT","Papyrus","Parchment","Party LET","Pegasus","Perpetua","Perpetua Titling MT","PetitaBold","Pickwick","Plantagenet Cherokee","Playbill","PMingLiU","PMingLiU-ExtB","Poor Richard","Poster","PosterBodoni BT","PRINCETOWN LET","Pristina","PTBarnum BT","Pythagoras","Raavi","Rage Italic","Ravie","Ribbon131 Bd BT","Rockwell","Rockwell Condensed","Rockwell Extra Bold","Rod","Roman","Sakkal Majalla","Santa Fe LET","Savoye LET","Sceptre","Script","Script MT Bold","SCRIPTINA","Serifa","Serifa BT","Serifa Th BT","ShelleyVolante BT","Sherwood","Shonar Bangla","Showcard Gothic","Shruti","Signboard","SILKSCREEN","SimHei","Simplified Arabic","Simplified Arabic Fixed","SimSun","SimSun-ExtB","Sinhala Sangam MN","Sketch Rockwell","Skia","Small Fonts","Snap ITC","Snell Roundhand","Socket","Souvenir Lt BT","Staccato222 BT","Steamer","Stencil","Storybook","Styllo","Subway","Swis721 BlkEx BT","Swiss911 XCm BT","Sylfaen","Synchro LET","System","Tamil Sangam MN","Technical","Teletype","Telugu Sangam MN","Tempus Sans ITC","Terminal","Thonburi","Traditional Arabic","Trajan","TRAJAN PRO","Tristan","Tubular","Tunga","Tw Cen MT","Tw Cen MT Condensed","Tw Cen MT Condensed Extra Bold","TypoUpright BT","Unicorn","Univers","Univers CE 55 Medium","Univers Condensed","Utsaah","Vagabond","Vani","Vijaya","Viner Hand ITC","VisualUI","Vivaldi","Vladimir Script","Vrinda","Westminster","WHITNEY","Wide Latin","ZapfEllipt BT","ZapfHumnst BT","ZapfHumnst Dm BT","Zapfino","Zurich BlkEx BT","Zurich Ex BT","ZWAdobeF"];i.options.extendedJsFonts&&(g=g.concat(p));for(var f=[],m=0,S=g.length;S>m;m++)c(g[m])&&f.push(g[m]);e.push({key:"js_fonts",value:f}),t(e)},1)},pluginsKey:function(e){return this.options.excludePlugins||(this.isIE()?this.options.excludeIEPlugins||e.push({key:"ie_plugins",value:this.getIEPlugins()}):e.push({key:"regular_plugins",value:this.getRegularPlugins()})),e},getRegularPlugins:function(){for(var e=[],t=0,i=navigator.plugins.length;i>t;t++)e.push(navigator.plugins[t]);return this.pluginsShouldBeSorted()&&(e=e.sort(function(e,t){return e.name>t.name?1:e.namet;t++){var a=this.options.sortPluginsFor[t];if(navigator.userAgent.match(a)){e=!0;break}}return e},touchSupportKey:function(e){return this.options.excludeTouchSupport||e.push({key:"touch_support",value:this.getTouchSupport()}),e},hasSessionStorage:function(){try{return!!window.sessionStorage}catch(e){return!0}},hasLocalStorage:function(){try{return!!window.localStorage}catch(e){return!0}},hasIndexedDB:function(){return!!window.indexedDB},getNavigatorCpuClass:function(){return navigator.cpuClass?navigator.cpuClass:"unknown"},getNavigatorPlatform:function(){return navigator.platform?navigator.platform:"unknown"},getDoNotTrack:function(){return navigator.doNotTrack?navigator.doNotTrack:"unknown"},getTouchSupport:function(){var e=0,t=!1;"undefined"!=typeof navigator.maxTouchPoints?e=navigator.maxTouchPoints:"undefined"!=typeof navigator.msMaxTouchPoints&&(e=navigator.msMaxTouchPoints);try{document.createEvent("TouchEvent"),t=!0}catch(i){}var a="ontouchstart"in window;return[e,t,a]},getCanvasFp:function(){var e=[],t=document.createElement("canvas");t.width=2e3,t.height=200,t.style.display="inline";var i=t.getContext("2d");return i.rect(0,0,10,10),i.rect(2,2,6,6),e.push("canvas winding:"+(i.isPointInPath(5,5,"evenodd")===!1?"yes":"no")),i.textBaseline="alphabetic",i.fillStyle="#f60",i.fillRect(125,1,62,20),i.fillStyle="#069",this.options.dontUseFakeFontInCanvas?i.font="11pt Arial":i.font="11pt no-real-font-123",i.fillText("Cwm fjordbank glyphs vext quiz, 😃",2,15),i.fillStyle="rgba(102, 204, 0, 0.7)",i.font="18pt Arial",i.fillText("Cwm fjordbank glyphs vext quiz, 😃",4,45),i.globalCompositeOperation="multiply",i.fillStyle="rgb(255,0,255)",i.beginPath(),i.arc(50,50,50,0,2*Math.PI,!0),i.closePath(),i.fill(),i.fillStyle="rgb(0,255,255)",i.beginPath(),i.arc(100,50,50,0,2*Math.PI,!0),i.closePath(),i.fill(),i.fillStyle="rgb(255,255,0)",i.beginPath(),i.arc(75,100,50,0,2*Math.PI,!0),i.closePath(),i.fill(),i.fillStyle="rgb(255,0,255)",i.arc(75,75,75,0,2*Math.PI,!0),i.arc(75,75,25,0,2*Math.PI,!0),i.fill("evenodd"),e.push("canvas fp:"+t.toDataURL()),e.join("~")},getWebglFp:function(){var e,t=function(t){return e.clearColor(0,0,0,1),e.enable(e.DEPTH_TEST),e.depthFunc(e.LEQUAL),e.clear(e.COLOR_BUFFER_BIT|e.DEPTH_BUFFER_BIT),"["+t[0]+", "+t[1]+"]"},i=function(e){var t,i=e.getExtension("EXT_texture_filter_anisotropic")||e.getExtension("WEBKIT_EXT_texture_filter_anisotropic")||e.getExtension("MOZ_EXT_texture_filter_anisotropic");return i?(t=e.getParameter(i.MAX_TEXTURE_MAX_ANISOTROPY_EXT),0===t&&(t=2),t):null};if(e=this.getWebglCanvas(),!e)return null;var a=[],r="attribute vec2 attrVertex;varying vec2 varyinTexCoordinate;uniform vec2 uniformOffset;void main(){varyinTexCoordinate=attrVertex+uniformOffset;gl_Position=vec4(attrVertex,0,1);}",n="precision mediump float;varying vec2 varyinTexCoordinate;void main() {gl_FragColor=vec4(varyinTexCoordinate,0,1);}",o=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,o);var s=new Float32Array([-.2,-.9,0,.4,-.26,0,0,.732134444,0]);e.bufferData(e.ARRAY_BUFFER,s,e.STATIC_DRAW),o.itemSize=3,o.numItems=3;var l=e.createProgram(),h=e.createShader(e.VERTEX_SHADER);e.shaderSource(h,r),e.compileShader(h);var u=e.createShader(e.FRAGMENT_SHADER);return e.shaderSource(u,n),e.compileShader(u),e.attachShader(l,h),e.attachShader(l,u),e.linkProgram(l),e.useProgram(l),l.vertexPosAttrib=e.getAttribLocation(l,"attrVertex"),l.offsetUniform=e.getUniformLocation(l,"uniformOffset"),e.enableVertexAttribArray(l.vertexPosArray),e.vertexAttribPointer(l.vertexPosAttrib,o.itemSize,e.FLOAT,!1,0,0),e.uniform2f(l.offsetUniform,1,1),e.drawArrays(e.TRIANGLE_STRIP,0,o.numItems),null!=e.canvas&&a.push(e.canvas.toDataURL()),a.push("extensions:"+e.getSupportedExtensions().join(";")),a.push("webgl aliased line width range:"+t(e.getParameter(e.ALIASED_LINE_WIDTH_RANGE))),a.push("webgl aliased point size range:"+t(e.getParameter(e.ALIASED_POINT_SIZE_RANGE))),a.push("webgl alpha bits:"+e.getParameter(e.ALPHA_BITS)),a.push("webgl antialiasing:"+(e.getContextAttributes().antialias?"yes":"no")),a.push("webgl blue bits:"+e.getParameter(e.BLUE_BITS)),a.push("webgl depth bits:"+e.getParameter(e.DEPTH_BITS)),a.push("webgl green bits:"+e.getParameter(e.GREEN_BITS)),a.push("webgl max anisotropy:"+i(e)),a.push("webgl max combined texture image units:"+e.getParameter(e.MAX_COMBINED_TEXTURE_IMAGE_UNITS)),a.push("webgl max cube map texture size:"+e.getParameter(e.MAX_CUBE_MAP_TEXTURE_SIZE)),a.push("webgl max fragment uniform vectors:"+e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS)),a.push("webgl max render buffer size:"+e.getParameter(e.MAX_RENDERBUFFER_SIZE)),a.push("webgl max texture image units:"+e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS)),a.push("webgl max texture size:"+e.getParameter(e.MAX_TEXTURE_SIZE)),a.push("webgl max varying vectors:"+e.getParameter(e.MAX_VARYING_VECTORS)),a.push("webgl max vertex attribs:"+e.getParameter(e.MAX_VERTEX_ATTRIBS)),a.push("webgl max vertex texture image units:"+e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS)),a.push("webgl max vertex uniform vectors:"+e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS)),a.push("webgl max viewport dims:"+t(e.getParameter(e.MAX_VIEWPORT_DIMS))),a.push("webgl red bits:"+e.getParameter(e.RED_BITS)),a.push("webgl renderer:"+e.getParameter(e.RENDERER)),a.push("webgl shading language version:"+e.getParameter(e.SHADING_LANGUAGE_VERSION)),a.push("webgl stencil bits:"+e.getParameter(e.STENCIL_BITS)),a.push("webgl vendor:"+e.getParameter(e.VENDOR)),a.push("webgl version:"+e.getParameter(e.VERSION)),e.getShaderPrecisionFormat?(a.push("webgl vertex shader high float precision:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.HIGH_FLOAT).precision),a.push("webgl vertex shader high float precision rangeMin:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.HIGH_FLOAT).rangeMin),a.push("webgl vertex shader high float precision rangeMax:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.HIGH_FLOAT).rangeMax),a.push("webgl vertex shader medium float precision:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).precision),a.push("webgl vertex shader medium float precision rangeMin:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).rangeMin),a.push("webgl vertex shader medium float precision rangeMax:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).rangeMax),a.push("webgl vertex shader low float precision:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.LOW_FLOAT).precision),a.push("webgl vertex shader low float precision rangeMin:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.LOW_FLOAT).rangeMin),a.push("webgl vertex shader low float precision rangeMax:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.LOW_FLOAT).rangeMax),a.push("webgl fragment shader high float precision:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).precision),a.push("webgl fragment shader high float precision rangeMin:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).rangeMin),a.push("webgl fragment shader high float precision rangeMax:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).rangeMax),a.push("webgl fragment shader medium float precision:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).precision),a.push("webgl fragment shader medium float precision rangeMin:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).rangeMin),a.push("webgl fragment shader medium float precision rangeMax:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).rangeMax),a.push("webgl fragment shader low float precision:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_FLOAT).precision),a.push("webgl fragment shader low float precision rangeMin:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_FLOAT).rangeMin),a.push("webgl fragment shader low float precision rangeMax:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_FLOAT).rangeMax),a.push("webgl vertex shader high int precision:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.HIGH_INT).precision),a.push("webgl vertex shader high int precision rangeMin:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.HIGH_INT).rangeMin),a.push("webgl vertex shader high int precision rangeMax:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.HIGH_INT).rangeMax),a.push("webgl vertex shader medium int precision:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_INT).precision),a.push("webgl vertex shader medium int precision rangeMin:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_INT).rangeMin),a.push("webgl vertex shader medium int precision rangeMax:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_INT).rangeMax),a.push("webgl vertex shader low int precision:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.LOW_INT).precision),a.push("webgl vertex shader low int precision rangeMin:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.LOW_INT).rangeMin),a.push("webgl vertex shader low int precision rangeMax:"+e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.LOW_INT).rangeMax),a.push("webgl fragment shader high int precision:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT).precision),a.push("webgl fragment shader high int precision rangeMin:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT).rangeMin),a.push("webgl fragment shader high int precision rangeMax:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_INT).rangeMax),a.push("webgl fragment shader medium int precision:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_INT).precision),a.push("webgl fragment shader medium int precision rangeMin:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_INT).rangeMin),a.push("webgl fragment shader medium int precision rangeMax:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_INT).rangeMax),a.push("webgl fragment shader low int precision:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_INT).precision),a.push("webgl fragment shader low int precision rangeMin:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_INT).rangeMin),a.push("webgl fragment shader low int precision rangeMax:"+e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.LOW_INT).rangeMax),a.join("~")):a.join("~")},getAdBlock:function(){var e=document.createElement("div");e.setAttribute("id","ads");try{return document.body.appendChild(e),!document.getElementById("ads")}catch(t){return!1}},getHasLiedLanguages:function(){if("undefined"!=typeof navigator.languages)try{var e=navigator.languages[0].substr(0,2);if(e!==navigator.language.substr(0,2))return!0}catch(t){return!0}return!1},getHasLiedResolution:function(){return screen.width=0?"Windows Phone":t.indexOf("win")>=0?"Windows":t.indexOf("android")>=0?"Android":t.indexOf("linux")>=0?"Linux":t.indexOf("iphone")>=0||t.indexOf("ipad")>=0?"iOS":t.indexOf("mac")>=0?"Mac":"Other";var r;if(r="ontouchstart"in window||navigator.maxTouchPoints>0||navigator.msMaxTouchPoints>0,r&&"Windows Phone"!==e&&"Android"!==e&&"iOS"!==e&&"Other"!==e)return!0;if("undefined"!=typeof i){if(i=i.toLowerCase(),i.indexOf("win")>=0&&"Windows"!==e&&"Windows Phone"!==e)return!0;if(i.indexOf("linux")>=0&&"Linux"!==e&&"Android"!==e)return!0;if(i.indexOf("mac")>=0&&"Mac"!==e&&"iOS"!==e)return!0;if(0===i.indexOf("win")&&0===i.indexOf("linux")&&i.indexOf("mac")>=0&&"other"!==e)return!0}return a.indexOf("win")>=0&&"Windows"!==e&&"Windows Phone"!==e?!0:(a.indexOf("linux")>=0||a.indexOf("android")>=0||a.indexOf("pike")>=0)&&"Linux"!==e&&"Android"!==e?!0:(a.indexOf("mac")>=0||a.indexOf("ipad")>=0||a.indexOf("ipod")>=0||a.indexOf("iphone")>=0)&&"Mac"!==e&&"iOS"!==e?!0:0===a.indexOf("win")&&0===a.indexOf("linux")&&a.indexOf("mac")>=0&&"other"!==e?!0:"undefined"==typeof navigator.plugins&&"Windows"!==e&&"Windows Phone"!==e},getHasLiedBrowser:function(){var e,t=navigator.userAgent.toLowerCase(),i=navigator.productSub;if(e=t.indexOf("firefox")>=0?"Firefox":t.indexOf("opera")>=0||t.indexOf("opr")>=0?"Opera":t.indexOf("chrome")>=0?"Chrome":t.indexOf("safari")>=0?"Safari":t.indexOf("trident")>=0?"Internet Explorer":"Other",("Chrome"===e||"Safari"===e||"Opera"===e)&&"20030107"!==i)return!0;var a=eval.toString().length;if(37===a&&"Safari"!==e&&"Firefox"!==e&&"Other"!==e)return!0;if(39===a&&"Internet Explorer"!==e&&"Other"!==e)return!0;if(33===a&&"Chrome"!==e&&"Opera"!==e&&"Other"!==e)return!0;var r;try{throw"a"}catch(n){try{n.toSource(),r=!0}catch(o){r=!1}}return!(!r||"Firefox"===e||"Other"===e)},isCanvasSupported:function(){var e=document.createElement("canvas");return!(!e.getContext||!e.getContext("2d"))},isWebGlSupported:function(){if(!this.isCanvasSupported())return!1;var e,t=document.createElement("canvas");try{e=t.getContext&&(t.getContext("webgl")||t.getContext("experimental-webgl"))}catch(i){e=!1}return!!window.WebGLRenderingContext&&!!e},isIE:function(){return"Microsoft Internet Explorer"===navigator.appName?!0:!("Netscape"!==navigator.appName||!/Trident/.test(navigator.userAgent))},hasSwfObjectLoaded:function(){return"undefined"!=typeof window.swfobject},hasMinFlashInstalled:function(){return swfobject.hasFlashPlayerVersion("9.0.0")},addFlashDivNode:function(){var e=document.createElement("div");e.setAttribute("id",this.options.swfContainerId),document.body.appendChild(e)},loadSwfAndDetectFonts:function(e){var t="___fp_swf_loaded";window[t]=function(t){e(t)};var i=this.options.swfContainerId;this.addFlashDivNode();var a={onReady:t},r={allowScriptAccess:"always",menu:"false"};swfobject.embedSWF(this.options.swfPath,i,"1","1","9.0.0",!1,a,r,{})},getWebglCanvas:function(){var e=document.createElement("canvas"),t=null;try{t=e.getContext("webgl")||e.getContext("experimental-webgl")}catch(i){}return t||(t=null),t},each:function(e,t,i){if(null!==e)if(this.nativeForEach&&e.forEach===this.nativeForEach)e.forEach(t,i);else if(e.length===+e.length){for(var a=0,r=e.length;r>a;a++)if(t.call(i,e[a],a,e)==={})return}else for(var n in e)if(e.hasOwnProperty(n)&&t.call(i,e[n],n,e)==={})return},map:function(e,t,i){var a=[];return null==e?a:this.nativeMap&&e.map===this.nativeMap?e.map(t,i):(this.each(e,function(e,r,n){a[a.length]=t.call(i,e,r,n)}),a)},x64Add:function(e,t){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],t=[t[0]>>>16,65535&t[0],t[1]>>>16,65535&t[1]];var i=[0,0,0,0];return i[3]+=e[3]+t[3],i[2]+=i[3]>>>16,i[3]&=65535,i[2]+=e[2]+t[2],i[1]+=i[2]>>>16,i[2]&=65535,i[1]+=e[1]+t[1],i[0]+=i[1]>>>16,i[1]&=65535,i[0]+=e[0]+t[0],i[0]&=65535,[i[0]<<16|i[1],i[2]<<16|i[3]]},x64Multiply:function(e,t){e=[e[0]>>>16,65535&e[0],e[1]>>>16,65535&e[1]],t=[t[0]>>>16,65535&t[0],t[1]>>>16,65535&t[1]];var i=[0,0,0,0];return i[3]+=e[3]*t[3],i[2]+=i[3]>>>16,i[3]&=65535,i[2]+=e[2]*t[3],i[1]+=i[2]>>>16,i[2]&=65535,i[2]+=e[3]*t[2],i[1]+=i[2]>>>16,i[2]&=65535,i[1]+=e[1]*t[3],i[0]+=i[1]>>>16,i[1]&=65535,i[1]+=e[2]*t[2],i[0]+=i[1]>>>16,i[1]&=65535,i[1]+=e[3]*t[1],i[0]+=i[1]>>>16,i[1]&=65535,i[0]+=e[0]*t[3]+e[1]*t[2]+e[2]*t[1]+e[3]*t[0],i[0]&=65535,[i[0]<<16|i[1],i[2]<<16|i[3]]},x64Rotl:function(e,t){return t%=64,32===t?[e[1],e[0]]:32>t?[e[0]<>>32-t,e[1]<>>32-t]:(t-=32,[e[1]<>>32-t,e[0]<>>32-t])},x64LeftShift:function(e,t){return t%=64,0===t?e:32>t?[e[0]<>>32-t,e[1]<>>1]),e=this.x64Multiply(e,[4283543511,3981806797]),e=this.x64Xor(e,[0,e[0]>>>1]),e=this.x64Multiply(e,[3301882366,444984403]),e=this.x64Xor(e,[0,e[0]>>>1])},x64hash128:function(e,t){e=e||"",t=t||0;for(var i=e.length%16,a=e.length-i,r=[0,t],n=[0,t],o=[0,0],s=[0,0],l=[2277735313,289559509],h=[1291169091,658871167],u=0;a>u;u+=16)o=[255&e.charCodeAt(u+4)|(255&e.charCodeAt(u+5))<<8|(255&e.charCodeAt(u+6))<<16|(255&e.charCodeAt(u+7))<<24,255&e.charCodeAt(u)|(255&e.charCodeAt(u+1))<<8|(255&e.charCodeAt(u+2))<<16|(255&e.charCodeAt(u+3))<<24],s=[255&e.charCodeAt(u+12)|(255&e.charCodeAt(u+13))<<8|(255&e.charCodeAt(u+14))<<16|(255&e.charCodeAt(u+15))<<24,255&e.charCodeAt(u+8)|(255&e.charCodeAt(u+9))<<8|(255&e.charCodeAt(u+10))<<16|(255&e.charCodeAt(u+11))<<24],o=this.x64Multiply(o,l),o=this.x64Rotl(o,31),o=this.x64Multiply(o,h),r=this.x64Xor(r,o),r=this.x64Rotl(r,27),r=this.x64Add(r,n),r=this.x64Add(this.x64Multiply(r,[0,5]),[0,1390208809]),s=this.x64Multiply(s,h),s=this.x64Rotl(s,33),s=this.x64Multiply(s,l),n=this.x64Xor(n,s),n=this.x64Rotl(n,31),n=this.x64Add(n,r),n=this.x64Add(this.x64Multiply(n,[0,5]),[0,944331445]);switch(o=[0,0],s=[0,0],i){case 15:s=this.x64Xor(s,this.x64LeftShift([0,e.charCodeAt(u+14)],48));case 14:s=this.x64Xor(s,this.x64LeftShift([0,e.charCodeAt(u+13)],40));case 13:s=this.x64Xor(s,this.x64LeftShift([0,e.charCodeAt(u+12)],32));case 12:s=this.x64Xor(s,this.x64LeftShift([0,e.charCodeAt(u+11)],24));case 11:s=this.x64Xor(s,this.x64LeftShift([0,e.charCodeAt(u+10)],16));case 10:s=this.x64Xor(s,this.x64LeftShift([0,e.charCodeAt(u+9)],8));case 9:s=this.x64Xor(s,[0,e.charCodeAt(u+8)]),s=this.x64Multiply(s,h), +s=this.x64Rotl(s,33),s=this.x64Multiply(s,l),n=this.x64Xor(n,s);case 8:o=this.x64Xor(o,this.x64LeftShift([0,e.charCodeAt(u+7)],56));case 7:o=this.x64Xor(o,this.x64LeftShift([0,e.charCodeAt(u+6)],48));case 6:o=this.x64Xor(o,this.x64LeftShift([0,e.charCodeAt(u+5)],40));case 5:o=this.x64Xor(o,this.x64LeftShift([0,e.charCodeAt(u+4)],32));case 4:o=this.x64Xor(o,this.x64LeftShift([0,e.charCodeAt(u+3)],24));case 3:o=this.x64Xor(o,this.x64LeftShift([0,e.charCodeAt(u+2)],16));case 2:o=this.x64Xor(o,this.x64LeftShift([0,e.charCodeAt(u+1)],8));case 1:o=this.x64Xor(o,[0,e.charCodeAt(u)]),o=this.x64Multiply(o,l),o=this.x64Rotl(o,31),o=this.x64Multiply(o,h),r=this.x64Xor(r,o)}return r=this.x64Xor(r,[0,e.length]),n=this.x64Xor(n,[0,e.length]),r=this.x64Add(r,n),n=this.x64Add(n,r),r=this.x64Fmix(r),n=this.x64Fmix(n),r=this.x64Add(r,n),n=this.x64Add(n,r),("00000000"+(r[0]>>>0).toString(16)).slice(-8)+("00000000"+(r[1]>>>0).toString(16)).slice(-8)+("00000000"+(n[0]>>>0).toString(16)).slice(-8)+("00000000"+(n[1]>>>0).toString(16)).slice(-8)}},e.VERSION="1.1.4",e}); \ No newline at end of file diff --git a/dashboard-ui/bower_components/fingerprintjs2/fingerprint2.js b/dashboard-ui/bower_components/fingerprintjs2/fingerprint2.js index 37a73ee7b..e622ba930 100644 --- a/dashboard-ui/bower_components/fingerprintjs2/fingerprint2.js +++ b/dashboard-ui/bower_components/fingerprintjs2/fingerprint2.js @@ -1,5 +1,5 @@ /* -* Fingerprintjs2 1.4.0 - Modern & flexible browser fingerprint library v2 +* Fingerprintjs2 1.1.4 - Modern & flexible browser fingerprint library v2 * https://github.com/Valve/fingerprintjs2 * Copyright (c) 2015 Valentin Vasilyev (valentin.vasilyev@outlook.com) * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license. @@ -84,7 +84,6 @@ keys = this.userAgentKey(keys); keys = this.languageKey(keys); keys = this.colorDepthKey(keys); - keys = this.pixelRatioKey(keys); keys = this.screenResolutionKey(keys); keys = this.availableScreenResolutionKey(keys); keys = this.timezoneOffsetKey(keys); @@ -142,15 +141,6 @@ } return keys; }, - pixelRatioKey: function(keys) { - if(!this.options.excludePixelRatio) { - keys.push({key: "pixel_ratio", value: this.getPixelRatio()}); - } - return keys; - }, - getPixelRatio: function() { - return window.devicePixelRatio || ""; - }, screenResolutionKey: function(keys) { if(!this.options.excludeScreenResolution) { return this.getScreenResolution(keys); @@ -344,57 +334,6 @@ // and if it doesn't match all 3 then that font is not available. var baseFonts = ["monospace", "sans-serif", "serif"]; - var fontList = [ - "Andale Mono", "Arial", "Arial Black", "Arial Hebrew", "Arial MT", "Arial Narrow", "Arial Rounded MT Bold", "Arial Unicode MS", - "Bitstream Vera Sans Mono", "Book Antiqua", "Bookman Old Style", - "Calibri", "Cambria", "Cambria Math", "Century", "Century Gothic", "Century Schoolbook", "Comic Sans", "Comic Sans MS", "Consolas", "Courier", "Courier New", - "Garamond", "Geneva", "Georgia", - "Helvetica", "Helvetica Neue", - "Impact", - "Lucida Bright", "Lucida Calligraphy", "Lucida Console", "Lucida Fax", "LUCIDA GRANDE", "Lucida Handwriting", "Lucida Sans", "Lucida Sans Typewriter", "Lucida Sans Unicode", - "Microsoft Sans Serif", "Monaco", "Monotype Corsiva", "MS Gothic", "MS Outlook", "MS PGothic", "MS Reference Sans Serif", "MS Sans Serif", "MS Serif", "MYRIAD", "MYRIAD PRO", - "Palatino", "Palatino Linotype", - "Segoe Print", "Segoe Script", "Segoe UI", "Segoe UI Light", "Segoe UI Semibold", "Segoe UI Symbol", - "Tahoma", "Times", "Times New Roman", "Times New Roman PS", "Trebuchet MS", - "Verdana", "Wingdings", "Wingdings 2", "Wingdings 3" - ]; - var extendedFontList = [ - "Abadi MT Condensed Light", "Academy Engraved LET", "ADOBE CASLON PRO", "Adobe Garamond", "ADOBE GARAMOND PRO", "Agency FB", "Aharoni", "Albertus Extra Bold", "Albertus Medium", "Algerian", "Amazone BT", "American Typewriter", - "American Typewriter Condensed", "AmerType Md BT", "Andalus", "Angsana New", "AngsanaUPC", "Antique Olive", "Aparajita", "Apple Chancery", "Apple Color Emoji", "Apple SD Gothic Neo", "Arabic Typesetting", "ARCHER", - "ARNO PRO", "Arrus BT", "Aurora Cn BT", "AvantGarde Bk BT", "AvantGarde Md BT", "AVENIR", "Ayuthaya", "Bandy", "Bangla Sangam MN", "Bank Gothic", "BankGothic Md BT", "Baskerville", - "Baskerville Old Face", "Batang", "BatangChe", "Bauer Bodoni", "Bauhaus 93", "Bazooka", "Bell MT", "Bembo", "Benguiat Bk BT", "Berlin Sans FB", "Berlin Sans FB Demi", "Bernard MT Condensed", "BernhardFashion BT", "BernhardMod BT", "Big Caslon", "BinnerD", - "Blackadder ITC", "BlairMdITC TT", "Bodoni 72", "Bodoni 72 Oldstyle", "Bodoni 72 Smallcaps", "Bodoni MT", "Bodoni MT Black", "Bodoni MT Condensed", "Bodoni MT Poster Compressed", - "Bookshelf Symbol 7", "Boulder", "Bradley Hand", "Bradley Hand ITC", "Bremen Bd BT", "Britannic Bold", "Broadway", "Browallia New", "BrowalliaUPC", "Brush Script MT", "Californian FB", "Calisto MT", "Calligrapher", "Candara", - "CaslonOpnface BT", "Castellar", "Centaur", "Cezanne", "CG Omega", "CG Times", "Chalkboard", "Chalkboard SE", "Chalkduster", "Charlesworth", "Charter Bd BT", "Charter BT", "Chaucer", - "ChelthmITC Bk BT", "Chiller", "Clarendon", "Clarendon Condensed", "CloisterBlack BT", "Cochin", "Colonna MT", "Constantia", "Cooper Black", "Copperplate", "Copperplate Gothic", "Copperplate Gothic Bold", - "Copperplate Gothic Light", "CopperplGoth Bd BT", "Corbel", "Cordia New", "CordiaUPC", "Cornerstone", "Coronet", "Cuckoo", "Curlz MT", "DaunPenh", "Dauphin", "David", "DB LCD Temp", "DELICIOUS", "Denmark", - "DFKai-SB", "Didot", "DilleniaUPC", "DIN", "DokChampa", "Dotum", "DotumChe", "Ebrima", "Edwardian Script ITC", "Elephant", "English 111 Vivace BT", "Engravers MT", "EngraversGothic BT", "Eras Bold ITC", "Eras Demi ITC", "Eras Light ITC", "Eras Medium ITC", - "EucrosiaUPC", "Euphemia", "Euphemia UCAS", "EUROSTILE", "Exotc350 Bd BT", "FangSong", "Felix Titling", "Fixedsys", "FONTIN", "Footlight MT Light", "Forte", - "FrankRuehl", "Fransiscan", "Freefrm721 Blk BT", "FreesiaUPC", "Freestyle Script", "French Script MT", "FrnkGothITC Bk BT", "Fruitger", "FRUTIGER", - "Futura", "Futura Bk BT", "Futura Lt BT", "Futura Md BT", "Futura ZBlk BT", "FuturaBlack BT", "Gabriola", "Galliard BT", "Gautami", "Geeza Pro", "Geometr231 BT", "Geometr231 Hv BT", "Geometr231 Lt BT", "GeoSlab 703 Lt BT", - "GeoSlab 703 XBd BT", "Gigi", "Gill Sans", "Gill Sans MT", "Gill Sans MT Condensed", "Gill Sans MT Ext Condensed Bold", "Gill Sans Ultra Bold", "Gill Sans Ultra Bold Condensed", "Gisha", "Gloucester MT Extra Condensed", "GOTHAM", "GOTHAM BOLD", - "Goudy Old Style", "Goudy Stout", "GoudyHandtooled BT", "GoudyOLSt BT", "Gujarati Sangam MN", "Gulim", "GulimChe", "Gungsuh", "GungsuhChe", "Gurmukhi MN", "Haettenschweiler", "Harlow Solid Italic", "Harrington", "Heather", "Heiti SC", "Heiti TC", "HELV", - "Herald", "High Tower Text", "Hiragino Kaku Gothic ProN", "Hiragino Mincho ProN", "Hoefler Text", "Humanst 521 Cn BT", "Humanst521 BT", "Humanst521 Lt BT", "Imprint MT Shadow", "Incised901 Bd BT", "Incised901 BT", - "Incised901 Lt BT", "INCONSOLATA", "Informal Roman", "Informal011 BT", "INTERSTATE", "IrisUPC", "Iskoola Pota", "JasmineUPC", "Jazz LET", "Jenson", "Jester", "Jokerman", "Juice ITC", "Kabel Bk BT", "Kabel Ult BT", "Kailasa", "KaiTi", "Kalinga", "Kannada Sangam MN", - "Kartika", "Kaufmann Bd BT", "Kaufmann BT", "Khmer UI", "KodchiangUPC", "Kokila", "Korinna BT", "Kristen ITC", "Krungthep", "Kunstler Script", "Lao UI", "Latha", "Leelawadee", "Letter Gothic", "Levenim MT", "LilyUPC", "Lithograph", "Lithograph Light", "Long Island", - "Lydian BT", "Magneto", "Maiandra GD", "Malayalam Sangam MN", "Malgun Gothic", - "Mangal", "Marigold", "Marion", "Marker Felt", "Market", "Marlett", "Matisse ITC", "Matura MT Script Capitals", "Meiryo", "Meiryo UI", "Microsoft Himalaya", "Microsoft JhengHei", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", - "Microsoft Uighur", "Microsoft YaHei", "Microsoft Yi Baiti", "MingLiU", "MingLiU_HKSCS", "MingLiU_HKSCS-ExtB", "MingLiU-ExtB", "Minion", "Minion Pro", "Miriam", "Miriam Fixed", "Mistral", "Modern", "Modern No. 20", "Mona Lisa Solid ITC TT", "Mongolian Baiti", - "MONO", "MoolBoran", "Mrs Eaves", "MS LineDraw", "MS Mincho", "MS PMincho", "MS Reference Specialty", "MS UI Gothic", "MT Extra", "MUSEO", "MV Boli", - "Nadeem", "Narkisim", "NEVIS", "News Gothic", "News GothicMT", "NewsGoth BT", "Niagara Engraved", "Niagara Solid", "Noteworthy", "NSimSun", "Nyala", "OCR A Extended", "Old Century", "Old English Text MT", "Onyx", "Onyx BT", "OPTIMA", "Oriya Sangam MN", - "OSAKA", "OzHandicraft BT", "Palace Script MT", "Papyrus", "Parchment", "Party LET", "Pegasus", "Perpetua", "Perpetua Titling MT", "PetitaBold", "Pickwick", "Plantagenet Cherokee", "Playbill", "PMingLiU", "PMingLiU-ExtB", - "Poor Richard", "Poster", "PosterBodoni BT", "PRINCETOWN LET", "Pristina", "PTBarnum BT", "Pythagoras", "Raavi", "Rage Italic", "Ravie", "Ribbon131 Bd BT", "Rockwell", "Rockwell Condensed", "Rockwell Extra Bold", "Rod", "Roman", "Sakkal Majalla", - "Santa Fe LET", "Savoye LET", "Sceptre", "Script", "Script MT Bold", "SCRIPTINA", "Serifa", "Serifa BT", "Serifa Th BT", "ShelleyVolante BT", "Sherwood", - "Shonar Bangla", "Showcard Gothic", "Shruti", "Signboard", "SILKSCREEN", "SimHei", "Simplified Arabic", "Simplified Arabic Fixed", "SimSun", "SimSun-ExtB", "Sinhala Sangam MN", "Sketch Rockwell", "Skia", "Small Fonts", "Snap ITC", "Snell Roundhand", "Socket", - "Souvenir Lt BT", "Staccato222 BT", "Steamer", "Stencil", "Storybook", "Styllo", "Subway", "Swis721 BlkEx BT", "Swiss911 XCm BT", "Sylfaen", "Synchro LET", "System", "Tamil Sangam MN", "Technical", "Teletype", "Telugu Sangam MN", "Tempus Sans ITC", - "Terminal", "Thonburi", "Traditional Arabic", "Trajan", "TRAJAN PRO", "Tristan", "Tubular", "Tunga", "Tw Cen MT", "Tw Cen MT Condensed", "Tw Cen MT Condensed Extra Bold", - "TypoUpright BT", "Unicorn", "Univers", "Univers CE 55 Medium", "Univers Condensed", "Utsaah", "Vagabond", "Vani", "Vijaya", "Viner Hand ITC", "VisualUI", "Vivaldi", "Vladimir Script", "Vrinda", "Westminster", "WHITNEY", "Wide Latin", - "ZapfEllipt BT", "ZapfHumnst BT", "ZapfHumnst Dm BT", "Zapfino", "Zurich BlkEx BT", "Zurich Ex BT", "ZWAdobeF"]; - - if(that.options.extendedJsFonts) { - fontList = fontList.concat(extendedFontList); - } - //we use m or w because these two characters take up the maximum width. // And we use a LLi so that the same matching fonts can get separated var testString = "mmmmmmmmmmlli"; @@ -404,106 +343,94 @@ var h = document.getElementsByTagName("body")[0]; - // div to load spans for the base fonts - var baseFontsDiv = document.createElement("div"); - - // div to load spans for the fonts to detect - var fontsDiv = document.createElement("div"); - + // create a SPAN in the document to get the width of the text we use to test + var s = document.createElement("span"); + /* + * We need this css as in some weird browser this + * span elements shows up for a microSec which creates a + * bad user experience + */ + s.style.position = "absolute"; + s.style.left = "-9999px"; + s.style.fontSize = testSize; + s.innerHTML = testString; var defaultWidth = {}; var defaultHeight = {}; - - // creates a span where the fonts will be loaded - var createSpan = function() { - var s = document.createElement("span"); - /* - * We need this css as in some weird browser this - * span elements shows up for a microSec which creates a - * bad user experience - */ - s.style.position = "absolute"; - s.style.left = "-9999px"; - s.style.fontSize = testSize; - s.innerHTML = testString; - return s; - }; - - // creates a span and load the font to detect and a base font for fallback - var createSpanWithFonts = function(fontToDetect, baseFont) { - var s = createSpan(); - s.style.fontFamily = "'" + fontToDetect + "'," + baseFont; - return s; - }; - - // creates spans for the base fonts and adds them to baseFontsDiv - var initializeBaseFontsSpans = function() { - var spans = []; - for (var index = 0, length = baseFonts.length; index < length; index++) { - var s = createSpan(); - s.style.fontFamily = baseFonts[index]; - baseFontsDiv.appendChild(s); - spans.push(s); - } - return spans; - }; - - // creates spans for the fonts to detect and adds them to fontsDiv - var initializeFontsSpans = function() { - var spans = {}; - for(var i = 0, l = fontList.length; i < l; i++) { - var fontSpans = []; - for(var j = 0, numDefaultFonts = baseFonts.length; j < numDefaultFonts; j++) { - var s = createSpanWithFonts(fontList[i], baseFonts[j]); - fontsDiv.appendChild(s); - fontSpans.push(s); - } - spans[fontList[i]] = fontSpans; // Stores {fontName : [spans for that font]} - } - return spans; - }; - - // checks if a font is available - var isFontAvailable = function(fontSpans) { + for (var index = 0, length = baseFonts.length; index < length; index++) { + //get the default width for the three base fonts + s.style.fontFamily = baseFonts[index]; + h.appendChild(s); + defaultWidth[baseFonts[index]] = s.offsetWidth; //width for the default font + defaultHeight[baseFonts[index]] = s.offsetHeight; //height for the defualt font + h.removeChild(s); + } + var detect = function (font) { var detected = false; - for(var i = 0; i < baseFonts.length; i++) { - detected = (fontSpans[i].offsetWidth !== defaultWidth[baseFonts[i]] || fontSpans[i].offsetHeight !== defaultHeight[baseFonts[i]]); - if(detected) { - return detected; - } + for (var index = 0, l = baseFonts.length; index < l; index++) { + s.style.fontFamily = font + "," + baseFonts[index]; // name of the font along with the base font for fallback. + h.appendChild(s); + var matched = (s.offsetWidth !== defaultWidth[baseFonts[index]] || s.offsetHeight !== defaultHeight[baseFonts[index]]); + h.removeChild(s); + detected = detected || matched; } return detected; }; + var fontList = [ + "Andale Mono", "Arial", "Arial Black", "Arial Hebrew", "Arial MT", "Arial Narrow", "Arial Rounded MT Bold", "Arial Unicode MS", + "Bitstream Vera Sans Mono", "Book Antiqua", "Bookman Old Style", + "Calibri", "Cambria", "Cambria Math", "Century", "Century Gothic", "Century Schoolbook", "Comic Sans", "Comic Sans MS", "Consolas", "Courier", "Courier New", + "Garamond", "Geneva", "Georgia", + "Helvetica", "Helvetica Neue", + "Impact", + "Lucida Bright", "Lucida Calligraphy", "Lucida Console", "Lucida Fax", "LUCIDA GRANDE", "Lucida Handwriting", "Lucida Sans", "Lucida Sans Typewriter", "Lucida Sans Unicode", + "Microsoft Sans Serif", "Monaco", "Monotype Corsiva", "MS Gothic", "MS Outlook", "MS PGothic", "MS Reference Sans Serif", "MS Sans Serif", "MS Serif", "MYRIAD", "MYRIAD PRO", + "Palatino", "Palatino Linotype", + "Segoe Print", "Segoe Script", "Segoe UI", "Segoe UI Light", "Segoe UI Semibold", "Segoe UI Symbol", + "Tahoma", "Times", "Times New Roman", "Times New Roman PS", "Trebuchet MS", + "Verdana", "Wingdings", "Wingdings 2", "Wingdings 3" + ]; + var extendedFontList = [ + "Abadi MT Condensed Light", "Academy Engraved LET", "ADOBE CASLON PRO", "Adobe Garamond", "ADOBE GARAMOND PRO", "Agency FB", "Aharoni", "Albertus Extra Bold", "Albertus Medium", "Algerian", "Amazone BT", "American Typewriter", + "American Typewriter Condensed", "AmerType Md BT", "Andalus", "Angsana New", "AngsanaUPC", "Antique Olive", "Aparajita", "Apple Chancery", "Apple Color Emoji", "Apple SD Gothic Neo", "Arabic Typesetting", "ARCHER", + "ARNO PRO", "Arrus BT", "Aurora Cn BT", "AvantGarde Bk BT", "AvantGarde Md BT", "AVENIR", "Ayuthaya", "Bandy", "Bangla Sangam MN", "Bank Gothic", "BankGothic Md BT", "Baskerville", + "Baskerville Old Face", "Batang", "BatangChe", "Bauer Bodoni", "Bauhaus 93", "Bazooka", "Bell MT", "Bembo", "Benguiat Bk BT", "Berlin Sans FB", "Berlin Sans FB Demi", "Bernard MT Condensed", "BernhardFashion BT", "BernhardMod BT", "Big Caslon", "BinnerD", + "Blackadder ITC", "BlairMdITC TT", "Bodoni 72", "Bodoni 72 Oldstyle", "Bodoni 72 Smallcaps", "Bodoni MT", "Bodoni MT Black", "Bodoni MT Condensed", "Bodoni MT Poster Compressed", + "Bookshelf Symbol 7", "Boulder", "Bradley Hand", "Bradley Hand ITC", "Bremen Bd BT", "Britannic Bold", "Broadway", "Browallia New", "BrowalliaUPC", "Brush Script MT", "Californian FB", "Calisto MT", "Calligrapher", "Candara", + "CaslonOpnface BT", "Castellar", "Centaur", "Cezanne", "CG Omega", "CG Times", "Chalkboard", "Chalkboard SE", "Chalkduster", "Charlesworth", "Charter Bd BT", "Charter BT", "Chaucer", + "ChelthmITC Bk BT", "Chiller", "Clarendon", "Clarendon Condensed", "CloisterBlack BT", "Cochin", "Colonna MT", "Constantia", "Cooper Black", "Copperplate", "Copperplate Gothic", "Copperplate Gothic Bold", + "Copperplate Gothic Light", "CopperplGoth Bd BT", "Corbel", "Cordia New", "CordiaUPC", "Cornerstone", "Coronet", "Cuckoo", "Curlz MT", "DaunPenh", "Dauphin", "David", "DB LCD Temp", "DELICIOUS", "Denmark", + "DFKai-SB", "Didot", "DilleniaUPC", "DIN", "DokChampa", "Dotum", "DotumChe", "Ebrima", "Edwardian Script ITC", "Elephant", "English 111 Vivace BT", "Engravers MT", "EngraversGothic BT", "Eras Bold ITC", "Eras Demi ITC", "Eras Light ITC", "Eras Medium ITC", + "EucrosiaUPC", "Euphemia", "Euphemia UCAS", "EUROSTILE", "Exotc350 Bd BT", "FangSong", "Felix Titling", "Fixedsys", "FONTIN", "Footlight MT Light", "Forte", + "FrankRuehl", "Fransiscan", "Freefrm721 Blk BT", "FreesiaUPC", "Freestyle Script", "French Script MT", "FrnkGothITC Bk BT", "Fruitger", "FRUTIGER", + "Futura", "Futura Bk BT", "Futura Lt BT", "Futura Md BT", "Futura ZBlk BT", "FuturaBlack BT", "Gabriola", "Galliard BT", "Gautami", "Geeza Pro", "Geometr231 BT", "Geometr231 Hv BT", "Geometr231 Lt BT", "GeoSlab 703 Lt BT", + "GeoSlab 703 XBd BT", "Gigi", "Gill Sans", "Gill Sans MT", "Gill Sans MT Condensed", "Gill Sans MT Ext Condensed Bold", "Gill Sans Ultra Bold", "Gill Sans Ultra Bold Condensed", "Gisha", "Gloucester MT Extra Condensed", "GOTHAM", "GOTHAM BOLD", + "Goudy Old Style", "Goudy Stout", "GoudyHandtooled BT", "GoudyOLSt BT", "Gujarati Sangam MN", "Gulim", "GulimChe", "Gungsuh", "GungsuhChe", "Gurmukhi MN", "Haettenschweiler", "Harlow Solid Italic", "Harrington", "Heather", "Heiti SC", "Heiti TC", "HELV", + "Herald", "High Tower Text", "Hiragino Kaku Gothic ProN", "Hiragino Mincho ProN", "Hoefler Text", "Humanst 521 Cn BT", "Humanst521 BT", "Humanst521 Lt BT", "Imprint MT Shadow", "Incised901 Bd BT", "Incised901 BT", + "Incised901 Lt BT", "INCONSOLATA", "Informal Roman", "Informal011 BT", "INTERSTATE", "IrisUPC", "Iskoola Pota", "JasmineUPC", "Jazz LET", "Jenson", "Jester", "Jokerman", "Juice ITC", "Kabel Bk BT", "Kabel Ult BT", "Kailasa", "KaiTi", "Kalinga", "Kannada Sangam MN", + "Kartika", "Kaufmann Bd BT", "Kaufmann BT", "Khmer UI", "KodchiangUPC", "Kokila", "Korinna BT", "Kristen ITC", "Krungthep", "Kunstler Script", "Lao UI", "Latha", "Leelawadee", "Letter Gothic", "Levenim MT", "LilyUPC", "Lithograph", "Lithograph Light", "Long Island", + "Lydian BT", "Magneto", "Maiandra GD", "Malayalam Sangam MN", "Malgun Gothic", + "Mangal", "Marigold", "Marion", "Marker Felt", "Market", "Marlett", "Matisse ITC", "Matura MT Script Capitals", "Meiryo", "Meiryo UI", "Microsoft Himalaya", "Microsoft JhengHei", "Microsoft New Tai Lue", "Microsoft PhagsPa", "Microsoft Tai Le", + "Microsoft Uighur", "Microsoft YaHei", "Microsoft Yi Baiti", "MingLiU", "MingLiU_HKSCS", "MingLiU_HKSCS-ExtB", "MingLiU-ExtB", "Minion", "Minion Pro", "Miriam", "Miriam Fixed", "Mistral", "Modern", "Modern No. 20", "Mona Lisa Solid ITC TT", "Mongolian Baiti", + "MONO", "MoolBoran", "Mrs Eaves", "MS LineDraw", "MS Mincho", "MS PMincho", "MS Reference Specialty", "MS UI Gothic", "MT Extra", "MUSEO", "MV Boli", + "Nadeem", "Narkisim", "NEVIS", "News Gothic", "News GothicMT", "NewsGoth BT", "Niagara Engraved", "Niagara Solid", "Noteworthy", "NSimSun", "Nyala", "OCR A Extended", "Old Century", "Old English Text MT", "Onyx", "Onyx BT", "OPTIMA", "Oriya Sangam MN", + "OSAKA", "OzHandicraft BT", "Palace Script MT", "Papyrus", "Parchment", "Party LET", "Pegasus", "Perpetua", "Perpetua Titling MT", "PetitaBold", "Pickwick", "Plantagenet Cherokee", "Playbill", "PMingLiU", "PMingLiU-ExtB", + "Poor Richard", "Poster", "PosterBodoni BT", "PRINCETOWN LET", "Pristina", "PTBarnum BT", "Pythagoras", "Raavi", "Rage Italic", "Ravie", "Ribbon131 Bd BT", "Rockwell", "Rockwell Condensed", "Rockwell Extra Bold", "Rod", "Roman", "Sakkal Majalla", + "Santa Fe LET", "Savoye LET", "Sceptre", "Script", "Script MT Bold", "SCRIPTINA", "Serifa", "Serifa BT", "Serifa Th BT", "ShelleyVolante BT", "Sherwood", + "Shonar Bangla", "Showcard Gothic", "Shruti", "Signboard", "SILKSCREEN", "SimHei", "Simplified Arabic", "Simplified Arabic Fixed", "SimSun", "SimSun-ExtB", "Sinhala Sangam MN", "Sketch Rockwell", "Skia", "Small Fonts", "Snap ITC", "Snell Roundhand", "Socket", + "Souvenir Lt BT", "Staccato222 BT", "Steamer", "Stencil", "Storybook", "Styllo", "Subway", "Swis721 BlkEx BT", "Swiss911 XCm BT", "Sylfaen", "Synchro LET", "System", "Tamil Sangam MN", "Technical", "Teletype", "Telugu Sangam MN", "Tempus Sans ITC", + "Terminal", "Thonburi", "Traditional Arabic", "Trajan", "TRAJAN PRO", "Tristan", "Tubular", "Tunga", "Tw Cen MT", "Tw Cen MT Condensed", "Tw Cen MT Condensed Extra Bold", + "TypoUpright BT", "Unicorn", "Univers", "Univers CE 55 Medium", "Univers Condensed", "Utsaah", "Vagabond", "Vani", "Vijaya", "Viner Hand ITC", "VisualUI", "Vivaldi", "Vladimir Script", "Vrinda", "Westminster", "WHITNEY", "Wide Latin", + "ZapfEllipt BT", "ZapfHumnst BT", "ZapfHumnst Dm BT", "Zapfino", "Zurich BlkEx BT", "Zurich Ex BT", "ZWAdobeF"]; - // create spans for base fonts - var baseFontsSpans = initializeBaseFontsSpans(); - - // add the spans to the DOM - h.appendChild(baseFontsDiv); - - // get the default width for the three base fonts - for (var index = 0, length = baseFonts.length; index < length; index++) { - defaultWidth[baseFonts[index]] = baseFontsSpans[index].offsetWidth; // width for the default font - defaultHeight[baseFonts[index]] = baseFontsSpans[index].offsetHeight; // height for the default font + if(that.options.extendedJsFonts) { + fontList = fontList.concat(extendedFontList); } - - // create spans for fonts to detect - var fontsSpans = initializeFontsSpans(); - - // add all the spans to the DOM - h.appendChild(fontsDiv); - - // check available fonts var available = []; - for(var i = 0, l = fontList.length; i < l; i++) { - if(isFontAvailable(fontsSpans[fontList[i]])) { - available.push(fontList[i]); - } + for (var i = 0, l = fontList.length; i < l; i++) { + if(detect(fontList[i])) { + available.push(fontList[i]); + } } - - // remove spans from DOM - h.removeChild(fontsDiv); - h.removeChild(baseFontsDiv); - keys.push({key: "js_fonts", value: available}); done(keys); }, 1); @@ -689,7 +616,7 @@ ctx.font = "11pt no-real-font-123"; } ctx.fillText("Cwm fjordbank glyphs vext quiz, \ud83d\ude03", 2, 15); - ctx.fillStyle = "rgba(102, 204, 0, 0.2)"; + ctx.fillStyle = "rgba(102, 204, 0, 0.7)"; ctx.font = "18pt Arial"; ctx.fillText("Cwm fjordbank glyphs vext quiz, \ud83d\ude03", 4, 45); @@ -843,18 +770,14 @@ }, getAdBlock: function(){ var ads = document.createElement("div"); - ads.innerHTML = " "; - ads.className = "adsbox"; - var result = false; + ads.setAttribute("id", "ads"); try { // body may not exist, that's why we need try/catch document.body.appendChild(ads); - result = document.getElementsByClassName("adsbox")[0].offsetHeight === 0; - document.body.removeChild(ads); + return document.getElementById("ads") ? false : true; } catch (e) { - result = false; + return false; } - return result; }, getHasLiedLanguages: function(){ //We check if navigator.language is equal to the first language of navigator.languages @@ -864,7 +787,7 @@ if(firstLanguages !== navigator.language.substr(0, 2)){ return true; } - } catch(err) { + } catch(err){ return true; } } @@ -1283,6 +1206,6 @@ return ("00000000" + (h1[0] >>> 0).toString(16)).slice(-8) + ("00000000" + (h1[1] >>> 0).toString(16)).slice(-8) + ("00000000" + (h2[0] >>> 0).toString(16)).slice(-8) + ("00000000" + (h2[1] >>> 0).toString(16)).slice(-8); } }; - Fingerprint2.VERSION = "1.4.0"; + Fingerprint2.VERSION = "1.1.4"; return Fingerprint2; }); diff --git a/dashboard-ui/bower_components/fingerprintjs2/flash/FontList.as b/dashboard-ui/bower_components/fingerprintjs2/flash/FontList.as deleted file mode 100644 index 030ab3cee..000000000 --- a/dashboard-ui/bower_components/fingerprintjs2/flash/FontList.as +++ /dev/null @@ -1,31 +0,0 @@ -package { - import flash.display.Sprite; - import flash.display.LoaderInfo; - import flash.text.Font; - import flash.external.ExternalInterface; - - public class FontList extends Sprite { - - public function FontList() { - var params:Object = loadParams(); - loadExternalInterface(params); - } - - private function loadParams():Object { - return LoaderInfo(this.root.loaderInfo).parameters; - } - - private function loadExternalInterface(params:Object):void { - ExternalInterface.call(params.onReady, fonts()); - } - - private function fonts():Array { - var fontNames:Array = []; - for each (var font:Font in Font.enumerateFonts(true) ) - { - fontNames.push(font.fontName); - } - return fontNames; - } - } -} diff --git a/dashboard-ui/bower_components/fingerprintjs2/flash/Makefile b/dashboard-ui/bower_components/fingerprintjs2/flash/Makefile deleted file mode 100644 index cb6e1cc33..000000000 --- a/dashboard-ui/bower_components/fingerprintjs2/flash/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -all: FontList.swf - -FontList.swf: clean - mxmlc -static-link-runtime-shared-libraries FontList.as - -clean: - rm -f FontList.swf diff --git a/dashboard-ui/bower_components/fingerprintjs2/flash/compiled/FontList.swf b/dashboard-ui/bower_components/fingerprintjs2/flash/compiled/FontList.swf deleted file mode 100644 index a7481e86b..000000000 Binary files a/dashboard-ui/bower_components/fingerprintjs2/flash/compiled/FontList.swf and /dev/null differ diff --git a/dashboard-ui/bower_components/fingerprintjs2/package.json b/dashboard-ui/bower_components/fingerprintjs2/package.json index d1acaecab..b7d16a8b4 100644 --- a/dashboard-ui/bower_components/fingerprintjs2/package.json +++ b/dashboard-ui/bower_components/fingerprintjs2/package.json @@ -1,6 +1,6 @@ { "name": "fingerprintjs2", - "version": "1.4.0", + "version": "1.1.4", "description": "Modern & flexible browser fingerprinting library", "main": "dist/fingerprint2.min.js", "devDependencies": { diff --git a/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/boot.js b/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/boot.js deleted file mode 100644 index 04ed64c1c..000000000 --- a/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/boot.js +++ /dev/null @@ -1,121 +0,0 @@ -/** - Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project. - - If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms. - - The location of `boot.js` can be specified and/or overridden in `jasmine.yml`. - - [jasmine-gem]: http://github.com/pivotal/jasmine-gem - */ - -(function() { - - /** - * ## Require & Instantiate - * - * Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference. - */ - window.jasmine = jasmineRequire.core(jasmineRequire); - - /** - * Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference. - */ - jasmineRequire.html(jasmine); - - /** - * Create the Jasmine environment. This is used to run all specs in a project. - */ - var env = jasmine.getEnv(); - - /** - * ## The Global Interface - * - * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged. - */ - var jasmineInterface = jasmineRequire.interface(jasmine, env); - - /** - * Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`. - */ - extend(window, jasmineInterface); - - /** - * ## Runner Parameters - * - * More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface. - */ - - var queryString = new jasmine.QueryString({ - getWindowLocation: function() { return window.location; } - }); - - var catchingExceptions = queryString.getParam("catch"); - env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions); - - var throwingExpectationFailures = queryString.getParam("throwFailures"); - env.throwOnExpectationFailure(throwingExpectationFailures); - - /** - * ## Reporters - * The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any). - */ - var htmlReporter = new jasmine.HtmlReporter({ - env: env, - onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); }, - onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); }, - addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); }, - getContainer: function() { return document.body; }, - createElement: function() { return document.createElement.apply(document, arguments); }, - createTextNode: function() { return document.createTextNode.apply(document, arguments); }, - timer: new jasmine.Timer() - }); - - /** - * The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript. - */ - env.addReporter(jasmineInterface.jsApiReporter); - env.addReporter(htmlReporter); - - /** - * Filter which specs will be run by matching the start of the full name against the `spec` query param. - */ - var specFilter = new jasmine.HtmlSpecFilter({ - filterString: function() { return queryString.getParam("spec"); } - }); - - env.specFilter = function(spec) { - return specFilter.matches(spec.getFullName()); - }; - - /** - * Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack. - */ - window.setTimeout = window.setTimeout; - window.setInterval = window.setInterval; - window.clearTimeout = window.clearTimeout; - window.clearInterval = window.clearInterval; - - /** - * ## Execution - * - * Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded. - */ - var currentWindowOnload = window.onload; - - window.onload = function() { - if (currentWindowOnload) { - currentWindowOnload(); - } - htmlReporter.initialize(); - env.execute(); - }; - - /** - * Helper function for readability above. - */ - function extend(destination, source) { - for (var property in source) destination[property] = source[property]; - return destination; - } - -}()); diff --git a/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine-html.js b/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine-html.js deleted file mode 100644 index 259f45ce2..000000000 --- a/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine-html.js +++ /dev/null @@ -1,446 +0,0 @@ -/* -Copyright (c) 2008-2015 Pivotal Labs - -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. -*/ -jasmineRequire.html = function(j$) { - j$.ResultsNode = jasmineRequire.ResultsNode(); - j$.HtmlReporter = jasmineRequire.HtmlReporter(j$); - j$.QueryString = jasmineRequire.QueryString(); - j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter(); -}; - -jasmineRequire.HtmlReporter = function(j$) { - - var noopTimer = { - start: function() {}, - elapsed: function() { return 0; } - }; - - function HtmlReporter(options) { - var env = options.env || {}, - getContainer = options.getContainer, - createElement = options.createElement, - createTextNode = options.createTextNode, - onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {}, - onThrowExpectationsClick = options.onThrowExpectationsClick || function() {}, - addToExistingQueryString = options.addToExistingQueryString || defaultQueryString, - timer = options.timer || noopTimer, - results = [], - specsExecuted = 0, - failureCount = 0, - pendingSpecCount = 0, - htmlReporterMain, - symbols, - failedSuites = []; - - this.initialize = function() { - clearPrior(); - htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'}, - createDom('div', {className: 'banner'}, - createDom('a', {className: 'title', href: 'http://jasmine.github.io/', target: '_blank'}), - createDom('span', {className: 'version'}, j$.version) - ), - createDom('ul', {className: 'symbol-summary'}), - createDom('div', {className: 'alert'}), - createDom('div', {className: 'results'}, - createDom('div', {className: 'failures'}) - ) - ); - getContainer().appendChild(htmlReporterMain); - - symbols = find('.symbol-summary'); - }; - - var totalSpecsDefined; - this.jasmineStarted = function(options) { - totalSpecsDefined = options.totalSpecsDefined || 0; - timer.start(); - }; - - var summary = createDom('div', {className: 'summary'}); - - var topResults = new j$.ResultsNode({}, '', null), - currentParent = topResults; - - this.suiteStarted = function(result) { - currentParent.addChild(result, 'suite'); - currentParent = currentParent.last(); - }; - - this.suiteDone = function(result) { - if (result.status == 'failed') { - failedSuites.push(result); - } - - if (currentParent == topResults) { - return; - } - - currentParent = currentParent.parent; - }; - - this.specStarted = function(result) { - currentParent.addChild(result, 'spec'); - }; - - var failures = []; - this.specDone = function(result) { - if(noExpectations(result) && typeof console !== 'undefined' && typeof console.error !== 'undefined') { - console.error('Spec \'' + result.fullName + '\' has no expectations.'); - } - - if (result.status != 'disabled') { - specsExecuted++; - } - - symbols.appendChild(createDom('li', { - className: noExpectations(result) ? 'empty' : result.status, - id: 'spec_' + result.id, - title: result.fullName - } - )); - - if (result.status == 'failed') { - failureCount++; - - var failure = - createDom('div', {className: 'spec-detail failed'}, - createDom('div', {className: 'description'}, - createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName) - ), - createDom('div', {className: 'messages'}) - ); - var messages = failure.childNodes[1]; - - for (var i = 0; i < result.failedExpectations.length; i++) { - var expectation = result.failedExpectations[i]; - messages.appendChild(createDom('div', {className: 'result-message'}, expectation.message)); - messages.appendChild(createDom('div', {className: 'stack-trace'}, expectation.stack)); - } - - failures.push(failure); - } - - if (result.status == 'pending') { - pendingSpecCount++; - } - }; - - this.jasmineDone = function() { - var banner = find('.banner'); - var alert = find('.alert'); - alert.appendChild(createDom('span', {className: 'duration'}, 'finished in ' + timer.elapsed() / 1000 + 's')); - - banner.appendChild( - createDom('div', { className: 'run-options' }, - createDom('span', { className: 'trigger' }, 'Options'), - createDom('div', { className: 'payload' }, - createDom('div', { className: 'exceptions' }, - createDom('input', { - className: 'raise', - id: 'raise-exceptions', - type: 'checkbox' - }), - createDom('label', { className: 'label', 'for': 'raise-exceptions' }, 'raise exceptions')), - createDom('div', { className: 'throw-failures' }, - createDom('input', { - className: 'throw', - id: 'throw-failures', - type: 'checkbox' - }), - createDom('label', { className: 'label', 'for': 'throw-failures' }, 'stop spec on expectation failure')) - ) - )); - - var raiseCheckbox = find('#raise-exceptions'); - - raiseCheckbox.checked = !env.catchingExceptions(); - raiseCheckbox.onclick = onRaiseExceptionsClick; - - var throwCheckbox = find('#throw-failures'); - throwCheckbox.checked = env.throwingExpectationFailures(); - throwCheckbox.onclick = onThrowExpectationsClick; - - var optionsMenu = find('.run-options'), - optionsTrigger = optionsMenu.querySelector('.trigger'), - optionsPayload = optionsMenu.querySelector('.payload'), - isOpen = /\bopen\b/; - - optionsTrigger.onclick = function() { - if (isOpen.test(optionsPayload.className)) { - optionsPayload.className = optionsPayload.className.replace(isOpen, ''); - } else { - optionsPayload.className += ' open'; - } - }; - - if (specsExecuted < totalSpecsDefined) { - var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all'; - alert.appendChild( - createDom('span', {className: 'bar skipped'}, - createDom('a', {href: '?', title: 'Run all specs'}, skippedMessage) - ) - ); - } - var statusBarMessage = ''; - var statusBarClassName = 'bar '; - - if (totalSpecsDefined > 0) { - statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount); - if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); } - statusBarClassName += (failureCount > 0) ? 'failed' : 'passed'; - } else { - statusBarClassName += 'skipped'; - statusBarMessage += 'No specs found'; - } - - alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage)); - - for(i = 0; i < failedSuites.length; i++) { - var failedSuite = failedSuites[i]; - for(var j = 0; j < failedSuite.failedExpectations.length; j++) { - var errorBarMessage = 'AfterAll ' + failedSuite.failedExpectations[j].message; - var errorBarClassName = 'bar errored'; - alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessage)); - } - } - - var results = find('.results'); - results.appendChild(summary); - - summaryList(topResults, summary); - - function summaryList(resultsTree, domParent) { - var specListNode; - for (var i = 0; i < resultsTree.children.length; i++) { - var resultNode = resultsTree.children[i]; - if (resultNode.type == 'suite') { - var suiteListNode = createDom('ul', {className: 'suite', id: 'suite-' + resultNode.result.id}, - createDom('li', {className: 'suite-detail'}, - createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description) - ) - ); - - summaryList(resultNode, suiteListNode); - domParent.appendChild(suiteListNode); - } - if (resultNode.type == 'spec') { - if (domParent.getAttribute('class') != 'specs') { - specListNode = createDom('ul', {className: 'specs'}); - domParent.appendChild(specListNode); - } - var specDescription = resultNode.result.description; - if(noExpectations(resultNode.result)) { - specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription; - } - if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') { - specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason; - } - specListNode.appendChild( - createDom('li', { - className: resultNode.result.status, - id: 'spec-' + resultNode.result.id - }, - createDom('a', {href: specHref(resultNode.result)}, specDescription) - ) - ); - } - } - } - - if (failures.length) { - alert.appendChild( - createDom('span', {className: 'menu bar spec-list'}, - createDom('span', {}, 'Spec List | '), - createDom('a', {className: 'failures-menu', href: '#'}, 'Failures'))); - alert.appendChild( - createDom('span', {className: 'menu bar failure-list'}, - createDom('a', {className: 'spec-list-menu', href: '#'}, 'Spec List'), - createDom('span', {}, ' | Failures '))); - - find('.failures-menu').onclick = function() { - setMenuModeTo('failure-list'); - }; - find('.spec-list-menu').onclick = function() { - setMenuModeTo('spec-list'); - }; - - setMenuModeTo('failure-list'); - - var failureNode = find('.failures'); - for (var i = 0; i < failures.length; i++) { - failureNode.appendChild(failures[i]); - } - } - }; - - return this; - - function find(selector) { - return getContainer().querySelector('.jasmine_html-reporter ' + selector); - } - - function clearPrior() { - // return the reporter - var oldReporter = find(''); - - if(oldReporter) { - getContainer().removeChild(oldReporter); - } - } - - function createDom(type, attrs, childrenVarArgs) { - var el = createElement(type); - - for (var i = 2; i < arguments.length; i++) { - var child = arguments[i]; - - if (typeof child === 'string') { - el.appendChild(createTextNode(child)); - } else { - if (child) { - el.appendChild(child); - } - } - } - - for (var attr in attrs) { - if (attr == 'className') { - el[attr] = attrs[attr]; - } else { - el.setAttribute(attr, attrs[attr]); - } - } - - return el; - } - - function pluralize(singular, count) { - var word = (count == 1 ? singular : singular + 's'); - - return '' + count + ' ' + word; - } - - function specHref(result) { - return addToExistingQueryString('spec', result.fullName); - } - - function defaultQueryString(key, value) { - return '?' + key + '=' + value; - } - - function setMenuModeTo(mode) { - htmlReporterMain.setAttribute('class', 'jasmine_html-reporter ' + mode); - } - - function noExpectations(result) { - return (result.failedExpectations.length + result.passedExpectations.length) === 0 && - result.status === 'passed'; - } - } - - return HtmlReporter; -}; - -jasmineRequire.HtmlSpecFilter = function() { - function HtmlSpecFilter(options) { - var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); - var filterPattern = new RegExp(filterString); - - this.matches = function(specName) { - return filterPattern.test(specName); - }; - } - - return HtmlSpecFilter; -}; - -jasmineRequire.ResultsNode = function() { - function ResultsNode(result, type, parent) { - this.result = result; - this.type = type; - this.parent = parent; - - this.children = []; - - this.addChild = function(result, type) { - this.children.push(new ResultsNode(result, type, this)); - }; - - this.last = function() { - return this.children[this.children.length - 1]; - }; - } - - return ResultsNode; -}; - -jasmineRequire.QueryString = function() { - function QueryString(options) { - - this.navigateWithNewParam = function(key, value) { - options.getWindowLocation().search = this.fullStringWithNewParam(key, value); - }; - - this.fullStringWithNewParam = function(key, value) { - var paramMap = queryStringToParamMap(); - paramMap[key] = value; - return toQueryString(paramMap); - }; - - this.getParam = function(key) { - return queryStringToParamMap()[key]; - }; - - return this; - - function toQueryString(paramMap) { - var qStrPairs = []; - for (var prop in paramMap) { - qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])); - } - return '?' + qStrPairs.join('&'); - } - - function queryStringToParamMap() { - var paramStr = options.getWindowLocation().search.substring(1), - params = [], - paramMap = {}; - - if (paramStr.length > 0) { - params = paramStr.split('&'); - for (var i = 0; i < params.length; i++) { - var p = params[i].split('='); - var value = decodeURIComponent(p[1]); - if (value === 'true' || value === 'false') { - value = JSON.parse(value); - } - paramMap[decodeURIComponent(p[0])] = value; - } - } - - return paramMap; - } - - } - - return QueryString; -}; diff --git a/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine-matchers.js b/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine-matchers.js deleted file mode 100644 index fff2033f0..000000000 --- a/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine-matchers.js +++ /dev/null @@ -1,1757 +0,0 @@ -(function e(t, n, r) { - function s(o, u) { - if (!n[o]) { - if (!t[o]) { - var a = typeof require == 'function' && require; - if (!u && a) { - return a(o, !0); - } - if (i) { - return i(o, !0); - } - var f = new Error('Cannot find module \'' + o + '\''); - throw f.code = 'MODULE_NOT_FOUND', f - } - var l = n[o] = { - exports: {} - }; - t[o][0].call(l.exports, function(e) { - var n = t[o][1][e]; - return s(n ? n : e); - }, l, l.exports, e, t, n, r); - } - return n[o].exports; - } - var i = typeof require == 'function' && require; - for (var o = 0; o < r.length; o++) { - s(r[o]); - } - return s; -})({ - 1: [function(require, module, exports) { - 'use strict'; - - /* - * Copyright © Jamie Mason, @fold_left, - * https://github.com/JamieMason - * - * 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 factory = require('./lib/factory'); - - var matchers = { - toBeAfter: require('./toBeAfter'), - toBeArray: require('./toBeArray'), - toBeArrayOfBooleans: require('./toBeArrayOfBooleans'), - toBeArrayOfNumbers: require('./toBeArrayOfNumbers'), - toBeArrayOfObjects: require('./toBeArrayOfObjects'), - toBeArrayOfSize: require('./toBeArrayOfSize'), - toBeArrayOfStrings: require('./toBeArrayOfStrings'), - toBeBefore: require('./toBeBefore'), - toBeBoolean: require('./toBeBoolean'), - toBeCalculable: require('./toBeCalculable'), - toBeDate: require('./toBeDate'), - toBeEmptyArray: require('./toBeEmptyArray'), - toBeEmptyObject: require('./toBeEmptyObject'), - toBeEmptyString: require('./toBeEmptyString'), - toBeEvenNumber: require('./toBeEvenNumber'), - toBeFalse: require('./toBeFalse'), - toBeFunction: require('./toBeFunction'), - toBeHtmlString: require('./toBeHtmlString'), - toBeIso8601: require('./toBeIso8601'), - toBeJsonString: require('./toBeJsonString'), - toBeLongerThan: require('./toBeLongerThan'), - toBeNonEmptyArray: require('./toBeNonEmptyArray'), - toBeNonEmptyObject: require('./toBeNonEmptyObject'), - toBeNonEmptyString: require('./toBeNonEmptyString'), - toBeNumber: require('./toBeNumber'), - toBeObject: require('./toBeObject'), - toBeOddNumber: require('./toBeOddNumber'), - toBeSameLengthAs: require('./toBeSameLengthAs'), - toBeShorterThan: require('./toBeShorterThan'), - toBeString: require('./toBeString'), - toBeTrue: require('./toBeTrue'), - toBeWhitespace: require('./toBeWhitespace'), - toBeWholeNumber: require('./toBeWholeNumber'), - toBeWithinRange: require('./toBeWithinRange'), - toEndWith: require('./toEndWith'), - toImplement: require('./toImplement'), - toStartWith: require('./toStartWith'), - toThrowAnyError: require('./toThrowAnyError'), - toThrowErrorOfType: require('./toThrowErrorOfType'), - toHaveArray: require('./toHaveArray'), - toHaveArrayOfBooleans: require('./toHaveArrayOfBooleans'), - toHaveArrayOfNumbers: require('./toHaveArrayOfNumbers'), - toHaveArrayOfObjects: require('./toHaveArrayOfObjects'), - toHaveArrayOfSize: require('./toHaveArrayOfSize'), - toHaveArrayOfStrings: require('./toHaveArrayOfStrings'), - toHaveBoolean: require('./toHaveBoolean'), - toHaveCalculable: require('./toHaveCalculable'), - toHaveDate: require('./toHaveDate'), - toHaveDateAfter: require('./toHaveDateAfter'), - toHaveDateBefore: require('./toHaveDateBefore'), - toHaveEmptyArray: require('./toHaveEmptyArray'), - toHaveEmptyObject: require('./toHaveEmptyObject'), - toHaveEmptyString: require('./toHaveEmptyString'), - toHaveEvenNumber: require('./toHaveEvenNumber'), - toHaveFalse: require('./toHaveFalse'), - toHaveHtmlString: require('./toHaveHtmlString'), - toHaveIso8601: require('./toHaveIso8601'), - toHaveJsonString: require('./toHaveJsonString'), - toHaveMember: require('./toHaveMember'), - toHaveMethod: require('./toHaveMethod'), - toHaveNonEmptyArray: require('./toHaveNonEmptyArray'), - toHaveNonEmptyObject: require('./toHaveNonEmptyObject'), - toHaveNonEmptyString: require('./toHaveNonEmptyString'), - toHaveNumber: require('./toHaveNumber'), - toHaveNumberWithinRange: require('./toHaveNumberWithinRange'), - toHaveObject: require('./toHaveObject'), - toHaveOddNumber: require('./toHaveOddNumber'), - toHaveString: require('./toHaveString'), - toHaveStringLongerThan: require('./toHaveStringLongerThan'), - toHaveStringSameLengthAs: require('./toHaveStringSameLengthAs'), - toHaveStringShorterThan: require('./toHaveStringShorterThan'), - toHaveTrue: require('./toHaveTrue'), - toHaveWhitespaceString: require('./toHaveWhitespaceString'), - toHaveWholeNumber: require('./toHaveWholeNumber') - }; - - for (var matcherName in matchers) { - factory(matcherName, matchers[matcherName]); - } - - module.exports = matchers; - - }, { - './lib/factory': 3, - './toBeAfter': 10, - './toBeArray': 11, - './toBeArrayOfBooleans': 12, - './toBeArrayOfNumbers': 13, - './toBeArrayOfObjects': 14, - './toBeArrayOfSize': 15, - './toBeArrayOfStrings': 16, - './toBeBefore': 17, - './toBeBoolean': 18, - './toBeCalculable': 19, - './toBeDate': 20, - './toBeEmptyArray': 21, - './toBeEmptyObject': 22, - './toBeEmptyString': 23, - './toBeEvenNumber': 24, - './toBeFalse': 25, - './toBeFunction': 26, - './toBeHtmlString': 27, - './toBeIso8601': 28, - './toBeJsonString': 29, - './toBeLongerThan': 30, - './toBeNonEmptyArray': 31, - './toBeNonEmptyObject': 32, - './toBeNonEmptyString': 33, - './toBeNumber': 34, - './toBeObject': 35, - './toBeOddNumber': 36, - './toBeSameLengthAs': 37, - './toBeShorterThan': 38, - './toBeString': 39, - './toBeTrue': 40, - './toBeWhitespace': 41, - './toBeWholeNumber': 42, - './toBeWithinRange': 43, - './toEndWith': 44, - './toHaveArray': 45, - './toHaveArrayOfBooleans': 46, - './toHaveArrayOfNumbers': 47, - './toHaveArrayOfObjects': 48, - './toHaveArrayOfSize': 49, - './toHaveArrayOfStrings': 50, - './toHaveBoolean': 51, - './toHaveCalculable': 52, - './toHaveDate': 53, - './toHaveDateAfter': 54, - './toHaveDateBefore': 55, - './toHaveEmptyArray': 56, - './toHaveEmptyObject': 57, - './toHaveEmptyString': 58, - './toHaveEvenNumber': 59, - './toHaveFalse': 60, - './toHaveHtmlString': 61, - './toHaveIso8601': 62, - './toHaveJsonString': 63, - './toHaveMember': 64, - './toHaveMethod': 65, - './toHaveNonEmptyArray': 66, - './toHaveNonEmptyObject': 67, - './toHaveNonEmptyString': 68, - './toHaveNumber': 69, - './toHaveNumberWithinRange': 70, - './toHaveObject': 71, - './toHaveOddNumber': 72, - './toHaveString': 73, - './toHaveStringLongerThan': 74, - './toHaveStringSameLengthAs': 75, - './toHaveStringShorterThan': 76, - './toHaveTrue': 77, - './toHaveWhitespaceString': 78, - './toHaveWholeNumber': 79, - './toImplement': 80, - './toStartWith': 81, - './toThrowAnyError': 82, - './toThrowErrorOfType': 83 - }], - 2: [function(require, module, exports) { - 'use strict'; - - module.exports = every; - - function every(array, truthTest) { - for (var i = 0, len = array.length; i < len; i++) { - if (!truthTest(array[i])) { - return false; - } - } - return true; - } - - }, {}], - 3: [function(require, module, exports) { - 'use strict'; - - var adapters = typeof jasmine.addMatchers === 'function' ? - require('./jasmine-v2') : - require('./jasmine-v1'); - - module.exports = function(name, matcher) { - var adapter = adapters[matcher.length]; - return adapter(name, matcher); - }; - - }, { - './jasmine-v1': 4, - './jasmine-v2': 5 - }], - 4: [function(require, module, exports) { - 'use strict'; - - module.exports = { - 1: createFactory(forActual), - 2: createFactory(forActualAndExpected), - 3: createFactory(forActualAndTwoExpected), - 4: createFactory(forKeyAndActualAndTwoExpected) - }; - - function createFactory(adapter) { - return function jasmineV1MatcherFactory(name, matcher) { - var matcherByName = new JasmineV1Matcher(name, adapter, matcher); - beforeEach(function() { - this.addMatchers(matcherByName); - }); - return matcherByName; - }; - } - - function JasmineV1Matcher(name, adapter, matcher) { - this[name] = adapter(name, matcher); - } - - function forActual(name, matcher) { - return function(optionalMessage) { - return matcher(this.actual, optionalMessage); - }; - } - - function forActualAndExpected(name, matcher) { - return function(expected, optionalMessage) { - return matcher(expected, this.actual, optionalMessage); - }; - } - - function forActualAndTwoExpected(name, matcher) { - return function(expected1, expected2, optionalMessage) { - return matcher(expected1, expected2, this.actual, optionalMessage); - }; - } - - function forKeyAndActualAndTwoExpected(name, matcher) { - return function(key, expected1, expected2, optionalMessage) { - return matcher(key, expected1, expected2, this.actual, optionalMessage); - }; - } - - }, {}], - 5: [function(require, module, exports) { - 'use strict'; - - var matcherFactory = require('./matcherFactory'); - var memberMatcherFactory = require('./memberMatcherFactory'); - - module.exports = { - 1: createFactory(getAdapter(1)), - 2: createFactory(getAdapter(2)), - 3: createFactory(getAdapter(3)), - 4: createFactory(getAdapter(4)) - }; - - function createFactory(adapter) { - return function jasmineV2MatcherFactory(name, matcher) { - var matcherByName = new JasmineV2Matcher(name, adapter, matcher); - beforeEach(function() { - jasmine.addMatchers(matcherByName); - }); - return matcherByName; - }; - } - - function JasmineV2Matcher(name, adapter, matcher) { - this[name] = adapter(name, matcher); - } - - function getAdapter(argsCount) { - return function adapter(name, matcher) { - var factory = isMemberMatcher(name) ? memberMatcherFactory : matcherFactory; - return factory[argsCount](name, matcher); - }; - } - - function isMemberMatcher(name) { - return name.search(/^toHave/) !== -1; - } - - }, { - './matcherFactory': 6, - './memberMatcherFactory': 7 - }], - 6: [function(require, module, exports) { - 'use strict'; - - module.exports = { - 1: forActual, - 2: forActualAndExpected, - 3: forActualAndTwoExpected - }; - - function forActual(name, matcher) { - return function(util) { - return { - compare: function(actual, optionalMessage) { - var passes = matcher(actual); - return { - pass: passes, - message: ( - optionalMessage ? - util.buildFailureMessage(name, passes, actual, optionalMessage) : - util.buildFailureMessage(name, passes, actual) - ) - }; - } - }; - }; - } - - function forActualAndExpected(name, matcher) { - return function(util) { - return { - compare: function(actual, expected, optionalMessage) { - var passes = matcher(expected, actual); - return { - pass: passes, - message: ( - optionalMessage ? - util.buildFailureMessage(name, passes, actual, expected, optionalMessage) : - util.buildFailureMessage(name, passes, actual, expected) - ) - }; - } - }; - }; - } - - function forActualAndTwoExpected(name, matcher) { - return function(util) { - return { - compare: function(actual, expected1, expected2, optionalMessage) { - var passes = matcher(expected1, expected2, actual); - return { - pass: passes, - message: ( - optionalMessage ? - util.buildFailureMessage(name, passes, actual, expected1, expected2, optionalMessage) : - util.buildFailureMessage(name, passes, actual, expected1, expected2) - ) - }; - } - }; - }; - } - - }, {}], - 7: [function(require, module, exports) { - 'use strict'; - - module.exports = { - 2: forKeyAndActual, - 3: forKeyAndActualAndExpected, - 4: forKeyAndActualAndTwoExpected - }; - - function forKeyAndActual(name, matcher) { - return function(util) { - return { - compare: function(actual, key, optionalMessage) { - var passes = matcher(key, actual); - return { - pass: passes, - message: ( - optionalMessage ? - util.buildFailureMessage(name, passes, actual, optionalMessage) : - util.buildFailureMessage(name, passes, actual) - ) - }; - } - }; - }; - } - - function forKeyAndActualAndExpected(name, matcher) { - return function(util) { - return { - compare: function(actual, key, expected, optionalMessage) { - var passes = matcher(key, expected, actual); - return { - pass: passes, - message: ( - optionalMessage ? - util.buildFailureMessage(name, passes, actual, expected, optionalMessage) : - util.buildFailureMessage(name, passes, actual, expected) - ) - }; - } - }; - }; - } - - function forKeyAndActualAndTwoExpected(name, matcher) { - return function(util) { - return { - compare: function(actual, key, expected1, expected2, optionalMessage) { - var passes = matcher(key, expected1, expected2, actual); - return { - pass: passes, - message: ( - optionalMessage ? - util.buildFailureMessage(name, passes, actual, expected1, expected2, optionalMessage) : - util.buildFailureMessage(name, passes, actual, expected1, expected2) - ) - }; - } - }; - }; - } - - }, {}], - 8: [function(require, module, exports) { - 'use strict'; - - module.exports = is; - - function is(value, type) { - return Object.prototype.toString.call(value) === '[object ' + type + ']'; - } - - }, {}], - 9: [function(require, module, exports) { - 'use strict'; - - module.exports = keys; - - function keys(object) { - var list = []; - for (var key in object) { - if (object.hasOwnProperty(key)) { - list.push(key); - } - } - return list; - } - - }, {}], - 10: [function(require, module, exports) { - 'use strict'; - - var toBeBefore = require('./toBeBefore'); - - module.exports = toBeAfter; - - function toBeAfter(otherDate, actual) { - return toBeBefore(actual, otherDate); - } - - }, { - './toBeBefore': 17 - }], - 11: [function(require, module, exports) { - 'use strict'; - - var is = require('./lib/is'); - - module.exports = toBeArray; - - function toBeArray(actual) { - return is(actual, 'Array'); - } - - }, { - './lib/is': 8 - }], - 12: [function(require, module, exports) { - 'use strict'; - - var every = require('./lib/every'); - var toBeArray = require('./toBeArray'); - var toBeBoolean = require('./toBeBoolean'); - - module.exports = toBeArrayOfBooleans; - - function toBeArrayOfBooleans(actual) { - return toBeArray(actual) && - every(actual, toBeBoolean); - } - - }, { - './lib/every': 2, - './toBeArray': 11, - './toBeBoolean': 18 - }], - 13: [function(require, module, exports) { - 'use strict'; - - var every = require('./lib/every'); - var toBeArray = require('./toBeArray'); - var toBeNumber = require('./toBeNumber'); - - module.exports = toBeArrayOfBooleans; - - function toBeArrayOfBooleans(actual) { - return toBeArray(actual) && - every(actual, toBeNumber); - } - - }, { - './lib/every': 2, - './toBeArray': 11, - './toBeNumber': 34 - }], - 14: [function(require, module, exports) { - 'use strict'; - - var every = require('./lib/every'); - var toBeArray = require('./toBeArray'); - var toBeObject = require('./toBeObject'); - - module.exports = toBeArrayOfBooleans; - - function toBeArrayOfBooleans(actual) { - return toBeArray(actual) && - every(actual, toBeObject); - } - - }, { - './lib/every': 2, - './toBeArray': 11, - './toBeObject': 35 - }], - 15: [function(require, module, exports) { - 'use strict'; - - var toBeArray = require('./toBeArray'); - - module.exports = toBeArrayOfSize; - - function toBeArrayOfSize(size, actual) { - return toBeArray(actual) && - actual.length === size; - } - - }, { - './toBeArray': 11 - }], - 16: [function(require, module, exports) { - 'use strict'; - - var every = require('./lib/every'); - var toBeArray = require('./toBeArray'); - var toBeString = require('./toBeString'); - - module.exports = toBeArrayOfStrings; - - function toBeArrayOfStrings(actual) { - return toBeArray(actual) && - every(actual, toBeString); - } - - }, { - './lib/every': 2, - './toBeArray': 11, - './toBeString': 39 - }], - 17: [function(require, module, exports) { - 'use strict'; - - var toBeDate = require('./toBeDate'); - - module.exports = toBeBefore; - - function toBeBefore(otherDate, actual) { - return toBeDate(actual) && - toBeDate(otherDate) && - actual.getTime() < otherDate.getTime(); - } - - }, { - './toBeDate': 20 - }], - 18: [function(require, module, exports) { - 'use strict'; - - var is = require('./lib/is'); - - module.exports = toBeBoolean; - - function toBeBoolean(actual) { - return is(actual, 'Boolean'); - } - - }, { - './lib/is': 8 - }], - 19: [function(require, module, exports) { - 'use strict'; - - module.exports = toBeCalculable; - - // Assert subject can be used in Mathemetic - // calculations despite not being a Number, - // for example `"1" * "2" === 2` whereas - // `"wut?" * 2 === NaN`. - function toBeCalculable(actual) { - return !isNaN(actual * 2); - } - - }, {}], - 20: [function(require, module, exports) { - 'use strict'; - - var is = require('./lib/is'); - - module.exports = toBeDate; - - function toBeDate(actual) { - return is(actual, 'Date'); - } - - }, { - './lib/is': 8 - }], - 21: [function(require, module, exports) { - 'use strict'; - - var toBeArrayOfSize = require('./toBeArrayOfSize'); - - module.exports = toBeEmptyArray; - - function toBeEmptyArray(actual) { - return toBeArrayOfSize(0, actual); - } - - }, { - './toBeArrayOfSize': 15 - }], - 22: [function(require, module, exports) { - 'use strict'; - - var keys = require('./lib/keys'); - var is = require('./lib/is'); - - module.exports = toBeEmptyObject; - - function toBeEmptyObject(actual) { - return is(actual, 'Object') && - keys(actual).length === 0; - } - - }, { - './lib/is': 8, - './lib/keys': 9 - }], - 23: [function(require, module, exports) { - 'use strict'; - - module.exports = toBeEmptyString; - - function toBeEmptyString(actual) { - return actual === ''; - } - - }, {}], - 24: [function(require, module, exports) { - 'use strict'; - - var toBeNumber = require('./toBeNumber'); - - module.exports = toBeEvenNumber; - - function toBeEvenNumber(actual) { - return toBeNumber(actual) && - actual % 2 === 0; - } - - }, { - './toBeNumber': 34 - }], - 25: [function(require, module, exports) { - 'use strict'; - - var is = require('./lib/is'); - - module.exports = toBeFalse; - - function toBeFalse(actual) { - return actual === false || - is(actual, 'Boolean') && - !actual.valueOf(); - } - - }, { - './lib/is': 8 - }], - 26: [function(require, module, exports) { - 'use strict'; - - module.exports = toBeFunction; - - function toBeFunction(actual) { - return typeof actual === 'function'; - } - - }, {}], - 27: [function(require, module, exports) { - 'use strict'; - - var toBeString = require('./toBeString'); - - module.exports = toBeHtmlString; - - function toBeHtmlString(actual) { - // < start with opening tag "<" - // ( start group 1 - // "[^"]*" allow string in "double quotes" - // | OR - // '[^']*' allow string in "single quotes" - // | OR - // [^'">] cant contains one single quotes, double quotes and ">" - // ) end group 1 - // * 0 or more - // > end with closing tag ">" - return toBeString(actual) && - actual.search(/<("[^"]*"|'[^']*'|[^'">])*>/) !== -1; - } - - }, { - './toBeString': 39 - }], - 28: [function(require, module, exports) { - 'use strict'; - - var toBeString = require('./toBeString'); - - module.exports = toBeIso8601; - - function toBeIso8601(actual) { - - if (!toBeString(actual)) { - return false; - } - - if ( - isIso8601(actual, [ - // 2013-07-08 - 4, '-', 2, '-', 2 - ]) || isIso8601(actual, [ - // 2013-07-08T07:29 - 4, '-', 2, '-', 2, 'T', 2, ':', 2 - ]) || isIso8601(actual, [ - // 2013-07-08T07:29:15 - 4, '-', 2, '-', 2, 'T', 2, ':', 2, ':', 2 - ]) || isIso8601(actual, [ - // 2013-07-08T07:29:15.863 - 4, '-', 2, '-', 2, 'T', 2, ':', 2, ':', 2, '.', 3 - ]) || isIso8601(actual, [ - // 2013-07-08T07:29:15.863Z - 4, '-', 2, '-', 2, 'T', 2, ':', 2, ':', 2, '.', 3, 'Z' - ]) - ) { - return new Date(actual).toString() !== 'Invalid Date'; - } - - return false; - - } - - function isIso8601(string, pattern) { - var returnValue = string.search( - new RegExp('^' + pattern.map(function(term) { - if (term === '-') { - return '\\-'; - } else if (typeof term === 'string') { - return term; - } else { - return '([0-9]{' + term + '})'; - } - }).join('') + '$') - ) !== -1; - return returnValue; - } - - }, { - './toBeString': 39 - }], - 29: [function(require, module, exports) { - 'use strict'; - - module.exports = toBeJsonString; - - function toBeJsonString(actual) { - var isParseable; - var json; - try { - json = JSON.parse(actual); - } catch (e) { - isParseable = false; - } - return isParseable !== false && - json !== null; - } - - }, {}], - 30: [function(require, module, exports) { - 'use strict'; - - var toBeString = require('./toBeString'); - - module.exports = toBeLongerThan; - - function toBeLongerThan(otherString, actual) { - return toBeString(actual) && - toBeString(otherString) && - actual.length > otherString.length; - } - - }, { - './toBeString': 39 - }], - 31: [function(require, module, exports) { - 'use strict'; - - var is = require('./lib/is'); - - module.exports = toBeNonEmptyArray; - - function toBeNonEmptyArray(actual) { - return is(actual, 'Array') && - actual.length > 0; - } - - }, { - './lib/is': 8 - }], - 32: [function(require, module, exports) { - 'use strict'; - - var keys = require('./lib/keys'); - var is = require('./lib/is'); - - module.exports = toBeNonEmptyObject; - - function toBeNonEmptyObject(actual) { - return is(actual, 'Object') && - keys(actual).length > 0; - } - - }, { - './lib/is': 8, - './lib/keys': 9 - }], - 33: [function(require, module, exports) { - 'use strict'; - - var toBeString = require('./toBeString'); - - module.exports = toBeNonEmptyString; - - function toBeNonEmptyString(actual) { - return toBeString(actual) && - actual.length > 0; - } - - }, { - './toBeString': 39 - }], - 34: [function(require, module, exports) { - 'use strict'; - - var is = require('./lib/is'); - - module.exports = toBeNumber; - - function toBeNumber(actual) { - return !isNaN(parseFloat(actual)) && - !is(actual, 'String'); - } - - }, { - './lib/is': 8 - }], - 35: [function(require, module, exports) { - 'use strict'; - - var is = require('./lib/is'); - - module.exports = toBeObject; - - function toBeObject(actual) { - return is(actual, 'Object'); - } - - }, { - './lib/is': 8 - }], - 36: [function(require, module, exports) { - 'use strict'; - - var toBeNumber = require('./toBeNumber'); - - module.exports = toBeOddNumber; - - function toBeOddNumber(actual) { - return toBeNumber(actual) && - actual % 2 !== 0; - } - - }, { - './toBeNumber': 34 - }], - 37: [function(require, module, exports) { - 'use strict'; - - var toBeString = require('./toBeString'); - - module.exports = toBeSameLengthAs; - - function toBeSameLengthAs(otherString, actual) { - return toBeString(actual) && - toBeString(otherString) && - actual.length === otherString.length; - } - - }, { - './toBeString': 39 - }], - 38: [function(require, module, exports) { - 'use strict'; - - var toBeString = require('./toBeString'); - - module.exports = toBeShorterThan; - - function toBeShorterThan(otherString, actual) { - return toBeString(actual) && - toBeString(otherString) && - actual.length < otherString.length; - } - - }, { - './toBeString': 39 - }], - 39: [function(require, module, exports) { - 'use strict'; - - var is = require('./lib/is'); - - module.exports = toBeString; - - function toBeString(actual) { - return is(actual, 'String'); - } - - }, { - './lib/is': 8 - }], - 40: [function(require, module, exports) { - 'use strict'; - - var is = require('./lib/is'); - - module.exports = toBeTrue; - - function toBeTrue(actual) { - return actual === true || - is(actual, 'Boolean') && - actual.valueOf(); - } - - }, { - './lib/is': 8 - }], - 41: [function(require, module, exports) { - 'use strict'; - - var toBeString = require('./toBeString'); - - module.exports = toBeWhitespace; - - function toBeWhitespace(actual) { - return toBeString(actual) && - actual.search(/\S/) === -1; - } - - }, { - './toBeString': 39 - }], - 42: [function(require, module, exports) { - 'use strict'; - - var toBeNumber = require('./toBeNumber'); - - module.exports = toBeWholeNumber; - - function toBeWholeNumber(actual) { - return toBeNumber(actual) && ( - actual === 0 || actual % 1 === 0 - ); - } - - }, { - './toBeNumber': 34 - }], - 43: [function(require, module, exports) { - 'use strict'; - - var toBeNumber = require('./toBeNumber'); - - module.exports = toBeWithinRange; - - function toBeWithinRange(floor, ceiling, actual) { - return toBeNumber(actual) && - actual >= floor && - actual <= ceiling; - } - - }, { - './toBeNumber': 34 - }], - 44: [function(require, module, exports) { - 'use strict'; - - var toBeNonEmptyString = require('./toBeNonEmptyString'); - - module.exports = toEndWith; - - function toEndWith(subString, actual) { - if (!toBeNonEmptyString(actual) || !toBeNonEmptyString(subString)) { - return false; - } - return actual.slice(actual.length - subString.length, actual.length) === subString; - } - - }, { - './toBeNonEmptyString': 33 - }], - 45: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeArray = require('./toBeArray'); - - module.exports = toHaveArray; - - function toHaveArray(key, actual) { - return toBeObject(actual) && - toBeArray(actual[key]); - } - - }, { - './toBeArray': 11, - './toBeObject': 35 - }], - 46: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeArrayOfBooleans = require('./toBeArrayOfBooleans'); - - module.exports = toHaveArrayOfBooleans; - - function toHaveArrayOfBooleans(key, actual) { - return toBeObject(actual) && - toBeArrayOfBooleans(actual[key]); - } - - }, { - './toBeArrayOfBooleans': 12, - './toBeObject': 35 - }], - 47: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeArrayOfNumbers = require('./toBeArrayOfNumbers'); - - module.exports = toHaveArrayOfNumbers; - - function toHaveArrayOfNumbers(key, actual) { - return toBeObject(actual) && - toBeArrayOfNumbers(actual[key]); - } - - }, { - './toBeArrayOfNumbers': 13, - './toBeObject': 35 - }], - 48: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeArrayOfObjects = require('./toBeArrayOfObjects'); - - module.exports = toHaveArrayOfObjects; - - function toHaveArrayOfObjects(key, actual) { - return toBeObject(actual) && - toBeArrayOfObjects(actual[key]); - } - - }, { - './toBeArrayOfObjects': 14, - './toBeObject': 35 - }], - 49: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeArrayOfSize = require('./toBeArrayOfSize'); - - module.exports = toHaveArrayOfSize; - - function toHaveArrayOfSize(key, size, actual) { - return toBeObject(actual) && - toBeArrayOfSize(size, actual[key]); - } - - }, { - './toBeArrayOfSize': 15, - './toBeObject': 35 - }], - 50: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeArrayOfStrings = require('./toBeArrayOfStrings'); - - module.exports = toHaveArrayOfStrings; - - function toHaveArrayOfStrings(key, actual) { - return toBeObject(actual) && - toBeArrayOfStrings(actual[key]); - } - - }, { - './toBeArrayOfStrings': 16, - './toBeObject': 35 - }], - 51: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeBoolean = require('./toBeBoolean'); - - module.exports = toHaveBoolean; - - function toHaveBoolean(key, actual) { - return toBeObject(actual) && - toBeBoolean(actual[key]); - } - - }, { - './toBeBoolean': 18, - './toBeObject': 35 - }], - 52: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeCalculable = require('./toBeCalculable'); - - module.exports = toHaveCalculable; - - function toHaveCalculable(key, actual) { - return toBeObject(actual) && - toBeCalculable(actual[key]); - } - - }, { - './toBeCalculable': 19, - './toBeObject': 35 - }], - 53: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeDate = require('./toBeDate'); - - module.exports = toHaveDate; - - function toHaveDate(key, actual) { - return toBeObject(actual) && - toBeDate(actual[key]); - } - - }, { - './toBeDate': 20, - './toBeObject': 35 - }], - 54: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeAfter = require('./toBeAfter'); - - module.exports = toHaveDateAfter; - - function toHaveDateAfter(key, date, actual) { - return toBeObject(actual) && - toBeAfter(date, actual[key]); - } - - }, { - './toBeAfter': 10, - './toBeObject': 35 - }], - 55: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeBefore = require('./toBeBefore'); - - module.exports = toHaveDateBefore; - - function toHaveDateBefore(key, date, actual) { - return toBeObject(actual) && - toBeBefore(date, actual[key]); - } - - }, { - './toBeBefore': 17, - './toBeObject': 35 - }], - 56: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeEmptyArray = require('./toBeEmptyArray'); - - module.exports = toHaveEmptyArray; - - function toHaveEmptyArray(key, actual) { - return toBeObject(actual) && - toBeEmptyArray(actual[key]); - } - - }, { - './toBeEmptyArray': 21, - './toBeObject': 35 - }], - 57: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeEmptyObject = require('./toBeEmptyObject'); - - module.exports = toHaveEmptyObject; - - function toHaveEmptyObject(key, actual) { - return toBeObject(actual) && - toBeEmptyObject(actual[key]); - } - - }, { - './toBeEmptyObject': 22, - './toBeObject': 35 - }], - 58: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeEmptyString = require('./toBeEmptyString'); - - module.exports = toHaveEmptyString; - - function toHaveEmptyString(key, actual) { - return toBeObject(actual) && - toBeEmptyString(actual[key]); - } - - }, { - './toBeEmptyString': 23, - './toBeObject': 35 - }], - 59: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeEvenNumber = require('./toBeEvenNumber'); - - module.exports = toHaveEvenNumber; - - function toHaveEvenNumber(key, actual) { - return toBeObject(actual) && - toBeEvenNumber(actual[key]); - } - - }, { - './toBeEvenNumber': 24, - './toBeObject': 35 - }], - 60: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeFalse = require('./toBeFalse'); - - module.exports = toHaveFalse; - - function toHaveFalse(key, actual) { - return toBeObject(actual) && - toBeFalse(actual[key]); - } - - }, { - './toBeFalse': 25, - './toBeObject': 35 - }], - 61: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeHtmlString = require('./toBeHtmlString'); - - module.exports = toHaveHtmlString; - - function toHaveHtmlString(key, actual) { - return toBeObject(actual) && - toBeHtmlString(actual[key]); - } - - }, { - './toBeHtmlString': 27, - './toBeObject': 35 - }], - 62: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeIso8601 = require('./toBeIso8601'); - - module.exports = toHaveIso8601; - - function toHaveIso8601(key, actual) { - return toBeObject(actual) && - toBeIso8601(actual[key]); - } - - }, { - './toBeIso8601': 28, - './toBeObject': 35 - }], - 63: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeJsonString = require('./toBeJsonString'); - - module.exports = toHaveJsonString; - - function toHaveJsonString(key, actual) { - return toBeObject(actual) && - toBeJsonString(actual[key]); - } - - }, { - './toBeJsonString': 29, - './toBeObject': 35 - }], - 64: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeString = require('./toBeString'); - - module.exports = toHaveMember; - - function toHaveMember(key, actual) { - return toBeString(key) && - toBeObject(actual) && - key in actual; - } - - }, { - './toBeObject': 35, - './toBeString': 39 - }], - 65: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeFunction = require('./toBeFunction'); - - module.exports = toHaveMethod; - - function toHaveMethod(key, actual) { - return toBeObject(actual) && - toBeFunction(actual[key]); - } - - }, { - './toBeFunction': 26, - './toBeObject': 35 - }], - 66: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeNonEmptyArray = require('./toBeNonEmptyArray'); - - module.exports = toHaveNonEmptyArray; - - function toHaveNonEmptyArray(key, actual) { - return toBeObject(actual) && - toBeNonEmptyArray(actual[key]); - } - - }, { - './toBeNonEmptyArray': 31, - './toBeObject': 35 - }], - 67: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeNonEmptyObject = require('./toBeNonEmptyObject'); - - module.exports = toHaveNonEmptyObject; - - function toHaveNonEmptyObject(key, actual) { - return toBeObject(actual) && - toBeNonEmptyObject(actual[key]); - } - - }, { - './toBeNonEmptyObject': 32, - './toBeObject': 35 - }], - 68: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeNonEmptyString = require('./toBeNonEmptyString'); - - module.exports = toHaveNonEmptyString; - - function toHaveNonEmptyString(key, actual) { - return toBeObject(actual) && - toBeNonEmptyString(actual[key]); - } - - }, { - './toBeNonEmptyString': 33, - './toBeObject': 35 - }], - 69: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeNumber = require('./toBeNumber'); - - module.exports = toHaveNumber; - - function toHaveNumber(key, actual) { - return toBeObject(actual) && - toBeNumber(actual[key]); - } - - }, { - './toBeNumber': 34, - './toBeObject': 35 - }], - 70: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeWithinRange = require('./toBeWithinRange'); - - module.exports = toHaveNumberWithinRange; - - function toHaveNumberWithinRange(key, floor, ceiling, actual) { - return toBeObject(actual) && - toBeWithinRange(floor, ceiling, actual[key]); - } - - }, { - './toBeObject': 35, - './toBeWithinRange': 43 - }], - 71: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - - module.exports = toHaveObject; - - function toHaveObject(key, actual) { - return toBeObject(actual) && - toBeObject(actual[key]); - } - - }, { - './toBeObject': 35 - }], - 72: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeOddNumber = require('./toBeOddNumber'); - - module.exports = toHaveOddNumber; - - function toHaveOddNumber(key, actual) { - return toBeObject(actual) && - toBeOddNumber(actual[key]); - } - - }, { - './toBeObject': 35, - './toBeOddNumber': 36 - }], - 73: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeString = require('./toBeString'); - - module.exports = toHaveString; - - function toHaveString(key, actual) { - return toBeObject(actual) && - toBeString(actual[key]); - } - - }, { - './toBeObject': 35, - './toBeString': 39 - }], - 74: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeLongerThan = require('./toBeLongerThan'); - - module.exports = toHaveStringLongerThan; - - function toHaveStringLongerThan(key, other, actual) { - return toBeObject(actual) && - toBeLongerThan(other, actual[key]); - } - - }, { - './toBeLongerThan': 30, - './toBeObject': 35 - }], - 75: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeSameLengthAs = require('./toBeSameLengthAs'); - - module.exports = toHaveStringSameLengthAs; - - function toHaveStringSameLengthAs(key, other, actual) { - return toBeObject(actual) && - toBeSameLengthAs(other, actual[key]); - } - - }, { - './toBeObject': 35, - './toBeSameLengthAs': 37 - }], - 76: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeShorterThan = require('./toBeShorterThan'); - - module.exports = toHaveStringShorterThan; - - function toHaveStringShorterThan(key, other, actual) { - return toBeObject(actual) && - toBeShorterThan(other, actual[key]); - } - - }, { - './toBeObject': 35, - './toBeShorterThan': 38 - }], - 77: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeTrue = require('./toBeTrue'); - - module.exports = toHaveTrue; - - function toHaveTrue(key, actual) { - return toBeObject(actual) && - toBeTrue(actual[key]); - } - - }, { - './toBeObject': 35, - './toBeTrue': 40 - }], - 78: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeWhitespace = require('./toBeWhitespace'); - - module.exports = toHaveWhitespaceString; - - function toHaveWhitespaceString(key, actual) { - return toBeObject(actual) && - toBeWhitespace(actual[key]); - } - - }, { - './toBeObject': 35, - './toBeWhitespace': 41 - }], - 79: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - var toBeWholeNumber = require('./toBeWholeNumber'); - - module.exports = toHaveWholeNumber; - - function toHaveWholeNumber(key, actual) { - return toBeObject(actual) && - toBeWholeNumber(actual[key]); - } - - }, { - './toBeObject': 35, - './toBeWholeNumber': 42 - }], - 80: [function(require, module, exports) { - 'use strict'; - - var toBeObject = require('./toBeObject'); - - module.exports = toImplement; - - function toImplement(api, actual) { - return toBeObject(api) && - toBeObject(actual) && - featuresAll(api, actual); - } - - function featuresAll(api, actual) { - for (var key in api) { - if (api.hasOwnProperty(key) && - key in actual === false) { - return false; - } - } - return true; - } - - }, { - './toBeObject': 35 - }], - 81: [function(require, module, exports) { - 'use strict'; - - var toBeNonEmptyString = require('./toBeNonEmptyString'); - - module.exports = toStartWith; - - function toStartWith(subString, actual) { - if (!toBeNonEmptyString(actual) || !toBeNonEmptyString(subString)) { - return false; - } - return actual.slice(0, subString.length) === subString; - } - - }, { - './toBeNonEmptyString': 33 - }], - 82: [function(require, module, exports) { - 'use strict'; - - module.exports = toThrowAnyError; - - function toThrowAnyError(actual) { - var threwError = false; - try { - actual(); - } catch (e) { - threwError = true; - } - return threwError; - } - - }, {}], - 83: [function(require, module, exports) { - 'use strict'; - - module.exports = toThrowErrorOfType; - - function toThrowErrorOfType(type, actual) { - var threwErrorOfType = false; - try { - actual(); - } catch (e) { - threwErrorOfType = (e.name === type); - } - return threwErrorOfType; - } - - }, {}] -}, {}, [1]); diff --git a/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine.css b/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine.css deleted file mode 100644 index f9f4ae901..000000000 --- a/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine.css +++ /dev/null @@ -1,58 +0,0 @@ -body { overflow-y: scroll; } - -.jasmine_html-reporter { background-color: #eee; padding: 5px; margin: -8px; font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333; } -.jasmine_html-reporter a { text-decoration: none; } -.jasmine_html-reporter a:hover { text-decoration: underline; } -.jasmine_html-reporter p, .jasmine_html-reporter h1, .jasmine_html-reporter h2, .jasmine_html-reporter h3, .jasmine_html-reporter h4, .jasmine_html-reporter h5, .jasmine_html-reporter h6 { margin: 0; line-height: 14px; } -.jasmine_html-reporter .banner, .jasmine_html-reporter .symbol-summary, .jasmine_html-reporter .summary, .jasmine_html-reporter .result-message, .jasmine_html-reporter .spec .description, .jasmine_html-reporter .spec-detail .description, .jasmine_html-reporter .alert .bar, .jasmine_html-reporter .stack-trace { padding-left: 9px; padding-right: 9px; } -.jasmine_html-reporter .banner { position: relative; } -.jasmine_html-reporter .banner .title { background: url('data:image/png;base64,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') no-repeat; background: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmVyc2lvbj0iMS4xIgogICB3aWR0aD0iNjgxLjk2MjUyIgogICBoZWlnaHQ9IjE4Ny41IgogICBpZD0ic3ZnMiIKICAgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOCI+PHJkZjpSREY+PGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPjxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PjxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz48L2NjOldvcms+PC9yZGY6UkRGPjwvbWV0YWRhdGE+PGRlZnMKICAgICBpZD0iZGVmczYiPjxjbGlwUGF0aAogICAgICAgaWQ9ImNsaXBQYXRoMTgiPjxwYXRoCiAgICAgICAgIGQ9Ik0gMCwxNTAwIDAsMCBsIDU0NTUuNzQsMCAwLDE1MDAgTCAwLDE1MDAgeiIKICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgaWQ9InBhdGgyMCIgLz48L2NsaXBQYXRoPjwvZGVmcz48ZwogICAgIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsMTg3LjUpIgogICAgIGlkPSJnMTAiPjxnCiAgICAgICB0cmFuc2Zvcm09InNjYWxlKDAuMSwwLjEpIgogICAgICAgaWQ9ImcxMiI+PGcKICAgICAgICAgaWQ9ImcxNCI+PGcKICAgICAgICAgICBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxOCkiCiAgICAgICAgICAgaWQ9ImcxNiI+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTU0NCw1OTkuNDM0IGMgMC45MiwtNDAuMzUyIDI1LjY4LC04MS42MDIgNzEuNTMsLTgxLjYwMiAyNy41MSwwIDQ3LjY4LDEyLjgzMiA2MS40NCwzNS43NTQgMTIuODMsMjIuOTMgMTIuODMsNTYuODUyIDEyLjgzLDgyLjUyNyBsIDAsMzI5LjE4NCAtNzEuNTIsMCAwLDEwNC41NDMgMjY2LjgzLDAgMCwtMTA0LjU0MyAtNzAuNiwwIDAsLTM0NC43NyBjIDAsLTU4LjY5MSAtMy42OCwtMTA0LjUzMSAtNDQuOTMsLTE1Mi4yMTggLTM2LjY4LC00Mi4xOCAtOTYuMjgsLTY2LjAyIC0xNTMuMTQsLTY2LjAyIC0xMTcuMzcsMCAtMjA3LjI0LDc3Ljk0MSAtMjAyLjY0LDE5Ny4xNDUgbCAxMzAuMiwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMjIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDIzMDEuNCw2NjIuNjk1IGMgMCw4MC43MDMgLTY2Ljk0LDE0NS44MTMgLTE0Ny42MywxNDUuODEzIC04My40NCwwIC0xNDcuNjMsLTY4Ljc4MSAtMTQ3LjYzLC0xNTEuMzAxIDAsLTc5Ljc4NSA2Ni45NCwtMTQ1LjgwMSAxNDUuOCwtMTQ1LjgwMSA4NC4zNSwwIDE0OS40Niw2Ny44NTIgMTQ5LjQ2LDE1MS4yODkgeiBtIC0xLjgzLC0xODEuNTQ3IGMgLTM1Ljc3LC01NC4wOTcgLTkzLjUzLC03OC44NTkgLTE1Ny43MiwtNzguODU5IC0xNDAuMywwIC0yNTEuMjQsMTE2LjQ0OSAtMjUxLjI0LDI1NC45MTggMCwxNDIuMTI5IDExMy43LDI2MC40MSAyNTYuNzQsMjYwLjQxIDYzLjI3LDAgMTE4LjI5LC0yOS4zMzYgMTUyLjIyLC04Mi41MjMgbCAwLDY5LjY4NyAxNzUuMTQsMCAwLC0xMDQuNTI3IC02MS40NCwwIDAsLTI4MC41OTggNjEuNDQsMCAwLC0xMDQuNTI3IC0xNzUuMTQsMCAwLDY2LjAxOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAyNjIyLjMzLDU1Ny4yNTggYyAzLjY3LC00NC4wMTYgMzMuMDEsLTczLjM0OCA3OC44NiwtNzMuMzQ4IDMzLjkzLDAgNjYuOTMsMjMuODI0IDY2LjkzLDYwLjUwNCAwLDQ4LjYwNiAtNDUuODQsNTYuODU2IC04My40NCw2Ni45NDEgLTg1LjI4LDIyLjAwNCAtMTc4LjgxLDQ4LjYwNiAtMTc4LjgxLDE1NS44NzkgMCw5My41MzYgNzguODYsMTQ3LjYzMyAxNjUuOTgsMTQ3LjYzMyA0NCwwIDgzLjQzLC05LjE3NiAxMTAuOTQsLTQ0LjAwOCBsIDAsMzMuOTIyIDgyLjUzLDAgMCwtMTMyLjk2NSAtMTA4LjIxLDAgYyAtMS44MywzNC44NTYgLTI4LjQyLDU3Ljc3NCAtNjMuMjYsNTcuNzc0IC0zMC4yNiwwIC02Mi4zNSwtMTcuNDIyIC02Mi4zNSwtNTEuMzQ4IDAsLTQ1Ljg0NyA0NC45MywtNTUuOTMgODAuNjksLTY0LjE4IDg4LjAyLC0yMC4xNzUgMTgyLjQ3LC00Ny42OTUgMTgyLjQ3LC0xNTcuNzM0IDAsLTk5LjAyNyAtODMuNDQsLTE1NC4wMzkgLTE3NS4xMywtMTU0LjAzOSAtNDkuNTMsMCAtOTQuNDYsMTUuNTgyIC0xMjYuNTUsNTMuMTggbCAwLC00MC4zNCAtODUuMjcsMCAwLDE0Mi4xMjkgMTE0LjYyLDAiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGgyNiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMjk4OC4xOCw4MDAuMjU0IC02My4yNiwwIDAsMTA0LjUyNyAxNjUuMDUsMCAwLC03My4zNTUgYyAzMS4xOCw1MS4zNDcgNzguODYsODUuMjc3IDE0MS4yMSw4NS4yNzcgNjcuODUsMCAxMjQuNzEsLTQxLjI1OCAxNTIuMjEsLTEwMi42OTkgMjYuNiw2Mi4zNTEgOTIuNjIsMTAyLjY5OSAxNjAuNDcsMTAyLjY5OSA1My4xOSwwIDEwNS40NiwtMjIgMTQxLjIxLC02Mi4zNTEgMzguNTIsLTQ0LjkzOCAzOC41MiwtOTMuNTMyIDM4LjUyLC0xNDkuNDU3IGwgMCwtMTg1LjIzOSA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40MiwwIDAsMTA0LjUyNyA2My4yOCwwIDAsMTU3LjcxNSBjIDAsMzIuMTAyIDAsNjAuNTI3IC0xNC42Nyw4OC45NTcgLTE4LjM0LDI2LjU4MiAtNDguNjEsNDAuMzQ0IC03OS43Nyw0MC4zNDQgLTMwLjI2LDAgLTYzLjI4LC0xMi44NDQgLTgyLjUzLC0zNi42NzIgLTIyLjkzLC0yOS4zNTUgLTIyLjkzLC01Ni44NjMgLTIyLjkzLC05Mi42MjkgbCAwLC0xNTcuNzE1IDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM4LjQxLDAgMCwxMDQuNTI3IDYzLjI4LDAgMCwxNTAuMzgzIGMgMCwyOS4zNDggMCw2Ni4wMjMgLTE0LjY3LDkxLjY5OSAtMTUuNTksMjkuMzM2IC00Ny42OSw0NC45MzQgLTgwLjcsNDQuOTM0IC0zMS4xOCwwIC01Ny43NywtMTEuMDA4IC03Ny45NCwtMzUuNzc0IC0yNC43NywtMzAuMjUzIC0yNi42LC02Mi4zNDMgLTI2LjYsLTk5Ljk0MSBsIDAsLTE1MS4zMDEgNjMuMjcsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNiwwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDI4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSAzOTk4LjY2LDk1MS41NDcgLTExMS44NywwIDAsMTE4LjI5MyAxMTEuODcsMCAwLC0xMTguMjkzIHogbSAwLC00MzEuODkxIDYzLjI3LDAgMCwtMTA0LjUyNyAtMjM5LjMzLDAgMCwxMDQuNTI3IDY0LjE5LDAgMCwyODAuNTk4IC02My4yNywwIDAsMTA0LjUyNyAxNzUuMTQsMCAwLC0zODUuMTI1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzAiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDQxNTkuMTIsODAwLjI1NCAtNjMuMjcsMCAwLDEwNC41MjcgMTc1LjE0LDAgMCwtNjkuNjg3IGMgMjkuMzUsNTQuMTAxIDg0LjM2LDgwLjY5OSAxNDQuODcsODAuNjk5IDUzLjE5LDAgMTA1LjQ1LC0yMi4wMTYgMTQxLjIyLC02MC41MjcgNDAuMzQsLTQ0LjkzNCA0MS4yNiwtODguMDMyIDQxLjI2LC0xNDMuOTU3IGwgMCwtMTkxLjY1MyA2My4yNywwIDAsLTEwNC41MjcgLTIzOC40LDAgMCwxMDQuNTI3IDYzLjI2LDAgMCwxNTguNjM3IGMgMCwzMC4yNjIgMCw2MS40MzQgLTE5LjI2LDg4LjAzNSAtMjAuMTcsMjYuNTgyIC01My4xOCwzOS40MTQgLTg2LjE5LDM5LjQxNCAtMzMuOTMsMCAtNjguNzcsLTEzLjc1IC04OC45NCwtNDEuMjUgLTIxLjA5LC0yNy41IC0yMS4wOSwtNjkuNjg3IC0yMS4wOSwtMTAyLjcwNyBsIDAsLTE0Mi4xMjkgNjMuMjYsMCAwLC0xMDQuNTI3IC0yMzguNCwwIDAsMTA0LjUyNyA2My4yNywwIDAsMjgwLjU5OCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDMyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA1MDgyLjQ4LDcwMy45NjUgYyAtMTkuMjQsNzAuNjA1IC04MS42LDExNS41NDcgLTE1NC4wNCwxMTUuNTQ3IC02Ni4wNCwwIC0xMjkuMywtNTEuMzQ4IC0xNDMuMDUsLTExNS41NDcgbCAyOTcuMDksMCB6IG0gODUuMjcsLTE0NC44ODMgYyAtMzguNTEsLTkzLjUyMyAtMTI5LjI3LC0xNTYuNzkzIC0yMzEuMDUsLTE1Ni43OTMgLTE0My4wNywwIC0yNTcuNjgsMTExLjg3MSAtMjU3LjY4LDI1NS44MzYgMCwxNDQuODgzIDEwOS4xMiwyNjEuMzI4IDI1NC45MSwyNjEuMzI4IDY3Ljg3LDAgMTM1LjcyLC0zMC4yNTggMTgzLjM5LC03OC44NjMgNDguNjIsLTUxLjM0NCA2OC43OSwtMTEzLjY5NSA2OC43OSwtMTgzLjM4MyBsIC0zLjY3LC0zOS40MzQgLTM5Ni4xMywwIGMgMTQuNjcsLTY3Ljg2MyA3Ny4wMywtMTE3LjM2MyAxNDYuNzIsLTExNy4zNjMgNDguNTksMCA5MC43NiwxOC4zMjggMTE4LjI4LDU4LjY3MiBsIDExNi40NCwwIgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDY5MC44OTUsODUwLjcwMyA5MC43NSwwIDIyLjU0MywzMS4wMzUgMCwyNDMuMTIyIC0xMzUuODI5LDAgMCwtMjQzLjE0MSAyMi41MzYsLTMxLjAxNiIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDM2IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA2MzIuMzk1LDc0Mi4yNTggMjguMDM5LDg2LjMwNCAtMjIuNTUxLDMxLjA0IC0yMzEuMjIzLDc1LjEyOCAtNDEuOTc2LC0xMjkuMTgzIDIzMS4yNTcsLTc1LjEzNyAzNi40NTQsMTEuODQ4IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoMzgiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDcxNy40NDksNjUzLjEwNSAtNzMuNDEsNTMuMzYgLTM2LjQ4OCwtMTEuODc1IC0xNDIuOTAzLC0xOTYuNjkyIDEwOS44ODMsLTc5LjgyOCAxNDIuOTE4LDE5Ni43MDMgMCwzOC4zMzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0MCIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gODI4LjUyLDcwNi40NjUgLTczLjQyNiwtNTMuMzQgMC4wMTEsLTM4LjM1OSBMIDg5OC4wMDQsNDE4LjA3IDEwMDcuOSw0OTcuODk4IDg2NC45NzMsNjk0LjYwOSA4MjguNTIsNzA2LjQ2NSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQyIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA4MTIuMDg2LDgyOC41ODYgMjguMDU1LC04Ni4zMiAzNi40ODQsLTExLjgzNiAyMzEuMjI1LDc1LjExNyAtNDEuOTcsMTI5LjE4MyAtMjMxLjIzOSwtNzUuMTQgLTIyLjU1NSwtMzEuMDA0IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNDQiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDczNi4zMDEsMTMzNS44OCBjIC0zMjMuMDQ3LDAgLTU4NS44NzUsLTI2Mi43OCAtNTg1Ljg3NSwtNTg1Ljc4MiAwLC0zMjMuMTE4IDI2Mi44MjgsLTU4NS45NzcgNTg1Ljg3NSwtNTg1Ljk3NyAzMjMuMDE5LDAgNTg1LjgwOSwyNjIuODU5IDU4NS44MDksNTg1Ljk3NyAwLDMyMy4wMDIgLTI2Mi43OSw1ODUuNzgyIC01ODUuODA5LDU4NS43ODIgbCAwLDAgeiBtIDAsLTExOC42MSBjIDI1Ny45NzIsMCA0NjcuMTg5LC0yMDkuMTMgNDY3LjE4OSwtNDY3LjE3MiAwLC0yNTguMTI5IC0yMDkuMjE3LC00NjcuMzQ4IC00NjcuMTg5LC00NjcuMzQ4IC0yNTguMDc0LDAgLTQ2Ny4yNTQsMjA5LjIxOSAtNDY3LjI1NCw0NjcuMzQ4IDAsMjU4LjA0MiAyMDkuMTgsNDY3LjE3MiA0NjcuMjU0LDQ2Ny4xNzIiCiAgICAgICAgICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgICAgICAgICAgaWQ9InBhdGg0NiIKICAgICAgICAgICAgIHN0eWxlPSJmaWxsOiM4YTQxODI7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOm5vbnplcm87c3Ryb2tlOm5vbmUiIC8+PHBhdGgKICAgICAgICAgICAgIGQ9Im0gMTA5MS4xMyw2MTkuODgzIC0xNzUuNzcxLDU3LjEyMSAxMS42MjksMzUuODA4IDE3NS43NjIsLTU3LjEyMSAtMTEuNjIsLTM1LjgwOCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDQ4IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA4NjYuOTU3LDkwMi4wNzQgODM2LjUsOTI0LjE5OSA5NDUuMTIxLDEwNzMuNzMgOTc1LjU4NiwxMDUxLjYxIDg2Ni45NTcsOTAyLjA3NCIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDUwIgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0iTSA2MDcuNDY1LDkwMy40NDUgNDk4Ljg1NSwxMDUyLjk3IDUyOS4zMiwxMDc1LjEgNjM3LjkzLDkyNS41NjYgNjA3LjQ2NSw5MDMuNDQ1IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTIiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjxwYXRoCiAgICAgICAgICAgICBkPSJtIDM4MC42ODgsNjIyLjEyOSAtMTEuNjI2LDM1LjgwMSAxNzUuNzU4LDU3LjA5IDExLjYyMSwtMzUuODAxIC0xNzUuNzUzLC01Ny4wOSIKICAgICAgICAgICAgIGlua3NjYXBlOmNvbm5lY3Rvci1jdXJ2YXR1cmU9IjAiCiAgICAgICAgICAgICBpZD0icGF0aDU0IgogICAgICAgICAgICAgc3R5bGU9ImZpbGw6IzhhNDE4MjtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6bm9uemVybztzdHJva2U6bm9uZSIgLz48cGF0aAogICAgICAgICAgICAgZD0ibSA3MTYuMjg5LDM3Ni41OSAzNy42NDA2LDAgMCwxODQuODE2IC0zNy42NDA2LDAgMCwtMTg0LjgxNiB6IgogICAgICAgICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgICAgICAgIGlkPSJwYXRoNTYiCiAgICAgICAgICAgICBzdHlsZT0iZmlsbDojOGE0MTgyO2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiAvPjwvZz48L2c+PC9nPjwvZz48L3N2Zz4=') no-repeat, none; -moz-background-size: 100%; -o-background-size: 100%; -webkit-background-size: 100%; background-size: 100%; display: block; float: left; width: 90px; height: 25px; } -.jasmine_html-reporter .banner .version { margin-left: 14px; position: relative; top: 6px; } -.jasmine_html-reporter #jasmine_content { position: fixed; right: 100%; } -.jasmine_html-reporter .version { color: #aaa; } -.jasmine_html-reporter .banner { margin-top: 14px; } -.jasmine_html-reporter .duration { color: #fff; float: right; line-height: 28px; padding-right: 9px; } -.jasmine_html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; } -.jasmine_html-reporter .symbol-summary li { display: inline-block; height: 8px; width: 14px; font-size: 16px; } -.jasmine_html-reporter .symbol-summary li.passed { font-size: 14px; } -.jasmine_html-reporter .symbol-summary li.passed:before { color: #007069; content: "\02022"; } -.jasmine_html-reporter .symbol-summary li.failed { line-height: 9px; } -.jasmine_html-reporter .symbol-summary li.failed:before { color: #ca3a11; content: "\d7"; font-weight: bold; margin-left: -1px; } -.jasmine_html-reporter .symbol-summary li.disabled { font-size: 14px; } -.jasmine_html-reporter .symbol-summary li.disabled:before { color: #bababa; content: "\02022"; } -.jasmine_html-reporter .symbol-summary li.pending { line-height: 17px; } -.jasmine_html-reporter .symbol-summary li.pending:before { color: #ba9d37; content: "*"; } -.jasmine_html-reporter .symbol-summary li.empty { font-size: 14px; } -.jasmine_html-reporter .symbol-summary li.empty:before { color: #ba9d37; content: "\02022"; } -.jasmine_html-reporter .run-options { float: right; margin-right: 5px; border: 1px solid #8a4182; color: #8a4182; position: relative; line-height: 20px; } -.jasmine_html-reporter .run-options .trigger { cursor: pointer; padding: 8px 16px; } -.jasmine_html-reporter .run-options .payload { position: absolute; display: none; right: -1px; border: 1px solid #8a4182; background-color: #eee; white-space: nowrap; padding: 4px 8px; } -.jasmine_html-reporter .run-options .payload.open { display: block; } -.jasmine_html-reporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } -.jasmine_html-reporter .bar.failed { background-color: #ca3a11; } -.jasmine_html-reporter .bar.passed { background-color: #007069; } -.jasmine_html-reporter .bar.skipped { background-color: #bababa; } -.jasmine_html-reporter .bar.errored { background-color: #ca3a11; } -.jasmine_html-reporter .bar.menu { background-color: #fff; color: #aaa; } -.jasmine_html-reporter .bar.menu a { color: #333; } -.jasmine_html-reporter .bar a { color: white; } -.jasmine_html-reporter.spec-list .bar.menu.failure-list, .jasmine_html-reporter.spec-list .results .failures { display: none; } -.jasmine_html-reporter.failure-list .bar.menu.spec-list, .jasmine_html-reporter.failure-list .summary { display: none; } -.jasmine_html-reporter .results { margin-top: 14px; } -.jasmine_html-reporter .summary { margin-top: 14px; } -.jasmine_html-reporter .summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; } -.jasmine_html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; } -.jasmine_html-reporter .summary li.passed a { color: #007069; } -.jasmine_html-reporter .summary li.failed a { color: #ca3a11; } -.jasmine_html-reporter .summary li.empty a { color: #ba9d37; } -.jasmine_html-reporter .summary li.pending a { color: #ba9d37; } -.jasmine_html-reporter .summary li.disabled a { color: #bababa; } -.jasmine_html-reporter .description + .suite { margin-top: 0; } -.jasmine_html-reporter .suite { margin-top: 14px; } -.jasmine_html-reporter .suite a { color: #333; } -.jasmine_html-reporter .failures .spec-detail { margin-bottom: 28px; } -.jasmine_html-reporter .failures .spec-detail .description { background-color: #ca3a11; } -.jasmine_html-reporter .failures .spec-detail .description a { color: white; } -.jasmine_html-reporter .result-message { padding-top: 14px; color: #333; white-space: pre; } -.jasmine_html-reporter .result-message span.result { display: block; } -.jasmine_html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666; border: 1px solid #ddd; background: white; white-space: pre; } diff --git a/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine.js b/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine.js deleted file mode 100644 index 312d591e1..000000000 --- a/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine.js +++ /dev/null @@ -1,3298 +0,0 @@ -/* -Copyright (c) 2008-2015 Pivotal Labs - -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 getJasmineRequireObj = (function (jasmineGlobal) { - var jasmineRequire; - - if (typeof module !== 'undefined' && module.exports) { - jasmineGlobal = global; - jasmineRequire = exports; - } else { - if (typeof window !== 'undefined' && typeof window.toString === 'function' && window.toString() === '[object GjsGlobal]') { - jasmineGlobal = window; - } - jasmineRequire = jasmineGlobal.jasmineRequire = jasmineGlobal.jasmineRequire || {}; - } - - function getJasmineRequire() { - return jasmineRequire; - } - - getJasmineRequire().core = function(jRequire) { - var j$ = {}; - - jRequire.base(j$, jasmineGlobal); - j$.util = jRequire.util(); - j$.errors = jRequire.errors(); - j$.Any = jRequire.Any(j$); - j$.Anything = jRequire.Anything(j$); - j$.CallTracker = jRequire.CallTracker(); - j$.MockDate = jRequire.MockDate(); - j$.Clock = jRequire.Clock(); - j$.DelayedFunctionScheduler = jRequire.DelayedFunctionScheduler(); - j$.Env = jRequire.Env(j$); - j$.ExceptionFormatter = jRequire.ExceptionFormatter(); - j$.Expectation = jRequire.Expectation(); - j$.buildExpectationResult = jRequire.buildExpectationResult(); - j$.JsApiReporter = jRequire.JsApiReporter(); - j$.matchersUtil = jRequire.matchersUtil(j$); - j$.ObjectContaining = jRequire.ObjectContaining(j$); - j$.ArrayContaining = jRequire.ArrayContaining(j$); - j$.pp = jRequire.pp(j$); - j$.QueueRunner = jRequire.QueueRunner(j$); - j$.ReportDispatcher = jRequire.ReportDispatcher(); - j$.Spec = jRequire.Spec(j$); - j$.SpyRegistry = jRequire.SpyRegistry(j$); - j$.SpyStrategy = jRequire.SpyStrategy(); - j$.StringMatching = jRequire.StringMatching(j$); - j$.Suite = jRequire.Suite(j$); - j$.Timer = jRequire.Timer(); - j$.TreeProcessor = jRequire.TreeProcessor(); - j$.version = jRequire.version(); - - j$.matchers = jRequire.requireMatchers(jRequire, j$); - - return j$; - }; - - return getJasmineRequire; -})(this); - -getJasmineRequireObj().requireMatchers = function(jRequire, j$) { - var availableMatchers = [ - 'toBe', - 'toBeCloseTo', - 'toBeDefined', - 'toBeFalsy', - 'toBeGreaterThan', - 'toBeLessThan', - 'toBeNaN', - 'toBeNull', - 'toBeTruthy', - 'toBeUndefined', - 'toContain', - 'toEqual', - 'toHaveBeenCalled', - 'toHaveBeenCalledWith', - 'toMatch', - 'toThrow', - 'toThrowError' - ], - matchers = {}; - - for (var i = 0; i < availableMatchers.length; i++) { - var name = availableMatchers[i]; - matchers[name] = jRequire[name](j$); - } - - return matchers; -}; - -getJasmineRequireObj().base = function(j$, jasmineGlobal) { - j$.unimplementedMethod_ = function() { - throw new Error('unimplemented method'); - }; - - j$.MAX_PRETTY_PRINT_DEPTH = 40; - j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 100; - j$.DEFAULT_TIMEOUT_INTERVAL = 5000; - - j$.getGlobal = function() { - return jasmineGlobal; - }; - - j$.getEnv = function(options) { - var env = j$.currentEnv_ = j$.currentEnv_ || new j$.Env(options); - //jasmine. singletons in here (setTimeout blah blah). - return env; - }; - - j$.isArray_ = function(value) { - return j$.isA_('Array', value); - }; - - j$.isString_ = function(value) { - return j$.isA_('String', value); - }; - - j$.isNumber_ = function(value) { - return j$.isA_('Number', value); - }; - - j$.isA_ = function(typeName, value) { - return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; - }; - - j$.isDomNode = function(obj) { - return obj.nodeType > 0; - }; - - j$.fnNameFor = function(func) { - return func.name || func.toString().match(/^\s*function\s*(\w*)\s*\(/)[1]; - }; - - j$.any = function(clazz) { - return new j$.Any(clazz); - }; - - j$.anything = function() { - return new j$.Anything(); - }; - - j$.objectContaining = function(sample) { - return new j$.ObjectContaining(sample); - }; - - j$.stringMatching = function(expected) { - return new j$.StringMatching(expected); - }; - - j$.arrayContaining = function(sample) { - return new j$.ArrayContaining(sample); - }; - - j$.createSpy = function(name, originalFn) { - - var spyStrategy = new j$.SpyStrategy({ - name: name, - fn: originalFn, - getSpy: function() { return spy; } - }), - callTracker = new j$.CallTracker(), - spy = function() { - var callData = { - object: this, - args: Array.prototype.slice.apply(arguments) - }; - - callTracker.track(callData); - var returnValue = spyStrategy.exec.apply(this, arguments); - callData.returnValue = returnValue; - - return returnValue; - }; - - for (var prop in originalFn) { - if (prop === 'and' || prop === 'calls') { - throw new Error('Jasmine spies would overwrite the \'and\' and \'calls\' properties on the object being spied upon'); - } - - spy[prop] = originalFn[prop]; - } - - spy.and = spyStrategy; - spy.calls = callTracker; - - return spy; - }; - - j$.isSpy = function(putativeSpy) { - if (!putativeSpy) { - return false; - } - return putativeSpy.and instanceof j$.SpyStrategy && - putativeSpy.calls instanceof j$.CallTracker; - }; - - j$.createSpyObj = function(baseName, methodNames) { - if (j$.isArray_(baseName) && j$.util.isUndefined(methodNames)) { - methodNames = baseName; - baseName = 'unknown'; - } - - if (!j$.isArray_(methodNames) || methodNames.length === 0) { - throw 'createSpyObj requires a non-empty array of method names to create spies for'; - } - var obj = {}; - for (var i = 0; i < methodNames.length; i++) { - obj[methodNames[i]] = j$.createSpy(baseName + '.' + methodNames[i]); - } - return obj; - }; -}; - -getJasmineRequireObj().util = function() { - - var util = {}; - - util.inherit = function(childClass, parentClass) { - var Subclass = function() { - }; - Subclass.prototype = parentClass.prototype; - childClass.prototype = new Subclass(); - }; - - util.htmlEscape = function(str) { - if (!str) { - return str; - } - return str.replace(/&/g, '&') - .replace(//g, '>'); - }; - - util.argsToArray = function(args) { - var arrayOfArgs = []; - for (var i = 0; i < args.length; i++) { - arrayOfArgs.push(args[i]); - } - return arrayOfArgs; - }; - - util.isUndefined = function(obj) { - return obj === void 0; - }; - - util.arrayContains = function(array, search) { - var i = array.length; - while (i--) { - if (array[i] === search) { - return true; - } - } - return false; - }; - - util.clone = function(obj) { - if (Object.prototype.toString.apply(obj) === '[object Array]') { - return obj.slice(); - } - - var cloned = {}; - for (var prop in obj) { - if (obj.hasOwnProperty(prop)) { - cloned[prop] = obj[prop]; - } - } - - return cloned; - }; - - return util; -}; - -getJasmineRequireObj().Spec = function(j$) { - function Spec(attrs) { - this.expectationFactory = attrs.expectationFactory; - this.resultCallback = attrs.resultCallback || function() {}; - this.id = attrs.id; - this.description = attrs.description || ''; - this.queueableFn = attrs.queueableFn; - this.beforeAndAfterFns = attrs.beforeAndAfterFns || function() { return {befores: [], afters: []}; }; - this.userContext = attrs.userContext || function() { return {}; }; - this.onStart = attrs.onStart || function() {}; - this.getSpecName = attrs.getSpecName || function() { return ''; }; - this.expectationResultFactory = attrs.expectationResultFactory || function() { }; - this.queueRunnerFactory = attrs.queueRunnerFactory || function() {}; - this.catchingExceptions = attrs.catchingExceptions || function() { return true; }; - this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; - - if (!this.queueableFn.fn) { - this.pend(); - } - - this.result = { - id: this.id, - description: this.description, - fullName: this.getFullName(), - failedExpectations: [], - passedExpectations: [], - pendingReason: '' - }; - } - - Spec.prototype.addExpectationResult = function(passed, data, isError) { - var expectationResult = this.expectationResultFactory(data); - if (passed) { - this.result.passedExpectations.push(expectationResult); - } else { - this.result.failedExpectations.push(expectationResult); - - if (this.throwOnExpectationFailure && !isError) { - throw new j$.errors.ExpectationFailed(); - } - } - }; - - Spec.prototype.expect = function(actual) { - return this.expectationFactory(actual, this); - }; - - Spec.prototype.execute = function(onComplete, enabled) { - var self = this; - - this.onStart(this); - - if (!this.isExecutable() || this.markedPending || enabled === false) { - complete(enabled); - return; - } - - var fns = this.beforeAndAfterFns(); - var allFns = fns.befores.concat(this.queueableFn).concat(fns.afters); - - this.queueRunnerFactory({ - queueableFns: allFns, - onException: function() { self.onException.apply(self, arguments); }, - onComplete: complete, - userContext: this.userContext() - }); - - function complete(enabledAgain) { - self.result.status = self.status(enabledAgain); - self.resultCallback(self.result); - - if (onComplete) { - onComplete(); - } - } - }; - - Spec.prototype.onException = function onException(e) { - if (Spec.isPendingSpecException(e)) { - this.pend(extractCustomPendingMessage(e)); - return; - } - - if (e instanceof j$.errors.ExpectationFailed) { - return; - } - - this.addExpectationResult(false, { - matcherName: '', - passed: false, - expected: '', - actual: '', - error: e - }, true); - }; - - Spec.prototype.disable = function() { - this.disabled = true; - }; - - Spec.prototype.pend = function(message) { - this.markedPending = true; - if (message) { - this.result.pendingReason = message; - } - }; - - Spec.prototype.getResult = function() { - this.result.status = this.status(); - return this.result; - }; - - Spec.prototype.status = function(enabled) { - if (this.disabled || enabled === false) { - return 'disabled'; - } - - if (this.markedPending) { - return 'pending'; - } - - if (this.result.failedExpectations.length > 0) { - return 'failed'; - } else { - return 'passed'; - } - }; - - Spec.prototype.isExecutable = function() { - return !this.disabled; - }; - - Spec.prototype.getFullName = function() { - return this.getSpecName(this); - }; - - var extractCustomPendingMessage = function(e) { - var fullMessage = e.toString(), - boilerplateStart = fullMessage.indexOf(Spec.pendingSpecExceptionMessage), - boilerplateEnd = boilerplateStart + Spec.pendingSpecExceptionMessage.length; - - return fullMessage.substr(boilerplateEnd); - }; - - Spec.pendingSpecExceptionMessage = '=> marked Pending'; - - Spec.isPendingSpecException = function(e) { - return !!(e && e.toString && e.toString().indexOf(Spec.pendingSpecExceptionMessage) !== -1); - }; - - return Spec; -}; - -if (typeof window == void 0 && typeof exports == 'object') { - exports.Spec = jasmineRequire.Spec; -} - -getJasmineRequireObj().Env = function(j$) { - function Env(options) { - options = options || {}; - - var self = this; - var global = options.global || j$.getGlobal(); - - var totalSpecsDefined = 0; - - var catchExceptions = true; - - var realSetTimeout = j$.getGlobal().setTimeout; - var realClearTimeout = j$.getGlobal().clearTimeout; - this.clock = new j$.Clock(global, function () { return new j$.DelayedFunctionScheduler(); }, new j$.MockDate(global)); - - var runnableLookupTable = {}; - var runnableResources = {}; - - var currentSpec = null; - var currentlyExecutingSuites = []; - var currentDeclarationSuite = null; - var throwOnExpectationFailure = false; - - var currentSuite = function() { - return currentlyExecutingSuites[currentlyExecutingSuites.length - 1]; - }; - - var currentRunnable = function() { - return currentSpec || currentSuite(); - }; - - var reporter = new j$.ReportDispatcher([ - 'jasmineStarted', - 'jasmineDone', - 'suiteStarted', - 'suiteDone', - 'specStarted', - 'specDone' - ]); - - this.specFilter = function() { - return true; - }; - - this.addCustomEqualityTester = function(tester) { - if(!currentRunnable()) { - throw new Error('Custom Equalities must be added in a before function or a spec'); - } - runnableResources[currentRunnable().id].customEqualityTesters.push(tester); - }; - - this.addMatchers = function(matchersToAdd) { - if(!currentRunnable()) { - throw new Error('Matchers must be added in a before function or a spec'); - } - var customMatchers = runnableResources[currentRunnable().id].customMatchers; - for (var matcherName in matchersToAdd) { - customMatchers[matcherName] = matchersToAdd[matcherName]; - } - }; - - j$.Expectation.addCoreMatchers(j$.matchers); - - var nextSpecId = 0; - var getNextSpecId = function() { - return 'spec' + nextSpecId++; - }; - - var nextSuiteId = 0; - var getNextSuiteId = function() { - return 'suite' + nextSuiteId++; - }; - - var expectationFactory = function(actual, spec) { - return j$.Expectation.Factory({ - util: j$.matchersUtil, - customEqualityTesters: runnableResources[spec.id].customEqualityTesters, - customMatchers: runnableResources[spec.id].customMatchers, - actual: actual, - addExpectationResult: addExpectationResult - }); - - function addExpectationResult(passed, result) { - return spec.addExpectationResult(passed, result); - } - }; - - var defaultResourcesForRunnable = function(id, parentRunnableId) { - var resources = {spies: [], customEqualityTesters: [], customMatchers: {}}; - - if(runnableResources[parentRunnableId]){ - resources.customEqualityTesters = j$.util.clone(runnableResources[parentRunnableId].customEqualityTesters); - resources.customMatchers = j$.util.clone(runnableResources[parentRunnableId].customMatchers); - } - - runnableResources[id] = resources; - }; - - var clearResourcesForRunnable = function(id) { - spyRegistry.clearSpies(); - delete runnableResources[id]; - }; - - var beforeAndAfterFns = function(suite) { - return function() { - var befores = [], - afters = []; - - while(suite) { - befores = befores.concat(suite.beforeFns); - afters = afters.concat(suite.afterFns); - - suite = suite.parentSuite; - } - - return { - befores: befores.reverse(), - afters: afters - }; - }; - }; - - var getSpecName = function(spec, suite) { - return suite.getFullName() + ' ' + spec.description; - }; - - // TODO: we may just be able to pass in the fn instead of wrapping here - var buildExpectationResult = j$.buildExpectationResult, - exceptionFormatter = new j$.ExceptionFormatter(), - expectationResultFactory = function(attrs) { - attrs.messageFormatter = exceptionFormatter.message; - attrs.stackFormatter = exceptionFormatter.stack; - - return buildExpectationResult(attrs); - }; - - // TODO: fix this naming, and here's where the value comes in - this.catchExceptions = function(value) { - catchExceptions = !!value; - return catchExceptions; - }; - - this.catchingExceptions = function() { - return catchExceptions; - }; - - var maximumSpecCallbackDepth = 20; - var currentSpecCallbackDepth = 0; - - function clearStack(fn) { - currentSpecCallbackDepth++; - if (currentSpecCallbackDepth >= maximumSpecCallbackDepth) { - currentSpecCallbackDepth = 0; - realSetTimeout(fn, 0); - } else { - fn(); - } - } - - var catchException = function(e) { - return j$.Spec.isPendingSpecException(e) || catchExceptions; - }; - - this.throwOnExpectationFailure = function(value) { - throwOnExpectationFailure = !!value; - }; - - this.throwingExpectationFailures = function() { - return throwOnExpectationFailure; - }; - - var queueRunnerFactory = function(options) { - options.catchException = catchException; - options.clearStack = options.clearStack || clearStack; - options.timeout = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout}; - options.fail = self.fail; - - new j$.QueueRunner(options).execute(); - }; - - var topSuite = new j$.Suite({ - env: this, - id: getNextSuiteId(), - description: 'Jasmine__TopLevel__Suite', - queueRunner: queueRunnerFactory - }); - runnableLookupTable[topSuite.id] = topSuite; - defaultResourcesForRunnable(topSuite.id); - currentDeclarationSuite = topSuite; - - this.topSuite = function() { - return topSuite; - }; - - this.execute = function(runnablesToRun) { - if(!runnablesToRun) { - if (focusedRunnables.length) { - runnablesToRun = focusedRunnables; - } else { - runnablesToRun = [topSuite.id]; - } - } - var processor = new j$.TreeProcessor({ - tree: topSuite, - runnableIds: runnablesToRun, - queueRunnerFactory: queueRunnerFactory, - nodeStart: function(suite) { - currentlyExecutingSuites.push(suite); - defaultResourcesForRunnable(suite.id, suite.parentSuite.id); - reporter.suiteStarted(suite.result); - }, - nodeComplete: function(suite, result) { - if (!suite.disabled) { - clearResourcesForRunnable(suite.id); - } - currentlyExecutingSuites.pop(); - reporter.suiteDone(result); - } - }); - - if(!processor.processTree().valid) { - throw new Error('Invalid order: would cause a beforeAll or afterAll to be run multiple times'); - } - - reporter.jasmineStarted({ - totalSpecsDefined: totalSpecsDefined - }); - - processor.execute(reporter.jasmineDone); - }; - - this.addReporter = function(reporterToAdd) { - reporter.addReporter(reporterToAdd); - }; - - var spyRegistry = new j$.SpyRegistry({currentSpies: function() { - if(!currentRunnable()) { - throw new Error('Spies must be created in a before function or a spec'); - } - return runnableResources[currentRunnable().id].spies; - }}); - - this.spyOn = function() { - return spyRegistry.spyOn.apply(spyRegistry, arguments); - }; - - var suiteFactory = function(description) { - var suite = new j$.Suite({ - env: self, - id: getNextSuiteId(), - description: description, - parentSuite: currentDeclarationSuite, - expectationFactory: expectationFactory, - expectationResultFactory: expectationResultFactory, - throwOnExpectationFailure: throwOnExpectationFailure - }); - - runnableLookupTable[suite.id] = suite; - return suite; - }; - - this.describe = function(description, specDefinitions) { - var suite = suiteFactory(description); - addSpecsToSuite(suite, specDefinitions); - return suite; - }; - - this.xdescribe = function(description, specDefinitions) { - var suite = this.describe(description, specDefinitions); - suite.disable(); - return suite; - }; - - var focusedRunnables = []; - - this.fdescribe = function(description, specDefinitions) { - var suite = suiteFactory(description); - suite.isFocused = true; - - focusedRunnables.push(suite.id); - unfocusAncestor(); - addSpecsToSuite(suite, specDefinitions); - - return suite; - }; - - function addSpecsToSuite(suite, specDefinitions) { - var parentSuite = currentDeclarationSuite; - parentSuite.addChild(suite); - currentDeclarationSuite = suite; - - var declarationError = null; - try { - specDefinitions.call(suite); - } catch (e) { - declarationError = e; - } - - if (declarationError) { - self.it('encountered a declaration exception', function() { - throw declarationError; - }); - } - - currentDeclarationSuite = parentSuite; - } - - function findFocusedAncestor(suite) { - while (suite) { - if (suite.isFocused) { - return suite.id; - } - suite = suite.parentSuite; - } - - return null; - } - - function unfocusAncestor() { - var focusedAncestor = findFocusedAncestor(currentDeclarationSuite); - if (focusedAncestor) { - for (var i = 0; i < focusedRunnables.length; i++) { - if (focusedRunnables[i] === focusedAncestor) { - focusedRunnables.splice(i, 1); - break; - } - } - } - } - - var specFactory = function(description, fn, suite, timeout) { - totalSpecsDefined++; - var spec = new j$.Spec({ - id: getNextSpecId(), - beforeAndAfterFns: beforeAndAfterFns(suite), - expectationFactory: expectationFactory, - resultCallback: specResultCallback, - getSpecName: function(spec) { - return getSpecName(spec, suite); - }, - onStart: specStarted, - description: description, - expectationResultFactory: expectationResultFactory, - queueRunnerFactory: queueRunnerFactory, - userContext: function() { return suite.clonedSharedUserContext(); }, - queueableFn: { - fn: fn, - timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } - }, - throwOnExpectationFailure: throwOnExpectationFailure - }); - - runnableLookupTable[spec.id] = spec; - - if (!self.specFilter(spec)) { - spec.disable(); - } - - return spec; - - function specResultCallback(result) { - clearResourcesForRunnable(spec.id); - currentSpec = null; - reporter.specDone(result); - } - - function specStarted(spec) { - currentSpec = spec; - defaultResourcesForRunnable(spec.id, suite.id); - reporter.specStarted(spec.result); - } - }; - - this.it = function(description, fn, timeout) { - var spec = specFactory(description, fn, currentDeclarationSuite, timeout); - currentDeclarationSuite.addChild(spec); - return spec; - }; - - this.xit = function() { - var spec = this.it.apply(this, arguments); - spec.pend(); - return spec; - }; - - this.fit = function(){ - var spec = this.it.apply(this, arguments); - - focusedRunnables.push(spec.id); - unfocusAncestor(); - return spec; - }; - - this.expect = function(actual) { - if (!currentRunnable()) { - throw new Error('\'expect\' was used when there was no current spec, this could be because an asynchronous test timed out'); - } - - return currentRunnable().expect(actual); - }; - - this.beforeEach = function(beforeEachFunction, timeout) { - currentDeclarationSuite.beforeEach({ - fn: beforeEachFunction, - timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } - }); - }; - - this.beforeAll = function(beforeAllFunction, timeout) { - currentDeclarationSuite.beforeAll({ - fn: beforeAllFunction, - timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } - }); - }; - - this.afterEach = function(afterEachFunction, timeout) { - currentDeclarationSuite.afterEach({ - fn: afterEachFunction, - timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } - }); - }; - - this.afterAll = function(afterAllFunction, timeout) { - currentDeclarationSuite.afterAll({ - fn: afterAllFunction, - timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; } - }); - }; - - this.pending = function(message) { - var fullMessage = j$.Spec.pendingSpecExceptionMessage; - if(message) { - fullMessage += message; - } - throw fullMessage; - }; - - this.fail = function(error) { - var message = 'Failed'; - if (error) { - message += ': '; - message += error.message || error; - } - - currentRunnable().addExpectationResult(false, { - matcherName: '', - passed: false, - expected: '', - actual: '', - message: message, - error: error && error.message ? error : null - }); - }; - } - - return Env; -}; - -getJasmineRequireObj().JsApiReporter = function() { - - var noopTimer = { - start: function(){}, - elapsed: function(){ return 0; } - }; - - function JsApiReporter(options) { - var timer = options.timer || noopTimer, - status = 'loaded'; - - this.started = false; - this.finished = false; - - this.jasmineStarted = function() { - this.started = true; - status = 'started'; - timer.start(); - }; - - var executionTime; - - this.jasmineDone = function() { - this.finished = true; - executionTime = timer.elapsed(); - status = 'done'; - }; - - this.status = function() { - return status; - }; - - var suites = [], - suites_hash = {}; - - this.suiteStarted = function(result) { - suites_hash[result.id] = result; - }; - - this.suiteDone = function(result) { - storeSuite(result); - }; - - this.suiteResults = function(index, length) { - return suites.slice(index, index + length); - }; - - function storeSuite(result) { - suites.push(result); - suites_hash[result.id] = result; - } - - this.suites = function() { - return suites_hash; - }; - - var specs = []; - - this.specDone = function(result) { - specs.push(result); - }; - - this.specResults = function(index, length) { - return specs.slice(index, index + length); - }; - - this.specs = function() { - return specs; - }; - - this.executionTime = function() { - return executionTime; - }; - - } - - return JsApiReporter; -}; - -getJasmineRequireObj().CallTracker = function() { - - function CallTracker() { - var calls = []; - - this.track = function(context) { - calls.push(context); - }; - - this.any = function() { - return !!calls.length; - }; - - this.count = function() { - return calls.length; - }; - - this.argsFor = function(index) { - var call = calls[index]; - return call ? call.args : []; - }; - - this.all = function() { - return calls; - }; - - this.allArgs = function() { - var callArgs = []; - for(var i = 0; i < calls.length; i++){ - callArgs.push(calls[i].args); - } - - return callArgs; - }; - - this.first = function() { - return calls[0]; - }; - - this.mostRecent = function() { - return calls[calls.length - 1]; - }; - - this.reset = function() { - calls = []; - }; - } - - return CallTracker; -}; - -getJasmineRequireObj().Clock = function() { - function Clock(global, delayedFunctionSchedulerFactory, mockDate) { - var self = this, - realTimingFunctions = { - setTimeout: global.setTimeout, - clearTimeout: global.clearTimeout, - setInterval: global.setInterval, - clearInterval: global.clearInterval - }, - fakeTimingFunctions = { - setTimeout: setTimeout, - clearTimeout: clearTimeout, - setInterval: setInterval, - clearInterval: clearInterval - }, - installed = false, - delayedFunctionScheduler, - timer; - - - self.install = function() { - if(!originalTimingFunctionsIntact()) { - throw new Error('Jasmine Clock was unable to install over custom global timer functions. Is the clock already installed?'); - } - replace(global, fakeTimingFunctions); - timer = fakeTimingFunctions; - delayedFunctionScheduler = delayedFunctionSchedulerFactory(); - installed = true; - - return self; - }; - - self.uninstall = function() { - delayedFunctionScheduler = null; - mockDate.uninstall(); - replace(global, realTimingFunctions); - - timer = realTimingFunctions; - installed = false; - }; - - self.withMock = function(closure) { - this.install(); - try { - closure(); - } finally { - this.uninstall(); - } - }; - - self.mockDate = function(initialDate) { - mockDate.install(initialDate); - }; - - self.setTimeout = function(fn, delay, params) { - if (legacyIE()) { - if (arguments.length > 2) { - throw new Error('IE < 9 cannot support extra params to setTimeout without a polyfill'); - } - return timer.setTimeout(fn, delay); - } - return Function.prototype.apply.apply(timer.setTimeout, [global, arguments]); - }; - - self.setInterval = function(fn, delay, params) { - if (legacyIE()) { - if (arguments.length > 2) { - throw new Error('IE < 9 cannot support extra params to setInterval without a polyfill'); - } - return timer.setInterval(fn, delay); - } - return Function.prototype.apply.apply(timer.setInterval, [global, arguments]); - }; - - self.clearTimeout = function(id) { - return Function.prototype.call.apply(timer.clearTimeout, [global, id]); - }; - - self.clearInterval = function(id) { - return Function.prototype.call.apply(timer.clearInterval, [global, id]); - }; - - self.tick = function(millis) { - if (installed) { - mockDate.tick(millis); - delayedFunctionScheduler.tick(millis); - } else { - throw new Error('Mock clock is not installed, use jasmine.clock().install()'); - } - }; - - return self; - - function originalTimingFunctionsIntact() { - return global.setTimeout === realTimingFunctions.setTimeout && - global.clearTimeout === realTimingFunctions.clearTimeout && - global.setInterval === realTimingFunctions.setInterval && - global.clearInterval === realTimingFunctions.clearInterval; - } - - function legacyIE() { - //if these methods are polyfilled, apply will be present - return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply; - } - - function replace(dest, source) { - for (var prop in source) { - dest[prop] = source[prop]; - } - } - - function setTimeout(fn, delay) { - return delayedFunctionScheduler.scheduleFunction(fn, delay, argSlice(arguments, 2)); - } - - function clearTimeout(id) { - return delayedFunctionScheduler.removeFunctionWithId(id); - } - - function setInterval(fn, interval) { - return delayedFunctionScheduler.scheduleFunction(fn, interval, argSlice(arguments, 2), true); - } - - function clearInterval(id) { - return delayedFunctionScheduler.removeFunctionWithId(id); - } - - function argSlice(argsObj, n) { - return Array.prototype.slice.call(argsObj, n); - } - } - - return Clock; -}; - -getJasmineRequireObj().DelayedFunctionScheduler = function() { - function DelayedFunctionScheduler() { - var self = this; - var scheduledLookup = []; - var scheduledFunctions = {}; - var currentTime = 0; - var delayedFnCount = 0; - - self.tick = function(millis) { - millis = millis || 0; - var endTime = currentTime + millis; - - runScheduledFunctions(endTime); - currentTime = endTime; - }; - - self.scheduleFunction = function(funcToCall, millis, params, recurring, timeoutKey, runAtMillis) { - var f; - if (typeof(funcToCall) === 'string') { - /* jshint evil: true */ - f = function() { return eval(funcToCall); }; - /* jshint evil: false */ - } else { - f = funcToCall; - } - - millis = millis || 0; - timeoutKey = timeoutKey || ++delayedFnCount; - runAtMillis = runAtMillis || (currentTime + millis); - - var funcToSchedule = { - runAtMillis: runAtMillis, - funcToCall: f, - recurring: recurring, - params: params, - timeoutKey: timeoutKey, - millis: millis - }; - - if (runAtMillis in scheduledFunctions) { - scheduledFunctions[runAtMillis].push(funcToSchedule); - } else { - scheduledFunctions[runAtMillis] = [funcToSchedule]; - scheduledLookup.push(runAtMillis); - scheduledLookup.sort(function (a, b) { - return a - b; - }); - } - - return timeoutKey; - }; - - self.removeFunctionWithId = function(timeoutKey) { - for (var runAtMillis in scheduledFunctions) { - var funcs = scheduledFunctions[runAtMillis]; - var i = indexOfFirstToPass(funcs, function (func) { - return func.timeoutKey === timeoutKey; - }); - - if (i > -1) { - if (funcs.length === 1) { - delete scheduledFunctions[runAtMillis]; - deleteFromLookup(runAtMillis); - } else { - funcs.splice(i, 1); - } - - // intervals get rescheduled when executed, so there's never more - // than a single scheduled function with a given timeoutKey - break; - } - } - }; - - return self; - - function indexOfFirstToPass(array, testFn) { - var index = -1; - - for (var i = 0; i < array.length; ++i) { - if (testFn(array[i])) { - index = i; - break; - } - } - - return index; - } - - function deleteFromLookup(key) { - var value = Number(key); - var i = indexOfFirstToPass(scheduledLookup, function (millis) { - return millis === value; - }); - - if (i > -1) { - scheduledLookup.splice(i, 1); - } - } - - function reschedule(scheduledFn) { - self.scheduleFunction(scheduledFn.funcToCall, - scheduledFn.millis, - scheduledFn.params, - true, - scheduledFn.timeoutKey, - scheduledFn.runAtMillis + scheduledFn.millis); - } - - function forEachFunction(funcsToRun, callback) { - for (var i = 0; i < funcsToRun.length; ++i) { - callback(funcsToRun[i]); - } - } - - function runScheduledFunctions(endTime) { - if (scheduledLookup.length === 0 || scheduledLookup[0] > endTime) { - return; - } - - do { - currentTime = scheduledLookup.shift(); - - var funcsToRun = scheduledFunctions[currentTime]; - delete scheduledFunctions[currentTime]; - - forEachFunction(funcsToRun, function(funcToRun) { - if (funcToRun.recurring) { - reschedule(funcToRun); - } - }); - - forEachFunction(funcsToRun, function(funcToRun) { - funcToRun.funcToCall.apply(null, funcToRun.params || []); - }); - } while (scheduledLookup.length > 0 && - // checking first if we're out of time prevents setTimeout(0) - // scheduled in a funcToRun from forcing an extra iteration - currentTime !== endTime && - scheduledLookup[0] <= endTime); - } - } - - return DelayedFunctionScheduler; -}; - -getJasmineRequireObj().ExceptionFormatter = function() { - function ExceptionFormatter() { - this.message = function(error) { - var message = ''; - - if (error.name && error.message) { - message += error.name + ': ' + error.message; - } else { - message += error.toString() + ' thrown'; - } - - if (error.fileName || error.sourceURL) { - message += ' in ' + (error.fileName || error.sourceURL); - } - - if (error.line || error.lineNumber) { - message += ' (line ' + (error.line || error.lineNumber) + ')'; - } - - return message; - }; - - this.stack = function(error) { - return error ? error.stack : null; - }; - } - - return ExceptionFormatter; -}; - -getJasmineRequireObj().Expectation = function() { - - function Expectation(options) { - this.util = options.util || { buildFailureMessage: function() {} }; - this.customEqualityTesters = options.customEqualityTesters || []; - this.actual = options.actual; - this.addExpectationResult = options.addExpectationResult || function(){}; - this.isNot = options.isNot; - - var customMatchers = options.customMatchers || {}; - for (var matcherName in customMatchers) { - this[matcherName] = Expectation.prototype.wrapCompare(matcherName, customMatchers[matcherName]); - } - } - - Expectation.prototype.wrapCompare = function(name, matcherFactory) { - return function() { - var args = Array.prototype.slice.call(arguments, 0), - expected = args.slice(0), - message = ''; - - args.unshift(this.actual); - - var matcher = matcherFactory(this.util, this.customEqualityTesters), - matcherCompare = matcher.compare; - - function defaultNegativeCompare() { - var result = matcher.compare.apply(null, args); - result.pass = !result.pass; - return result; - } - - if (this.isNot) { - matcherCompare = matcher.negativeCompare || defaultNegativeCompare; - } - - var result = matcherCompare.apply(null, args); - - if (!result.pass) { - if (!result.message) { - args.unshift(this.isNot); - args.unshift(name); - message = this.util.buildFailureMessage.apply(null, args); - } else { - if (Object.prototype.toString.apply(result.message) === '[object Function]') { - message = result.message(); - } else { - message = result.message; - } - } - } - - if (expected.length == 1) { - expected = expected[0]; - } - - // TODO: how many of these params are needed? - this.addExpectationResult( - result.pass, - { - matcherName: name, - passed: result.pass, - message: message, - actual: this.actual, - expected: expected // TODO: this may need to be arrayified/sliced - } - ); - }; - }; - - Expectation.addCoreMatchers = function(matchers) { - var prototype = Expectation.prototype; - for (var matcherName in matchers) { - var matcher = matchers[matcherName]; - prototype[matcherName] = prototype.wrapCompare(matcherName, matcher); - } - }; - - Expectation.Factory = function(options) { - options = options || {}; - - var expect = new Expectation(options); - - // TODO: this would be nice as its own Object - NegativeExpectation - // TODO: copy instead of mutate options - options.isNot = true; - expect.not = new Expectation(options); - - return expect; - }; - - return Expectation; -}; - -//TODO: expectation result may make more sense as a presentation of an expectation. -getJasmineRequireObj().buildExpectationResult = function() { - function buildExpectationResult(options) { - var messageFormatter = options.messageFormatter || function() {}, - stackFormatter = options.stackFormatter || function() {}; - - var result = { - matcherName: options.matcherName, - message: message(), - stack: stack(), - passed: options.passed - }; - - if(!result.passed) { - result.expected = options.expected; - result.actual = options.actual; - } - - return result; - - function message() { - if (options.passed) { - return 'Passed.'; - } else if (options.message) { - return options.message; - } else if (options.error) { - return messageFormatter(options.error); - } - return ''; - } - - function stack() { - if (options.passed) { - return ''; - } - - var error = options.error; - if (!error) { - try { - throw new Error(message()); - } catch (e) { - error = e; - } - } - return stackFormatter(error); - } - } - - return buildExpectationResult; -}; - -getJasmineRequireObj().MockDate = function() { - function MockDate(global) { - var self = this; - var currentTime = 0; - - if (!global || !global.Date) { - self.install = function() {}; - self.tick = function() {}; - self.uninstall = function() {}; - return self; - } - - var GlobalDate = global.Date; - - self.install = function(mockDate) { - if (mockDate instanceof GlobalDate) { - currentTime = mockDate.getTime(); - } else { - currentTime = new GlobalDate().getTime(); - } - - global.Date = FakeDate; - }; - - self.tick = function(millis) { - millis = millis || 0; - currentTime = currentTime + millis; - }; - - self.uninstall = function() { - currentTime = 0; - global.Date = GlobalDate; - }; - - createDateProperties(); - - return self; - - function FakeDate() { - switch(arguments.length) { - case 0: - return new GlobalDate(currentTime); - case 1: - return new GlobalDate(arguments[0]); - case 2: - return new GlobalDate(arguments[0], arguments[1]); - case 3: - return new GlobalDate(arguments[0], arguments[1], arguments[2]); - case 4: - return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3]); - case 5: - return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], - arguments[4]); - case 6: - return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], - arguments[4], arguments[5]); - default: - return new GlobalDate(arguments[0], arguments[1], arguments[2], arguments[3], - arguments[4], arguments[5], arguments[6]); - } - } - - function createDateProperties() { - FakeDate.prototype = GlobalDate.prototype; - - FakeDate.now = function() { - if (GlobalDate.now) { - return currentTime; - } else { - throw new Error('Browser does not support Date.now()'); - } - }; - - FakeDate.toSource = GlobalDate.toSource; - FakeDate.toString = GlobalDate.toString; - FakeDate.parse = GlobalDate.parse; - FakeDate.UTC = GlobalDate.UTC; - } - } - - return MockDate; -}; - -getJasmineRequireObj().pp = function(j$) { - - function PrettyPrinter() { - this.ppNestLevel_ = 0; - this.seen = []; - } - - PrettyPrinter.prototype.format = function(value) { - this.ppNestLevel_++; - try { - if (j$.util.isUndefined(value)) { - this.emitScalar('undefined'); - } else if (value === null) { - this.emitScalar('null'); - } else if (value === 0 && 1/value === -Infinity) { - this.emitScalar('-0'); - } else if (value === j$.getGlobal()) { - this.emitScalar(''); - } else if (value.jasmineToString) { - this.emitScalar(value.jasmineToString()); - } else if (typeof value === 'string') { - this.emitString(value); - } else if (j$.isSpy(value)) { - this.emitScalar('spy on ' + value.and.identity()); - } else if (value instanceof RegExp) { - this.emitScalar(value.toString()); - } else if (typeof value === 'function') { - this.emitScalar('Function'); - } else if (typeof value.nodeType === 'number') { - this.emitScalar('HTMLNode'); - } else if (value instanceof Date) { - this.emitScalar('Date(' + value + ')'); - } else if (j$.util.arrayContains(this.seen, value)) { - this.emitScalar(''); - } else if (j$.isArray_(value) || j$.isA_('Object', value)) { - this.seen.push(value); - if (j$.isArray_(value)) { - this.emitArray(value); - } else { - this.emitObject(value); - } - this.seen.pop(); - } else { - this.emitScalar(value.toString()); - } - } finally { - this.ppNestLevel_--; - } - }; - - PrettyPrinter.prototype.iterateObject = function(obj, fn) { - for (var property in obj) { - if (!Object.prototype.hasOwnProperty.call(obj, property)) { continue; } - fn(property, obj.__lookupGetter__ ? (!j$.util.isUndefined(obj.__lookupGetter__(property)) && - obj.__lookupGetter__(property) !== null) : false); - } - }; - - PrettyPrinter.prototype.emitArray = j$.unimplementedMethod_; - PrettyPrinter.prototype.emitObject = j$.unimplementedMethod_; - PrettyPrinter.prototype.emitScalar = j$.unimplementedMethod_; - PrettyPrinter.prototype.emitString = j$.unimplementedMethod_; - - function StringPrettyPrinter() { - PrettyPrinter.call(this); - - this.string = ''; - } - - j$.util.inherit(StringPrettyPrinter, PrettyPrinter); - - StringPrettyPrinter.prototype.emitScalar = function(value) { - this.append(value); - }; - - StringPrettyPrinter.prototype.emitString = function(value) { - this.append('\'' + value + '\''); - }; - - StringPrettyPrinter.prototype.emitArray = function(array) { - if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { - this.append('Array'); - return; - } - var length = Math.min(array.length, j$.MAX_PRETTY_PRINT_ARRAY_LENGTH); - this.append('[ '); - for (var i = 0; i < length; i++) { - if (i > 0) { - this.append(', '); - } - this.format(array[i]); - } - if(array.length > length){ - this.append(', ...'); - } - - var self = this; - var first = array.length === 0; - this.iterateObject(array, function(property, isGetter) { - if (property.match(/^\d+$/)) { - return; - } - - if (first) { - first = false; - } else { - self.append(', '); - } - - self.formatProperty(array, property, isGetter); - }); - - this.append(' ]'); - }; - - StringPrettyPrinter.prototype.emitObject = function(obj) { - var constructorName = obj.constructor ? j$.fnNameFor(obj.constructor) : 'null'; - this.append(constructorName); - - if (this.ppNestLevel_ > j$.MAX_PRETTY_PRINT_DEPTH) { - return; - } - - var self = this; - this.append('({ '); - var first = true; - - this.iterateObject(obj, function(property, isGetter) { - if (first) { - first = false; - } else { - self.append(', '); - } - - self.formatProperty(obj, property, isGetter); - }); - - this.append(' })'); - }; - - StringPrettyPrinter.prototype.formatProperty = function(obj, property, isGetter) { - this.append(property); - this.append(': '); - if (isGetter) { - this.append(''); - } else { - this.format(obj[property]); - } - }; - - StringPrettyPrinter.prototype.append = function(value) { - this.string += value; - }; - - return function(value) { - var stringPrettyPrinter = new StringPrettyPrinter(); - stringPrettyPrinter.format(value); - return stringPrettyPrinter.string; - }; -}; - -getJasmineRequireObj().QueueRunner = function(j$) { - - function once(fn) { - var called = false; - return function() { - if (!called) { - called = true; - fn(); - } - }; - } - - function QueueRunner(attrs) { - this.queueableFns = attrs.queueableFns || []; - this.onComplete = attrs.onComplete || function() {}; - this.clearStack = attrs.clearStack || function(fn) {fn();}; - this.onException = attrs.onException || function() {}; - this.catchException = attrs.catchException || function() { return true; }; - this.userContext = attrs.userContext || {}; - this.timeout = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout}; - this.fail = attrs.fail || function() {}; - } - - QueueRunner.prototype.execute = function() { - this.run(this.queueableFns, 0); - }; - - QueueRunner.prototype.run = function(queueableFns, recursiveIndex) { - var length = queueableFns.length, - self = this, - iterativeIndex; - - - for(iterativeIndex = recursiveIndex; iterativeIndex < length; iterativeIndex++) { - var queueableFn = queueableFns[iterativeIndex]; - if (queueableFn.fn.length > 0) { - attemptAsync(queueableFn); - return; - } else { - attemptSync(queueableFn); - } - } - - var runnerDone = iterativeIndex >= length; - - if (runnerDone) { - this.clearStack(this.onComplete); - } - - function attemptSync(queueableFn) { - try { - queueableFn.fn.call(self.userContext); - } catch (e) { - handleException(e, queueableFn); - } - } - - function attemptAsync(queueableFn) { - var clearTimeout = function () { - Function.prototype.apply.apply(self.timeout.clearTimeout, [j$.getGlobal(), [timeoutId]]); - }, - next = once(function () { - clearTimeout(timeoutId); - self.run(queueableFns, iterativeIndex + 1); - }), - timeoutId; - - next.fail = function() { - self.fail.apply(null, arguments); - next(); - }; - - if (queueableFn.timeout) { - timeoutId = Function.prototype.apply.apply(self.timeout.setTimeout, [j$.getGlobal(), [function() { - var error = new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'); - onException(error, queueableFn); - next(); - }, queueableFn.timeout()]]); - } - - try { - queueableFn.fn.call(self.userContext, next); - } catch (e) { - handleException(e, queueableFn); - next(); - } - } - - function onException(e, queueableFn) { - self.onException(e); - } - - function handleException(e, queueableFn) { - onException(e, queueableFn); - if (!self.catchException(e)) { - //TODO: set a var when we catch an exception and - //use a finally block to close the loop in a nice way.. - throw e; - } - } - }; - - return QueueRunner; -}; - -getJasmineRequireObj().ReportDispatcher = function() { - function ReportDispatcher(methods) { - - var dispatchedMethods = methods || []; - - for (var i = 0; i < dispatchedMethods.length; i++) { - var method = dispatchedMethods[i]; - this[method] = (function(m) { - return function() { - dispatch(m, arguments); - }; - }(method)); - } - - var reporters = []; - - this.addReporter = function(reporter) { - reporters.push(reporter); - }; - - return this; - - function dispatch(method, args) { - for (var i = 0; i < reporters.length; i++) { - var reporter = reporters[i]; - if (reporter[method]) { - reporter[method].apply(reporter, args); - } - } - } - } - - return ReportDispatcher; -}; - - -getJasmineRequireObj().SpyRegistry = function(j$) { - - function SpyRegistry(options) { - options = options || {}; - var currentSpies = options.currentSpies || function() { return []; }; - - this.spyOn = function(obj, methodName) { - if (j$.util.isUndefined(obj)) { - throw new Error('spyOn could not find an object to spy upon for ' + methodName + '()'); - } - - if (j$.util.isUndefined(methodName)) { - throw new Error('No method name supplied'); - } - - if (j$.util.isUndefined(obj[methodName])) { - throw new Error(methodName + '() method does not exist'); - } - - if (obj[methodName] && j$.isSpy(obj[methodName])) { - //TODO?: should this return the current spy? Downside: may cause user confusion about spy state - throw new Error(methodName + ' has already been spied upon'); - } - - var spy = j$.createSpy(methodName, obj[methodName]); - - currentSpies().push({ - spy: spy, - baseObj: obj, - methodName: methodName, - originalValue: obj[methodName] - }); - - obj[methodName] = spy; - - return spy; - }; - - this.clearSpies = function() { - var spies = currentSpies(); - for (var i = 0; i < spies.length; i++) { - var spyEntry = spies[i]; - spyEntry.baseObj[spyEntry.methodName] = spyEntry.originalValue; - } - }; - } - - return SpyRegistry; -}; - -getJasmineRequireObj().SpyStrategy = function() { - - function SpyStrategy(options) { - options = options || {}; - - var identity = options.name || 'unknown', - originalFn = options.fn || function() {}, - getSpy = options.getSpy || function() {}, - plan = function() {}; - - this.identity = function() { - return identity; - }; - - this.exec = function() { - return plan.apply(this, arguments); - }; - - this.callThrough = function() { - plan = originalFn; - return getSpy(); - }; - - this.returnValue = function(value) { - plan = function() { - return value; - }; - return getSpy(); - }; - - this.returnValues = function() { - var values = Array.prototype.slice.call(arguments); - plan = function () { - return values.shift(); - }; - return getSpy(); - }; - - this.throwError = function(something) { - var error = (something instanceof Error) ? something : new Error(something); - plan = function() { - throw error; - }; - return getSpy(); - }; - - this.callFake = function(fn) { - plan = fn; - return getSpy(); - }; - - this.stub = function(fn) { - plan = function() {}; - return getSpy(); - }; - } - - return SpyStrategy; -}; - -getJasmineRequireObj().Suite = function(j$) { - function Suite(attrs) { - this.env = attrs.env; - this.id = attrs.id; - this.parentSuite = attrs.parentSuite; - this.description = attrs.description; - this.expectationFactory = attrs.expectationFactory; - this.expectationResultFactory = attrs.expectationResultFactory; - this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure; - - this.beforeFns = []; - this.afterFns = []; - this.beforeAllFns = []; - this.afterAllFns = []; - this.disabled = false; - - this.children = []; - - this.result = { - id: this.id, - description: this.description, - fullName: this.getFullName(), - failedExpectations: [] - }; - } - - Suite.prototype.expect = function(actual) { - return this.expectationFactory(actual, this); - }; - - Suite.prototype.getFullName = function() { - var fullName = this.description; - for (var parentSuite = this.parentSuite; parentSuite; parentSuite = parentSuite.parentSuite) { - if (parentSuite.parentSuite) { - fullName = parentSuite.description + ' ' + fullName; - } - } - return fullName; - }; - - Suite.prototype.disable = function() { - this.disabled = true; - }; - - Suite.prototype.beforeEach = function(fn) { - this.beforeFns.unshift(fn); - }; - - Suite.prototype.beforeAll = function(fn) { - this.beforeAllFns.push(fn); - }; - - Suite.prototype.afterEach = function(fn) { - this.afterFns.unshift(fn); - }; - - Suite.prototype.afterAll = function(fn) { - this.afterAllFns.push(fn); - }; - - Suite.prototype.addChild = function(child) { - this.children.push(child); - }; - - Suite.prototype.status = function() { - if (this.disabled) { - return 'disabled'; - } - - if (this.result.failedExpectations.length > 0) { - return 'failed'; - } else { - return 'finished'; - } - }; - - Suite.prototype.isExecutable = function() { - return !this.disabled; - }; - - Suite.prototype.canBeReentered = function() { - return this.beforeAllFns.length === 0 && this.afterAllFns.length === 0; - }; - - Suite.prototype.getResult = function() { - this.result.status = this.status(); - return this.result; - }; - - Suite.prototype.sharedUserContext = function() { - if (!this.sharedContext) { - this.sharedContext = this.parentSuite ? clone(this.parentSuite.sharedUserContext()) : {}; - } - - return this.sharedContext; - }; - - Suite.prototype.clonedSharedUserContext = function() { - return clone(this.sharedUserContext()); - }; - - Suite.prototype.onException = function() { - if (arguments[0] instanceof j$.errors.ExpectationFailed) { - return; - } - - if(isAfterAll(this.children)) { - var data = { - matcherName: '', - passed: false, - expected: '', - actual: '', - error: arguments[0] - }; - this.result.failedExpectations.push(this.expectationResultFactory(data)); - } else { - for (var i = 0; i < this.children.length; i++) { - var child = this.children[i]; - child.onException.apply(child, arguments); - } - } - }; - - Suite.prototype.addExpectationResult = function () { - if(isAfterAll(this.children) && isFailure(arguments)){ - var data = arguments[1]; - this.result.failedExpectations.push(this.expectationResultFactory(data)); - if(this.throwOnExpectationFailure) { - throw new j$.errors.ExpectationFailed(); - } - } else { - for (var i = 0; i < this.children.length; i++) { - var child = this.children[i]; - try { - child.addExpectationResult.apply(child, arguments); - } catch(e) { - // keep going - } - } - } - }; - - function isAfterAll(children) { - return children && children[0].result.status; - } - - function isFailure(args) { - return !args[0]; - } - - function clone(obj) { - var clonedObj = {}; - for (var prop in obj) { - if (obj.hasOwnProperty(prop)) { - clonedObj[prop] = obj[prop]; - } - } - - return clonedObj; - } - - return Suite; -}; - -if (typeof window == void 0 && typeof exports == 'object') { - exports.Suite = jasmineRequire.Suite; -} - -getJasmineRequireObj().Timer = function() { - var defaultNow = (function(Date) { - return function() { return new Date().getTime(); }; - })(Date); - - function Timer(options) { - options = options || {}; - - var now = options.now || defaultNow, - startTime; - - this.start = function() { - startTime = now(); - }; - - this.elapsed = function() { - return now() - startTime; - }; - } - - return Timer; -}; - -getJasmineRequireObj().TreeProcessor = function() { - function TreeProcessor(attrs) { - var tree = attrs.tree, - runnableIds = attrs.runnableIds, - queueRunnerFactory = attrs.queueRunnerFactory, - nodeStart = attrs.nodeStart || function() {}, - nodeComplete = attrs.nodeComplete || function() {}, - stats = { valid: true }, - processed = false, - defaultMin = Infinity, - defaultMax = 1 - Infinity; - - this.processTree = function() { - processNode(tree, false); - processed = true; - return stats; - }; - - this.execute = function(done) { - if (!processed) { - this.processTree(); - } - - if (!stats.valid) { - throw 'invalid order'; - } - - var childFns = wrapChildren(tree, 0); - - queueRunnerFactory({ - queueableFns: childFns, - userContext: tree.sharedUserContext(), - onException: function() { - tree.onException.apply(tree, arguments); - }, - onComplete: done - }); - }; - - function runnableIndex(id) { - for (var i = 0; i < runnableIds.length; i++) { - if (runnableIds[i] === id) { - return i; - } - } - } - - function processNode(node, parentEnabled) { - var executableIndex = runnableIndex(node.id); - - if (executableIndex !== undefined) { - parentEnabled = true; - } - - parentEnabled = parentEnabled && node.isExecutable(); - - if (!node.children) { - stats[node.id] = { - executable: parentEnabled && node.isExecutable(), - segments: [{ - index: 0, - owner: node, - nodes: [node], - min: startingMin(executableIndex), - max: startingMax(executableIndex) - }] - }; - } else { - var hasExecutableChild = false; - - for (var i = 0; i < node.children.length; i++) { - var child = node.children[i]; - - processNode(child, parentEnabled); - - if (!stats.valid) { - return; - } - - var childStats = stats[child.id]; - - hasExecutableChild = hasExecutableChild || childStats.executable; - } - - stats[node.id] = { - executable: hasExecutableChild - }; - - segmentChildren(node, stats[node.id], executableIndex); - - if (!node.canBeReentered() && stats[node.id].segments.length > 1) { - stats = { valid: false }; - } - } - } - - function startingMin(executableIndex) { - return executableIndex === undefined ? defaultMin : executableIndex; - } - - function startingMax(executableIndex) { - return executableIndex === undefined ? defaultMax : executableIndex; - } - - function segmentChildren(node, nodeStats, executableIndex) { - var currentSegment = { index: 0, owner: node, nodes: [], min: startingMin(executableIndex), max: startingMax(executableIndex) }, - result = [currentSegment], - lastMax = defaultMax, - orderedChildSegments = orderChildSegments(node.children); - - function isSegmentBoundary(minIndex) { - return lastMax !== defaultMax && minIndex !== defaultMin && lastMax < minIndex - 1; - } - - for (var i = 0; i < orderedChildSegments.length; i++) { - var childSegment = orderedChildSegments[i], - maxIndex = childSegment.max, - minIndex = childSegment.min; - - if (isSegmentBoundary(minIndex)) { - currentSegment = {index: result.length, owner: node, nodes: [], min: defaultMin, max: defaultMax}; - result.push(currentSegment); - } - - currentSegment.nodes.push(childSegment); - currentSegment.min = Math.min(currentSegment.min, minIndex); - currentSegment.max = Math.max(currentSegment.max, maxIndex); - lastMax = maxIndex; - } - - nodeStats.segments = result; - } - - function orderChildSegments(children) { - var specifiedOrder = [], - unspecifiedOrder = []; - - for (var i = 0; i < children.length; i++) { - var child = children[i], - segments = stats[child.id].segments; - - for (var j = 0; j < segments.length; j++) { - var seg = segments[j]; - - if (seg.min === defaultMin) { - unspecifiedOrder.push(seg); - } else { - specifiedOrder.push(seg); - } - } - } - - specifiedOrder.sort(function(a, b) { - return a.min - b.min; - }); - - return specifiedOrder.concat(unspecifiedOrder); - } - - function executeNode(node, segmentNumber) { - if (node.children) { - return { - fn: function(done) { - nodeStart(node); - - queueRunnerFactory({ - onComplete: function() { - nodeComplete(node, node.getResult()); - done(); - }, - queueableFns: wrapChildren(node, segmentNumber), - userContext: node.sharedUserContext(), - onException: function() { - node.onException.apply(node, arguments); - } - }); - } - }; - } else { - return { - fn: function(done) { node.execute(done, stats[node.id].executable); } - }; - } - } - - function wrapChildren(node, segmentNumber) { - var result = [], - segmentChildren = stats[node.id].segments[segmentNumber].nodes; - - for (var i = 0; i < segmentChildren.length; i++) { - result.push(executeNode(segmentChildren[i].owner, segmentChildren[i].index)); - } - - if (!stats[node.id].executable) { - return result; - } - - return node.beforeAllFns.concat(result).concat(node.afterAllFns); - } - } - - return TreeProcessor; -}; - -getJasmineRequireObj().Any = function(j$) { - - function Any(expectedObject) { - this.expectedObject = expectedObject; - } - - Any.prototype.asymmetricMatch = function(other) { - if (this.expectedObject == String) { - return typeof other == 'string' || other instanceof String; - } - - if (this.expectedObject == Number) { - return typeof other == 'number' || other instanceof Number; - } - - if (this.expectedObject == Function) { - return typeof other == 'function' || other instanceof Function; - } - - if (this.expectedObject == Object) { - return typeof other == 'object'; - } - - if (this.expectedObject == Boolean) { - return typeof other == 'boolean'; - } - - return other instanceof this.expectedObject; - }; - - Any.prototype.jasmineToString = function() { - return ''; - }; - - return Any; -}; - -getJasmineRequireObj().Anything = function(j$) { - - function Anything() {} - - Anything.prototype.asymmetricMatch = function(other) { - return !j$.util.isUndefined(other) && other !== null; - }; - - Anything.prototype.jasmineToString = function() { - return ''; - }; - - return Anything; -}; - -getJasmineRequireObj().ArrayContaining = function(j$) { - function ArrayContaining(sample) { - this.sample = sample; - } - - ArrayContaining.prototype.asymmetricMatch = function(other) { - var className = Object.prototype.toString.call(this.sample); - if (className !== '[object Array]') { throw new Error('You must provide an array to arrayContaining, not \'' + this.sample + '\'.'); } - - for (var i = 0; i < this.sample.length; i++) { - var item = this.sample[i]; - if (!j$.matchersUtil.contains(other, item)) { - return false; - } - } - - return true; - }; - - ArrayContaining.prototype.jasmineToString = function () { - return ''; - }; - - return ArrayContaining; -}; - -getJasmineRequireObj().ObjectContaining = function(j$) { - - function ObjectContaining(sample) { - this.sample = sample; - } - - function getPrototype(obj) { - if (Object.getPrototypeOf) { - return Object.getPrototypeOf(obj); - } - - if (obj.constructor.prototype == obj) { - return null; - } - - return obj.constructor.prototype; - } - - function hasProperty(obj, property) { - if (!obj) { - return false; - } - - if (Object.prototype.hasOwnProperty.call(obj, property)) { - return true; - } - - return hasProperty(getPrototype(obj), property); - } - - ObjectContaining.prototype.asymmetricMatch = function(other) { - if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); } - - for (var property in this.sample) { - if (!hasProperty(other, property) || - !j$.matchersUtil.equals(this.sample[property], other[property])) { - return false; - } - } - - return true; - }; - - ObjectContaining.prototype.jasmineToString = function() { - return ''; - }; - - return ObjectContaining; -}; - -getJasmineRequireObj().StringMatching = function(j$) { - - function StringMatching(expected) { - if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) { - throw new Error('Expected is not a String or a RegExp'); - } - - this.regexp = new RegExp(expected); - } - - StringMatching.prototype.asymmetricMatch = function(other) { - return this.regexp.test(other); - }; - - StringMatching.prototype.jasmineToString = function() { - return ''; - }; - - return StringMatching; -}; - -getJasmineRequireObj().errors = function() { - function ExpectationFailed() {} - - ExpectationFailed.prototype = new Error(); - ExpectationFailed.prototype.constructor = ExpectationFailed; - - return { - ExpectationFailed: ExpectationFailed - }; -}; -getJasmineRequireObj().matchersUtil = function(j$) { - // TODO: what to do about jasmine.pp not being inject? move to JSON.stringify? gut PrettyPrinter? - - return { - equals: function(a, b, customTesters) { - customTesters = customTesters || []; - - return eq(a, b, [], [], customTesters); - }, - - contains: function(haystack, needle, customTesters) { - customTesters = customTesters || []; - - if ((Object.prototype.toString.apply(haystack) === '[object Array]') || - (!!haystack && !haystack.indexOf)) - { - for (var i = 0; i < haystack.length; i++) { - if (eq(haystack[i], needle, [], [], customTesters)) { - return true; - } - } - return false; - } - - return !!haystack && haystack.indexOf(needle) >= 0; - }, - - buildFailureMessage: function() { - var args = Array.prototype.slice.call(arguments, 0), - matcherName = args[0], - isNot = args[1], - actual = args[2], - expected = args.slice(3), - englishyPredicate = matcherName.replace(/[A-Z]/g, function(s) { return ' ' + s.toLowerCase(); }); - - var message = 'Expected ' + - j$.pp(actual) + - (isNot ? ' not ' : ' ') + - englishyPredicate; - - if (expected.length > 0) { - for (var i = 0; i < expected.length; i++) { - if (i > 0) { - message += ','; - } - message += ' ' + j$.pp(expected[i]); - } - } - - return message + '.'; - } - }; - - function isAsymmetric(obj) { - return obj && j$.isA_('Function', obj.asymmetricMatch); - } - - function asymmetricMatch(a, b) { - var asymmetricA = isAsymmetric(a), - asymmetricB = isAsymmetric(b); - - if (asymmetricA && asymmetricB) { - return undefined; - } - - if (asymmetricA) { - return a.asymmetricMatch(b); - } - - if (asymmetricB) { - return b.asymmetricMatch(a); - } - } - - // Equality function lovingly adapted from isEqual in - // [Underscore](http://underscorejs.org) - function eq(a, b, aStack, bStack, customTesters) { - var result = true; - - var asymmetricResult = asymmetricMatch(a, b); - if (!j$.util.isUndefined(asymmetricResult)) { - return asymmetricResult; - } - - for (var i = 0; i < customTesters.length; i++) { - var customTesterResult = customTesters[i](a, b); - if (!j$.util.isUndefined(customTesterResult)) { - return customTesterResult; - } - } - - if (a instanceof Error && b instanceof Error) { - return a.message == b.message; - } - - // Identical objects are equal. `0 === -0`, but they aren't identical. - // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). - if (a === b) { return a !== 0 || 1 / a == 1 / b; } - // A strict comparison is necessary because `null == undefined`. - if (a === null || b === null) { return a === b; } - var className = Object.prototype.toString.call(a); - if (className != Object.prototype.toString.call(b)) { return false; } - switch (className) { - // Strings, numbers, dates, and booleans are compared by value. - case '[object String]': - // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is - // equivalent to `new String("5")`. - return a == String(b); - case '[object Number]': - // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for - // other numeric values. - return a != +a ? b != +b : (a === 0 ? 1 / a == 1 / b : a == +b); - case '[object Date]': - case '[object Boolean]': - // Coerce dates and booleans to numeric primitive values. Dates are compared by their - // millisecond representations. Note that invalid dates with millisecond representations - // of `NaN` are not equivalent. - return +a == +b; - // RegExps are compared by their source patterns and flags. - case '[object RegExp]': - return a.source == b.source && - a.global == b.global && - a.multiline == b.multiline && - a.ignoreCase == b.ignoreCase; - } - if (typeof a != 'object' || typeof b != 'object') { return false; } - - var aIsDomNode = j$.isDomNode(a); - var bIsDomNode = j$.isDomNode(b); - if (aIsDomNode && bIsDomNode) { - // At first try to use DOM3 method isEqualNode - if (a.isEqualNode) { - return a.isEqualNode(b); - } - // IE8 doesn't support isEqualNode, try to use outerHTML && innerText - var aIsElement = a instanceof Element; - var bIsElement = b instanceof Element; - if (aIsElement && bIsElement) { - return a.outerHTML == b.outerHTML; - } - if (aIsElement || bIsElement) { - return false; - } - return a.innerText == b.innerText && a.textContent == b.textContent; - } - if (aIsDomNode || bIsDomNode) { - return false; - } - - // Assume equality for cyclic structures. The algorithm for detecting cyclic - // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. - var length = aStack.length; - while (length--) { - // Linear search. Performance is inversely proportional to the number of - // unique nested structures. - if (aStack[length] == a) { return bStack[length] == b; } - } - // Add the first object to the stack of traversed objects. - aStack.push(a); - bStack.push(b); - var size = 0; - // Recursively compare objects and arrays. - // Compare array lengths to determine if a deep comparison is necessary. - if (className == '[object Array]' && a.length !== b.length) { - result = false; - } - - if (result) { - // Objects with different constructors are not equivalent, but `Object`s - // or `Array`s from different frames are. - if (className !== '[object Array]') { - var aCtor = a.constructor, bCtor = b.constructor; - if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor && - isFunction(bCtor) && bCtor instanceof bCtor)) { - return false; - } - } - // Deep compare objects. - for (var key in a) { - if (has(a, key)) { - // Count the expected number of properties. - size++; - // Deep compare each member. - if (!(result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters))) { break; } - } - } - // Ensure that both objects contain the same number of properties. - if (result) { - for (key in b) { - if (has(b, key) && !(size--)) { break; } - } - result = !size; - } - } - // Remove the first object from the stack of traversed objects. - aStack.pop(); - bStack.pop(); - - return result; - - function has(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); - } - - function isFunction(obj) { - return typeof obj === 'function'; - } - } -}; - -getJasmineRequireObj().toBe = function() { - function toBe() { - return { - compare: function(actual, expected) { - return { - pass: actual === expected - }; - } - }; - } - - return toBe; -}; - -getJasmineRequireObj().toBeCloseTo = function() { - - function toBeCloseTo() { - return { - compare: function(actual, expected, precision) { - if (precision !== 0) { - precision = precision || 2; - } - - return { - pass: Math.abs(expected - actual) < (Math.pow(10, -precision) / 2) - }; - } - }; - } - - return toBeCloseTo; -}; - -getJasmineRequireObj().toBeDefined = function() { - function toBeDefined() { - return { - compare: function(actual) { - return { - pass: (void 0 !== actual) - }; - } - }; - } - - return toBeDefined; -}; - -getJasmineRequireObj().toBeFalsy = function() { - function toBeFalsy() { - return { - compare: function(actual) { - return { - pass: !!!actual - }; - } - }; - } - - return toBeFalsy; -}; - -getJasmineRequireObj().toBeGreaterThan = function() { - - function toBeGreaterThan() { - return { - compare: function(actual, expected) { - return { - pass: actual > expected - }; - } - }; - } - - return toBeGreaterThan; -}; - - -getJasmineRequireObj().toBeLessThan = function() { - function toBeLessThan() { - return { - - compare: function(actual, expected) { - return { - pass: actual < expected - }; - } - }; - } - - return toBeLessThan; -}; -getJasmineRequireObj().toBeNaN = function(j$) { - - function toBeNaN() { - return { - compare: function(actual) { - var result = { - pass: (actual !== actual) - }; - - if (result.pass) { - result.message = 'Expected actual not to be NaN.'; - } else { - result.message = function() { return 'Expected ' + j$.pp(actual) + ' to be NaN.'; }; - } - - return result; - } - }; - } - - return toBeNaN; -}; - -getJasmineRequireObj().toBeNull = function() { - - function toBeNull() { - return { - compare: function(actual) { - return { - pass: actual === null - }; - } - }; - } - - return toBeNull; -}; - -getJasmineRequireObj().toBeTruthy = function() { - - function toBeTruthy() { - return { - compare: function(actual) { - return { - pass: !!actual - }; - } - }; - } - - return toBeTruthy; -}; - -getJasmineRequireObj().toBeUndefined = function() { - - function toBeUndefined() { - return { - compare: function(actual) { - return { - pass: void 0 === actual - }; - } - }; - } - - return toBeUndefined; -}; - -getJasmineRequireObj().toContain = function() { - function toContain(util, customEqualityTesters) { - customEqualityTesters = customEqualityTesters || []; - - return { - compare: function(actual, expected) { - - return { - pass: util.contains(actual, expected, customEqualityTesters) - }; - } - }; - } - - return toContain; -}; - -getJasmineRequireObj().toEqual = function() { - - function toEqual(util, customEqualityTesters) { - customEqualityTesters = customEqualityTesters || []; - - return { - compare: function(actual, expected) { - var result = { - pass: false - }; - - result.pass = util.equals(actual, expected, customEqualityTesters); - - return result; - } - }; - } - - return toEqual; -}; - -getJasmineRequireObj().toHaveBeenCalled = function(j$) { - - function toHaveBeenCalled() { - return { - compare: function(actual) { - var result = {}; - - if (!j$.isSpy(actual)) { - throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); - } - - if (arguments.length > 1) { - throw new Error('toHaveBeenCalled does not take arguments, use toHaveBeenCalledWith'); - } - - result.pass = actual.calls.any(); - - result.message = result.pass ? - 'Expected spy ' + actual.and.identity() + ' not to have been called.' : - 'Expected spy ' + actual.and.identity() + ' to have been called.'; - - return result; - } - }; - } - - return toHaveBeenCalled; -}; - -getJasmineRequireObj().toHaveBeenCalledWith = function(j$) { - - function toHaveBeenCalledWith(util, customEqualityTesters) { - return { - compare: function() { - var args = Array.prototype.slice.call(arguments, 0), - actual = args[0], - expectedArgs = args.slice(1), - result = { pass: false }; - - if (!j$.isSpy(actual)) { - throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.'); - } - - if (!actual.calls.any()) { - result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but it was never called.'; }; - return result; - } - - if (util.contains(actual.calls.allArgs(), expectedArgs, customEqualityTesters)) { - result.pass = true; - result.message = function() { return 'Expected spy ' + actual.and.identity() + ' not to have been called with ' + j$.pp(expectedArgs) + ' but it was.'; }; - } else { - result.message = function() { return 'Expected spy ' + actual.and.identity() + ' to have been called with ' + j$.pp(expectedArgs) + ' but actual calls were ' + j$.pp(actual.calls.allArgs()).replace(/^\[ | \]$/g, '') + '.'; }; - } - - return result; - } - }; - } - - return toHaveBeenCalledWith; -}; - -getJasmineRequireObj().toMatch = function(j$) { - - function toMatch() { - return { - compare: function(actual, expected) { - if (!j$.isString_(expected) && !j$.isA_('RegExp', expected)) { - throw new Error('Expected is not a String or a RegExp'); - } - - var regexp = new RegExp(expected); - - return { - pass: regexp.test(actual) - }; - } - }; - } - - return toMatch; -}; - -getJasmineRequireObj().toThrow = function(j$) { - - function toThrow(util) { - return { - compare: function(actual, expected) { - var result = { pass: false }, - threw = false, - thrown; - - if (typeof actual != 'function') { - throw new Error('Actual is not a Function'); - } - - try { - actual(); - } catch (e) { - threw = true; - thrown = e; - } - - if (!threw) { - result.message = 'Expected function to throw an exception.'; - return result; - } - - if (arguments.length == 1) { - result.pass = true; - result.message = function() { return 'Expected function not to throw, but it threw ' + j$.pp(thrown) + '.'; }; - - return result; - } - - if (util.equals(thrown, expected)) { - result.pass = true; - result.message = function() { return 'Expected function not to throw ' + j$.pp(expected) + '.'; }; - } else { - result.message = function() { return 'Expected function to throw ' + j$.pp(expected) + ', but it threw ' + j$.pp(thrown) + '.'; }; - } - - return result; - } - }; - } - - return toThrow; -}; - -getJasmineRequireObj().toThrowError = function(j$) { - function toThrowError (util) { - return { - compare: function(actual) { - var threw = false, - pass = {pass: true}, - fail = {pass: false}, - thrown; - - if (typeof actual != 'function') { - throw new Error('Actual is not a Function'); - } - - var errorMatcher = getMatcher.apply(null, arguments); - - try { - actual(); - } catch (e) { - threw = true; - thrown = e; - } - - if (!threw) { - fail.message = 'Expected function to throw an Error.'; - return fail; - } - - if (!(thrown instanceof Error)) { - fail.message = function() { return 'Expected function to throw an Error, but it threw ' + j$.pp(thrown) + '.'; }; - return fail; - } - - if (errorMatcher.hasNoSpecifics()) { - pass.message = 'Expected function not to throw an Error, but it threw ' + j$.fnNameFor(thrown) + '.'; - return pass; - } - - if (errorMatcher.matches(thrown)) { - pass.message = function() { - return 'Expected function not to throw ' + errorMatcher.errorTypeDescription + errorMatcher.messageDescription() + '.'; - }; - return pass; - } else { - fail.message = function() { - return 'Expected function to throw ' + errorMatcher.errorTypeDescription + errorMatcher.messageDescription() + - ', but it threw ' + errorMatcher.thrownDescription(thrown) + '.'; - }; - return fail; - } - } - }; - - function getMatcher() { - var expected = null, - errorType = null; - - if (arguments.length == 2) { - expected = arguments[1]; - if (isAnErrorType(expected)) { - errorType = expected; - expected = null; - } - } else if (arguments.length > 2) { - errorType = arguments[1]; - expected = arguments[2]; - if (!isAnErrorType(errorType)) { - throw new Error('Expected error type is not an Error.'); - } - } - - if (expected && !isStringOrRegExp(expected)) { - if (errorType) { - throw new Error('Expected error message is not a string or RegExp.'); - } else { - throw new Error('Expected is not an Error, string, or RegExp.'); - } - } - - function messageMatch(message) { - if (typeof expected == 'string') { - return expected == message; - } else { - return expected.test(message); - } - } - - return { - errorTypeDescription: errorType ? j$.fnNameFor(errorType) : 'an exception', - thrownDescription: function(thrown) { - var thrownName = errorType ? j$.fnNameFor(thrown.constructor) : 'an exception', - thrownMessage = ''; - - if (expected) { - thrownMessage = ' with message ' + j$.pp(thrown.message); - } - - return thrownName + thrownMessage; - }, - messageDescription: function() { - if (expected === null) { - return ''; - } else if (expected instanceof RegExp) { - return ' with a message matching ' + j$.pp(expected); - } else { - return ' with message ' + j$.pp(expected); - } - }, - hasNoSpecifics: function() { - return expected === null && errorType === null; - }, - matches: function(error) { - return (errorType === null || error instanceof errorType) && - (expected === null || messageMatch(error.message)); - } - }; - } - - function isStringOrRegExp(potential) { - return potential instanceof RegExp || (typeof potential == 'string'); - } - - function isAnErrorType(type) { - if (typeof type !== 'function') { - return false; - } - - var Surrogate = function() {}; - Surrogate.prototype = type.prototype; - return (new Surrogate()) instanceof Error; - } - } - - return toThrowError; -}; - -getJasmineRequireObj().interface = function(jasmine, env) { - var jasmineInterface = { - describe: function(description, specDefinitions) { - return env.describe(description, specDefinitions); - }, - - xdescribe: function(description, specDefinitions) { - return env.xdescribe(description, specDefinitions); - }, - - fdescribe: function(description, specDefinitions) { - return env.fdescribe(description, specDefinitions); - }, - - it: function() { - return env.it.apply(env, arguments); - }, - - xit: function() { - return env.xit.apply(env, arguments); - }, - - fit: function() { - return env.fit.apply(env, arguments); - }, - - beforeEach: function() { - return env.beforeEach.apply(env, arguments); - }, - - afterEach: function() { - return env.afterEach.apply(env, arguments); - }, - - beforeAll: function() { - return env.beforeAll.apply(env, arguments); - }, - - afterAll: function() { - return env.afterAll.apply(env, arguments); - }, - - expect: function(actual) { - return env.expect(actual); - }, - - pending: function() { - return env.pending.apply(env, arguments); - }, - - fail: function() { - return env.fail.apply(env, arguments); - }, - - spyOn: function(obj, methodName) { - return env.spyOn(obj, methodName); - }, - - jsApiReporter: new jasmine.JsApiReporter({ - timer: new jasmine.Timer() - }), - - jasmine: jasmine - }; - - jasmine.addCustomEqualityTester = function(tester) { - env.addCustomEqualityTester(tester); - }; - - jasmine.addMatchers = function(matchers) { - return env.addMatchers(matchers); - }; - - jasmine.clock = function() { - return env.clock; - }; - - return jasmineInterface; -}; - -getJasmineRequireObj().version = function() { - return '2.3.4'; -}; diff --git a/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine_favicon.png b/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine_favicon.png deleted file mode 100644 index 3b84583be..000000000 Binary files a/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/jasmine_favicon.png and /dev/null differ diff --git a/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/terminal.js b/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/terminal.js deleted file mode 100644 index b9cf1a5e7..000000000 --- a/dashboard-ui/bower_components/fingerprintjs2/specs/lib/jasmine-2.3.4/terminal.js +++ /dev/null @@ -1,261 +0,0 @@ -(function(global) { - var UNDEFINED, - exportObject; - - if (typeof module !== "undefined" && module.exports) { - exportObject = exports; - } else { - exportObject = global.jasmineReporters = global.jasmineReporters || {}; - } - - function elapsed(start, end) { return (end - start)/1000; } - function isFailed(obj) { return obj.status === "failed"; } - function isSkipped(obj) { return obj.status === "pending"; } - function isDisabled(obj) { return obj.status === "disabled"; } - function extend(dupe, obj) { // performs a shallow copy of all props of `obj` onto `dupe` - for (var prop in obj) { - if (obj.hasOwnProperty(prop)) { - dupe[prop] = obj[prop]; - } - } - return dupe; - } - function log(str) { - var con = global.console || console; - if (con && con.log && str && str.length) { - con.log(str); - } - } - - - /** - * Basic reporter that outputs spec results to the terminal. - * Use this reporter in your build pipeline. - * - * Usage: - * - * jasmine.getEnv().addReporter(new jasmineReporters.TerminalReporter(options); - * - * @param {object} [options] - * @param {number} [options.verbosity] meaningful values are 0 through 3; anything - * greater than 3 is treated as 3 (default: 2) - * @param {boolean} [options.color] print in color or not (default: true) - * @param {boolean} [opts.showStack] show stack trace for failed specs (default: false) - */ - var DEFAULT_VERBOSITY = 2, - ATTRIBUTES_TO_ANSI = { - "off": 0, - "bold": 1, - "red": 31, - "green": 32, - "yellow": 33, - "blue": 34, - "magenta": 35, - "cyan": 36 - }; - - exportObject.TerminalReporter = function(options) { - var self = this; - self.started = false; - self.finished = false; - - // sanitize arguments - options = options || {}; - self.verbosity = typeof options.verbosity === "number" ? options.verbosity : DEFAULT_VERBOSITY; - self.color = options.color; - self.showStack = options.showStack; - - var indent_string = ' ', - startTime, - currentSuite = null, - totalSpecsExecuted = 0, - totalSpecsSkipped = 0, - totalSpecsDisabled = 0, - totalSpecsFailed = 0, - totalSpecsDefined, - // when use use fit, jasmine never calls suiteStarted / suiteDone, so make a fake one to use - fakeFocusedSuite = { - id: 'focused', - description: 'focused specs', - fullName: 'focused specs' - }; - - var __suites = {}, __specs = {}; - function getSuite(suite) { - __suites[suite.id] = extend(__suites[suite.id] || {}, suite); - return __suites[suite.id]; - } - function getSpec(spec) { - __specs[spec.id] = extend(__specs[spec.id] || {}, spec); - return __specs[spec.id]; - } - - self.jasmineStarted = function(summary) { - totalSpecsDefined = summary && summary.totalSpecsDefined || NaN; - startTime = exportObject.startTime = new Date(); - self.started = true; - }; - self.suiteStarted = function(suite) { - suite = getSuite(suite); - suite._specs = 0; - suite._nestedSpecs = 0; - suite._failures = 0; - suite._nestedFailures = 0; - suite._skipped = 0; - suite._nestedSkipped = 0; - suite._disabled = 0; - suite._nestedDisabled = 0; - suite._depth = currentSuite ? currentSuite._depth+1 : 1; - suite._parent = currentSuite; - currentSuite = suite; - if (self.verbosity > 2) { - log(indentWithLevel(suite._depth, inColor(suite.description, "bold"))); - } - }; - self.specStarted = function(spec) { - if (!currentSuite) { - // focused spec (fit) -- suiteStarted was never called - self.suiteStarted(fakeFocusedSuite); - } - spec = getSpec(spec); - spec._suite = currentSuite; - spec._depth = currentSuite._depth+1; - currentSuite._specs++; - if (self.verbosity > 2) { - log(indentWithLevel(spec._depth, spec.description + ' ...')); - } - }; - self.specDone = function(spec) { - spec = getSpec(spec); - var failed = false, - skipped = false, - disabled = false, - color = 'green', - resultText = ''; - if (isSkipped(spec)) { - skipped = true; - color = ''; - spec._suite._skipped++; - totalSpecsSkipped++; - } - if (isFailed(spec)) { - failed = true; - color = 'red'; - spec._suite._failures++; - totalSpecsFailed++; - } - if (isDisabled(spec)) { - disabled = true; - color = 'yellow'; - spec._suite._disabled++; - totalSpecsDisabled++; - } - totalSpecsExecuted++; - - if (self.verbosity === 2) { - resultText = failed ? 'F' : skipped ? 'S' : disabled ? 'D' : '.'; - } else if (self.verbosity > 2) { - resultText = ' ' + (failed ? 'Failed' : skipped ? 'Skipped' : disabled ? 'Disabled' : 'Passed'); - } - log(inColor(resultText, color)); - - if (failed) { - if (self.verbosity === 1) { - log(spec.fullName); - } else if (self.verbosity === 2) { - log(' '); - log(indentWithLevel(spec._depth, spec.fullName)); - } - - for (var i = 0; i < spec.failedExpectations.length; i++) { - log(inColor(indentWithLevel(spec._depth, indent_string + spec.failedExpectations[i].message), color)); - if (self.showStack){ - logStackLines(spec._depth, spec.failedExpectations[i].stack.split('\n')); - } - } - } - }; - self.suiteDone = function(suite) { - suite = getSuite(suite); - if (suite._parent === UNDEFINED) { - // disabled suite (xdescribe) -- suiteStarted was never called - self.suiteStarted(suite); - } - if (suite._parent) { - suite._parent._specs += suite._specs + suite._nestedSpecs; - suite._parent._failures += suite._failures + suite._nestedFailures; - suite._parent._skipped += suite._skipped + suite._nestedSkipped; - suite._parent._disabled += suite._disabled + suite._nestedDisabled; - - } - currentSuite = suite._parent; - if (self.verbosity < 3) { - return; - } - - var total = suite._specs + suite._nestedSpecs, - failed = suite._failures + suite._nestedFailures, - skipped = suite._skipped + suite._nestedSkipped, - disabled = suite._disabled + suite._nestedDisabled, - passed = total - failed - skipped, - color = failed ? 'red+bold' : 'green+bold', - str = passed + ' of ' + total + ' passed (' + skipped + ' skipped, ' + disabled + ' disabled)'; - log(indentWithLevel(suite._depth, inColor(str+'.', color))); - }; - self.jasmineDone = function() { - if (currentSuite) { - // focused spec (fit) -- suiteDone was never called - self.suiteDone(fakeFocusedSuite); - } - var now = new Date(), - dur = elapsed(startTime, now), - total = totalSpecsDefined || totalSpecsExecuted, - disabled = total - totalSpecsExecuted + totalSpecsDisabled, - skipped = totalSpecsSkipped, - spec_str = total + (total === 1 ? " spec, " : " specs, "), - fail_str = totalSpecsFailed + (totalSpecsFailed === 1 ? " failure, " : " failures, "), - skip_str = skipped + " skipped, ", - disabled_str = disabled + " disabled in ", - summary_str = spec_str + fail_str + skip_str + disabled_str + dur + "s.", - result_str = (totalSpecsFailed && "FAILURE: " || "SUCCESS: ") + summary_str, - result_color = totalSpecsFailed && "red+bold" || "green+bold"; - - if (self.verbosity === 2) { - log(''); - } - - if (self.verbosity > 0) { - log(inColor(result_str, result_color)); - } - //log("Specs skipped but not reported (entire suite skipped or targeted to specific specs)", totalSpecsDefined - totalSpecsExecuted + totalSpecsDisabled); - - self.finished = true; - // this is so phantomjs-testrunner.js can tell if we're done executing - exportObject.endTime = now; - }; - function indentWithLevel(level, string) { - return new Array(level).join(indent_string) + string; - } - function logStackLines(depth, lines) { - lines.forEach(function(line){ - log(inColor(indentWithLevel(depth, indent_string + line), 'magenta')); - }); - } - function inColor(string, color) { - var color_attributes = color && color.split("+"), - ansi_string = "", - i; - - if (!self.color || !color_attributes) { - return string; - } - - for(i = 0; i < color_attributes.length; i++) { - ansi_string += "\033[" + ATTRIBUTES_TO_ANSI[color_attributes[i]] + "m"; - } - ansi_string += string + "\033[" + ATTRIBUTES_TO_ANSI["off"] + "m"; - - return ansi_string; - } - }; -})(this); diff --git a/dashboard-ui/bower_components/fingerprintjs2/specs/phantomjs-testrunner.js b/dashboard-ui/bower_components/fingerprintjs2/specs/phantomjs-testrunner.js deleted file mode 100644 index c0f4c6a46..000000000 --- a/dashboard-ui/bower_components/fingerprintjs2/specs/phantomjs-testrunner.js +++ /dev/null @@ -1,230 +0,0 @@ -/* globals jasmineRequire, phantom */ -// Verify arguments -var system = require('system'); -var args; - -if(phantom.args) { - args = phantom.args; -} else { - args = system.args.slice(1);//use system args for phantom 2.0+ -} - -if (args.length === 0) { - console.log("Simple JasmineBDD test runner for phantom.js"); - console.log("Usage: phantomjs-testrunner.js url_to_runner.html"); - console.log("Accepts http:// and file:// urls"); - console.log(""); - console.log("NOTE: This script depends on jasmine.HtmlReporter being used\non the page, for the DOM elements it creates.\n"); - phantom.exit(2); -} -else { - var fs = require("fs"), - pages = [], - page, address, resultsKey, i, l; - - - var setupPageFn = function(p, k) { - return function() { - overloadPageEvaluate(p); - setupWriteFileFunction(p, k, fs.separator); - }; - }; - - for (i = 0, l = args.length; i < l; i++) { - address = args[i]; - console.log("Loading " + address); - - // if provided a url without a protocol, try to use file:// - address = address.indexOf("://") === -1 ? "file://" + address : address; - - // create a WebPage object to work with - page = require("webpage").create(); - page.url = address; - - // When initialized, inject the reporting functions before the page is loaded - // (and thus before it will try to utilize the functions) - resultsKey = "__jr" + Math.ceil(Math.random() * 1000000); - page.onInitialized = setupPageFn(page, resultsKey); - page.open(address, processPage(null, page, resultsKey)); - pages.push(page); - - page.onConsoleMessage = logAndWorkAroundDefaultLineBreaking; - } - - // bail when all pages have been processed - setInterval(function(){ - var exit_code = 0; - for (i = 0, l = pages.length; i < l; i++) { - page = pages[i]; - if (page.__exit_code === null) { - // wait until later - return; - } - exit_code |= page.__exit_code; - } - phantom.exit(exit_code); - }, 100); -} - -// Thanks to hoisting, these helpers are still available when needed above -/** - * Logs a message. Does not add a line-break for single characters '.' and 'F' or lines ending in ' ...' - * - * @param msg - */ -function logAndWorkAroundDefaultLineBreaking(msg) { - var interpretAsWithoutNewline = /(^(\033\[\d+m)*[\.F](\033\[\d+m)*$)|( \.\.\.$)/; - if (navigator.userAgent.indexOf("Windows") < 0 && interpretAsWithoutNewline.test(msg)) { - try { - system.stdout.write(msg); - } catch (e) { - var fs = require('fs'); - fs.write('/dev/stdout', msg, 'w'); - } - } else { - console.log(msg); - } -} - -/** - * Stringifies the function, replacing any %placeholders% with mapped values. - * - * @param {function} fn The function to replace occurrences within. - * @param {object} replacements Key => Value object of string replacements. - */ -function replaceFunctionPlaceholders(fn, replacements) { - if (replacements && typeof replacements === "object") { - fn = fn.toString(); - for (var p in replacements) { - if (replacements.hasOwnProperty(p)) { - var match = new RegExp("%" + p + "%", "g"); - do { - fn = fn.replace(match, replacements[p]); - } while(fn.indexOf(match) !== -1); - } - } - } - return fn; -} - -/** - * Replaces the "evaluate" method with one we can easily do substitution with. - * - * @param {phantomjs.WebPage} page The WebPage object to overload - */ -function overloadPageEvaluate(page) { - page._evaluate = page.evaluate; - page.evaluate = function(fn, replacements) { return page._evaluate(replaceFunctionPlaceholders(fn, replacements)); }; - return page; -} - -/** Stubs a fake writeFile function into the test runner. - * - * @param {phantomjs.WebPage} page The WebPage object to inject functions into. - * @param {string} key The name of the global object in which file data should - * be stored for later retrieval. - */ -// TODO: not bothering with error checking for now (closed environment) -function setupWriteFileFunction(page, key, path_separator) { - page.evaluate(function(){ - window["%resultsObj%"] = {}; - window.fs_path_separator = "%fs_path_separator%"; - window.__phantom_writeFile = function(filename, text) { - window["%resultsObj%"][filename] = text; - }; - }, {resultsObj: key, fs_path_separator: path_separator.replace("\\", "\\\\")}); -} - -/** - * Returns the loaded page's filename => output object. - * - * @param {phantomjs.WebPage} page The WebPage object to retrieve data from. - * @param {string} key The name of the global object to be returned. Should - * be the same key provided to setupWriteFileFunction. - */ -function getXmlResults(page, key) { - return page.evaluate(function(){ - return window["%resultsObj%"] || {}; - }, {resultsObj: key}); -} - -/** - * Processes a page. - * - * @param {string} status The status from opening the page via WebPage#open. - * @param {phantomjs.WebPage} page The WebPage to be processed. - */ -function processPage(status, page, resultsKey) { - if (status === null && page) { - page.__exit_code = null; - return function(stat){ - processPage(stat, page, resultsKey); - }; - } - if (status !== "success") { - console.error("Unable to load resource: " + address); - page.__exit_code = 2; - } - else { - var isFinished = function() { - return page.evaluate(function(){ - // if there's a JUnitXmlReporter, return a boolean indicating if it is finished - if (window.jasmineReporters && window.jasmineReporters.startTime) { - return !!window.jasmineReporters.endTime; - } - // otherwise, scrape the DOM for the HtmlReporter "finished in ..." output - var durElem = document.querySelector(".html-reporter .duration"); - if (!durElem) { - durElem = document.querySelector(".jasmine_html-reporter .duration"); - } - return durElem && durElem.textContent && durElem.textContent.toLowerCase().indexOf("finished in") === 0; - }); - }; - var getResultsFromHtmlRunner = function() { - return page.evaluate(function(){ - var resultElem = document.querySelector(".html-reporter .alert .bar"); - if (!resultElem) { - resultElem = document.querySelector(".jasmine_html-reporter .alert .bar"); - } - return resultElem && resultElem.textContent && - resultElem.textContent.match(/(\d+) spec.* (\d+) failure.*/) || - ["Unable to determine success or failure."]; - }); - }; - var timeout = 60000; - var loopInterval = 100; - var ival = setInterval(function(){ - if (isFinished()) { - // get the results that need to be written to disk - var fs = require("fs"), - xml_results = getXmlResults(page, resultsKey), - output; - for (var filename in xml_results) { - if (xml_results.hasOwnProperty(filename) && (output = xml_results[filename]) && typeof(output) === "string") { - fs.write(filename, output, "w"); - } - } - - // print out a success / failure message of the results - var results = getResultsFromHtmlRunner(); - var failures = Number(results[2]); - if (failures > 0) { - page.__exit_code = 1; - clearInterval(ival); - } - else { - page.__exit_code = 0; - clearInterval(ival); - } - } - else { - timeout -= loopInterval; - if (timeout <= 0) { - console.log('Page has timed out; aborting.'); - page.__exit_code = 2; - clearInterval(ival); - } - } - }, loopInterval); - } -} diff --git a/dashboard-ui/bower_components/fingerprintjs2/specs/phantomjs.runner.sh b/dashboard-ui/bower_components/fingerprintjs2/specs/phantomjs.runner.sh deleted file mode 100644 index 22b61d995..000000000 --- a/dashboard-ui/bower_components/fingerprintjs2/specs/phantomjs.runner.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -# sanity check to make sure phantomjs exists in the PATH -hash /usr/bin/env phantomjs &> /dev/null -if [ $? -eq 1 ]; then - echo "ERROR: phantomjs is not installed" - echo "Please visit http://www.phantomjs.org/" - exit 1 -fi - -# sanity check number of args -if [ $# -lt 1 ] -then - echo "Usage: `basename $0` path_to_runner.html" - echo - exit 1 -fi - -SCRIPTDIR=$(dirname `perl -e 'use Cwd "abs_path";print abs_path(shift)' $0`) -TESTFILE="" -while (( "$#" )); do - if [ ${1:0:7} == "http://" -o ${1:0:8} == "https://" ]; then - TESTFILE="$TESTFILE $1" - else - TESTFILE="$TESTFILE `perl -e 'use Cwd "abs_path";print abs_path(shift)' $1`" - fi - shift -done - -# cleanup previous test runs -cd $SCRIPTDIR -rm -f *.xml - -# make sure phantomjs submodule is initialized -cd .. -git submodule update --init - -# fire up the phantomjs environment and run the test -cd $SCRIPTDIR -/usr/bin/env phantomjs $SCRIPTDIR/phantomjs-testrunner.js $TESTFILE diff --git a/dashboard-ui/bower_components/fingerprintjs2/specs/spec_runner.html b/dashboard-ui/bower_components/fingerprintjs2/specs/spec_runner.html deleted file mode 100644 index 6125ec1e1..000000000 --- a/dashboard-ui/bower_components/fingerprintjs2/specs/spec_runner.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - Fingerprint2 spec runner - - - - - - - - - - - - - - - - - - - - - - diff --git a/dashboard-ui/bower_components/fingerprintjs2/specs/specs.js b/dashboard-ui/bower_components/fingerprintjs2/specs/specs.js deleted file mode 100644 index 9afa7a7f1..000000000 --- a/dashboard-ui/bower_components/fingerprintjs2/specs/specs.js +++ /dev/null @@ -1,189 +0,0 @@ -"use strict"; -describe("Fingerprint2", function () { - describe("new", function () { - it("creates a new instance of FP2", function () { - expect(new Fingerprint2()).not.toBeNull(); - }); - - it("accepts an empty options object", function () { - expect(new Fingerprint2({})).not.toBeNull(); - }); - - it("uses default options", function () { - var fp2 = new Fingerprint2(); - expect(fp2.options.swfContainerId).toEqual("fingerprintjs2"); - expect(fp2.options.swfPath).toEqual("flash/compiled/FontList.swf"); - }); - - it("allows to override default options", function () { - var fp2 = new Fingerprint2({swfPath: "newpath"}); - expect(fp2.options.swfContainerId).toEqual("fingerprintjs2"); - expect(fp2.options.swfPath).toEqual("newpath"); - }); - - it("allows to add new options", function () { - var fp2 = new Fingerprint2({excludeUserAgent: true}); - expect(fp2.options.swfContainerId).toEqual("fingerprintjs2"); - expect(fp2.options.swfPath).toEqual("flash/compiled/FontList.swf"); - expect(fp2.options.excludeUserAgent).toBe(true); - }); - - describe("sortPluginsFor", function () { - it("has default value", function (){ - var fp2 = new Fingerprint2(); - expect(fp2.options.sortPluginsFor).toEqual([/palemoon/i]); - }); - - it("allows to set new array of regexes", function () { - var fp2 = new Fingerprint2({sortPluginsFor: [/firefox/i, /chrome/i]}); - expect(fp2.options.sortPluginsFor).toEqual([/firefox/i, /chrome/i]); - }); - }); - }); - - describe("get", function () { - describe("default options", function () { - it("calculates fingerprint", function (done) { - var fp2 = new Fingerprint2(); - fp2.get(function(result){ - expect(result).toMatch(/^[0-9a-f]{32}$/i); - done(); - }); - }); - - it("does not try calling flash font detection", function (done) { - var fp2 = new Fingerprint2(); - spyOn(fp2, "flashFontsKey"); - fp2.get(function(result) { - expect(fp2.flashFontsKey).not.toHaveBeenCalled(); - done(); - }); - }); - }); - - describe("non-default options", function () { - it("does not use userAgent when excluded", function (done) { - var fp2 = new Fingerprint2({excludeUserAgent: true}); - spyOn(fp2, "getUserAgent"); - fp2.get(function(result) { - expect(fp2.getUserAgent).not.toHaveBeenCalled(); - done(); - }); - }); - - it("does not use pixelRatio when excluded", function (done) { - var fp2 = new Fingerprint2({excludePixelRatio: true}); - spyOn(fp2, "getPixelRatio"); - fp2.get(function(result) { - expect(fp2.getPixelRatio).not.toHaveBeenCalled(); - done(); - }); - }); - - it("does not use screen resolution when excluded", function (done) { - var fp2 = new Fingerprint2({excludeScreenResolution: true}); - spyOn(fp2, "getScreenResolution"); - fp2.get(function(result) { - expect(fp2.getScreenResolution).not.toHaveBeenCalled(); - done(); - }); - }); - - it("does not use available screen resolution when excluded", function (done) { - var fp2 = new Fingerprint2({excludeAvailableScreenResolution: true}); - spyOn(fp2, "getAvailableScreenResolution"); - fp2.get(function(result) { - expect(fp2.getAvailableScreenResolution).not.toHaveBeenCalled(); - done(); - }); - }); - - it("does not use plugins info when excluded", function (done) { - var fp2 = new Fingerprint2({excludePlugins: true}); - spyOn(fp2, "getRegularPlugins"); - fp2.get(function(result) { - expect(fp2.getRegularPlugins).not.toHaveBeenCalled(); - done(); - }); - }); - - it("does not use IE plugins info when excluded", function (done) { - var fp2 = new Fingerprint2({excludeIEPlugins: true}); - spyOn(fp2, "getIEPlugins"); - fp2.get(function(result) { - expect(fp2.getIEPlugins).not.toHaveBeenCalled(); - done(); - }); - }); - - }); - - describe("returns components", function () { - it("does it return components as a second argument to callback", function (done) { - var fp2 = new Fingerprint2(); - fp2.get(function(result, components) { - expect(components).not.toBeNull(); - done(); - }); - }); - - it("checks if returned components is array", function (done) { - var fp2 = new Fingerprint2(); - fp2.get(function(result, components) { - expect(components).toBeArrayOfObjects(); - done(); - }); - }); - - it("checks if js_fonts component is array", function (done) { - var fp2 = new Fingerprint2(); - fp2.get(function(result, components) { - for(var x = 0; x < components.length; x++) { - if(components[x].key == "js_fonts") { - expect(components[x].value).toBeArray(); - } - } - done(); - }); - }); - - it("returns user_agent as the first element", function (done) { - var fp2 = new Fingerprint2(); - fp2.get(function(result, components) { - expect(components[0].key).toEqual("user_agent"); - done(); - }); - }); - }); - - describe("baseFontArray iteration", function () { - it("only iterates specified items", function (done) { - var baseFonts = ["monospace", "sans-serif", "serif"]; - var ctr = 0; - for (var x in baseFonts) { - ctr++; - } - - expect(baseFonts.length).toEqual(3); - expect(ctr).toEqual(baseFonts.length); - - // Somewhere deep in your JavaScript library... - Array.prototype.foo = 1; - Array.prototype.bar = 2; - ctr = 0; - for (var x in baseFonts) { - console.log(x); - ctr++; - // Now foo & bar is a part of EVERY array and - // will show up here as a value of 'x'. - } - - expect(baseFonts.length).toEqual(3); - // sadface - expect(ctr).not.toEqual(baseFonts.length); - expect(ctr).toEqual(5); - done(); - }); - }); - }); -}); diff --git a/dashboard-ui/bower_components/hls.js/demo/benchmark.html b/dashboard-ui/bower_components/hls.js/demo/benchmark.html deleted file mode 100644 index 813ca1163..000000000 --- a/dashboard-ui/bower_components/hls.js/demo/benchmark.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - -

- - diff --git a/dashboard-ui/bower_components/hls.js/demo/canvas.js b/dashboard-ui/bower_components/hls.js/demo/canvas.js deleted file mode 100644 index ddf844030..000000000 --- a/dashboard-ui/bower_components/hls.js/demo/canvas.js +++ /dev/null @@ -1,574 +0,0 @@ - - var eventLeftMargin = 180; - var eventRightMargin = 0; - - function canvasLoadEventUpdate(canvas, minTime, maxTime, events) { - var ctx = canvas.getContext('2d'); - for (var i =0, y_offset = 20; i < events.length; i++) { - var event = events[i], start = event.time, end = event.time + event.duration + event.latency; - if((start >= minTime && start <= maxTime)) { - y_offset+=20; - } - } - canvas.height = y_offset; - - ctx.fillStyle = "green"; - ctx.globalAlpha = 0.5; - ctx.fillRect(0,0,eventLeftMargin, canvas.height); - ctx.fillRect(canvas.width-eventRightMargin,0,eventRightMargin, canvas.height); - ctx.globalAlpha = 1; - - //draw legend - var x_offset = 5; - ctx.font = "12px Arial"; - - legend = "load event"; - ctx.fillStyle = "black"; - ctx.fillText(legend,x_offset,15); - x_offset = eventLeftMargin+5; - - - legend = 'start - end'; - ctx.fillStyle = "black"; - ctx.fillText(legend,x_offset,15); - x_offset += ctx.measureText(legend).width+5; - - legend = '[latency'; - ctx.fillStyle = "orange"; - ctx.fillText(legend,x_offset,15); - x_offset += ctx.measureText(legend).width+5; - - legend = 'loading'; - ctx.fillStyle = "green"; - ctx.fillText(legend,x_offset,15); - x_offset += ctx.measureText(legend).width+5; - - legend = 'parsing'; - ctx.fillStyle = "blue"; - ctx.fillText(legend,x_offset,15); - x_offset += ctx.measureText(legend).width+5; - - legend = 'appending]'; - ctx.fillStyle = "red"; - ctx.fillText(legend,x_offset,15); - x_offset += ctx.measureText(legend).width+5; - - legend = 'size bitrate'; - ctx.fillStyle = "black"; - ctx.fillText(legend,x_offset,15); - x_offset += ctx.measureText(legend).width+5; - - for (i =0, y_offset = 20; i < events.length; i++) { - var event = events[i], start = Math.round(event.time), end = Math.round(event.time + event.duration + event.latency); - if((start >= minTime && start <= maxTime)) { - canvasDrawLoadEvent(ctx,y_offset,event,minTime,maxTime); - y_offset+=20; - } - } - } - - function canvasVideoEventUpdate(canvas, minTime, maxTime, events) { - var ctx = canvas.getContext('2d'); - for (var i =0, y_offset = 20; i < events.length; i++) { - var event = events[i], start = event.time, end = event.time; - if((start >= minTime && start <= maxTime)) { - y_offset+=20; - } - } - canvas.height = y_offset; - ctx.fillStyle = "green"; - ctx.globalAlpha = 0.5; - ctx.fillRect(0,0,eventLeftMargin, canvas.height); - ctx.fillRect(canvas.width-eventRightMargin,0,eventRightMargin, canvas.height); - ctx.globalAlpha = 1; - - //draw legend - var x_offset = 5; - ctx.font = "12px Arial"; - - legend = 'video event'; - ctx.fillStyle = "black"; - ctx.fillText(legend,x_offset,15); - - x_offset = eventLeftMargin+5; - legend = 'time'; - ctx.fillStyle = "black"; - ctx.fillText(legend,x_offset,15); - - x_offset += ctx.measureText(legend).width+5; - legend = '[duration]'; - ctx.fillStyle = "blue"; - ctx.fillText(legend,x_offset,15); - - for (i =0, y_offset = 20; i < events.length; i++) { - var event = events[i], start = Math.round(event.time), end = Math.round(event.time); - if((start >= minTime && start <= maxTime)) { - canvasDrawVideoEvent(ctx,y_offset,event,minTime,maxTime); - y_offset+=20; - } - } - } - - function canvasBufferWindowUpdate(canvas, minTime, maxTime, focusTime, events) { - var ctx = canvas.getContext('2d'), - minTimeBuffer, minTimePos,focusTimeBuffer,focusTimePos, - bufferChartStart = eventLeftMargin, - bufferChartWidth = ctx.canvas.width-eventLeftMargin-eventRightMargin; - ctx.clearRect (0,0,canvas.width, canvas.height); - - if(events.length === 0) { - return; - } - - ctx.fillStyle = "green"; - ctx.globalAlpha = 0.5; - ctx.fillRect(0,0,eventLeftMargin, canvas.height); - ctx.globalAlpha = 1; - - //draw legend - var x_offset = 5; - var y_offset = 0; - ctx.font = "15px Arial"; - - var maxBuffer = 0, firstEventIdx = -1, focusEventIdx= -1, event; - for (var i =0 ; i < events.length; i++) { - event = events[i]; - maxBuffer = Math.max(maxBuffer, event.buffer+event.pos); - if(firstEventIdx === -1 && event.time >= minTime) { - firstEventIdx = Math.max(0,i-1); - } - if(focusEventIdx === -1 && event.time >= focusTime) { - focusEventIdx = Math.max(0,i-1); - } - } - // compute position and buffer length at pos minTime using linear approximation - if((firstEventIdx+1) < events.length) { - minTimePos = events[firstEventIdx].pos + (minTime-events[firstEventIdx].time)*(events[firstEventIdx+1].pos-events[firstEventIdx].pos)/(events[firstEventIdx+1].time-events[firstEventIdx].time); - minTimeBuffer = minTimePos + events[firstEventIdx].buffer + (minTime-events[firstEventIdx].time)*(events[firstEventIdx+1].buffer-events[firstEventIdx].buffer)/(events[firstEventIdx+1].time-events[firstEventIdx].time); - } else { - minTimeBuffer = 0; - minTimePos = 0; - } - - // compute position and buffer length at pos focusTime using linear approximation - if((focusEventIdx+1) < events.length) { - focusTimePos = events[focusEventIdx].pos + (focusTime-events[focusEventIdx].time)*(events[focusEventIdx+1].pos-events[focusEventIdx].pos)/(events[focusEventIdx+1].time-events[focusEventIdx].time); - focusTimeBuffer = events[focusEventIdx].buffer + (focusTime-events[focusEventIdx].time)*(events[focusEventIdx+1].buffer-events[focusEventIdx].buffer)/(events[focusEventIdx+1].time-events[focusEventIdx].time); - } else { - focusTimePos = 0; - focusTimeBuffer = 0; - } - - maxBuffer*=1.1; - - y_offset += 15; - legend = 'play pos/buffer zoomed'; - ctx.fillStyle = "black"; - ctx.fillText(legend,x_offset,y_offset); - - y_offset += 15; - legend = '[' + minTime + ',' + maxTime + ']'; - ctx.fillText(legend,x_offset,y_offset); - - y_offset += 15; - legend = 'focus time:' + focusTime + ' ms'; - ctx.fillText(legend,x_offset,y_offset); - - y_offset += 15; - legend = 'focus position:' + Math.round(focusTimePos) + ' ms'; - ctx.fillText(legend,x_offset,y_offset); - - y_offset += 15; - legend = 'focus buffer:' + Math.round(focusTimeBuffer) + ' ms'; - ctx.fillText(legend,x_offset,y_offset); - - ctx.fillStyle = "blue"; - ctx.beginPath(); - ctx.moveTo(bufferChartStart, ctx.canvas.height); - ctx.lineTo(bufferChartStart, ctx.canvas.height*(1 - minTimeBuffer/maxBuffer)); - for (var i =firstEventIdx+1 ; i < events.length; i++) { - event = events[i]; - x_offset = bufferChartStart + (bufferChartWidth*(event.time-minTime))/(maxTime-minTime); - y_offset = ctx.canvas.height*(1 - (event.buffer+event.pos)/maxBuffer); - ctx.lineTo(x_offset,y_offset); - } - ctx.lineTo(x_offset, canvas.height); - ctx.fill(); - - ctx.fillStyle = "brown"; - ctx.beginPath(); - ctx.moveTo(bufferChartStart, ctx.canvas.height); - ctx.lineTo(bufferChartStart, ctx.canvas.height*(1 - minTimePos/maxBuffer)); - for (var i =firstEventIdx+1 ; i < events.length; i++) { - event = events[i]; - x_offset = bufferChartStart + (bufferChartWidth*(event.time-minTime))/(maxTime-minTime); - y_offset = ctx.canvas.height*(1 - (event.pos)/maxBuffer); - ctx.lineTo(x_offset,y_offset); - } - ctx.lineTo(x_offset, canvas.height); - ctx.fill(); - - ctx.fillStyle = "white"; - ctx.fillRect(canvas.width-eventRightMargin,0,eventRightMargin, canvas.height); - ctx.fillStyle = "green"; - ctx.globalAlpha = 0.5; - ctx.fillRect(canvas.width-eventRightMargin,0,eventRightMargin, canvas.height); - ctx.globalAlpha = 1; - - ctx.fillStyle = "black"; - x_offset = bufferChartStart + (bufferChartWidth*(focusTime-minTime))/(maxTime-minTime); - ctx.moveTo(x_offset, ctx.canvas.height); - y_offset = ctx.canvas.height*(1 - (focusTimePos+focusTimeBuffer)/maxBuffer); - ctx.lineTo(x_offset,y_offset); - ctx.stroke(); - } - - function canvasBufferTimeRangeUpdate(canvas, minTime, maxTime, windowMinTime, windowMaxTime, events) { - var ctx = canvas.getContext('2d'), - bufferChartStart = eventLeftMargin, - bufferChartWidth = ctx.canvas.width-eventLeftMargin-eventRightMargin, - x_offset = 0,y_offset = 0, - event; - ctx.clearRect (0,0,canvas.width, canvas.height); - - ctx.fillStyle = "green"; - ctx.globalAlpha = 0.5; - ctx.fillRect(0,0,eventLeftMargin, canvas.height); - ctx.fillRect(canvas.width-eventRightMargin,0,eventRightMargin, canvas.height); - ctx.globalAlpha = 1; - - x_offset = 5; - y_offset = 15; - legend = 'play pos/buffer'; - ctx.fillStyle = "black"; - ctx.font = "15px Arial"; - ctx.fillText(legend,x_offset,y_offset); - - if(events.length === 0) { - return; - } - - var maxBuffer = 0; - for (var i =0 ; i < events.length; i++) { - maxBuffer = Math.max(maxBuffer, events[i].buffer + events[i].pos); - } - - y_offset+=15; - legend = 'last pos:' + events[events.length-1].pos + ' ms'; - ctx.fillText(legend,x_offset,y_offset); - - y_offset+=15; - legend = 'last buffer:' + events[events.length-1].buffer + ' ms'; - ctx.fillText(legend,x_offset,y_offset); - - y_offset+=15; - legend = 'max buffer:' + maxBuffer + ' ms'; - ctx.fillText(legend,x_offset,y_offset); - - y_offset += 15; - legend = 'nb samples:' + events.length; - ctx.fillText(legend,x_offset,y_offset); - - maxBuffer*=1.1; - - ctx.fillStyle = "blue"; - ctx.beginPath(); - ctx.moveTo(bufferChartStart, ctx.canvas.height); - for (var i =0 ; i < events.length; i++) { - event = events[i]; - x_offset = bufferChartStart + (bufferChartWidth*(event.time-minTime))/(maxTime-minTime); - y_offset = ctx.canvas.height*(1 - (event.buffer+event.pos)/maxBuffer); - ctx.lineTo(x_offset,y_offset); - } - ctx.lineTo(x_offset, canvas.height); - ctx.fill(); - - ctx.fillStyle = "brown"; - ctx.beginPath(); - ctx.moveTo(bufferChartStart, ctx.canvas.height); - for (var i =0 ; i < events.length; i++) { - event = events[i]; - x_offset = bufferChartStart + (bufferChartWidth*(event.time-minTime))/(maxTime-minTime); - y_offset = ctx.canvas.height*(1 - event.pos/maxBuffer); - ctx.lineTo(x_offset,y_offset); - } - ctx.lineTo(x_offset, canvas.height); - ctx.fill(); - - ctx.globalAlpha = 0.7; - ctx.fillStyle = "grey"; - var x_start = bufferChartStart; - var x_w = bufferChartWidth*(windowMinTime-minTime)/(maxTime-minTime); - ctx.fillRect(x_start,0,x_w, canvas.height); - var x_start = bufferChartStart+bufferChartWidth*(windowMaxTime-minTime)/(maxTime-minTime); - var x_w = canvas.width-x_start-eventRightMargin; - ctx.fillRect(x_start,0,x_w, canvas.height); - ctx.globalAlpha = 1; - } - - function canvasBitrateEventUpdate(canvas, minTime, maxTime, windowMinTime, windowMaxTime, levelEvents, bitrateEvents) { - var ctx = canvas.getContext('2d'), - bufferChartStart = eventLeftMargin, - bufferChartWidth = ctx.canvas.width-eventLeftMargin-eventRightMargin, - x_offset = 0,y_offset = 0, - event, maxLevel, minLevel, sumLevel, maxBitrate, minBitrate, sumDuration; - ctx.clearRect (0,0,canvas.width, canvas.height); - - if(levelEvents.length === 0) { - return; - } - - maxBitrate = minBitrate = bitrateEvents[0].bitrate; - sumLevel = sumDuration = 0; - for (var i =0 ; i < bitrateEvents.length; i++) { - sumLevel += bitrateEvents[i].duration*bitrateEvents[i].level; - sumDuration += bitrateEvents[i].duration; - maxBitrate = Math.max(maxBitrate, bitrateEvents[i].bitrate); - minBitrate = Math.min(minBitrate, bitrateEvents[i].bitrate); - } - - maxLevel = minLevel = levelEvents[0].id; - for (var i =0 ; i < levelEvents.length; i++) { - maxLevel = Math.max(maxLevel, levelEvents[i].id); - minLevel = Math.min(minLevel, levelEvents[i].id); - } - - ctx.fillStyle = "green"; - ctx.globalAlpha = 0.5; - ctx.fillRect(0,0,eventLeftMargin, canvas.height); - ctx.fillRect(canvas.width-eventRightMargin,0,eventRightMargin, canvas.height); - ctx.globalAlpha = 1; - - x_offset = 5; - y_offset = 0; - ctx.fillStyle = "black"; - ctx.font = "15px Arial"; - - y_offset+=15; - legend = 'last bitrate:' + (bitrateEvents[bitrateEvents.length-1].bitrate/1000).toFixed(2) + "Mb/s"; - ctx.fillText(legend,x_offset,y_offset); - - y_offset+=15; - legend = 'min bitrate:' + (minBitrate/1000).toFixed(2) + "Mb/s"; - ctx.fillText(legend,x_offset,y_offset); - - y_offset+=15; - legend = 'max bitrate:' + (maxBitrate/1000).toFixed(2) + "Mb/s"; - ctx.fillText(legend,x_offset,y_offset); - - y_offset+=15; - legend = 'min/last/max level:' + minLevel + '/' + levelEvents[levelEvents.length-1].id + '/' + maxLevel; - ctx.fillText(legend,x_offset,y_offset); - - y_offset += 15; - legend = 'nb level switch:' + (levelEvents.length-1); - ctx.fillText(legend,x_offset,y_offset); - - y_offset += 15; - legend = 'average level:' + (sumLevel/sumDuration).toFixed(2); - ctx.fillText(legend,x_offset,y_offset); - - maxBitrate*=1.1; - - ctx.strokeStyle = "blue"; - ctx.beginPath(); - ctx.moveTo(bufferChartStart, ctx.canvas.height); - for (var i =0 ; i < bitrateEvents.length; i++) { - event = bitrateEvents[i]; - x_offset = bufferChartStart + (bufferChartWidth*(event.time-minTime))/(maxTime-minTime); - y_offset = ctx.canvas.height*(1 - event.bitrate/maxBitrate); - ctx.lineTo(x_offset,y_offset); - } - ctx.lineTo(bufferChartStart+bufferChartWidth, y_offset); - ctx.stroke(); - - ctx.strokeStyle = "black"; - ctx.beginPath(); - x_offset = bufferChartStart; - y_offset = ctx.canvas.height; - ctx.moveTo(x_offset, y_offset); - for (var i =0 ; i < levelEvents.length; i++) { - event = levelEvents[i]; - x_offset = bufferChartStart + (bufferChartWidth*(event.time-minTime))/(maxTime-minTime); - ctx.lineTo(x_offset,y_offset); - y_offset = ctx.canvas.height*(1 - event.bitrate/maxBitrate); - ctx.lineTo(x_offset,y_offset); - } - ctx.lineTo(bufferChartStart+bufferChartWidth, y_offset); - ctx.stroke(); - - ctx.globalAlpha = 0.7; - ctx.fillStyle = "grey"; - var x_start = bufferChartStart; - var x_w = bufferChartWidth*(windowMinTime-minTime)/(maxTime-minTime); - ctx.fillRect(x_start,0,x_w, canvas.height); - var x_start = bufferChartStart+bufferChartWidth*(windowMaxTime-minTime)/(maxTime-minTime); - var x_w = canvas.width-x_start-eventRightMargin; - ctx.fillRect(x_start,0,x_w, canvas.height); - ctx.globalAlpha = 1; - - } - - - function canvasDrawLoadEvent(ctx,yoffset,event,minTime,maxTime) { - var legend,offset,x_start,x_w, - networkChartStart = eventLeftMargin, - networkChartWidth = ctx.canvas.width-eventLeftMargin-eventRightMargin, - tend = Math.round(event.time + event.duration + event.latency); - - //draw start - ctx.fillStyle = "black"; - ctx.font = "12px Arial"; - legend = Math.round(event.time); - offset = ctx.measureText(legend).width+5; - x_start = networkChartStart-offset+networkChartWidth*(event.time-minTime)/(maxTime-minTime); - ctx.fillText(legend,x_start,yoffset+12); - - //draw latency rectangle - ctx.fillStyle = "orange"; - x_start = networkChartStart + networkChartWidth*(event.time-minTime)/(maxTime-minTime); - x_w = networkChartWidth*event.latency/(maxTime-minTime); - ctx.fillRect(x_start,yoffset,x_w, 15); - //draw download rectangle - ctx.fillStyle = "green"; - x_start = networkChartStart + networkChartWidth*(event.time+event.latency-minTime)/(maxTime-minTime); - x_w = networkChartWidth*event.load/(maxTime-minTime); - ctx.fillRect(x_start,yoffset,x_w, 15); - - if(event.parsing) { - //draw parsing rectangle - ctx.fillStyle = "blue"; - x_start = networkChartStart + networkChartWidth*(event.time+event.latency+event.load-minTime)/(maxTime-minTime); - x_w = networkChartWidth*event.parsing/(maxTime-minTime); - ctx.fillRect(x_start,yoffset,x_w, 15); - - if(event.buffer) { - //draw buffering rectangle - ctx.fillStyle = "red"; - x_start = networkChartStart + networkChartWidth*(event.time+event.latency+event.load+event.parsing-minTime)/(maxTime-minTime); - x_w = networkChartWidth*event.buffer/(maxTime-minTime); - ctx.fillRect(x_start,yoffset,x_w, 15); - } - } - - //draw end time - ctx.fillStyle = "black"; - ctx.font = "12px Arial"; - legend = tend; - x_start += x_w + 5; - ctx.fillText(legend,x_start,yoffset+12); - x_start += ctx.measureText(legend).width+5; - - legend = "[" + Math.round(event.latency); - ctx.fillStyle = "orange"; - ctx.fillText(legend,x_start,yoffset+12); - x_start += ctx.measureText(legend).width+5; - - legend = Math.round(event.load); - if(!event.parsing) legend += "]"; - ctx.fillStyle = "green"; - ctx.fillText(legend,x_start,yoffset+12); - x_start += ctx.measureText(legend).width+5; - - if(event.parsing) { - legend = Math.round(event.parsing); - if(!event.buffer) legend +="]"; - ctx.fillStyle = "blue"; - ctx.fillText(legend,x_start,yoffset+12); - x_start += ctx.measureText(legend).width+5; - - if(event.buffer) { - legend = Math.round(event.buffer) + "]"; - ctx.fillStyle = "red"; - ctx.fillText(legend,x_start,yoffset+12); - x_start += ctx.measureText(legend).width+5; - } - } - - if(event.size) { - if(event.size > 1000*1000) { - legend = (event.size/1000000).toFixed(1) + 'MB'; - } else { - legend = Math.round(event.size/1000) + 'kB'; - } - ctx.fillStyle = "black"; - ctx.fillText(legend,x_start,yoffset+12); - x_start += ctx.measureText(legend).width+5; - } - - if(event.bw) { - if(event.bw > 1000) { - legend = (event.bw/1000).toFixed(1) + 'Mbps'; - } else { - legend = event.bw + ' kbps'; - } - ctx.fillStyle = "black"; - ctx.fillText(legend,x_start,yoffset+12); - x_start += ctx.measureText(legend).width+5; - } - - // draw event name - ctx.fillStyle = "black"; - ctx.font = "15px Arial"; - legend = event.type; - if(event.id2 !== undefined) { - legend += ' ' + event.id2; - } - if(event.id !== undefined) { - if(event.type === 'fragment') { - legend += ' @'; - } - legend += ' ' + event.id; - } - if(event.start !== undefined) { - legend += ' [' + event.start + ',' + event.end + ']'; - } - ctx.fillText(legend,5,yoffset+15); - } - - function canvasDrawVideoEvent(ctx,yoffset,event,minTime,maxTime) { - var legend,offset,x_start,x_w, - networkChartStart = eventLeftMargin, - networkChartWidth = ctx.canvas.width-eventLeftMargin-eventRightMargin; - - // draw event name - ctx.fillStyle = "black"; - ctx.font = "15px Arial"; - legend = event.type; - if (event.name !== undefined) legend+= ':' + event.name; - ctx.fillText(legend,5,yoffset+15); - - - //draw start time - ctx.fillStyle = "black"; - ctx.font = "12px Arial"; - legend = Math.round(event.time); - offset = ctx.measureText(legend).width+5; - x_start = networkChartStart-offset+networkChartWidth*(event.time-minTime)/(maxTime-minTime); - ctx.fillText(legend,x_start,yoffset+12); - - - //draw event rectangle - x_start = networkChartStart + networkChartWidth*(event.time-minTime)/(maxTime-minTime); - if(event.duration) { - x_w = networkChartWidth*event.duration/(maxTime-minTime); - } else { - x_w = 1; - } - ctx.fillRect(x_start,yoffset,x_w, 15); - - if(event.duration) { - - //draw end time - ctx.fillStyle = "black"; - ctx.font = "12px Arial"; - legend = Math.round(event.time+event.duration); - x_start += x_w + 5; - ctx.fillText(legend,x_start,yoffset+12); - x_start += ctx.measureText(legend).width+5; - - legend = "[" + Math.round(event.duration) + "]"; - ctx.fillStyle = "blue"; - ctx.fillText(legend,x_start,yoffset+12); - } - } diff --git a/dashboard-ui/bower_components/hls.js/demo/index.html b/dashboard-ui/bower_components/hls.js/demo/index.html deleted file mode 100644 index d0132fc1c..000000000 --- a/dashboard-ui/bower_components/hls.js/demo/index.html +++ /dev/null @@ -1,973 +0,0 @@ - - - - - hls.js demo - - - - - - - - - -
-
-

hls.js demo page

-
-
- -
-
-

- test with your HLS streams below in Chrome, Firefox, IE11 or Safari ! -
Advanced controls are also available at the bottom of this page. -

-
-
-
- - - - - - - - -
- - - -
-
- - -
-

-

-
-    
- - - - -
- -
-

Playback Control

- - - - - -

- -
- - -
-
- -
-

Quality Control

- - - - - - - - - - - - - - - - - - - - - -
current level

next level

load level

cap level

-
- -
-

Real Time Metrics Display

-
-
-
- - - - - - - -
- -
- -
-
-
- - - -
-
- - - - - - - -
-
-
- -
-

Stats Display

-

-      
-
-
-

- - - - - - - - - - - - diff --git a/dashboard-ui/bower_components/hls.js/demo/jsonpack.js b/dashboard-ui/bower_components/hls.js/demo/jsonpack.js deleted file mode 100644 index b0baeefb8..000000000 --- a/dashboard-ui/bower_components/hls.js/demo/jsonpack.js +++ /dev/null @@ -1,578 +0,0 @@ -/* - Copyright (c) 2013, Rodrigo González, Sapienlab All Rights Reserved. - Available via MIT LICENSE. See https://github.com/roro89/jsonpack/blob/master/LICENSE.md for details. - */ -(function(define) { - - define([], function() { - - var TOKEN_TRUE = -1; - var TOKEN_FALSE = -2; - var TOKEN_NULL = -3; - var TOKEN_EMPTY_STRING = -4; - var TOKEN_UNDEFINED = -5; - - var pack = function(json, options) { - - // Canonizes the options - options = options || {}; - - // A shorthand for debugging - var verbose = options.verbose || false; - - verbose && console.log('Normalize the JSON Object'); - - // JSON as Javascript Object (Not string representation) - json = typeof json === 'string' ? this.JSON.parse(json) : json; - - verbose && console.log('Creating a empty dictionary'); - - // The dictionary - var dictionary = { - strings : [], - integers : [], - floats : [] - }; - - verbose && console.log('Creating the AST'); - - // The AST - var ast = (function recursiveAstBuilder(item) { - - verbose && console.log('Calling recursiveAstBuilder with ' + this.JSON.stringify(item)); - - // The type of the item - var type = typeof item; - - // Case 7: The item is null - if (item === null) { - return { - type : 'null', - index : TOKEN_NULL - }; - } - - //add undefined - if (typeof item === 'undefined') { - return { - type : 'undefined', - index : TOKEN_UNDEFINED - }; - } - - // Case 1: The item is Array Object - if ( item instanceof Array) { - - // Create a new sub-AST of type Array (@) - var ast = ['@']; - - // Add each items - for (var i in item) { - - if (!item.hasOwnProperty(i)) continue; - - ast.push(recursiveAstBuilder(item[i])); - } - - // And return - return ast; - - } - - // Case 2: The item is Object - if (type === 'object') { - - // Create a new sub-AST of type Object ($) - var ast = ['$']; - - // Add each items - for (var key in item) { - - if (!item.hasOwnProperty(key)) - continue; - - ast.push(recursiveAstBuilder(key)); - ast.push(recursiveAstBuilder(item[key])); - } - - // And return - return ast; - - } - - // Case 3: The item empty string - if (item === '') { - return { - type : 'empty', - index : TOKEN_EMPTY_STRING - }; - } - - // Case 4: The item is String - if (type === 'string') { - - // The index of that word in the dictionary - var index = _indexOf.call(dictionary.strings, item); - - // If not, add to the dictionary and actualize the index - if (index == -1) { - dictionary.strings.push(_encode(item)); - index = dictionary.strings.length - 1; - } - - // Return the token - return { - type : 'strings', - index : index - }; - } - - // Case 5: The item is integer - if (type === 'number' && item % 1 === 0) { - - // The index of that number in the dictionary - var index = _indexOf.call(dictionary.integers, item); - - // If not, add to the dictionary and actualize the index - if (index == -1) { - dictionary.integers.push(_base10To36(item)); - index = dictionary.integers.length - 1; - } - - // Return the token - return { - type : 'integers', - index : index - }; - } - - // Case 6: The item is float - if (type === 'number') { - // The index of that number in the dictionary - var index = _indexOf.call(dictionary.floats, item); - - // If not, add to the dictionary and actualize the index - if (index == -1) { - // Float not use base 36 - dictionary.floats.push(item); - index = dictionary.floats.length - 1; - } - - // Return the token - return { - type : 'floats', - index : index - }; - } - - // Case 7: The item is boolean - if (type === 'boolean') { - return { - type : 'boolean', - index : item ? TOKEN_TRUE : TOKEN_FALSE - }; - } - - // Default - throw new Error('Unexpected argument of type ' + typeof (item)); - - })(json); - - // A set of shorthands proxies for the length of the dictionaries - var stringLength = dictionary.strings.length; - var integerLength = dictionary.integers.length; - var floatLength = dictionary.floats.length; - - verbose && console.log('Parsing the dictionary'); - - // Create a raw dictionary - var packed = dictionary.strings.join('|'); - packed += '^' + dictionary.integers.join('|'); - packed += '^' + dictionary.floats.join('|'); - - verbose && console.log('Parsing the structure'); - - // And add the structure - packed += '^' + (function recursiveParser(item) { - - verbose && console.log('Calling a recursiveParser with ' + this.JSON.stringify(item)); - - // If the item is Array, then is a object of - // type [object Object] or [object Array] - if ( item instanceof Array) { - - // The packed resulting - var packed = item.shift(); - - for (var i in item) { - - if (!item.hasOwnProperty(i)) - continue; - - packed += recursiveParser(item[i]) + '|'; - } - - return (packed[packed.length - 1] === '|' ? packed.slice(0, -1) : packed) + ']'; - - } - - // A shorthand proxies - var type = item.type, index = item.index; - - if (type === 'strings') { - // Just return the base 36 of index - return _base10To36(index); - } - - if (type === 'integers') { - // Return a base 36 of index plus stringLength offset - return _base10To36(stringLength + index); - } - - if (type === 'floats') { - // Return a base 36 of index plus stringLength and integerLength offset - return _base10To36(stringLength + integerLength + index); - } - - if (type === 'boolean') { - return item.index; - } - - if (type === 'null') { - return TOKEN_NULL; - } - - if (type === 'undefined') { - return TOKEN_UNDEFINED; - } - - if (type === 'empty') { - return TOKEN_EMPTY_STRING; - } - - throw new TypeError('The item is alien!'); - - })(ast); - - verbose && console.log('Ending parser'); - - // If debug, return a internal representation of dictionary and stuff - if (options.debug) - return { - dictionary : dictionary, - ast : ast, - packed : packed - }; - - return packed; - - }; - - var unpack = function(packed, options) { - - // Canonizes the options - options = options || {}; - - // A raw buffer - var rawBuffers = packed.split('^'); - - // Create a dictionary - options.verbose && console.log('Building dictionary'); - var dictionary = []; - - // Add the strings values - var buffer = rawBuffers[0]; - if (buffer !== '') { - buffer = buffer.split('|'); - options.verbose && console.log('Parse the strings dictionary'); - for (var i=0, n=buffer.length; i - - - hls.js metrics page - - - - - - - - -
-
-

hls.js metrics page

-
-
-

-  
-  
-    window size
-    
- - - - - - - -
- -
- -
- - - -
- - - - -
-
- - - - - - - diff --git a/dashboard-ui/bower_components/hls.js/demo/metrics.js b/dashboard-ui/bower_components/hls.js/demo/metrics.js deleted file mode 100644 index 7e6fc83d8..000000000 --- a/dashboard-ui/bower_components/hls.js/demo/metrics.js +++ /dev/null @@ -1,201 +0,0 @@ - function showMetrics() { - if(metricsDisplayed) { - var width = window.innerWidth-30; - $("#bufferWindow_c")[0].width = - $("#bitrateTimerange_c")[0].width = - $("#bufferTimerange_c")[0].width = - $("#videoEvent_c")[0].width = - $("#metricsButton")[0].width = - $("#loadEvent_c")[0].width = width; - $("#bufferWindow_c").show(); - $("#bitrateTimerange_c").show(); - $("#bufferTimerange_c").show(); - $("#videoEvent_c").show(); - $("#metricsButton").show(); - $("#loadEvent_c").show(); - } - } - - - function toggleMetricsDisplay() { - metricsDisplayed = !metricsDisplayed; - if(metricsDisplayed) { - showMetrics(); - } else { - hideMetrics(); - } - } - - function hideMetrics() { - if(!metricsDisplayed) { - $("#bufferWindow_c").hide(); - $("#bitrateTimerange_c").hide(); - $("#bufferTimerange_c").hide(); - $("#videoEvent_c").hide(); - $("#metricsButton").hide(); - $("#loadEvent_c").hide(); - } - } - - function timeRangeSetSliding(duration) { - windowDuration = duration; - windowSliding = true; - refreshCanvas(); - } - -var timeRangeMouseDown=false; - function timeRangeCanvasonMouseDown(evt) { - var canvas = evt.currentTarget, - bRect = canvas.getBoundingClientRect(), - mouseX = Math.round((evt.clientX - bRect.left)*(canvas.width/bRect.width)); - windowStart = Math.max(0,Math.round((mouseX-eventLeftMargin) * getWindowTimeRange().now / (canvas.width-eventLeftMargin))); - windowEnd = windowStart+500; - timeRangeMouseDown = true; - windowSliding = false; - //console.log('windowStart/windowEnd:' + '/' + windowStart + '/' + windowEnd); - $("#windowStart").val(windowStart); - $("#windowEnd").val(windowEnd); - refreshCanvas(); - } - - function timeRangeCanvasonMouseMove(evt) { - if(timeRangeMouseDown) { - var canvas = evt.currentTarget, - bRect = canvas.getBoundingClientRect(), - mouseX = Math.round((evt.clientX - bRect.left)*(canvas.width/bRect.width)), - pos = Math.max(0,Math.round((mouseX-eventLeftMargin) * getWindowTimeRange().now / (canvas.width-eventLeftMargin))); - if(pos < windowStart) { - windowStart = pos; - } else { - windowEnd = pos; - } - if(windowStart === windowEnd) { - // to avoid division by zero ... - windowEnd +=50; - } - //console.log('windowStart/windowEnd:' + '/' + windowStart + '/' + windowEnd); - $("#windowStart").val(windowStart); - $("#windowEnd").val(windowEnd); - refreshCanvas(); - } - } - - function timeRangeCanvasonMouseUp(evt) { - timeRangeMouseDown = false; - } - - function timeRangeCanvasonMouseOut(evt) { - timeRangeMouseDown = false; - } - - function windowCanvasonMouseMove(evt) { - var canvas = evt.currentTarget, - bRect = canvas.getBoundingClientRect(), - mouseX = Math.round((evt.clientX - bRect.left)*(canvas.width/bRect.width)), - timeRange = getWindowTimeRange(); - windowFocus = timeRange.min + Math.max(0,Math.round((mouseX-eventLeftMargin) * (timeRange.max - timeRange.min) / (canvas.width-eventLeftMargin))); - //console.log(windowFocus); - refreshCanvas(); - } - -var windowDuration=20000,windowSliding=true,windowStart=0,windowEnd=10000,windowFocus,metricsDisplayed=false; -$("#windowStart").val(windowStart); -$("#windowEnd").val(windowEnd); - function refreshCanvas() { - if(metricsDisplayed) { - try { - var windowTime = getWindowTimeRange(); - canvasBufferTimeRangeUpdate($("#bufferTimerange_c")[0], 0, windowTime.now, windowTime.min,windowTime.max, events.buffer); - if(windowTime.min !== 0 || windowTime.max !== windowTime.now) { - $("#bufferWindow_c").show(); - canvasBufferWindowUpdate($("#bufferWindow_c")[0], windowTime.min,windowTime.max, windowTime.focus, events.buffer); - } else { - $("#bufferWindow_c").hide(); - } - canvasBitrateEventUpdate($("#bitrateTimerange_c")[0], 0, windowTime.now, windowTime.min,windowTime.max, events.level, events.bitrate); - canvasVideoEventUpdate($("#videoEvent_c")[0], windowTime.min,windowTime.max, events.video); - canvasLoadEventUpdate($("#loadEvent_c")[0], windowTime.min,windowTime.max, events.load); - } catch(err) { - console.log("refreshCanvas error:" +err.message); - } - } - } - - function getWindowTimeRange() { - var tnow,minTime,maxTime; - if(events.buffer.length) { - tnow = events.buffer[events.buffer.length-1].time; - } else { - tnow = 0; - } - if(windowSliding) { - // let's show the requested window - if(windowDuration) { - minTime = Math.max(0, tnow-windowDuration), - maxTime = Math.min(minTime + windowDuration, tnow); - } else { - minTime = 0; - maxTime = tnow; - } - } else { - minTime = windowStart; - maxTime = windowEnd; - } - if(windowFocus === undefined || windowFocus < minTime || windowFocus > maxTime) { - windowFocus = minTime; - } - return { min : minTime, max: maxTime, now : tnow, focus : windowFocus} - } - -function timeRangeZoomIn() { - if(windowSliding) { - windowDuration/=2; - } else { - var duration = windowEnd-windowStart; - windowStart+=duration/4; - windowEnd-=duration/4; - if(windowStart === windowEnd) { - windowEnd+=50; - } - } - $("#windowStart").val(windowStart); - $("#windowEnd").val(windowEnd); - refreshCanvas(); -} - -function timeRangeZoomOut() { - if(windowSliding) { - windowDuration*=2; - } else { - var duration = windowEnd-windowStart; - windowStart-=duration/2; - windowEnd+=duration/2; - windowStart=Math.max(0,windowStart); - windowEnd=Math.min(events.buffer[events.buffer.length-1].time,windowEnd); - } - $("#windowStart").val(windowStart); - $("#windowEnd").val(windowEnd); - refreshCanvas(); -} - -function timeRangeSlideLeft() { - var duration = windowEnd-windowStart; - windowStart-=duration/4; - windowEnd-=duration/4; - windowStart=Math.max(0,windowStart); - windowEnd=Math.min(events.buffer[events.buffer.length-1].time,windowEnd); - $("#windowStart").val(windowStart); - $("#windowEnd").val(windowEnd); - refreshCanvas(); -} - -function timeRangeSlideRight() { - var duration = windowEnd-windowStart; - windowStart+=duration/4; - windowEnd+=duration/4; - windowStart=Math.max(0,windowStart); - windowEnd=Math.min(events.buffer[events.buffer.length-1].time,windowEnd); - $("#windowStart").val(windowStart); - $("#windowEnd").val(windowEnd); - refreshCanvas(); -} diff --git a/dashboard-ui/bower_components/hls.js/dist/hls.js b/dashboard-ui/bower_components/hls.js/dist/hls.js deleted file mode 100644 index c076cbf44..000000000 --- a/dashboard-ui/bower_components/hls.js/dist/hls.js +++ /dev/null @@ -1,8992 +0,0 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Hls = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; - - list = this._events[type]; - length = list.length; - position = -1; - - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); - - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } - - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; - - if (!this._events) - return this; - - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else if (listeners) { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; - -EventEmitter.prototype.listenerCount = function(type) { - if (this._events) { - var evlistener = this._events[type]; - - if (isFunction(evlistener)) - return 1; - else if (evlistener) - return evlistener.length; - } - return 0; -}; - -EventEmitter.listenerCount = function(emitter, type) { - return emitter.listenerCount(type); -}; - -function isFunction(arg) { - return typeof arg === 'function'; -} - -function isNumber(arg) { - return typeof arg === 'number'; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isUndefined(arg) { - return arg === void 0; -} - -},{}],2:[function(require,module,exports){ -var bundleFn = arguments[3]; -var sources = arguments[4]; -var cache = arguments[5]; - -var stringify = JSON.stringify; - -module.exports = function (fn) { - var keys = []; - var wkey; - var cacheKeys = Object.keys(cache); - - for (var i = 0, l = cacheKeys.length; i < l; i++) { - var key = cacheKeys[i]; - var exp = cache[key].exports; - // Using babel as a transpiler to use esmodule, the export will always - // be an object with the default export as a property of it. To ensure - // the existing api and babel esmodule exports are both supported we - // check for both - if (exp === fn || exp.default === fn) { - wkey = key; - break; - } - } - - if (!wkey) { - wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); - var wcache = {}; - for (var i = 0, l = cacheKeys.length; i < l; i++) { - var key = cacheKeys[i]; - wcache[key] = key; - } - sources[wkey] = [ - Function(['require','module','exports'], '(' + fn + ')(self)'), - wcache - ]; - } - var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16); - - var scache = {}; scache[wkey] = wkey; - sources[skey] = [ - Function(['require'], ( - // try to call default if defined to also support babel esmodule - // exports - 'var f = require(' + stringify(wkey) + ');' + - '(f.default ? f.default : f)(self);' - )), - scache - ]; - - var src = '(' + bundleFn + ')({' - + Object.keys(sources).map(function (key) { - return stringify(key) + ':[' - + sources[key][0] - + ',' + stringify(sources[key][1]) + ']' - ; - }).join(',') - + '},{},[' + stringify(skey) + '])' - ; - - var URL = window.URL || window.webkitURL || window.mozURL || window.msURL; - - return new Worker(URL.createObjectURL( - new Blob([src], { type: 'text/javascript' }) - )); -}; - -},{}],3:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -var _eventHandler = require('../event-handler'); - -var _eventHandler2 = _interopRequireDefault(_eventHandler); - -var _bufferHelper = require('../helper/buffer-helper'); - -var _bufferHelper2 = _interopRequireDefault(_bufferHelper); - -var _errors = require('../errors'); - -var _logger = require('../utils/logger'); - -var _ewmaBandwidthEstimator = require('./ewma-bandwidth-estimator'); - -var _ewmaBandwidthEstimator2 = _interopRequireDefault(_ewmaBandwidthEstimator); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* - * simple ABR Controller - * - compute next level based on last fragment bw heuristics - * - implement an abandon rules triggered if we have less than 2 frag buffered and if computed bw shows that we risk buffer stalling - */ - -var AbrController = function (_EventHandler) { - _inherits(AbrController, _EventHandler); - - function AbrController(hls) { - _classCallCheck(this, AbrController); - - var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(AbrController).call(this, hls, _events2.default.FRAG_LOADING, _events2.default.FRAG_LOADED, _events2.default.ERROR)); - - _this.lastLoadedFragLevel = 0; - _this._autoLevelCapping = -1; - _this._nextAutoLevel = -1; - _this.hls = hls; - _this.onCheck = _this.abandonRulesCheck.bind(_this); - return _this; - } - - _createClass(AbrController, [{ - key: 'destroy', - value: function destroy() { - this.clearTimer(); - _eventHandler2.default.prototype.destroy.call(this); - } - }, { - key: 'onFragLoading', - value: function onFragLoading(data) { - if (!this.timer) { - this.timer = setInterval(this.onCheck, 100); - } - - // lazy init of bw Estimator, rationale is that we use different params for Live/VoD - // so we need to wait for stream manifest / playlist type to instantiate it. - if (!this.bwEstimator) { - var hls = this.hls, - level = data.frag.level, - isLive = hls.levels[level].details.live, - config = hls.config, - ewmaFast = void 0, - ewmaSlow = void 0; - - if (isLive) { - ewmaFast = config.abrEwmaFastLive; - ewmaSlow = config.abrEwmaSlowLive; - } else { - ewmaFast = config.abrEwmaFastVoD; - ewmaSlow = config.abrEwmaSlowVoD; - } - this.bwEstimator = new _ewmaBandwidthEstimator2.default(hls, ewmaSlow, ewmaFast, config.abrEwmaDefaultEstimate); - } - - var frag = data.frag; - frag.trequest = performance.now(); - this.fragCurrent = frag; - } - }, { - key: 'abandonRulesCheck', - value: function abandonRulesCheck() { - /* - monitor fragment retrieval time... - we compute expected time of arrival of the complete fragment. - we compare it to expected time of buffer starvation - */ - var hls = this.hls, - v = hls.media, - frag = this.fragCurrent; - - // if loader has been destroyed or loading has been aborted, stop timer and return - if (!frag.loader || frag.loader.stats && frag.loader.stats.aborted) { - _logger.logger.warn('frag loader destroy or aborted, disarm abandonRulesCheck'); - this.clearTimer(); - return; - } - /* only monitor frag retrieval time if - (video not paused OR first fragment being loaded(ready state === HAVE_NOTHING = 0)) AND autoswitching enabled AND not lowest level (=> means that we have several levels) */ - if (v && (!v.paused || !v.readyState) && frag.autoLevel && frag.level) { - var requestDelay = performance.now() - frag.trequest; - // monitor fragment load progress after half of expected fragment duration,to stabilize bitrate - if (requestDelay > 500 * frag.duration) { - var levels = hls.levels, - loadRate = Math.max(1, frag.loaded * 1000 / requestDelay), - // byte/s; at least 1 byte/s to avoid division by zero - // compute expected fragment length using frag duration and level bitrate. also ensure that expected len is gte than already loaded size - expectedLen = Math.max(frag.loaded, Math.round(frag.duration * levels[frag.level].bitrate / 8)); - - var pos = v.currentTime; - var fragLoadedDelay = (expectedLen - frag.loaded) / loadRate; - var bufferStarvationDelay = _bufferHelper2.default.bufferInfo(v, pos, hls.config.maxBufferHole).end - pos; - // consider emergency switch down only if we have less than 2 frag buffered AND - // time to finish loading current fragment is bigger than buffer starvation delay - // ie if we risk buffer starvation if bw does not increase quickly - if (bufferStarvationDelay < 2 * frag.duration && fragLoadedDelay > bufferStarvationDelay) { - var fragLevelNextLoadedDelay = void 0, - nextLoadLevel = void 0; - // lets iterate through lower level and try to find the biggest one that could avoid rebuffering - // we start from current level - 1 and we step down , until we find a matching level - for (nextLoadLevel = frag.level - 1; nextLoadLevel >= 0; nextLoadLevel--) { - // compute time to load next fragment at lower level - // 0.8 : consider only 80% of current bw to be conservative - // 8 = bits per byte (bps/Bps) - fragLevelNextLoadedDelay = frag.duration * levels[nextLoadLevel].bitrate / (8 * 0.8 * loadRate); - _logger.logger.log('fragLoadedDelay/bufferStarvationDelay/fragLevelNextLoadedDelay[' + nextLoadLevel + '] :' + fragLoadedDelay.toFixed(1) + '/' + bufferStarvationDelay.toFixed(1) + '/' + fragLevelNextLoadedDelay.toFixed(1)); - if (fragLevelNextLoadedDelay < bufferStarvationDelay) { - // we found a lower level that be rebuffering free with current estimated bw ! - break; - } - } - // only emergency switch down if it takes less time to load new fragment at lowest level instead - // of finishing loading current one ... - if (fragLevelNextLoadedDelay < fragLoadedDelay) { - // ensure nextLoadLevel is not negative - nextLoadLevel = Math.max(0, nextLoadLevel); - // force next load level in auto mode - hls.nextLoadLevel = nextLoadLevel; - // update bw estimate for this fragment before cancelling load (this will help reducing the bw) - this.bwEstimator.sample(requestDelay, frag.loaded); - // abort fragment loading ... - _logger.logger.warn('loading too slow, abort fragment loading and switch to level ' + nextLoadLevel); - //abort fragment loading - frag.loader.abort(); - this.clearTimer(); - hls.trigger(_events2.default.FRAG_LOAD_EMERGENCY_ABORTED, { frag: frag }); - } - } - } - } - } - }, { - key: 'onFragLoaded', - value: function onFragLoaded(data) { - var stats = data.stats; - // only update stats on first frag loading - // if same frag is loaded multiple times, it might be in browser cache, and loaded quickly - // and leading to wrong bw estimation - if (stats.aborted === undefined && data.frag.loadCounter === 1) { - this.bwEstimator.sample(performance.now() - stats.trequest, stats.loaded); - } - - // stop monitoring bw once frag loaded - this.clearTimer(); - // store level id after successful fragment load - this.lastLoadedFragLevel = data.frag.level; - // reset forced auto level value so that next level will be selected - this._nextAutoLevel = -1; - } - }, { - key: 'onError', - value: function onError(data) { - // stop timer in case of frag loading error - switch (data.details) { - case _errors.ErrorDetails.FRAG_LOAD_ERROR: - case _errors.ErrorDetails.FRAG_LOAD_TIMEOUT: - this.clearTimer(); - break; - default: - break; - } - } - }, { - key: 'clearTimer', - value: function clearTimer() { - if (this.timer) { - clearInterval(this.timer); - this.timer = null; - } - } - - /** Return the capping/max level value that could be used by automatic level selection algorithm **/ - - }, { - key: 'autoLevelCapping', - get: function get() { - return this._autoLevelCapping; - } - - /** set the capping/max level value that could be used by automatic level selection algorithm **/ - , - set: function set(newLevel) { - this._autoLevelCapping = newLevel; - } - }, { - key: 'nextAutoLevel', - get: function get() { - var hls = this.hls, - i, - maxAutoLevel, - levels = hls.levels, - config = hls.config; - if (this._autoLevelCapping === -1 && levels && levels.length) { - maxAutoLevel = levels.length - 1; - } else { - maxAutoLevel = this._autoLevelCapping; - } - - // in case next auto level has been forced, return it straight-away (but capped) - if (this._nextAutoLevel !== -1) { - return Math.min(this._nextAutoLevel, maxAutoLevel); - } - - var avgbw = this.bwEstimator ? this.bwEstimator.getEstimate() : config.abrEwmaDefaultEstimate, - adjustedbw = void 0; - // follow algorithm captured from stagefright : - // https://android.googlesource.com/platform/frameworks/av/+/master/media/libstagefright/httplive/LiveSession.cpp - // Pick the highest bandwidth stream below or equal to estimated bandwidth. - for (i = 0; i <= maxAutoLevel; i++) { - // consider only 80% of the available bandwidth, but if we are switching up, - // be even more conservative (70%) to avoid overestimating and immediately - // switching back. - if (i <= this.lastLoadedFragLevel) { - adjustedbw = config.abrBandWidthFactor * avgbw; - } else { - adjustedbw = config.abrBandWidthUpFactor * avgbw; - } - if (adjustedbw < levels[i].bitrate) { - return Math.max(0, i - 1); - } - } - return i - 1; - }, - set: function set(nextLevel) { - this._nextAutoLevel = nextLevel; - } - }]); - - return AbrController; -}(_eventHandler2.default); - -exports.default = AbrController; - -},{"../errors":21,"../event-handler":22,"../events":23,"../helper/buffer-helper":24,"../utils/logger":38,"./ewma-bandwidth-estimator":6}],4:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -var _eventHandler = require('../event-handler'); - -var _eventHandler2 = _interopRequireDefault(_eventHandler); - -var _logger = require('../utils/logger'); - -var _errors = require('../errors'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* - * Buffer Controller - */ - -var BufferController = function (_EventHandler) { - _inherits(BufferController, _EventHandler); - - function BufferController(hls) { - _classCallCheck(this, BufferController); - - // the value that we have set mediasource.duration to - // (the actual duration may be tweaked slighly by the browser) - - var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(BufferController).call(this, hls, _events2.default.MEDIA_ATTACHING, _events2.default.MEDIA_DETACHING, _events2.default.BUFFER_RESET, _events2.default.BUFFER_APPENDING, _events2.default.BUFFER_CODECS, _events2.default.BUFFER_EOS, _events2.default.BUFFER_FLUSHING, _events2.default.LEVEL_UPDATED)); - - _this._msDuration = null; - // the value that we want to set mediaSource.duration to - _this._levelDuration = null; - - // Source Buffer listeners - _this.onsbue = _this.onSBUpdateEnd.bind(_this); - _this.onsbe = _this.onSBUpdateError.bind(_this); - return _this; - } - - _createClass(BufferController, [{ - key: 'destroy', - value: function destroy() { - _eventHandler2.default.prototype.destroy.call(this); - } - }, { - key: 'onMediaAttaching', - value: function onMediaAttaching(data) { - var media = this.media = data.media; - if (media) { - // setup the media source - var ms = this.mediaSource = new MediaSource(); - //Media Source listeners - this.onmso = this.onMediaSourceOpen.bind(this); - this.onmse = this.onMediaSourceEnded.bind(this); - this.onmsc = this.onMediaSourceClose.bind(this); - ms.addEventListener('sourceopen', this.onmso); - ms.addEventListener('sourceended', this.onmse); - ms.addEventListener('sourceclose', this.onmsc); - // link video and media Source - media.src = URL.createObjectURL(ms); - } - } - }, { - key: 'onMediaDetaching', - value: function onMediaDetaching() { - var ms = this.mediaSource; - if (ms) { - if (ms.readyState === 'open') { - try { - // endOfStream could trigger exception if any sourcebuffer is in updating state - // we don't really care about checking sourcebuffer state here, - // as we are anyway detaching the MediaSource - // let's just avoid this exception to propagate - ms.endOfStream(); - } catch (err) { - _logger.logger.warn('onMediaDetaching:' + err.message + ' while calling endOfStream'); - } - } - ms.removeEventListener('sourceopen', this.onmso); - ms.removeEventListener('sourceended', this.onmse); - ms.removeEventListener('sourceclose', this.onmsc); - - try { - // unlink MediaSource from video tag - this.media.src = ''; - this.media.removeAttribute('src'); - } catch (err) { - _logger.logger.warn('onMediaDetaching:' + err.message + ' while unlinking video.src'); - } - this.mediaSource = null; - this.media = null; - this.pendingTracks = null; - this.sourceBuffer = null; - } - this.onmso = this.onmse = this.onmsc = null; - this.hls.trigger(_events2.default.MEDIA_DETACHED); - } - }, { - key: 'onMediaSourceOpen', - value: function onMediaSourceOpen() { - _logger.logger.log('media source opened'); - this.hls.trigger(_events2.default.MEDIA_ATTACHED, { media: this.media }); - // once received, don't listen anymore to sourceopen event - this.mediaSource.removeEventListener('sourceopen', this.onmso); - // if any buffer codecs pending, treat it here. - var pendingTracks = this.pendingTracks; - if (pendingTracks) { - this.onBufferCodecs(pendingTracks); - this.pendingTracks = null; - this.doAppending(); - } - } - }, { - key: 'onMediaSourceClose', - value: function onMediaSourceClose() { - _logger.logger.log('media source closed'); - } - }, { - key: 'onMediaSourceEnded', - value: function onMediaSourceEnded() { - _logger.logger.log('media source ended'); - } - }, { - key: 'onSBUpdateEnd', - value: function onSBUpdateEnd() { - - if (this._needsFlush) { - this.doFlush(); - } - - if (this._needsEos) { - this.onBufferEos(); - } - - this.hls.trigger(_events2.default.BUFFER_APPENDED); - - this.doAppending(); - } - }, { - key: 'onSBUpdateError', - value: function onSBUpdateError(event) { - _logger.logger.error('sourceBuffer error:' + event); - // according to http://www.w3.org/TR/media-source/#sourcebuffer-append-error - // this error might not always be fatal (it is fatal if decode error is set, in that case - // it will be followed by a mediaElement error ...) - this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.BUFFER_APPENDING_ERROR, fatal: false }); - // we don't need to do more than that, as accordin to the spec, updateend will be fired just after - } - }, { - key: 'onBufferReset', - value: function onBufferReset() { - var sourceBuffer = this.sourceBuffer; - if (sourceBuffer) { - for (var type in sourceBuffer) { - var sb = sourceBuffer[type]; - try { - this.mediaSource.removeSourceBuffer(sb); - sb.removeEventListener('updateend', this.onsbue); - sb.removeEventListener('error', this.onsbe); - } catch (err) {} - } - this.sourceBuffer = null; - } - this.flushRange = []; - this.appended = 0; - } - }, { - key: 'onBufferCodecs', - value: function onBufferCodecs(tracks) { - var mediaSource = this.mediaSource; - - // delay sourcebuffer creation if media source not opened yet - if (!mediaSource || mediaSource.readyState !== 'open') { - this.pendingTracks = tracks; - return; - } - - if (!this.sourceBuffer) { - var sourceBuffer = {}; - for (var trackName in tracks) { - var track = tracks[trackName]; - // use levelCodec as first priority - var codec = track.levelCodec || track.codec; - var mimeType = track.container + ';codecs=' + codec; - _logger.logger.log('creating sourceBuffer with mimeType:' + mimeType); - var sb = sourceBuffer[trackName] = mediaSource.addSourceBuffer(mimeType); - sb.addEventListener('updateend', this.onsbue); - sb.addEventListener('error', this.onsbe); - } - this.sourceBuffer = sourceBuffer; - } - } - }, { - key: 'onBufferAppending', - value: function onBufferAppending(data) { - if (!this.segments) { - this.segments = [data]; - } else { - this.segments.push(data); - } - this.doAppending(); - } - }, { - key: 'onBufferAppendFail', - value: function onBufferAppendFail(data) { - _logger.logger.error('sourceBuffer error:' + data.event); - // according to http://www.w3.org/TR/media-source/#sourcebuffer-append-error - // this error might not always be fatal (it is fatal if decode error is set, in that case - // it will be followed by a mediaElement error ...) - this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.BUFFER_APPENDING_ERROR, fatal: false, frag: this.fragCurrent }); - } - }, { - key: 'onBufferEos', - value: function onBufferEos() { - var sb = this.sourceBuffer, - mediaSource = this.mediaSource; - if (!mediaSource || mediaSource.readyState !== 'open') { - return; - } - if (!(sb.audio && sb.audio.updating || sb.video && sb.video.updating)) { - _logger.logger.log('all media data available, signal endOfStream() to MediaSource and stop loading fragment'); - //Notify the media element that it now has all of the media data - mediaSource.endOfStream(); - this._needsEos = false; - } else { - this._needsEos = true; - } - } - }, { - key: 'onBufferFlushing', - value: function onBufferFlushing(data) { - this.flushRange.push({ start: data.startOffset, end: data.endOffset }); - // attempt flush immediatly - this.flushBufferCounter = 0; - this.doFlush(); - } - }, { - key: 'onLevelUpdated', - value: function onLevelUpdated(event) { - var details = event.details; - if (details.fragments.length === 0) { - return; - } - this._levelDuration = details.totalduration + details.fragments[0].start; - this.updateMediaElementDuration(); - } - - // https://github.com/dailymotion/hls.js/issues/355 - - }, { - key: 'updateMediaElementDuration', - value: function updateMediaElementDuration() { - if (this._levelDuration === null) { - return; - } - var media = this.media; - var mediaSource = this.mediaSource; - if (!media || !mediaSource || media.readyState === 0 || mediaSource.readyState !== 'open') { - return; - } - for (var type in mediaSource.sourceBuffers) { - if (mediaSource.sourceBuffers[type].updating) { - // can't set duration whilst a buffer is updating - return; - } - } - if (this._msDuration === null) { - // initialise to the value that the media source is reporting - this._msDuration = mediaSource.duration; - } - // this._levelDuration was the last value we set. - // not using mediaSource.duration as the browser may tweak this value - // only update mediasource duration if its value increase, this is to avoid - // flushing already buffered portion when switching between quality level, as they - if (this._levelDuration > this._msDuration) { - _logger.logger.log('Updating mediasource duration to ' + this._levelDuration); - mediaSource.duration = this._levelDuration; - this._msDuration = this._levelDuration; - } - } - }, { - key: 'doFlush', - value: function doFlush() { - // loop through all buffer ranges to flush - while (this.flushRange.length) { - var range = this.flushRange[0]; - // flushBuffer will abort any buffer append in progress and flush Audio/Video Buffer - if (this.flushBuffer(range.start, range.end)) { - // range flushed, remove from flush array - this.flushRange.shift(); - this.flushBufferCounter = 0; - } else { - this._needsFlush = true; - // avoid looping, wait for SB update end to retrigger a flush - return; - } - } - if (this.flushRange.length === 0) { - // everything flushed - this._needsFlush = false; - - // let's recompute this.appended, which is used to avoid flush looping - var appended = 0; - var sourceBuffer = this.sourceBuffer; - if (sourceBuffer) { - for (var type in sourceBuffer) { - appended += sourceBuffer[type].buffered.length; - } - } - this.appended = appended; - this.hls.trigger(_events2.default.BUFFER_FLUSHED); - } - } - }, { - key: 'doAppending', - value: function doAppending() { - var hls = this.hls, - sourceBuffer = this.sourceBuffer, - segments = this.segments; - if (sourceBuffer) { - if (this.media.error) { - segments = []; - _logger.logger.error('trying to append although a media error occured, flush segment and abort'); - return; - } - for (var type in sourceBuffer) { - if (sourceBuffer[type].updating) { - //logger.log('sb update in progress'); - return; - } - } - if (segments.length) { - var segment = segments.shift(); - try { - //logger.log(`appending ${segment.type} SB, size:${segment.data.length}); - sourceBuffer[segment.type].appendBuffer(segment.data); - this.appendError = 0; - this.appended++; - } catch (err) { - // in case any error occured while appending, put back segment in segments table - _logger.logger.error('error while trying to append buffer:' + err.message); - segments.unshift(segment); - var event = { type: _errors.ErrorTypes.MEDIA_ERROR }; - if (err.code !== 22) { - if (this.appendError) { - this.appendError++; - } else { - this.appendError = 1; - } - event.details = _errors.ErrorDetails.BUFFER_APPEND_ERROR; - event.frag = this.fragCurrent; - /* with UHD content, we could get loop of quota exceeded error until - browser is able to evict some data from sourcebuffer. retrying help recovering this - */ - if (this.appendError > hls.config.appendErrorMaxRetry) { - _logger.logger.log('fail ' + hls.config.appendErrorMaxRetry + ' times to append segment in sourceBuffer'); - segments = []; - event.fatal = true; - hls.trigger(_events2.default.ERROR, event); - return; - } else { - event.fatal = false; - hls.trigger(_events2.default.ERROR, event); - } - } else { - // QuotaExceededError: http://www.w3.org/TR/html5/infrastructure.html#quotaexceedederror - // let's stop appending any segments, and report BUFFER_FULL_ERROR error - this.segments = []; - event.details = _errors.ErrorDetails.BUFFER_FULL_ERROR; - hls.trigger(_events2.default.ERROR, event); - return; - } - } - } - } - } - - /* - flush specified buffered range, - return true once range has been flushed. - as sourceBuffer.remove() is asynchronous, flushBuffer will be retriggered on sourceBuffer update end - */ - - }, { - key: 'flushBuffer', - value: function flushBuffer(startOffset, endOffset) { - var sb, i, bufStart, bufEnd, flushStart, flushEnd; - //logger.log('flushBuffer,pos/start/end: ' + this.media.currentTime + '/' + startOffset + '/' + endOffset); - // safeguard to avoid infinite looping : don't try to flush more than the nb of appended segments - if (this.flushBufferCounter < this.appended && this.sourceBuffer) { - for (var type in this.sourceBuffer) { - sb = this.sourceBuffer[type]; - if (!sb.updating) { - for (i = 0; i < sb.buffered.length; i++) { - bufStart = sb.buffered.start(i); - bufEnd = sb.buffered.end(i); - // workaround firefox not able to properly flush multiple buffered range. - if (navigator.userAgent.toLowerCase().indexOf('firefox') !== -1 && endOffset === Number.POSITIVE_INFINITY) { - flushStart = startOffset; - flushEnd = endOffset; - } else { - flushStart = Math.max(bufStart, startOffset); - flushEnd = Math.min(bufEnd, endOffset); - } - /* sometimes sourcebuffer.remove() does not flush - the exact expected time range. - to avoid rounding issues/infinite loop, - only flush buffer range of length greater than 500ms. - */ - if (Math.min(flushEnd, bufEnd) - flushStart > 0.5) { - this.flushBufferCounter++; - _logger.logger.log('flush ' + type + ' [' + flushStart + ',' + flushEnd + '], of [' + bufStart + ',' + bufEnd + '], pos:' + this.media.currentTime); - sb.remove(flushStart, flushEnd); - return false; - } - } - } else { - //logger.log('abort ' + type + ' append in progress'); - // this will abort any appending in progress - //sb.abort(); - _logger.logger.warn('cannot flush, sb updating in progress'); - return false; - } - } - } else { - _logger.logger.warn('abort flushing too many retries'); - } - _logger.logger.log('buffer flushed'); - // everything flushed ! - return true; - } - }]); - - return BufferController; -}(_eventHandler2.default); - -exports.default = BufferController; - -},{"../errors":21,"../event-handler":22,"../events":23,"../utils/logger":38}],5:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -var _eventHandler = require('../event-handler'); - -var _eventHandler2 = _interopRequireDefault(_eventHandler); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* - * cap stream level to media size dimension controller - */ - -var CapLevelController = function (_EventHandler) { - _inherits(CapLevelController, _EventHandler); - - function CapLevelController(hls) { - _classCallCheck(this, CapLevelController); - - return _possibleConstructorReturn(this, Object.getPrototypeOf(CapLevelController).call(this, hls, _events2.default.MEDIA_ATTACHING, _events2.default.MANIFEST_PARSED)); - } - - _createClass(CapLevelController, [{ - key: 'destroy', - value: function destroy() { - if (this.hls.config.capLevelToPlayerSize) { - this.media = null; - this.autoLevelCapping = Number.POSITIVE_INFINITY; - if (this.timer) { - this.timer = clearInterval(this.timer); - } - } - } - }, { - key: 'onMediaAttaching', - value: function onMediaAttaching(data) { - this.media = data.media instanceof HTMLVideoElement ? data.media : null; - } - }, { - key: 'onManifestParsed', - value: function onManifestParsed(data) { - if (this.hls.config.capLevelToPlayerSize) { - this.autoLevelCapping = Number.POSITIVE_INFINITY; - this.levels = data.levels; - this.hls.firstLevel = this.getMaxLevel(data.firstLevel); - clearInterval(this.timer); - this.timer = setInterval(this.detectPlayerSize.bind(this), 1000); - this.detectPlayerSize(); - } - } - }, { - key: 'detectPlayerSize', - value: function detectPlayerSize() { - if (this.media) { - var levelsLength = this.levels ? this.levels.length : 0; - if (levelsLength) { - this.hls.autoLevelCapping = this.getMaxLevel(levelsLength - 1); - if (this.hls.autoLevelCapping > this.autoLevelCapping) { - // if auto level capping has a higher value for the previous one, flush the buffer using nextLevelSwitch - // usually happen when the user go to the fullscreen mode. - this.hls.streamController.nextLevelSwitch(); - } - this.autoLevelCapping = this.hls.autoLevelCapping; - } - } - } - - /* - * returns level should be the one with the dimensions equal or greater than the media (player) dimensions (so the video will be downscaled) - */ - - }, { - key: 'getMaxLevel', - value: function getMaxLevel(capLevelIndex) { - var result = void 0, - i = void 0, - level = void 0, - mWidth = this.mediaWidth, - mHeight = this.mediaHeight, - lWidth = 0, - lHeight = 0; - - for (i = 0; i <= capLevelIndex; i++) { - level = this.levels[i]; - result = i; - lWidth = level.width; - lHeight = level.height; - if (mWidth <= lWidth || mHeight <= lHeight) { - break; - } - } - return result; - } - }, { - key: 'contentScaleFactor', - get: function get() { - var pixelRatio = 1; - try { - pixelRatio = window.devicePixelRatio; - } catch (e) {} - return pixelRatio; - } - }, { - key: 'mediaWidth', - get: function get() { - var width = void 0; - if (this.media) { - width = this.media.width || this.media.clientWidth || this.media.offsetWidth; - width *= this.contentScaleFactor; - } - return width; - } - }, { - key: 'mediaHeight', - get: function get() { - var height = void 0; - if (this.media) { - height = this.media.height || this.media.clientHeight || this.media.offsetHeight; - height *= this.contentScaleFactor; - } - return height; - } - }]); - - return CapLevelController; -}(_eventHandler2.default); - -exports.default = CapLevelController; - -},{"../event-handler":22,"../events":23}],6:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /* - * EWMA Bandwidth Estimator - * - heavily inspired from shaka-player - * Tracks bandwidth samples and estimates available bandwidth. - * Based on the minimum of two exponentially-weighted moving averages with - * different half-lives. - */ - -var _ewma = require('../utils/ewma'); - -var _ewma2 = _interopRequireDefault(_ewma); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var EwmaBandWidthEstimator = function () { - function EwmaBandWidthEstimator(hls, slow, fast, defaultEstimate) { - _classCallCheck(this, EwmaBandWidthEstimator); - - this.hls = hls; - this.defaultEstimate_ = defaultEstimate; - this.minWeight_ = 0.001; - this.minDelayMs_ = 50; - this.slow_ = new _ewma2.default(slow); - this.fast_ = new _ewma2.default(fast); - } - - _createClass(EwmaBandWidthEstimator, [{ - key: 'sample', - value: function sample(durationMs, numBytes) { - durationMs = Math.max(durationMs, this.minDelayMs_); - var bandwidth = 8000 * numBytes / durationMs, - - //console.log('instant bw:'+ Math.round(bandwidth)); - // we weight sample using loading duration.... - weight = durationMs / 1000; - this.fast_.sample(weight, bandwidth); - this.slow_.sample(weight, bandwidth); - } - }, { - key: 'getEstimate', - value: function getEstimate() { - if (!this.fast_ || !this.slow_ || this.fast_.getTotalWeight() < this.minWeight_) { - return this.defaultEstimate_; - } - //console.log('slow estimate:'+ Math.round(this.slow_.getEstimate())); - //console.log('fast estimate:'+ Math.round(this.fast_.getEstimate())); - // Take the minimum of these two estimates. This should have the effect of - // adapting down quickly, but up more slowly. - return Math.min(this.fast_.getEstimate(), this.slow_.getEstimate()); - } - }, { - key: 'destroy', - value: function destroy() {} - }]); - - return EwmaBandWidthEstimator; -}(); - -exports.default = EwmaBandWidthEstimator; - -},{"../utils/ewma":37}],7:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -var _eventHandler = require('../event-handler'); - -var _eventHandler2 = _interopRequireDefault(_eventHandler); - -var _logger = require('../utils/logger'); - -var _errors = require('../errors'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* - * Level Controller - */ - -var LevelController = function (_EventHandler) { - _inherits(LevelController, _EventHandler); - - function LevelController(hls) { - _classCallCheck(this, LevelController); - - var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(LevelController).call(this, hls, _events2.default.MANIFEST_LOADED, _events2.default.LEVEL_LOADED, _events2.default.ERROR)); - - _this.ontick = _this.tick.bind(_this); - _this._manualLevel = _this._autoLevelCapping = -1; - return _this; - } - - _createClass(LevelController, [{ - key: 'destroy', - value: function destroy() { - if (this.timer) { - clearTimeout(this.timer); - this.timer = null; - } - this._manualLevel = -1; - } - }, { - key: 'startLoad', - value: function startLoad() { - this.canload = true; - // speed up live playlist refresh if timer exists - if (this.timer) { - this.tick(); - } - } - }, { - key: 'stopLoad', - value: function stopLoad() { - this.canload = false; - } - }, { - key: 'onManifestLoaded', - value: function onManifestLoaded(data) { - var levels0 = [], - levels = [], - bitrateStart, - i, - bitrateSet = {}, - videoCodecFound = false, - audioCodecFound = false, - hls = this.hls; - - // regroup redundant level together - data.levels.forEach(function (level) { - if (level.videoCodec) { - videoCodecFound = true; - } - if (level.audioCodec) { - audioCodecFound = true; - } - var redundantLevelId = bitrateSet[level.bitrate]; - if (redundantLevelId === undefined) { - bitrateSet[level.bitrate] = levels0.length; - level.url = [level.url]; - level.urlId = 0; - levels0.push(level); - } else { - levels0[redundantLevelId].url.push(level.url); - } - }); - - // remove audio-only level if we also have levels with audio+video codecs signalled - if (videoCodecFound && audioCodecFound) { - levels0.forEach(function (level) { - if (level.videoCodec) { - levels.push(level); - } - }); - } else { - levels = levels0; - } - - // only keep level with supported audio/video codecs - levels = levels.filter(function (level) { - var checkSupportedAudio = function checkSupportedAudio(codec) { - return MediaSource.isTypeSupported('audio/mp4;codecs=' + codec); - }; - var checkSupportedVideo = function checkSupportedVideo(codec) { - return MediaSource.isTypeSupported('video/mp4;codecs=' + codec); - }; - var audioCodec = level.audioCodec, - videoCodec = level.videoCodec; - - return (!audioCodec || checkSupportedAudio(audioCodec)) && (!videoCodec || checkSupportedVideo(videoCodec)); - }); - - if (levels.length) { - // start bitrate is the first bitrate of the manifest - bitrateStart = levels[0].bitrate; - // sort level on bitrate - levels.sort(function (a, b) { - return a.bitrate - b.bitrate; - }); - this._levels = levels; - // find index of first level in sorted levels - for (i = 0; i < levels.length; i++) { - if (levels[i].bitrate === bitrateStart) { - this._firstLevel = i; - _logger.logger.log('manifest loaded,' + levels.length + ' level(s) found, first bitrate:' + bitrateStart); - break; - } - } - hls.trigger(_events2.default.MANIFEST_PARSED, { levels: this._levels, firstLevel: this._firstLevel, stats: data.stats }); - } else { - hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.MANIFEST_INCOMPATIBLE_CODECS_ERROR, fatal: true, url: hls.url, reason: 'no level with compatible codecs found in manifest' }); - } - return; - } - }, { - key: 'setLevelInternal', - value: function setLevelInternal(newLevel) { - var levels = this._levels; - // check if level idx is valid - if (newLevel >= 0 && newLevel < levels.length) { - // stopping live reloading timer if any - if (this.timer) { - clearTimeout(this.timer); - this.timer = null; - } - this._level = newLevel; - _logger.logger.log('switching to level ' + newLevel); - this.hls.trigger(_events2.default.LEVEL_SWITCH, { level: newLevel }); - var level = levels[newLevel]; - // check if we need to load playlist for this level - if (level.details === undefined || level.details.live === true) { - // level not retrieved yet, or live playlist we need to (re)load it - _logger.logger.log('(re)loading playlist for level ' + newLevel); - var urlId = level.urlId; - this.hls.trigger(_events2.default.LEVEL_LOADING, { url: level.url[urlId], level: newLevel, id: urlId }); - } - } else { - // invalid level id given, trigger error - this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.OTHER_ERROR, details: _errors.ErrorDetails.LEVEL_SWITCH_ERROR, level: newLevel, fatal: false, reason: 'invalid level idx' }); - } - } - }, { - key: 'onError', - value: function onError(data) { - if (data.fatal) { - return; - } - - var details = data.details, - hls = this.hls, - levelId = void 0, - level = void 0, - levelError = false; - // try to recover not fatal errors - switch (details) { - case _errors.ErrorDetails.FRAG_LOAD_ERROR: - case _errors.ErrorDetails.FRAG_LOAD_TIMEOUT: - case _errors.ErrorDetails.FRAG_LOOP_LOADING_ERROR: - case _errors.ErrorDetails.KEY_LOAD_ERROR: - case _errors.ErrorDetails.KEY_LOAD_TIMEOUT: - levelId = data.frag.level; - break; - case _errors.ErrorDetails.LEVEL_LOAD_ERROR: - case _errors.ErrorDetails.LEVEL_LOAD_TIMEOUT: - levelId = data.level; - levelError = true; - break; - default: - break; - } - /* try to switch to a redundant stream if any available. - * if no redundant stream available, emergency switch down (if in auto mode and current level not 0) - * otherwise, we cannot recover this network error ... - * don't raise FRAG_LOAD_ERROR and FRAG_LOAD_TIMEOUT as fatal, as it is handled by mediaController - */ - if (levelId !== undefined) { - level = this._levels[levelId]; - if (level.urlId < level.url.length - 1) { - level.urlId++; - level.details = undefined; - _logger.logger.warn('level controller,' + details + ' for level ' + levelId + ': switching to redundant stream id ' + level.urlId); - } else { - // we could try to recover if in auto mode and current level not lowest level (0) - var recoverable = this._manualLevel === -1 && levelId; - if (recoverable) { - _logger.logger.warn('level controller,' + details + ': emergency switch-down for next fragment'); - hls.abrController.nextAutoLevel = 0; - } else if (level && level.details && level.details.live) { - _logger.logger.warn('level controller,' + details + ' on live stream, discard'); - if (levelError) { - // reset this._level so that another call to set level() will retrigger a frag load - this._level = undefined; - } - // FRAG_LOAD_ERROR and FRAG_LOAD_TIMEOUT are handled by mediaController - } else if (details !== _errors.ErrorDetails.FRAG_LOAD_ERROR && details !== _errors.ErrorDetails.FRAG_LOAD_TIMEOUT) { - _logger.logger.error('cannot recover ' + details + ' error'); - this._level = undefined; - // stopping live reloading timer if any - if (this.timer) { - clearTimeout(this.timer); - this.timer = null; - } - // redispatch same error but with fatal set to true - data.fatal = true; - hls.trigger(_events2.default.ERROR, data); - } - } - } - } - }, { - key: 'onLevelLoaded', - value: function onLevelLoaded(data) { - // only process level loaded events matching with expected level - if (data.level === this._level) { - var newDetails = data.details; - // if current playlist is a live playlist, arm a timer to reload it - if (newDetails.live) { - var reloadInterval = 1000 * newDetails.targetduration, - curLevel = this._levels[data.level], - curDetails = curLevel.details; - if (curDetails && newDetails.endSN === curDetails.endSN) { - // follow HLS Spec, If the client reloads a Playlist file and finds that it has not - // changed then it MUST wait for a period of one-half the target - // duration before retrying. - reloadInterval /= 2; - _logger.logger.log('same live playlist, reload twice faster'); - } - // decrement reloadInterval with level loading delay - reloadInterval -= performance.now() - data.stats.trequest; - // in any case, don't reload more than every second - reloadInterval = Math.max(1000, Math.round(reloadInterval)); - _logger.logger.log('live playlist, reload in ' + reloadInterval + ' ms'); - this.timer = setTimeout(this.ontick, reloadInterval); - } else { - this.timer = null; - } - } - } - }, { - key: 'tick', - value: function tick() { - var levelId = this._level; - if (levelId !== undefined && this.canload) { - var level = this._levels[levelId], - urlId = level.urlId; - this.hls.trigger(_events2.default.LEVEL_LOADING, { url: level.url[urlId], level: levelId, id: urlId }); - } - } - }, { - key: 'levels', - get: function get() { - return this._levels; - } - }, { - key: 'level', - get: function get() { - return this._level; - }, - set: function set(newLevel) { - var levels = this._levels; - if (levels && levels.length > newLevel) { - if (this._level !== newLevel || levels[newLevel].details === undefined) { - this.setLevelInternal(newLevel); - } - } - } - }, { - key: 'manualLevel', - get: function get() { - return this._manualLevel; - }, - set: function set(newLevel) { - this._manualLevel = newLevel; - if (this._startLevel === undefined) { - this._startLevel = newLevel; - } - if (newLevel !== -1) { - this.level = newLevel; - } - } - }, { - key: 'firstLevel', - get: function get() { - return this._firstLevel; - }, - set: function set(newLevel) { - this._firstLevel = newLevel; - } - }, { - key: 'startLevel', - get: function get() { - if (this._startLevel === undefined) { - return this._firstLevel; - } else { - return this._startLevel; - } - }, - set: function set(newLevel) { - this._startLevel = newLevel; - } - }, { - key: 'nextLoadLevel', - get: function get() { - if (this._manualLevel !== -1) { - return this._manualLevel; - } else { - return this.hls.abrController.nextAutoLevel; - } - }, - set: function set(nextLevel) { - this.level = nextLevel; - if (this._manualLevel === -1) { - this.hls.abrController.nextAutoLevel = nextLevel; - } - } - }]); - - return LevelController; -}(_eventHandler2.default); - -exports.default = LevelController; - -},{"../errors":21,"../event-handler":22,"../events":23,"../utils/logger":38}],8:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _demuxer = require('../demux/demuxer'); - -var _demuxer2 = _interopRequireDefault(_demuxer); - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -var _eventHandler = require('../event-handler'); - -var _eventHandler2 = _interopRequireDefault(_eventHandler); - -var _logger = require('../utils/logger'); - -var _binarySearch = require('../utils/binary-search'); - -var _binarySearch2 = _interopRequireDefault(_binarySearch); - -var _bufferHelper = require('../helper/buffer-helper'); - -var _bufferHelper2 = _interopRequireDefault(_bufferHelper); - -var _levelHelper = require('../helper/level-helper'); - -var _levelHelper2 = _interopRequireDefault(_levelHelper); - -var _errors = require('../errors'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* - * Stream Controller - */ - -var State = { - STOPPED: 'STOPPED', - STARTING: 'STARTING', - IDLE: 'IDLE', - PAUSED: 'PAUSED', - KEY_LOADING: 'KEY_LOADING', - FRAG_LOADING: 'FRAG_LOADING', - FRAG_LOADING_WAITING_RETRY: 'FRAG_LOADING_WAITING_RETRY', - WAITING_LEVEL: 'WAITING_LEVEL', - PARSING: 'PARSING', - PARSED: 'PARSED', - ENDED: 'ENDED', - ERROR: 'ERROR' -}; - -var StreamController = function (_EventHandler) { - _inherits(StreamController, _EventHandler); - - function StreamController(hls) { - _classCallCheck(this, StreamController); - - var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(StreamController).call(this, hls, _events2.default.MEDIA_ATTACHED, _events2.default.MEDIA_DETACHING, _events2.default.MANIFEST_LOADING, _events2.default.MANIFEST_PARSED, _events2.default.LEVEL_LOADED, _events2.default.KEY_LOADED, _events2.default.FRAG_LOADED, _events2.default.FRAG_LOAD_EMERGENCY_ABORTED, _events2.default.FRAG_PARSING_INIT_SEGMENT, _events2.default.FRAG_PARSING_DATA, _events2.default.FRAG_PARSED, _events2.default.ERROR, _events2.default.BUFFER_APPENDED, _events2.default.BUFFER_FLUSHED)); - - _this.config = hls.config; - _this.audioCodecSwap = false; - _this.ticks = 0; - _this.ontick = _this.tick.bind(_this); - return _this; - } - - _createClass(StreamController, [{ - key: 'destroy', - value: function destroy() { - this.stopLoad(); - if (this.timer) { - clearInterval(this.timer); - this.timer = null; - } - _eventHandler2.default.prototype.destroy.call(this); - this.state = State.STOPPED; - } - }, { - key: 'startLoad', - value: function startLoad(startPosition) { - if (this.levels) { - var media = this.media, - lastCurrentTime = this.lastCurrentTime; - this.stopLoad(); - this.demuxer = new _demuxer2.default(this.hls); - if (!this.timer) { - this.timer = setInterval(this.ontick, 100); - } - this.level = -1; - this.fragLoadError = 0; - if (media && lastCurrentTime > 0) { - _logger.logger.log('configure startPosition @' + lastCurrentTime); - if (!this.lastPaused) { - _logger.logger.log('resuming video'); - media.play(); - } - this.state = State.IDLE; - } else { - this.lastCurrentTime = this.startPosition ? this.startPosition : startPosition; - this.state = State.STARTING; - } - this.nextLoadPosition = this.startPosition = this.lastCurrentTime; - this.tick(); - } else { - _logger.logger.warn('cannot start loading as manifest not parsed yet'); - this.state = State.STOPPED; - } - } - }, { - key: 'stopLoad', - value: function stopLoad() { - var frag = this.fragCurrent; - if (frag) { - if (frag.loader) { - frag.loader.abort(); - } - this.fragCurrent = null; - } - this.fragPrevious = null; - if (this.demuxer) { - this.demuxer.destroy(); - this.demuxer = null; - } - this.state = State.STOPPED; - } - }, { - key: 'tick', - value: function tick() { - this.ticks++; - if (this.ticks === 1) { - this.doTick(); - if (this.ticks > 1) { - setTimeout(this.tick, 1); - } - this.ticks = 0; - } - } - }, { - key: 'doTick', - value: function doTick() { - var pos, - level, - levelDetails, - hls = this.hls, - config = hls.config, - media = this.media, - isSeeking = media && media.seeking; - //logger.log(this.state); - switch (this.state) { - case State.ERROR: - //don't do anything in error state to avoid breaking further ... - case State.PAUSED: - //don't do anything in paused state either ... - break; - case State.STARTING: - // determine load level - var startLevel = hls.startLevel; - if (startLevel === -1) { - // -1 : guess start Level by doing a bitrate test by loading first fragment of lowest quality level - startLevel = 0; - this.fragBitrateTest = true; - } - // set new level to playlist loader : this will trigger start level load - // hls.nextLoadLevel remains until it is set to a new value or until a new frag is successfully loaded - this.level = hls.nextLoadLevel = startLevel; - this.state = State.WAITING_LEVEL; - this.loadedmetadata = false; - break; - case State.IDLE: - // if video not attached AND - // start fragment already requested OR start frag prefetch disable - // exit loop - // => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop - if (!media && (this.startFragRequested || !config.startFragPrefetch)) { - break; - } - // determine next candidate fragment to be loaded, based on current position and - // end of buffer position - // ensure 60s of buffer upfront - // if we have not yet loaded any fragment, start loading from start position - if (this.loadedmetadata) { - pos = media.currentTime; - } else { - pos = this.nextLoadPosition; - } - level = hls.nextLoadLevel; - var bufferInfo = _bufferHelper2.default.bufferInfo(media, pos, config.maxBufferHole), - bufferLen = bufferInfo.len, - bufferEnd = bufferInfo.end, - fragPrevious = this.fragPrevious, - maxBufLen; - // compute max Buffer Length that we could get from this load level, based on level bitrate. don't buffer more than 60 MB and more than 30s - if (this.levels[level].hasOwnProperty('bitrate')) { - maxBufLen = Math.max(8 * config.maxBufferSize / this.levels[level].bitrate, config.maxBufferLength); - maxBufLen = Math.min(maxBufLen, config.maxMaxBufferLength); - } else { - maxBufLen = config.maxBufferLength; - } - // if buffer length is less than maxBufLen try to load a new fragment - if (bufferLen < maxBufLen) { - // set next load level : this will trigger a playlist load if needed - hls.nextLoadLevel = level; - this.level = level; - levelDetails = this.levels[level].details; - // if level info not retrieved yet, switch state and wait for level retrieval - // if live playlist, ensure that new playlist has been refreshed to avoid loading/try to load - // a useless and outdated fragment (that might even introduce load error if it is already out of the live playlist) - if (typeof levelDetails === 'undefined' || levelDetails.live && this.levelLastLoaded !== level) { - this.state = State.WAITING_LEVEL; - break; - } - // find fragment index, contiguous with end of buffer position - var fragments = levelDetails.fragments, - fragLen = fragments.length, - start = fragments[0].start, - end = fragments[fragLen - 1].start + fragments[fragLen - 1].duration, - frag = void 0; - - // in case of live playlist we need to ensure that requested position is not located before playlist start - if (levelDetails.live) { - // check if requested position is within seekable boundaries : - //logger.log(`start/pos/bufEnd/seeking:${start.toFixed(3)}/${pos.toFixed(3)}/${bufferEnd.toFixed(3)}/${media.seeking}`); - var maxLatency = config.liveMaxLatencyDuration !== undefined ? config.liveMaxLatencyDuration : config.liveMaxLatencyDurationCount * levelDetails.targetduration; - - if (bufferEnd < Math.max(start, end - maxLatency)) { - var targetLatency = config.liveSyncDuration !== undefined ? config.liveSyncDuration : config.liveSyncDurationCount * levelDetails.targetduration; - var liveSyncPosition = start + Math.max(0, levelDetails.totalduration - targetLatency); - _logger.logger.log('buffer end: ' + bufferEnd + ' is located too far from the end of live sliding playlist, reset currentTime to : ' + liveSyncPosition.toFixed(3)); - bufferEnd = liveSyncPosition; - if (media && media.readyState && media.duration > liveSyncPosition) { - media.currentTime = liveSyncPosition; - } - } - - // if end of buffer greater than live edge, don't load any fragment - // this could happen if live playlist intermittently slides in the past. - // level 1 loaded [182580161,182580167] - // level 1 loaded [182580162,182580169] - // Loading 182580168 of [182580162 ,182580169],level 1 .. - // Loading 182580169 of [182580162 ,182580169],level 1 .. - // level 1 loaded [182580162,182580168] <============= here we should have bufferEnd > end. in that case break to avoid reloading 182580168 - // level 1 loaded [182580164,182580171] - // - if (levelDetails.PTSKnown && bufferEnd > end) { - break; - } - - if (this.startFragRequested && !levelDetails.PTSKnown) { - /* we are switching level on live playlist, but we don't have any PTS info for that quality level ... - try to load frag matching with next SN. - even if SN are not synchronized between playlists, loading this frag will help us - compute playlist sliding and find the right one after in case it was not the right consecutive one */ - if (fragPrevious) { - var targetSN = fragPrevious.sn + 1; - if (targetSN >= levelDetails.startSN && targetSN <= levelDetails.endSN) { - frag = fragments[targetSN - levelDetails.startSN]; - _logger.logger.log('live playlist, switching playlist, load frag with next SN: ' + frag.sn); - } - } - if (!frag) { - /* we have no idea about which fragment should be loaded. - so let's load mid fragment. it will help computing playlist sliding and find the right one - */ - frag = fragments[Math.min(fragLen - 1, Math.round(fragLen / 2))]; - _logger.logger.log('live playlist, switching playlist, unknown, load middle frag : ' + frag.sn); - } - } - } else { - // VoD playlist: if bufferEnd before start of playlist, load first fragment - if (bufferEnd < start) { - frag = fragments[0]; - } - } - if (!frag) { - (function () { - var maxFragLookUpTolerance = config.maxFragLookUpTolerance; - if (bufferEnd < end) { - // no frag look up tolerance in case bufferEnd close to end, or media seeking - if (bufferEnd > end - maxFragLookUpTolerance || isSeeking) { - maxFragLookUpTolerance = 0; - } - frag = _binarySearch2.default.search(fragments, function (candidate) { - // offset should be within fragment boundary - config.maxFragLookUpTolerance - // this is to cope with situations like - // bufferEnd = 9.991 - // frag[Ø] : [0,10] - // frag[1] : [10,20] - // bufferEnd is within frag[0] range ... although what we are expecting is to return frag[1] here - // frag start frag start+duration - // |-----------------------------| - // <---> <---> - // ...--------><-----------------------------><---------.... - // previous frag matching fragment next frag - // return -1 return 0 return 1 - //logger.log(`level/sn/start/end/bufEnd:${level}/${candidate.sn}/${candidate.start}/${(candidate.start+candidate.duration)}/${bufferEnd}`); - if (candidate.start + candidate.duration - maxFragLookUpTolerance <= bufferEnd) { - return 1; - } else if (candidate.start - maxFragLookUpTolerance > bufferEnd) { - return -1; - } - return 0; - }); - } else { - // reach end of playlist - frag = fragments[fragLen - 1]; - } - })(); - } - if (frag) { - start = frag.start; - //logger.log('find SN matching with pos:' + bufferEnd + ':' + frag.sn); - if (fragPrevious && frag.level === fragPrevious.level && frag.sn === fragPrevious.sn) { - if (frag.sn < levelDetails.endSN) { - var deltaPTS = fragPrevious.deltaPTS, - curSNIdx = frag.sn - levelDetails.startSN; - // if there is a significant delta between audio and video, larger than max allowed hole, - // and if previous remuxed fragment did not start with a keyframe. (fragPrevious.dropped) - // let's try to load previous fragment again to get last keyframe - // then we will reload again current fragment (that way we should be able to fill the buffer hole ...) - if (deltaPTS && deltaPTS > config.maxBufferHole && fragPrevious.dropped) { - frag = fragments[curSNIdx - 1]; - _logger.logger.warn('SN just loaded, with large PTS gap between audio and video, maybe frag is not starting with a keyframe ? load previous one to try to overcome this'); - // decrement previous frag load counter to avoid frag loop loading error when next fragment will get reloaded - fragPrevious.loadCounter--; - } else { - frag = fragments[curSNIdx + 1]; - _logger.logger.log('SN just loaded, load next one: ' + frag.sn); - } - // ensure frag is not undefined - if (!frag) { - break; - } - } else { - // have we reached end of VOD playlist ? - if (!levelDetails.live) { - // Finalize the media stream - this.hls.trigger(_events2.default.BUFFER_EOS); - // We might be loading the last fragment but actually the media - // is currently processing a seek command and waiting for new data to resume at another point. - // Going to ended state while media is seeking can spawn an infinite buffering broken state. - if (!isSeeking) { - this.state = State.ENDED; - } - } - break; - } - } - //logger.log(' loading frag ' + i +',pos/bufEnd:' + pos.toFixed(3) + '/' + bufferEnd.toFixed(3)); - if (frag.decryptdata.uri != null && frag.decryptdata.key == null) { - _logger.logger.log('Loading key for ' + frag.sn + ' of [' + levelDetails.startSN + ' ,' + levelDetails.endSN + '],level ' + level); - this.state = State.KEY_LOADING; - hls.trigger(_events2.default.KEY_LOADING, { frag: frag }); - } else { - _logger.logger.log('Loading ' + frag.sn + ' of [' + levelDetails.startSN + ' ,' + levelDetails.endSN + '],level ' + level + ', currentTime:' + pos + ',bufferEnd:' + bufferEnd.toFixed(3)); - // ensure that we are not reloading the same fragments in loop ... - if (this.fragLoadIdx !== undefined) { - this.fragLoadIdx++; - } else { - this.fragLoadIdx = 0; - } - if (frag.loadCounter) { - frag.loadCounter++; - var maxThreshold = config.fragLoadingLoopThreshold; - // if this frag has already been loaded 3 times, and if it has been reloaded recently - if (frag.loadCounter > maxThreshold && Math.abs(this.fragLoadIdx - frag.loadIdx) < maxThreshold) { - hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.FRAG_LOOP_LOADING_ERROR, fatal: false, frag: frag }); - return; - } - } else { - frag.loadCounter = 1; - } - frag.loadIdx = this.fragLoadIdx; - this.fragCurrent = frag; - this.startFragRequested = true; - frag.autoLevel = hls.autoLevelEnabled; - hls.trigger(_events2.default.FRAG_LOADING, { frag: frag }); - this.state = State.FRAG_LOADING; - } - } - } - break; - case State.WAITING_LEVEL: - level = this.levels[this.level]; - // check if playlist is already loaded - if (level && level.details) { - this.state = State.IDLE; - } - break; - case State.FRAG_LOADING_WAITING_RETRY: - var now = performance.now(); - var retryDate = this.retryDate; - // if current time is gt than retryDate, or if media seeking let's switch to IDLE state to retry loading - if (!retryDate || now >= retryDate || isSeeking) { - _logger.logger.log('mediaController: retryDate reached, switch back to IDLE state'); - this.state = State.IDLE; - } - break; - case State.STOPPED: - case State.FRAG_LOADING: - case State.PARSING: - case State.PARSED: - case State.ENDED: - break; - default: - break; - } - // check buffer - this._checkBuffer(); - // check/update current fragment - this._checkFragmentChanged(); - } - }, { - key: 'getBufferRange', - value: function getBufferRange(position) { - var i, - range, - bufferRange = this.bufferRange; - if (bufferRange) { - for (i = bufferRange.length - 1; i >= 0; i--) { - range = bufferRange[i]; - if (position >= range.start && position <= range.end) { - return range; - } - } - } - return null; - } - }, { - key: 'followingBufferRange', - value: function followingBufferRange(range) { - if (range) { - // try to get range of next fragment (500ms after this range) - return this.getBufferRange(range.end + 0.5); - } - return null; - } - }, { - key: 'isBuffered', - value: function isBuffered(position) { - var media = this.media; - if (media) { - var buffered = media.buffered; - for (var i = 0; i < buffered.length; i++) { - if (position >= buffered.start(i) && position <= buffered.end(i)) { - return true; - } - } - } - return false; - } - }, { - key: '_checkFragmentChanged', - value: function _checkFragmentChanged() { - var rangeCurrent, - currentTime, - video = this.media; - if (video && video.seeking === false) { - currentTime = video.currentTime; - /* if video element is in seeked state, currentTime can only increase. - (assuming that playback rate is positive ...) - As sometimes currentTime jumps back to zero after a - media decode error, check this, to avoid seeking back to - wrong position after a media decode error - */ - if (currentTime > video.playbackRate * this.lastCurrentTime) { - this.lastCurrentTime = currentTime; - } - if (this.isBuffered(currentTime)) { - rangeCurrent = this.getBufferRange(currentTime); - } else if (this.isBuffered(currentTime + 0.1)) { - /* ensure that FRAG_CHANGED event is triggered at startup, - when first video frame is displayed and playback is paused. - add a tolerance of 100ms, in case current position is not buffered, - check if current pos+100ms is buffered and use that buffer range - for FRAG_CHANGED event reporting */ - rangeCurrent = this.getBufferRange(currentTime + 0.1); - } - if (rangeCurrent) { - var fragPlaying = rangeCurrent.frag; - if (fragPlaying !== this.fragPlaying) { - this.fragPlaying = fragPlaying; - this.hls.trigger(_events2.default.FRAG_CHANGED, { frag: fragPlaying }); - } - } - } - } - - /* - on immediate level switch : - - pause playback if playing - - cancel any pending load request - - and trigger a buffer flush - */ - - }, { - key: 'immediateLevelSwitch', - value: function immediateLevelSwitch() { - _logger.logger.log('immediateLevelSwitch'); - if (!this.immediateSwitch) { - this.immediateSwitch = true; - var media = this.media, - previouslyPaused = void 0; - if (media) { - previouslyPaused = media.paused; - media.pause(); - } else { - // don't restart playback after instant level switch in case media not attached - previouslyPaused = true; - } - this.previouslyPaused = previouslyPaused; - } - var fragCurrent = this.fragCurrent; - if (fragCurrent && fragCurrent.loader) { - fragCurrent.loader.abort(); - } - this.fragCurrent = null; - // increase fragment load Index to avoid frag loop loading error after buffer flush - this.fragLoadIdx += 2 * this.config.fragLoadingLoopThreshold; - this.state = State.PAUSED; - // flush everything - this.hls.trigger(_events2.default.BUFFER_FLUSHING, { startOffset: 0, endOffset: Number.POSITIVE_INFINITY }); - } - - /* - on immediate level switch end, after new fragment has been buffered : - - nudge video decoder by slightly adjusting video currentTime - - resume the playback if needed - */ - - }, { - key: 'immediateLevelSwitchEnd', - value: function immediateLevelSwitchEnd() { - this.immediateSwitch = false; - var media = this.media; - if (media && media.readyState) { - media.currentTime -= 0.0001; - if (!this.previouslyPaused) { - media.play(); - } - } - } - }, { - key: 'nextLevelSwitch', - value: function nextLevelSwitch() { - /* try to switch ASAP without breaking video playback : - in order to ensure smooth but quick level switching, - we need to find the next flushable buffer range - we should take into account new segment fetch time - */ - var media = this.media; - // ensure that media is defined and that metadata are available (to retrieve currentTime) - if (media && media.readyState) { - var fetchdelay = void 0, - currentRange = void 0, - nextRange = void 0; - // increase fragment load Index to avoid frag loop loading error after buffer flush - this.fragLoadIdx += 2 * this.config.fragLoadingLoopThreshold; - currentRange = this.getBufferRange(media.currentTime); - if (currentRange && currentRange.start > 1) { - // flush buffer preceding current fragment (flush until current fragment start offset) - // minus 1s to avoid video freezing, that could happen if we flush keyframe of current video ... - this.state = State.PAUSED; - this.hls.trigger(_events2.default.BUFFER_FLUSHING, { startOffset: 0, endOffset: currentRange.start - 1 }); - } - if (!media.paused) { - // add a safety delay of 1s - var nextLevelId = this.hls.nextLoadLevel, - nextLevel = this.levels[nextLevelId], - fragLastKbps = this.fragLastKbps; - if (fragLastKbps && this.fragCurrent) { - fetchdelay = this.fragCurrent.duration * nextLevel.bitrate / (1000 * fragLastKbps) + 1; - } else { - fetchdelay = 0; - } - } else { - fetchdelay = 0; - } - //logger.log('fetchdelay:'+fetchdelay); - // find buffer range that will be reached once new fragment will be fetched - nextRange = this.getBufferRange(media.currentTime + fetchdelay); - if (nextRange) { - // we can flush buffer range following this one without stalling playback - nextRange = this.followingBufferRange(nextRange); - if (nextRange) { - // if we are here, we can also cancel any loading/demuxing in progress, as they are useless - var fragCurrent = this.fragCurrent; - if (fragCurrent && fragCurrent.loader) { - fragCurrent.loader.abort(); - } - this.fragCurrent = null; - // flush position is the start position of this new buffer - this.state = State.PAUSED; - this.hls.trigger(_events2.default.BUFFER_FLUSHING, { startOffset: nextRange.start, endOffset: Number.POSITIVE_INFINITY }); - } - } - } - } - }, { - key: 'onMediaAttached', - value: function onMediaAttached(data) { - var media = this.media = data.media; - this.onvseeking = this.onMediaSeeking.bind(this); - this.onvseeked = this.onMediaSeeked.bind(this); - this.onvended = this.onMediaEnded.bind(this); - media.addEventListener('seeking', this.onvseeking); - media.addEventListener('seeked', this.onvseeked); - media.addEventListener('ended', this.onvended); - var config = this.config; - if (this.levels && config.autoStartLoad) { - this.hls.startLoad(config.startPosition); - } - } - }, { - key: 'onMediaDetaching', - value: function onMediaDetaching() { - var media = this.media; - if (media && media.ended) { - _logger.logger.log('MSE detaching and video ended, reset startPosition'); - this.startPosition = this.lastCurrentTime = 0; - } - - // reset fragment loading counter on MSE detaching to avoid reporting FRAG_LOOP_LOADING_ERROR after error recovery - var levels = this.levels; - if (levels) { - // reset fragment load counter - levels.forEach(function (level) { - if (level.details) { - level.details.fragments.forEach(function (fragment) { - fragment.loadCounter = undefined; - }); - } - }); - } - // remove video listeners - if (media) { - media.removeEventListener('seeking', this.onvseeking); - media.removeEventListener('seeked', this.onvseeked); - media.removeEventListener('ended', this.onvended); - this.onvseeking = this.onvseeked = this.onvended = null; - } - this.media = null; - this.loadedmetadata = false; - this.stopLoad(); - } - }, { - key: 'onMediaSeeking', - value: function onMediaSeeking() { - if (this.state === State.FRAG_LOADING) { - // check if currently loaded fragment is inside buffer. - //if outside, cancel fragment loading, otherwise do nothing - if (_bufferHelper2.default.bufferInfo(this.media, this.media.currentTime, this.config.maxBufferHole).len === 0) { - _logger.logger.log('seeking outside of buffer while fragment load in progress, cancel fragment load'); - var fragCurrent = this.fragCurrent; - if (fragCurrent) { - if (fragCurrent.loader) { - fragCurrent.loader.abort(); - } - this.fragCurrent = null; - } - this.fragPrevious = null; - // switch to IDLE state to load new fragment - this.state = State.IDLE; - } - } else if (this.state === State.ENDED) { - // switch to IDLE state to check for potential new fragment - this.state = State.IDLE; - } - if (this.media) { - this.lastCurrentTime = this.media.currentTime; - } - // avoid reporting fragment loop loading error in case user is seeking several times on same position - if (this.fragLoadIdx !== undefined) { - this.fragLoadIdx += 2 * this.config.fragLoadingLoopThreshold; - } - // tick to speed up processing - this.tick(); - } - }, { - key: 'onMediaSeeked', - value: function onMediaSeeked() { - // tick to speed up FRAGMENT_PLAYING triggering - this.tick(); - } - }, { - key: 'onMediaEnded', - value: function onMediaEnded() { - _logger.logger.log('media ended'); - // reset startPosition and lastCurrentTime to restart playback @ stream beginning - this.startPosition = this.lastCurrentTime = 0; - } - }, { - key: 'onManifestLoading', - value: function onManifestLoading() { - // reset buffer on manifest loading - _logger.logger.log('trigger BUFFER_RESET'); - this.hls.trigger(_events2.default.BUFFER_RESET); - this.bufferRange = []; - this.stalled = false; - } - }, { - key: 'onManifestParsed', - value: function onManifestParsed(data) { - var aac = false, - heaac = false, - codec; - data.levels.forEach(function (level) { - // detect if we have different kind of audio codecs used amongst playlists - codec = level.audioCodec; - if (codec) { - if (codec.indexOf('mp4a.40.2') !== -1) { - aac = true; - } - if (codec.indexOf('mp4a.40.5') !== -1) { - heaac = true; - } - } - }); - this.audioCodecSwitch = aac && heaac; - if (this.audioCodecSwitch) { - _logger.logger.log('both AAC/HE-AAC audio found in levels; declaring level codec as HE-AAC'); - } - this.levels = data.levels; - this.startLevelLoaded = false; - this.startFragRequested = false; - var config = this.config; - if (config.autoStartLoad) { - this.hls.startLoad(config.startPosition); - } - } - }, { - key: 'onLevelLoaded', - value: function onLevelLoaded(data) { - var newDetails = data.details, - newLevelId = data.level, - curLevel = this.levels[newLevelId], - duration = newDetails.totalduration, - sliding = 0; - - _logger.logger.log('level ' + newLevelId + ' loaded [' + newDetails.startSN + ',' + newDetails.endSN + '],duration:' + duration); - this.levelLastLoaded = newLevelId; - - if (newDetails.live) { - var curDetails = curLevel.details; - if (curDetails) { - // we already have details for that level, merge them - _levelHelper2.default.mergeDetails(curDetails, newDetails); - sliding = newDetails.fragments[0].start; - if (newDetails.PTSKnown) { - _logger.logger.log('live playlist sliding:' + sliding.toFixed(3)); - } else { - _logger.logger.log('live playlist - outdated PTS, unknown sliding'); - } - } else { - newDetails.PTSKnown = false; - _logger.logger.log('live playlist - first load, unknown sliding'); - } - } else { - newDetails.PTSKnown = false; - } - // override level info - curLevel.details = newDetails; - this.hls.trigger(_events2.default.LEVEL_UPDATED, { details: newDetails, level: newLevelId }); - - if (this.startFragRequested === false) { - // compute start position if set to -1. use it straight away if value is defined - if (this.startPosition === -1) { - // first, check if start time offset has been set in playlist, if yes, use this value - var startTimeOffset = newDetails.startTimeOffset; - if (!isNaN(startTimeOffset)) { - _logger.logger.log('start time offset found in playlist, adjust startPosition to ' + startTimeOffset); - this.startPosition = startTimeOffset; - } else { - // if live playlist, set start position to be fragment N-this.config.liveSyncDurationCount (usually 3) - if (newDetails.live) { - var targetLatency = this.config.liveSyncDuration !== undefined ? this.config.liveSyncDuration : this.config.liveSyncDurationCount * newDetails.targetduration; - this.startPosition = Math.max(0, sliding + duration - targetLatency); - } else { - this.startPosition = 0; - } - } - } - this.nextLoadPosition = this.startPosition; - } - // only switch batck to IDLE state if we were waiting for level to start downloading a new fragment - if (this.state === State.WAITING_LEVEL) { - this.state = State.IDLE; - } - //trigger handler right now - this.tick(); - } - }, { - key: 'onKeyLoaded', - value: function onKeyLoaded() { - if (this.state === State.KEY_LOADING) { - this.state = State.IDLE; - this.tick(); - } - } - }, { - key: 'onFragLoaded', - value: function onFragLoaded(data) { - var fragCurrent = this.fragCurrent; - if (this.state === State.FRAG_LOADING && fragCurrent && data.frag.level === fragCurrent.level && data.frag.sn === fragCurrent.sn) { - - _logger.logger.log('Loaded ' + fragCurrent.sn + ' of level ' + fragCurrent.level); - if (this.fragBitrateTest === true) { - // switch back to IDLE state ... we just loaded a fragment to determine adequate start bitrate and initialize autoswitch algo - this.state = State.IDLE; - this.fragBitrateTest = false; - this.startFragRequested = false; - data.stats.tparsed = data.stats.tbuffered = performance.now(); - this.hls.trigger(_events2.default.FRAG_BUFFERED, { stats: data.stats, frag: fragCurrent }); - } else { - this.state = State.PARSING; - // transmux the MPEG-TS data to ISO-BMFF segments - this.stats = data.stats; - var currentLevel = this.levels[this.level], - details = currentLevel.details, - duration = details.totalduration, - start = fragCurrent.startDTS !== undefined ? fragCurrent.startDTS : fragCurrent.start, - level = fragCurrent.level, - sn = fragCurrent.sn, - audioCodec = currentLevel.audioCodec || this.config.defaultAudioCodec; - if (this.audioCodecSwap) { - _logger.logger.log('swapping playlist audio codec'); - if (audioCodec === undefined) { - audioCodec = this.lastAudioCodec; - } - if (audioCodec) { - if (audioCodec.indexOf('mp4a.40.5') !== -1) { - audioCodec = 'mp4a.40.2'; - } else { - audioCodec = 'mp4a.40.5'; - } - } - } - this.pendingAppending = 0; - _logger.logger.log('Demuxing ' + sn + ' of [' + details.startSN + ' ,' + details.endSN + '],level ' + level + ', cc ' + fragCurrent.cc); - var demuxer = this.demuxer; - if (demuxer) { - demuxer.push(data.payload, audioCodec, currentLevel.videoCodec, start, fragCurrent.cc, level, sn, duration, fragCurrent.decryptdata); - } - } - } - this.fragLoadError = 0; - } - }, { - key: 'onFragParsingInitSegment', - value: function onFragParsingInitSegment(data) { - if (this.state === State.PARSING) { - var tracks = data.tracks, - trackName, - track; - - // include levelCodec in audio and video tracks - track = tracks.audio; - if (track) { - var audioCodec = this.levels[this.level].audioCodec, - ua = navigator.userAgent.toLowerCase(); - if (audioCodec && this.audioCodecSwap) { - _logger.logger.log('swapping playlist audio codec'); - if (audioCodec.indexOf('mp4a.40.5') !== -1) { - audioCodec = 'mp4a.40.2'; - } else { - audioCodec = 'mp4a.40.5'; - } - } - // in case AAC and HE-AAC audio codecs are signalled in manifest - // force HE-AAC , as it seems that most browsers prefers that way, - // except for mono streams OR on FF - // these conditions might need to be reviewed ... - if (this.audioCodecSwitch) { - // don't force HE-AAC if mono stream - if (track.metadata.channelCount !== 1 && - // don't force HE-AAC if firefox - ua.indexOf('firefox') === -1) { - audioCodec = 'mp4a.40.5'; - } - } - // HE-AAC is broken on Android, always signal audio codec as AAC even if variant manifest states otherwise - if (ua.indexOf('android') !== -1) { - audioCodec = 'mp4a.40.2'; - _logger.logger.log('Android: force audio codec to' + audioCodec); - } - track.levelCodec = audioCodec; - } - track = tracks.video; - if (track) { - track.levelCodec = this.levels[this.level].videoCodec; - } - - // if remuxer specify that a unique track needs to generated, - // let's merge all tracks together - if (data.unique) { - var mergedTrack = { - codec: '', - levelCodec: '' - }; - for (trackName in data.tracks) { - track = tracks[trackName]; - mergedTrack.container = track.container; - if (mergedTrack.codec) { - mergedTrack.codec += ','; - mergedTrack.levelCodec += ','; - } - if (track.codec) { - mergedTrack.codec += track.codec; - } - if (track.levelCodec) { - mergedTrack.levelCodec += track.levelCodec; - } - } - tracks = { audiovideo: mergedTrack }; - } - this.hls.trigger(_events2.default.BUFFER_CODECS, tracks); - // loop through tracks that are going to be provided to bufferController - for (trackName in tracks) { - track = tracks[trackName]; - _logger.logger.log('track:' + trackName + ',container:' + track.container + ',codecs[level/parsed]=[' + track.levelCodec + '/' + track.codec + ']'); - var initSegment = track.initSegment; - if (initSegment) { - this.pendingAppending++; - this.hls.trigger(_events2.default.BUFFER_APPENDING, { type: trackName, data: initSegment }); - } - } - //trigger handler right now - this.tick(); - } - } - }, { - key: 'onFragParsingData', - value: function onFragParsingData(data) { - var _this2 = this; - - if (this.state === State.PARSING) { - this.tparse2 = Date.now(); - var level = this.levels[this.level], - frag = this.fragCurrent; - - _logger.logger.log('parsed ' + data.type + ',PTS:[' + data.startPTS.toFixed(3) + ',' + data.endPTS.toFixed(3) + '],DTS:[' + data.startDTS.toFixed(3) + '/' + data.endDTS.toFixed(3) + '],nb:' + data.nb + ',dropped:' + (data.dropped || 0)); - - var drift = _levelHelper2.default.updateFragPTSDTS(level.details, frag.sn, data.startPTS, data.endPTS, data.startDTS, data.endDTS), - hls = this.hls; - hls.trigger(_events2.default.LEVEL_PTS_UPDATED, { details: level.details, level: this.level, drift: drift }); - - // has remuxer dropped video frames located before first keyframe ? - if (data.type === 'video') { - frag.dropped = data.dropped; - } - - [data.data1, data.data2].forEach(function (buffer) { - if (buffer) { - _this2.pendingAppending++; - hls.trigger(_events2.default.BUFFER_APPENDING, { type: data.type, data: buffer }); - } - }); - - this.nextLoadPosition = data.endPTS; - this.bufferRange.push({ type: data.type, start: data.startPTS, end: data.endPTS, frag: frag }); - - //trigger handler right now - this.tick(); - } else { - _logger.logger.warn('not in PARSING state but ' + this.state + ', ignoring FRAG_PARSING_DATA event'); - } - } - }, { - key: 'onFragParsed', - value: function onFragParsed() { - if (this.state === State.PARSING) { - this.stats.tparsed = performance.now(); - this.state = State.PARSED; - this._checkAppendedParsed(); - } - } - }, { - key: 'onBufferAppended', - value: function onBufferAppended() { - switch (this.state) { - case State.PARSING: - case State.PARSED: - this.pendingAppending--; - this._checkAppendedParsed(); - break; - default: - break; - } - } - }, { - key: '_checkAppendedParsed', - value: function _checkAppendedParsed() { - //trigger handler right now - if (this.state === State.PARSED && this.pendingAppending === 0) { - var frag = this.fragCurrent, - stats = this.stats; - if (frag) { - this.fragPrevious = frag; - stats.tbuffered = performance.now(); - this.fragLastKbps = Math.round(8 * stats.length / (stats.tbuffered - stats.tfirst)); - this.hls.trigger(_events2.default.FRAG_BUFFERED, { stats: stats, frag: frag }); - _logger.logger.log('media buffered : ' + this.timeRangesToString(this.media.buffered)); - this.state = State.IDLE; - } - this.tick(); - } - } - }, { - key: 'onError', - value: function onError(data) { - switch (data.details) { - case _errors.ErrorDetails.FRAG_LOAD_ERROR: - case _errors.ErrorDetails.FRAG_LOAD_TIMEOUT: - if (!data.fatal) { - var loadError = this.fragLoadError; - if (loadError) { - loadError++; - } else { - loadError = 1; - } - if (loadError <= this.config.fragLoadingMaxRetry) { - this.fragLoadError = loadError; - // reset load counter to avoid frag loop loading error - data.frag.loadCounter = 0; - // exponential backoff capped to 64s - var delay = Math.min(Math.pow(2, loadError - 1) * this.config.fragLoadingRetryDelay, 64000); - _logger.logger.warn('mediaController: frag loading failed, retry in ' + delay + ' ms'); - this.retryDate = performance.now() + delay; - // retry loading state - this.state = State.FRAG_LOADING_WAITING_RETRY; - } else { - _logger.logger.error('mediaController: ' + data.details + ' reaches max retry, redispatch as fatal ...'); - // redispatch same error but with fatal set to true - data.fatal = true; - this.hls.trigger(_events2.default.ERROR, data); - this.state = State.ERROR; - } - } - break; - case _errors.ErrorDetails.FRAG_LOOP_LOADING_ERROR: - case _errors.ErrorDetails.LEVEL_LOAD_ERROR: - case _errors.ErrorDetails.LEVEL_LOAD_TIMEOUT: - case _errors.ErrorDetails.KEY_LOAD_ERROR: - case _errors.ErrorDetails.KEY_LOAD_TIMEOUT: - // when in ERROR state, don't switch back to IDLE state in case a non-fatal error is received - if (this.state !== State.ERROR) { - // if fatal error, stop processing, otherwise move to IDLE to retry loading - this.state = data.fatal ? State.ERROR : State.IDLE; - _logger.logger.warn('mediaController: ' + data.details + ' while loading frag,switch to ' + this.state + ' state ...'); - } - break; - case _errors.ErrorDetails.BUFFER_FULL_ERROR: - // only reduce max buf len if in appending state - if (this.state === State.PARSING || this.state === State.PARSED) { - // reduce max buffer length as it might be too high. we do this to avoid loop flushing ... - this.config.maxMaxBufferLength /= 2; - _logger.logger.warn('reduce max buffer length to ' + this.config.maxMaxBufferLength + 's and switch to IDLE state'); - // increase fragment load Index to avoid frag loop loading error after buffer flush - this.fragLoadIdx += 2 * this.config.fragLoadingLoopThreshold; - this.state = State.IDLE; - } - break; - default: - break; - } - } - }, { - key: '_checkBuffer', - value: function _checkBuffer() { - var media = this.media; - // if ready state different from HAVE_NOTHING (numeric value 0), we are allowed to seek - if (media && media.readyState) { - var currentTime = media.currentTime, - buffered = media.buffered; - // adjust currentTime to start position on loaded metadata - if (!this.loadedmetadata && buffered.length) { - this.loadedmetadata = true; - // only adjust currentTime if startPosition not equal to 0 - var startPosition = this.startPosition; - // if currentTime === 0 AND not matching with expected startPosition - if (!currentTime && currentTime !== startPosition) { - if (startPosition) { - _logger.logger.log('target start position:' + startPosition); - // at that stage, there should be only one buffered range, as we reach that code after first fragment has been - var bufferStart = buffered.start(0), - bufferEnd = buffered.end(0); - // if startPosition not buffered, let's seek to buffered.start(0) - if (startPosition < bufferStart || startPosition > bufferEnd) { - startPosition = bufferStart; - _logger.logger.log('target start position not buffered, seek to buffered.start(0) ' + bufferStart); - } - _logger.logger.log('adjust currentTime from ' + currentTime + ' to ' + startPosition); - media.currentTime = startPosition; - } - } - } else { - var bufferInfo = _bufferHelper2.default.bufferInfo(media, currentTime, 0), - expectedPlaying = !(media.paused || // not playing when media is paused - media.ended || // not playing when media is ended - media.buffered.length === 0), - // not playing if nothing buffered - jumpThreshold = 0.4, - // tolerance needed as some browsers stalls playback before reaching buffered range end - playheadMoving = currentTime > media.playbackRate * this.lastCurrentTime; - - if (this.stalled && playheadMoving) { - this.stalled = false; - _logger.logger.log('playback not stuck anymore @' + currentTime); - } - // check buffer upfront - // if less than jumpThreshold second is buffered, let's check in more details - if (expectedPlaying && bufferInfo.len <= jumpThreshold) { - if (playheadMoving) { - // playhead moving - jumpThreshold = 0; - this.seekHoleNudgeDuration = 0; - } else { - // playhead not moving AND media expected to play - if (!this.stalled) { - this.seekHoleNudgeDuration = 0; - _logger.logger.log('playback seems stuck @' + currentTime); - this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.BUFFER_STALLED_ERROR, fatal: false }); - this.stalled = true; - } else { - this.seekHoleNudgeDuration += this.config.seekHoleNudgeDuration; - } - } - // if we are below threshold, try to jump to start of next buffer range if close - if (bufferInfo.len <= jumpThreshold) { - // no buffer available @ currentTime, check if next buffer is close (within a config.maxSeekHole second range) - var nextBufferStart = bufferInfo.nextStart, - delta = nextBufferStart - currentTime; - if (nextBufferStart && delta < this.config.maxSeekHole && delta > 0) { - // next buffer is close ! adjust currentTime to nextBufferStart - // this will ensure effective video decoding - _logger.logger.log('adjust currentTime from ' + media.currentTime + ' to next buffered @ ' + nextBufferStart + ' + nudge ' + this.seekHoleNudgeDuration); - var hole = nextBufferStart + this.seekHoleNudgeDuration - media.currentTime; - media.currentTime = nextBufferStart + this.seekHoleNudgeDuration; - this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.BUFFER_SEEK_OVER_HOLE, fatal: false, hole: hole }); - } - } - } - } - } - } - }, { - key: 'onFragLoadEmergencyAborted', - value: function onFragLoadEmergencyAborted() { - this.state = State.IDLE; - this.tick(); - } - }, { - key: 'onBufferFlushed', - value: function onBufferFlushed() { - /* after successful buffer flushing, rebuild buffer Range array - loop through existing buffer range and check if - corresponding range is still buffered. only push to new array already buffered range - */ - var newRange = [], - range, - i; - for (i = 0; i < this.bufferRange.length; i++) { - range = this.bufferRange[i]; - if (this.isBuffered((range.start + range.end) / 2)) { - newRange.push(range); - } - } - this.bufferRange = newRange; - - // handle end of immediate switching if needed - if (this.immediateSwitch) { - this.immediateLevelSwitchEnd(); - } - // move to IDLE once flush complete. this should trigger new fragment loading - this.state = State.IDLE; - // reset reference to frag - this.fragPrevious = null; - } - }, { - key: 'swapAudioCodec', - value: function swapAudioCodec() { - this.audioCodecSwap = !this.audioCodecSwap; - } - }, { - key: 'timeRangesToString', - value: function timeRangesToString(r) { - var log = '', - len = r.length; - for (var i = 0; i < len; i++) { - log += '[' + r.start(i) + ',' + r.end(i) + ']'; - } - return log; - } - }, { - key: 'currentLevel', - get: function get() { - if (this.media) { - var range = this.getBufferRange(this.media.currentTime); - if (range) { - return range.frag.level; - } - } - return -1; - } - }, { - key: 'nextBufferRange', - get: function get() { - if (this.media) { - // first get end range of current fragment - return this.followingBufferRange(this.getBufferRange(this.media.currentTime)); - } else { - return null; - } - } - }, { - key: 'nextLevel', - get: function get() { - var range = this.nextBufferRange; - if (range) { - return range.frag.level; - } else { - return -1; - } - } - }]); - - return StreamController; -}(_eventHandler2.default); - -exports.default = StreamController; - -},{"../demux/demuxer":17,"../errors":21,"../event-handler":22,"../events":23,"../helper/buffer-helper":24,"../helper/level-helper":25,"../utils/binary-search":35,"../utils/logger":38}],9:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -var _eventHandler = require('../event-handler'); - -var _eventHandler2 = _interopRequireDefault(_eventHandler); - -var _cea708Interpreter = require('../utils/cea-708-interpreter'); - -var _cea708Interpreter2 = _interopRequireDefault(_cea708Interpreter); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* - * Timeline Controller - */ - -var TimelineController = function (_EventHandler) { - _inherits(TimelineController, _EventHandler); - - function TimelineController(hls) { - _classCallCheck(this, TimelineController); - - var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(TimelineController).call(this, hls, _events2.default.MEDIA_ATTACHING, _events2.default.MEDIA_DETACHING, _events2.default.FRAG_PARSING_USERDATA, _events2.default.MANIFEST_LOADING, _events2.default.FRAG_LOADED)); - - _this.hls = hls; - _this.config = hls.config; - - if (_this.config.enableCEA708Captions) { - _this.cea708Interpreter = new _cea708Interpreter2.default(); - } - return _this; - } - - _createClass(TimelineController, [{ - key: 'destroy', - value: function destroy() { - _eventHandler2.default.prototype.destroy.call(this); - } - }, { - key: 'onMediaAttaching', - value: function onMediaAttaching(data) { - var media = this.media = data.media; - this.cea708Interpreter.attach(media); - } - }, { - key: 'onMediaDetaching', - value: function onMediaDetaching() { - this.cea708Interpreter.detach(); - } - }, { - key: 'onManifestLoading', - value: function onManifestLoading() { - this.lastPts = Number.POSITIVE_INFINITY; - } - }, { - key: 'onFragLoaded', - value: function onFragLoaded(data) { - var pts = data.frag.start; //Number.POSITIVE_INFINITY; - - // if this is a frag for a previously loaded timerange, remove all captions - // TODO: consider just removing captions for the timerange - if (pts <= this.lastPts) { - this.cea708Interpreter.clear(); - } - - this.lastPts = pts; - } - }, { - key: 'onFragParsingUserdata', - value: function onFragParsingUserdata(data) { - // push all of the CEA-708 messages into the interpreter - // immediately. It will create the proper timestamps based on our PTS value - for (var i = 0; i < data.samples.length; i++) { - this.cea708Interpreter.push(data.samples[i].pts, data.samples[i].bytes); - } - } - }]); - - return TimelineController; -}(_eventHandler2.default); - -exports.default = TimelineController; - -},{"../event-handler":22,"../events":23,"../utils/cea-708-interpreter":36}],10:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/* - * - * This file contains an adaptation of the AES decryption algorithm - * from the Standford Javascript Cryptography Library. That work is - * covered by the following copyright and permissions notice: - * - * Copyright 2009-2010 Emily Stark, Mike Hamburg, Dan Boneh. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation - * are those of the authors and should not be interpreted as representing - * official policies, either expressed or implied, of the authors. - */ - -var AES = function () { - - /** - * Schedule out an AES key for both encryption and decryption. This - * is a low-level class. Use a cipher mode to do bulk encryption. - * - * @constructor - * @param key {Array} The key as an array of 4, 6 or 8 words. - */ - - function AES(key) { - _classCallCheck(this, AES); - - /** - * The expanded S-box and inverse S-box tables. These will be computed - * on the client so that we don't have to send them down the wire. - * - * There are two tables, _tables[0] is for encryption and - * _tables[1] is for decryption. - * - * The first 4 sub-tables are the expanded S-box with MixColumns. The - * last (_tables[01][4]) is the S-box itself. - * - * @private - */ - this._tables = [[[], [], [], [], []], [[], [], [], [], []]]; - - this._precompute(); - - var i, - j, - tmp, - encKey, - decKey, - sbox = this._tables[0][4], - decTable = this._tables[1], - keyLen = key.length, - rcon = 1; - - if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) { - throw new Error('Invalid aes key size=' + keyLen); - } - - encKey = key.slice(0); - decKey = []; - this._key = [encKey, decKey]; - - // schedule encryption keys - for (i = keyLen; i < 4 * keyLen + 28; i++) { - tmp = encKey[i - 1]; - - // apply sbox - if (i % keyLen === 0 || keyLen === 8 && i % keyLen === 4) { - tmp = sbox[tmp >>> 24] << 24 ^ sbox[tmp >> 16 & 255] << 16 ^ sbox[tmp >> 8 & 255] << 8 ^ sbox[tmp & 255]; - - // shift rows and add rcon - if (i % keyLen === 0) { - tmp = tmp << 8 ^ tmp >>> 24 ^ rcon << 24; - rcon = rcon << 1 ^ (rcon >> 7) * 283; - } - } - - encKey[i] = encKey[i - keyLen] ^ tmp; - } - - // schedule decryption keys - for (j = 0; i; j++, i--) { - tmp = encKey[j & 3 ? i : i - 4]; - if (i <= 4 || j < 4) { - decKey[j] = tmp; - } else { - decKey[j] = decTable[0][sbox[tmp >>> 24]] ^ decTable[1][sbox[tmp >> 16 & 255]] ^ decTable[2][sbox[tmp >> 8 & 255]] ^ decTable[3][sbox[tmp & 255]]; - } - } - } - - /** - * Expand the S-box tables. - * - * @private - */ - - - _createClass(AES, [{ - key: '_precompute', - value: function _precompute() { - var encTable = this._tables[0], - decTable = this._tables[1], - sbox = encTable[4], - sboxInv = decTable[4], - i, - x, - xInv, - d = [], - th = [], - x2, - x4, - x8, - s, - tEnc, - tDec; - - // Compute double and third tables - for (i = 0; i < 256; i++) { - th[(d[i] = i << 1 ^ (i >> 7) * 283) ^ i] = i; - } - - for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) { - // Compute sbox - s = xInv ^ xInv << 1 ^ xInv << 2 ^ xInv << 3 ^ xInv << 4; - s = s >> 8 ^ s & 255 ^ 99; - sbox[x] = s; - sboxInv[s] = x; - - // Compute MixColumns - x8 = d[x4 = d[x2 = d[x]]]; - tDec = x8 * 0x1010101 ^ x4 * 0x10001 ^ x2 * 0x101 ^ x * 0x1010100; - tEnc = d[s] * 0x101 ^ s * 0x1010100; - - for (i = 0; i < 4; i++) { - encTable[i][x] = tEnc = tEnc << 24 ^ tEnc >>> 8; - decTable[i][s] = tDec = tDec << 24 ^ tDec >>> 8; - } - } - - // Compactify. Considerable speedup on Firefox. - for (i = 0; i < 5; i++) { - encTable[i] = encTable[i].slice(0); - decTable[i] = decTable[i].slice(0); - } - } - - /** - * Decrypt 16 bytes, specified as four 32-bit words. - * @param encrypted0 {number} the first word to decrypt - * @param encrypted1 {number} the second word to decrypt - * @param encrypted2 {number} the third word to decrypt - * @param encrypted3 {number} the fourth word to decrypt - * @param out {Int32Array} the array to write the decrypted words - * into - * @param offset {number} the offset into the output array to start - * writing results - * @return {Array} The plaintext. - */ - - }, { - key: 'decrypt', - value: function decrypt(encrypted0, encrypted1, encrypted2, encrypted3, out, offset) { - var key = this._key[1], - - // state variables a,b,c,d are loaded with pre-whitened data - a = encrypted0 ^ key[0], - b = encrypted3 ^ key[1], - c = encrypted2 ^ key[2], - d = encrypted1 ^ key[3], - a2, - b2, - c2, - nInnerRounds = key.length / 4 - 2, - // key.length === 2 ? - i, - kIndex = 4, - table = this._tables[1], - - - // load up the tables - table0 = table[0], - table1 = table[1], - table2 = table[2], - table3 = table[3], - sbox = table[4]; - - // Inner rounds. Cribbed from OpenSSL. - for (i = 0; i < nInnerRounds; i++) { - a2 = table0[a >>> 24] ^ table1[b >> 16 & 255] ^ table2[c >> 8 & 255] ^ table3[d & 255] ^ key[kIndex]; - b2 = table0[b >>> 24] ^ table1[c >> 16 & 255] ^ table2[d >> 8 & 255] ^ table3[a & 255] ^ key[kIndex + 1]; - c2 = table0[c >>> 24] ^ table1[d >> 16 & 255] ^ table2[a >> 8 & 255] ^ table3[b & 255] ^ key[kIndex + 2]; - d = table0[d >>> 24] ^ table1[a >> 16 & 255] ^ table2[b >> 8 & 255] ^ table3[c & 255] ^ key[kIndex + 3]; - kIndex += 4; - a = a2;b = b2;c = c2; - } - - // Last round. - for (i = 0; i < 4; i++) { - out[(3 & -i) + offset] = sbox[a >>> 24] << 24 ^ sbox[b >> 16 & 255] << 16 ^ sbox[c >> 8 & 255] << 8 ^ sbox[d & 255] ^ key[kIndex++]; - a2 = a;a = b;b = c;c = d;d = a2; - } - } - }]); - - return AES; -}(); - -exports.default = AES; - -},{}],11:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /* - * - * This file contains an adaptation of the AES decryption algorithm - * from the Standford Javascript Cryptography Library. That work is - * covered by the following copyright and permissions notice: - * - * Copyright 2009-2010 Emily Stark, Mike Hamburg, Dan Boneh. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation - * are those of the authors and should not be interpreted as representing - * official policies, either expressed or implied, of the authors. - */ - -var _aes = require('./aes'); - -var _aes2 = _interopRequireDefault(_aes); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var AES128Decrypter = function () { - function AES128Decrypter(key, initVector) { - _classCallCheck(this, AES128Decrypter); - - this.key = key; - this.iv = initVector; - } - - /** - * Convert network-order (big-endian) bytes into their little-endian - * representation. - */ - - - _createClass(AES128Decrypter, [{ - key: 'ntoh', - value: function ntoh(word) { - return word << 24 | (word & 0xff00) << 8 | (word & 0xff0000) >> 8 | word >>> 24; - } - - /** - * Decrypt bytes using AES-128 with CBC and PKCS#7 padding. - * @param encrypted {Uint8Array} the encrypted bytes - * @param key {Uint32Array} the bytes of the decryption key - * @param initVector {Uint32Array} the initialization vector (IV) to - * use for the first round of CBC. - * @return {Uint8Array} the decrypted bytes - * - * @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard - * @see http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29 - * @see https://tools.ietf.org/html/rfc2315 - */ - - }, { - key: 'doDecrypt', - value: function doDecrypt(encrypted, key, initVector) { - var - // word-level access to the encrypted bytes - encrypted32 = new Int32Array(encrypted.buffer, encrypted.byteOffset, encrypted.byteLength >> 2), - decipher = new _aes2.default(Array.prototype.slice.call(key)), - - - // byte and word-level access for the decrypted output - decrypted = new Uint8Array(encrypted.byteLength), - decrypted32 = new Int32Array(decrypted.buffer), - - - // temporary variables for working with the IV, encrypted, and - // decrypted data - init0, - init1, - init2, - init3, - encrypted0, - encrypted1, - encrypted2, - encrypted3, - - - // iteration variable - wordIx; - - // pull out the words of the IV to ensure we don't modify the - // passed-in reference and easier access - init0 = ~ ~initVector[0]; - init1 = ~ ~initVector[1]; - init2 = ~ ~initVector[2]; - init3 = ~ ~initVector[3]; - - // decrypt four word sequences, applying cipher-block chaining (CBC) - // to each decrypted block - for (wordIx = 0; wordIx < encrypted32.length; wordIx += 4) { - // convert big-endian (network order) words into little-endian - // (javascript order) - encrypted0 = ~ ~this.ntoh(encrypted32[wordIx]); - encrypted1 = ~ ~this.ntoh(encrypted32[wordIx + 1]); - encrypted2 = ~ ~this.ntoh(encrypted32[wordIx + 2]); - encrypted3 = ~ ~this.ntoh(encrypted32[wordIx + 3]); - - // decrypt the block - decipher.decrypt(encrypted0, encrypted1, encrypted2, encrypted3, decrypted32, wordIx); - - // XOR with the IV, and restore network byte-order to obtain the - // plaintext - decrypted32[wordIx] = this.ntoh(decrypted32[wordIx] ^ init0); - decrypted32[wordIx + 1] = this.ntoh(decrypted32[wordIx + 1] ^ init1); - decrypted32[wordIx + 2] = this.ntoh(decrypted32[wordIx + 2] ^ init2); - decrypted32[wordIx + 3] = this.ntoh(decrypted32[wordIx + 3] ^ init3); - - // setup the IV for the next round - init0 = encrypted0; - init1 = encrypted1; - init2 = encrypted2; - init3 = encrypted3; - } - - return decrypted; - } - }, { - key: 'localDecrypt', - value: function localDecrypt(encrypted, key, initVector, decrypted) { - var bytes = this.doDecrypt(encrypted, key, initVector); - decrypted.set(bytes, encrypted.byteOffset); - } - }, { - key: 'decrypt', - value: function decrypt(encrypted) { - var step = 4 * 8000, - - //encrypted32 = new Int32Array(encrypted.buffer), - encrypted32 = new Int32Array(encrypted), - decrypted = new Uint8Array(encrypted.byteLength), - i = 0; - - // split up the encryption job and do the individual chunks asynchronously - var key = this.key; - var initVector = this.iv; - this.localDecrypt(encrypted32.subarray(i, i + step), key, initVector, decrypted); - - for (i = step; i < encrypted32.length; i += step) { - initVector = new Uint32Array([this.ntoh(encrypted32[i - 4]), this.ntoh(encrypted32[i - 3]), this.ntoh(encrypted32[i - 2]), this.ntoh(encrypted32[i - 1])]); - this.localDecrypt(encrypted32.subarray(i, i + step), key, initVector, decrypted); - } - - return decrypted; - } - }]); - - return AES128Decrypter; -}(); - -exports.default = AES128Decrypter; - -},{"./aes":10}],12:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /* - * AES128 decryption. - */ - -var _aes128Decrypter = require('./aes128-decrypter'); - -var _aes128Decrypter2 = _interopRequireDefault(_aes128Decrypter); - -var _errors = require('../errors'); - -var _logger = require('../utils/logger'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var Decrypter = function () { - function Decrypter(hls) { - _classCallCheck(this, Decrypter); - - this.hls = hls; - try { - var browserCrypto = window ? window.crypto : crypto; - this.subtle = browserCrypto.subtle || browserCrypto.webkitSubtle; - this.disableWebCrypto = !this.subtle; - } catch (e) { - this.disableWebCrypto = true; - } - } - - _createClass(Decrypter, [{ - key: 'destroy', - value: function destroy() {} - }, { - key: 'decrypt', - value: function decrypt(data, key, iv, callback) { - if (this.disableWebCrypto && this.hls.config.enableSoftwareAES) { - this.decryptBySoftware(data, key, iv, callback); - } else { - this.decryptByWebCrypto(data, key, iv, callback); - } - } - }, { - key: 'decryptByWebCrypto', - value: function decryptByWebCrypto(data, key, iv, callback) { - var _this = this; - - _logger.logger.log('decrypting by WebCrypto API'); - - this.subtle.importKey('raw', key, { name: 'AES-CBC', length: 128 }, false, ['decrypt']).then(function (importedKey) { - _this.subtle.decrypt({ name: 'AES-CBC', iv: iv.buffer }, importedKey, data).then(callback).catch(function (err) { - _this.onWebCryptoError(err, data, key, iv, callback); - }); - }).catch(function (err) { - _this.onWebCryptoError(err, data, key, iv, callback); - }); - } - }, { - key: 'decryptBySoftware', - value: function decryptBySoftware(data, key8, iv8, callback) { - _logger.logger.log('decrypting by JavaScript Implementation'); - - var view = new DataView(key8.buffer); - var key = new Uint32Array([view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)]); - - view = new DataView(iv8.buffer); - var iv = new Uint32Array([view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12)]); - - var decrypter = new _aes128Decrypter2.default(key, iv); - callback(decrypter.decrypt(data).buffer); - } - }, { - key: 'onWebCryptoError', - value: function onWebCryptoError(err, data, key, iv, callback) { - if (this.hls.config.enableSoftwareAES) { - _logger.logger.log('disabling to use WebCrypto API'); - this.disableWebCrypto = true; - this.decryptBySoftware(data, key, iv, callback); - } else { - _logger.logger.error('decrypting error : ' + err.message); - this.hls.trigger(Event.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.FRAG_DECRYPT_ERROR, fatal: true, reason: err.message }); - } - } - }]); - - return Decrypter; -}(); - -exports.default = Decrypter; - -},{"../errors":21,"../utils/logger":38,"./aes128-decrypter":11}],13:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * AAC demuxer - */ - - -var _adts = require('./adts'); - -var _adts2 = _interopRequireDefault(_adts); - -var _logger = require('../utils/logger'); - -var _id = require('../demux/id3'); - -var _id2 = _interopRequireDefault(_id); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var AACDemuxer = function () { - function AACDemuxer(observer, remuxerClass) { - _classCallCheck(this, AACDemuxer); - - this.observer = observer; - this.remuxerClass = remuxerClass; - this.remuxer = new this.remuxerClass(observer); - this._aacTrack = { container: 'audio/adts', type: 'audio', id: -1, sequenceNumber: 0, samples: [], len: 0 }; - } - - _createClass(AACDemuxer, [{ - key: 'push', - - - // feed incoming data to the front of the parsing pipeline - value: function push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) { - var track = this._aacTrack, - id3 = new _id2.default(data), - pts = 90 * id3.timeStamp, - config, - frameLength, - frameDuration, - frameIndex, - offset, - headerLength, - stamp, - len, - aacSample; - // look for ADTS header (0xFFFx) - for (offset = id3.length, len = data.length; offset < len - 1; offset++) { - if (data[offset] === 0xff && (data[offset + 1] & 0xf0) === 0xf0) { - break; - } - } - - if (!track.audiosamplerate) { - config = _adts2.default.getAudioConfig(this.observer, data, offset, audioCodec); - track.config = config.config; - track.audiosamplerate = config.samplerate; - track.channelCount = config.channelCount; - track.codec = config.codec; - track.duration = duration; - _logger.logger.log('parsed codec:' + track.codec + ',rate:' + config.samplerate + ',nb channel:' + config.channelCount); - } - frameIndex = 0; - frameDuration = 1024 * 90000 / track.audiosamplerate; - while (offset + 5 < len) { - // The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header - headerLength = !!(data[offset + 1] & 0x01) ? 7 : 9; - // retrieve frame size - frameLength = (data[offset + 3] & 0x03) << 11 | data[offset + 4] << 3 | (data[offset + 5] & 0xE0) >>> 5; - frameLength -= headerLength; - //stamp = pes.pts; - - if (frameLength > 0 && offset + headerLength + frameLength <= len) { - stamp = pts + frameIndex * frameDuration; - //logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}/${(stamp/90).toFixed(0)}`); - aacSample = { unit: data.subarray(offset + headerLength, offset + headerLength + frameLength), pts: stamp, dts: stamp }; - track.samples.push(aacSample); - track.len += frameLength; - offset += frameLength + headerLength; - frameIndex++; - // look for ADTS header (0xFFFx) - for (; offset < len - 1; offset++) { - if (data[offset] === 0xff && (data[offset + 1] & 0xf0) === 0xf0) { - break; - } - } - } else { - break; - } - } - this.remuxer.remux(this._aacTrack, { samples: [] }, { samples: [{ pts: pts, dts: pts, unit: id3.payload }] }, { samples: [] }, timeOffset); - } - }, { - key: 'destroy', - value: function destroy() {} - }], [{ - key: 'probe', - value: function probe(data) { - // check if data contains ID3 timestamp and ADTS sync worc - var id3 = new _id2.default(data), - offset, - len; - if (id3.hasTimeStamp) { - // look for ADTS header (0xFFFx) - for (offset = id3.length, len = data.length; offset < len - 1; offset++) { - if (data[offset] === 0xff && (data[offset + 1] & 0xf0) === 0xf0) { - //logger.log('ADTS sync word found !'); - return true; - } - } - } - return false; - } - }]); - - return AACDemuxer; -}(); - -exports.default = AACDemuxer; - -},{"../demux/id3":19,"../utils/logger":38,"./adts":14}],14:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * ADTS parser helper - */ - - -var _logger = require('../utils/logger'); - -var _errors = require('../errors'); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var ADTS = function () { - function ADTS() { - _classCallCheck(this, ADTS); - } - - _createClass(ADTS, null, [{ - key: 'getAudioConfig', - value: function getAudioConfig(observer, data, offset, audioCodec) { - var adtsObjectType, - // :int - adtsSampleingIndex, - // :int - adtsExtensionSampleingIndex, - // :int - adtsChanelConfig, - // :int - config, - userAgent = navigator.userAgent.toLowerCase(), - adtsSampleingRates = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350]; - // byte 2 - adtsObjectType = ((data[offset + 2] & 0xC0) >>> 6) + 1; - adtsSampleingIndex = (data[offset + 2] & 0x3C) >>> 2; - if (adtsSampleingIndex > adtsSampleingRates.length - 1) { - observer.trigger(Event.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.FRAG_PARSING_ERROR, fatal: true, reason: 'invalid ADTS sampling index:' + adtsSampleingIndex }); - return; - } - adtsChanelConfig = (data[offset + 2] & 0x01) << 2; - // byte 3 - adtsChanelConfig |= (data[offset + 3] & 0xC0) >>> 6; - _logger.logger.log('manifest codec:' + audioCodec + ',ADTS data:type:' + adtsObjectType + ',sampleingIndex:' + adtsSampleingIndex + '[' + adtsSampleingRates[adtsSampleingIndex] + 'Hz],channelConfig:' + adtsChanelConfig); - // firefox: freq less than 24kHz = AAC SBR (HE-AAC) - if (userAgent.indexOf('firefox') !== -1) { - if (adtsSampleingIndex >= 6) { - adtsObjectType = 5; - config = new Array(4); - // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies - // there is a factor 2 between frame sample rate and output sample rate - // multiply frequency by 2 (see table below, equivalent to substract 3) - adtsExtensionSampleingIndex = adtsSampleingIndex - 3; - } else { - adtsObjectType = 2; - config = new Array(2); - adtsExtensionSampleingIndex = adtsSampleingIndex; - } - // Android : always use AAC - } else if (userAgent.indexOf('android') !== -1) { - adtsObjectType = 2; - config = new Array(2); - adtsExtensionSampleingIndex = adtsSampleingIndex; - } else { - /* for other browsers (chrome ...) - always force audio type to be HE-AAC SBR, as some browsers do not support audio codec switch properly (like Chrome ...) - */ - adtsObjectType = 5; - config = new Array(4); - // if (manifest codec is HE-AAC or HE-AACv2) OR (manifest codec not specified AND frequency less than 24kHz) - if (audioCodec && (audioCodec.indexOf('mp4a.40.29') !== -1 || audioCodec.indexOf('mp4a.40.5') !== -1) || !audioCodec && adtsSampleingIndex >= 6) { - // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies - // there is a factor 2 between frame sample rate and output sample rate - // multiply frequency by 2 (see table below, equivalent to substract 3) - adtsExtensionSampleingIndex = adtsSampleingIndex - 3; - } else { - // if (manifest codec is AAC) AND (frequency less than 24kHz AND nb channel is 1) OR (manifest codec not specified and mono audio) - // Chrome fails to play back with low frequency AAC LC mono when initialized with HE-AAC. This is not a problem with stereo. - if (audioCodec && audioCodec.indexOf('mp4a.40.2') !== -1 && adtsSampleingIndex >= 6 && adtsChanelConfig === 1 || !audioCodec && adtsChanelConfig === 1) { - adtsObjectType = 2; - config = new Array(2); - } - adtsExtensionSampleingIndex = adtsSampleingIndex; - } - } - /* refer to http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Audio_Specific_Config - ISO 14496-3 (AAC).pdf - Table 1.13 — Syntax of AudioSpecificConfig() - Audio Profile / Audio Object Type - 0: Null - 1: AAC Main - 2: AAC LC (Low Complexity) - 3: AAC SSR (Scalable Sample Rate) - 4: AAC LTP (Long Term Prediction) - 5: SBR (Spectral Band Replication) - 6: AAC Scalable - sampling freq - 0: 96000 Hz - 1: 88200 Hz - 2: 64000 Hz - 3: 48000 Hz - 4: 44100 Hz - 5: 32000 Hz - 6: 24000 Hz - 7: 22050 Hz - 8: 16000 Hz - 9: 12000 Hz - 10: 11025 Hz - 11: 8000 Hz - 12: 7350 Hz - 13: Reserved - 14: Reserved - 15: frequency is written explictly - Channel Configurations - These are the channel configurations: - 0: Defined in AOT Specifc Config - 1: 1 channel: front-center - 2: 2 channels: front-left, front-right - */ - // audioObjectType = profile => profile, the MPEG-4 Audio Object Type minus 1 - config[0] = adtsObjectType << 3; - // samplingFrequencyIndex - config[0] |= (adtsSampleingIndex & 0x0E) >> 1; - config[1] |= (adtsSampleingIndex & 0x01) << 7; - // channelConfiguration - config[1] |= adtsChanelConfig << 3; - if (adtsObjectType === 5) { - // adtsExtensionSampleingIndex - config[1] |= (adtsExtensionSampleingIndex & 0x0E) >> 1; - config[2] = (adtsExtensionSampleingIndex & 0x01) << 7; - // adtsObjectType (force to 2, chrome is checking that object type is less than 5 ??? - // https://chromium.googlesource.com/chromium/src.git/+/master/media/formats/mp4/aac.cc - config[2] |= 2 << 2; - config[3] = 0; - } - return { config: config, samplerate: adtsSampleingRates[adtsSampleingIndex], channelCount: adtsChanelConfig, codec: 'mp4a.40.' + adtsObjectType }; - } - }]); - - return ADTS; -}(); - -exports.default = ADTS; - -},{"../errors":21,"../utils/logger":38}],15:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /* inline demuxer. - * probe fragments and instantiate appropriate demuxer depending on content type (TSDemuxer, AACDemuxer, ...) - */ - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -var _errors = require('../errors'); - -var _aacdemuxer = require('../demux/aacdemuxer'); - -var _aacdemuxer2 = _interopRequireDefault(_aacdemuxer); - -var _tsdemuxer = require('../demux/tsdemuxer'); - -var _tsdemuxer2 = _interopRequireDefault(_tsdemuxer); - -var _mp4Remuxer = require('../remux/mp4-remuxer'); - -var _mp4Remuxer2 = _interopRequireDefault(_mp4Remuxer); - -var _passthroughRemuxer = require('../remux/passthrough-remuxer'); - -var _passthroughRemuxer2 = _interopRequireDefault(_passthroughRemuxer); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var DemuxerInline = function () { - function DemuxerInline(hls, typeSupported) { - _classCallCheck(this, DemuxerInline); - - this.hls = hls; - this.typeSupported = typeSupported; - } - - _createClass(DemuxerInline, [{ - key: 'destroy', - value: function destroy() { - var demuxer = this.demuxer; - if (demuxer) { - demuxer.destroy(); - } - } - }, { - key: 'push', - value: function push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) { - var demuxer = this.demuxer; - if (!demuxer) { - var hls = this.hls; - // probe for content type - if (_tsdemuxer2.default.probe(data)) { - if (this.typeSupported.mp2t === true) { - demuxer = new _tsdemuxer2.default(hls, _passthroughRemuxer2.default); - } else { - demuxer = new _tsdemuxer2.default(hls, _mp4Remuxer2.default); - } - } else if (_aacdemuxer2.default.probe(data)) { - demuxer = new _aacdemuxer2.default(hls, _mp4Remuxer2.default); - } else { - hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.FRAG_PARSING_ERROR, fatal: true, reason: 'no demux matching with content found' }); - return; - } - this.demuxer = demuxer; - } - demuxer.push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration); - } - }]); - - return DemuxerInline; -}(); - -exports.default = DemuxerInline; - -},{"../demux/aacdemuxer":13,"../demux/tsdemuxer":20,"../errors":21,"../events":23,"../remux/mp4-remuxer":32,"../remux/passthrough-remuxer":33}],16:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _demuxerInline = require('../demux/demuxer-inline'); - -var _demuxerInline2 = _interopRequireDefault(_demuxerInline); - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -var _events3 = require('events'); - -var _events4 = _interopRequireDefault(_events3); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var DemuxerWorker = function DemuxerWorker(self) { - // observer setup - var observer = new _events4.default(); - observer.trigger = function trigger(event) { - for (var _len = arguments.length, data = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - data[_key - 1] = arguments[_key]; - } - - observer.emit.apply(observer, [event, event].concat(data)); - }; - - observer.off = function off(event) { - for (var _len2 = arguments.length, data = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { - data[_key2 - 1] = arguments[_key2]; - } - - observer.removeListener.apply(observer, [event].concat(data)); - }; - self.addEventListener('message', function (ev) { - var data = ev.data; - //console.log('demuxer cmd:' + data.cmd); - switch (data.cmd) { - case 'init': - self.demuxer = new _demuxerInline2.default(observer, data.typeSupported); - break; - case 'demux': - self.demuxer.push(new Uint8Array(data.data), data.audioCodec, data.videoCodec, data.timeOffset, data.cc, data.level, data.sn, data.duration); - break; - default: - break; - } - }); - - // listen to events triggered by Demuxer - observer.on(_events2.default.FRAG_PARSING_INIT_SEGMENT, function (ev, data) { - self.postMessage({ event: ev, tracks: data.tracks, unique: data.unique }); - }); - - observer.on(_events2.default.FRAG_PARSING_DATA, function (ev, data) { - var objData = { event: ev, type: data.type, startPTS: data.startPTS, endPTS: data.endPTS, startDTS: data.startDTS, endDTS: data.endDTS, data1: data.data1.buffer, data2: data.data2.buffer, nb: data.nb, dropped: data.dropped }; - // pass data1/data2 as transferable object (no copy) - self.postMessage(objData, [objData.data1, objData.data2]); - }); - - observer.on(_events2.default.FRAG_PARSED, function (event) { - self.postMessage({ event: event }); - }); - - observer.on(_events2.default.ERROR, function (event, data) { - self.postMessage({ event: event, data: data }); - }); - - observer.on(_events2.default.FRAG_PARSING_METADATA, function (event, data) { - var objData = { event: event, samples: data.samples }; - self.postMessage(objData); - }); - - observer.on(_events2.default.FRAG_PARSING_USERDATA, function (event, data) { - var objData = { event: event, samples: data.samples }; - self.postMessage(objData); - }); -}; /* demuxer web worker. - * - listen to worker message, and trigger DemuxerInline upon reception of Fragments. - * - provides MP4 Boxes back to main thread using [transferable objects](https://developers.google.com/web/updates/2011/12/Transferable-Objects-Lightning-Fast) in order to minimize message passing overhead. - */ - -exports.default = DemuxerWorker; - -},{"../demux/demuxer-inline":15,"../events":23,"events":1}],17:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -var _demuxerInline = require('../demux/demuxer-inline'); - -var _demuxerInline2 = _interopRequireDefault(_demuxerInline); - -var _demuxerWorker = require('../demux/demuxer-worker'); - -var _demuxerWorker2 = _interopRequireDefault(_demuxerWorker); - -var _logger = require('../utils/logger'); - -var _decrypter = require('../crypt/decrypter'); - -var _decrypter2 = _interopRequireDefault(_decrypter); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var Demuxer = function () { - function Demuxer(hls) { - _classCallCheck(this, Demuxer); - - this.hls = hls; - var typeSupported = { - mp4: MediaSource.isTypeSupported('video/mp4'), - mp2t: hls.config.enableMP2TPassThrough && MediaSource.isTypeSupported('video/mp2t') - }; - if (hls.config.enableWorker && typeof Worker !== 'undefined') { - _logger.logger.log('demuxing in webworker'); - try { - var work = require('webworkify'); - this.w = work(_demuxerWorker2.default); - this.onwmsg = this.onWorkerMessage.bind(this); - this.w.addEventListener('message', this.onwmsg); - this.w.postMessage({ cmd: 'init', typeSupported: typeSupported }); - } catch (err) { - _logger.logger.error('error while initializing DemuxerWorker, fallback on DemuxerInline'); - this.demuxer = new _demuxerInline2.default(hls, typeSupported); - } - } else { - this.demuxer = new _demuxerInline2.default(hls, typeSupported); - } - this.demuxInitialized = true; - } - - _createClass(Demuxer, [{ - key: 'destroy', - value: function destroy() { - if (this.w) { - this.w.removeEventListener('message', this.onwmsg); - this.w.terminate(); - this.w = null; - } else { - this.demuxer.destroy(); - this.demuxer = null; - } - if (this.decrypter) { - this.decrypter.destroy(); - this.decrypter = null; - } - } - }, { - key: 'pushDecrypted', - value: function pushDecrypted(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) { - if (this.w) { - // post fragment payload as transferable objects (no copy) - this.w.postMessage({ cmd: 'demux', data: data, audioCodec: audioCodec, videoCodec: videoCodec, timeOffset: timeOffset, cc: cc, level: level, sn: sn, duration: duration }, [data]); - } else { - this.demuxer.push(new Uint8Array(data), audioCodec, videoCodec, timeOffset, cc, level, sn, duration); - } - } - }, { - key: 'push', - value: function push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration, decryptdata) { - if (data.byteLength > 0 && decryptdata != null && decryptdata.key != null && decryptdata.method === 'AES-128') { - if (this.decrypter == null) { - this.decrypter = new _decrypter2.default(this.hls); - } - - var localthis = this; - this.decrypter.decrypt(data, decryptdata.key, decryptdata.iv, function (decryptedData) { - localthis.pushDecrypted(decryptedData, audioCodec, videoCodec, timeOffset, cc, level, sn, duration); - }); - } else { - this.pushDecrypted(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration); - } - } - }, { - key: 'onWorkerMessage', - value: function onWorkerMessage(ev) { - var data = ev.data; - //console.log('onWorkerMessage:' + data.event); - switch (data.event) { - case _events2.default.FRAG_PARSING_INIT_SEGMENT: - var obj = {}; - obj.tracks = data.tracks; - obj.unique = data.unique; - this.hls.trigger(_events2.default.FRAG_PARSING_INIT_SEGMENT, obj); - break; - case _events2.default.FRAG_PARSING_DATA: - this.hls.trigger(_events2.default.FRAG_PARSING_DATA, { - data1: new Uint8Array(data.data1), - data2: new Uint8Array(data.data2), - startPTS: data.startPTS, - endPTS: data.endPTS, - startDTS: data.startDTS, - endDTS: data.endDTS, - type: data.type, - nb: data.nb, - dropped: data.dropped - }); - break; - case _events2.default.FRAG_PARSING_METADATA: - this.hls.trigger(_events2.default.FRAG_PARSING_METADATA, { - samples: data.samples - }); - break; - case _events2.default.FRAG_PARSING_USERDATA: - this.hls.trigger(_events2.default.FRAG_PARSING_USERDATA, { - samples: data.samples - }); - break; - default: - this.hls.trigger(data.event, data.data); - break; - } - } - }]); - - return Demuxer; -}(); - -exports.default = Demuxer; - -},{"../crypt/decrypter":12,"../demux/demuxer-inline":15,"../demux/demuxer-worker":16,"../events":23,"../utils/logger":38,"webworkify":2}],18:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264. - */ - -var _logger = require('../utils/logger'); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var ExpGolomb = function () { - function ExpGolomb(data) { - _classCallCheck(this, ExpGolomb); - - this.data = data; - // the number of bytes left to examine in this.data - this.bytesAvailable = this.data.byteLength; - // the current word being examined - this.word = 0; // :uint - // the number of bits left to examine in the current word - this.bitsAvailable = 0; // :uint - } - - // ():void - - - _createClass(ExpGolomb, [{ - key: 'loadWord', - value: function loadWord() { - var position = this.data.byteLength - this.bytesAvailable, - workingBytes = new Uint8Array(4), - availableBytes = Math.min(4, this.bytesAvailable); - if (availableBytes === 0) { - throw new Error('no bytes available'); - } - workingBytes.set(this.data.subarray(position, position + availableBytes)); - this.word = new DataView(workingBytes.buffer).getUint32(0); - // track the amount of this.data that has been processed - this.bitsAvailable = availableBytes * 8; - this.bytesAvailable -= availableBytes; - } - - // (count:int):void - - }, { - key: 'skipBits', - value: function skipBits(count) { - var skipBytes; // :int - if (this.bitsAvailable > count) { - this.word <<= count; - this.bitsAvailable -= count; - } else { - count -= this.bitsAvailable; - skipBytes = count >> 3; - count -= skipBytes >> 3; - this.bytesAvailable -= skipBytes; - this.loadWord(); - this.word <<= count; - this.bitsAvailable -= count; - } - } - - // (size:int):uint - - }, { - key: 'readBits', - value: function readBits(size) { - var bits = Math.min(this.bitsAvailable, size), - // :uint - valu = this.word >>> 32 - bits; // :uint - if (size > 32) { - _logger.logger.error('Cannot read more than 32 bits at a time'); - } - this.bitsAvailable -= bits; - if (this.bitsAvailable > 0) { - this.word <<= bits; - } else if (this.bytesAvailable > 0) { - this.loadWord(); - } - bits = size - bits; - if (bits > 0) { - return valu << bits | this.readBits(bits); - } else { - return valu; - } - } - - // ():uint - - }, { - key: 'skipLZ', - value: function skipLZ() { - var leadingZeroCount; // :uint - for (leadingZeroCount = 0; leadingZeroCount < this.bitsAvailable; ++leadingZeroCount) { - if (0 !== (this.word & 0x80000000 >>> leadingZeroCount)) { - // the first bit of working word is 1 - this.word <<= leadingZeroCount; - this.bitsAvailable -= leadingZeroCount; - return leadingZeroCount; - } - } - // we exhausted word and still have not found a 1 - this.loadWord(); - return leadingZeroCount + this.skipLZ(); - } - - // ():void - - }, { - key: 'skipUEG', - value: function skipUEG() { - this.skipBits(1 + this.skipLZ()); - } - - // ():void - - }, { - key: 'skipEG', - value: function skipEG() { - this.skipBits(1 + this.skipLZ()); - } - - // ():uint - - }, { - key: 'readUEG', - value: function readUEG() { - var clz = this.skipLZ(); // :uint - return this.readBits(clz + 1) - 1; - } - - // ():int - - }, { - key: 'readEG', - value: function readEG() { - var valu = this.readUEG(); // :int - if (0x01 & valu) { - // the number is odd if the low order bit is set - return 1 + valu >>> 1; // add 1 to make it even, and divide by 2 - } else { - return -1 * (valu >>> 1); // divide by two then make it negative - } - } - - // Some convenience functions - // :Boolean - - }, { - key: 'readBoolean', - value: function readBoolean() { - return 1 === this.readBits(1); - } - - // ():int - - }, { - key: 'readUByte', - value: function readUByte() { - return this.readBits(8); - } - - // ():int - - }, { - key: 'readUShort', - value: function readUShort() { - return this.readBits(16); - } - // ():int - - }, { - key: 'readUInt', - value: function readUInt() { - return this.readBits(32); - } - - /** - * Advance the ExpGolomb decoder past a scaling list. The scaling - * list is optionally transmitted as part of a sequence parameter - * set and is not relevant to transmuxing. - * @param count {number} the number of entries in this scaling list - * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1 - */ - - }, { - key: 'skipScalingList', - value: function skipScalingList(count) { - var lastScale = 8, - nextScale = 8, - j, - deltaScale; - for (j = 0; j < count; j++) { - if (nextScale !== 0) { - deltaScale = this.readEG(); - nextScale = (lastScale + deltaScale + 256) % 256; - } - lastScale = nextScale === 0 ? lastScale : nextScale; - } - } - - /** - * Read a sequence parameter set and return some interesting video - * properties. A sequence parameter set is the H264 metadata that - * describes the properties of upcoming video frames. - * @param data {Uint8Array} the bytes of a sequence parameter set - * @return {object} an object with configuration parsed from the - * sequence parameter set, including the dimensions of the - * associated video frames. - */ - - }, { - key: 'readSPS', - value: function readSPS() { - var frameCropLeftOffset = 0, - frameCropRightOffset = 0, - frameCropTopOffset = 0, - frameCropBottomOffset = 0, - sarScale = 1, - profileIdc, - profileCompat, - levelIdc, - numRefFramesInPicOrderCntCycle, - picWidthInMbsMinus1, - picHeightInMapUnitsMinus1, - frameMbsOnlyFlag, - scalingListCount, - i; - this.readUByte(); - profileIdc = this.readUByte(); // profile_idc - profileCompat = this.readBits(5); // constraint_set[0-4]_flag, u(5) - this.skipBits(3); // reserved_zero_3bits u(3), - levelIdc = this.readUByte(); //level_idc u(8) - this.skipUEG(); // seq_parameter_set_id - // some profiles have more optional data we don't need - if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 || profileIdc === 244 || profileIdc === 44 || profileIdc === 83 || profileIdc === 86 || profileIdc === 118 || profileIdc === 128) { - var chromaFormatIdc = this.readUEG(); - if (chromaFormatIdc === 3) { - this.skipBits(1); // separate_colour_plane_flag - } - this.skipUEG(); // bit_depth_luma_minus8 - this.skipUEG(); // bit_depth_chroma_minus8 - this.skipBits(1); // qpprime_y_zero_transform_bypass_flag - if (this.readBoolean()) { - // seq_scaling_matrix_present_flag - scalingListCount = chromaFormatIdc !== 3 ? 8 : 12; - for (i = 0; i < scalingListCount; i++) { - if (this.readBoolean()) { - // seq_scaling_list_present_flag[ i ] - if (i < 6) { - this.skipScalingList(16); - } else { - this.skipScalingList(64); - } - } - } - } - } - this.skipUEG(); // log2_max_frame_num_minus4 - var picOrderCntType = this.readUEG(); - if (picOrderCntType === 0) { - this.readUEG(); //log2_max_pic_order_cnt_lsb_minus4 - } else if (picOrderCntType === 1) { - this.skipBits(1); // delta_pic_order_always_zero_flag - this.skipEG(); // offset_for_non_ref_pic - this.skipEG(); // offset_for_top_to_bottom_field - numRefFramesInPicOrderCntCycle = this.readUEG(); - for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) { - this.skipEG(); // offset_for_ref_frame[ i ] - } - } - this.skipUEG(); // max_num_ref_frames - this.skipBits(1); // gaps_in_frame_num_value_allowed_flag - picWidthInMbsMinus1 = this.readUEG(); - picHeightInMapUnitsMinus1 = this.readUEG(); - frameMbsOnlyFlag = this.readBits(1); - if (frameMbsOnlyFlag === 0) { - this.skipBits(1); // mb_adaptive_frame_field_flag - } - this.skipBits(1); // direct_8x8_inference_flag - if (this.readBoolean()) { - // frame_cropping_flag - frameCropLeftOffset = this.readUEG(); - frameCropRightOffset = this.readUEG(); - frameCropTopOffset = this.readUEG(); - frameCropBottomOffset = this.readUEG(); - } - if (this.readBoolean()) { - // vui_parameters_present_flag - if (this.readBoolean()) { - // aspect_ratio_info_present_flag - var sarRatio = void 0; - var aspectRatioIdc = this.readUByte(); - switch (aspectRatioIdc) { - case 1: - sarRatio = [1, 1];break; - case 2: - sarRatio = [12, 11];break; - case 3: - sarRatio = [10, 11];break; - case 4: - sarRatio = [16, 11];break; - case 5: - sarRatio = [40, 33];break; - case 6: - sarRatio = [24, 11];break; - case 7: - sarRatio = [20, 11];break; - case 8: - sarRatio = [32, 11];break; - case 9: - sarRatio = [80, 33];break; - case 10: - sarRatio = [18, 11];break; - case 11: - sarRatio = [15, 11];break; - case 12: - sarRatio = [64, 33];break; - case 13: - sarRatio = [160, 99];break; - case 14: - sarRatio = [4, 3];break; - case 15: - sarRatio = [3, 2];break; - case 16: - sarRatio = [2, 1];break; - case 255: - { - sarRatio = [this.readUByte() << 8 | this.readUByte(), this.readUByte() << 8 | this.readUByte()]; - break; - } - } - if (sarRatio) { - sarScale = sarRatio[0] / sarRatio[1]; - } - } - } - return { - width: Math.ceil(((picWidthInMbsMinus1 + 1) * 16 - frameCropLeftOffset * 2 - frameCropRightOffset * 2) * sarScale), - height: (2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 - (frameMbsOnlyFlag ? 2 : 4) * (frameCropTopOffset + frameCropBottomOffset) - }; - } - }, { - key: 'readSliceType', - value: function readSliceType() { - // skip NALu type - this.readUByte(); - // discard first_mb_in_slice - this.readUEG(); - // return slice_type - return this.readUEG(); - } - }]); - - return ExpGolomb; -}(); - -exports.default = ExpGolomb; - -},{"../utils/logger":38}],19:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * ID3 parser - */ - - -var _logger = require('../utils/logger'); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -//import Hex from '../utils/hex'; - -var ID3 = function () { - function ID3(data) { - _classCallCheck(this, ID3); - - this._hasTimeStamp = false; - var offset = 0, - byte1, - byte2, - byte3, - byte4, - tagSize, - endPos, - header, - len; - do { - header = this.readUTF(data, offset, 3); - offset += 3; - // first check for ID3 header - if (header === 'ID3') { - // skip 24 bits - offset += 3; - // retrieve tag(s) length - byte1 = data[offset++] & 0x7f; - byte2 = data[offset++] & 0x7f; - byte3 = data[offset++] & 0x7f; - byte4 = data[offset++] & 0x7f; - tagSize = (byte1 << 21) + (byte2 << 14) + (byte3 << 7) + byte4; - endPos = offset + tagSize; - //logger.log(`ID3 tag found, size/end: ${tagSize}/${endPos}`); - - // read ID3 tags - this._parseID3Frames(data, offset, endPos); - offset = endPos; - } else if (header === '3DI') { - // http://id3.org/id3v2.4.0-structure chapter 3.4. ID3v2 footer - offset += 7; - _logger.logger.log('3DI footer found, end: ' + offset); - } else { - offset -= 3; - len = offset; - if (len) { - //logger.log(`ID3 len: ${len}`); - if (!this.hasTimeStamp) { - _logger.logger.warn('ID3 tag found, but no timestamp'); - } - this._length = len; - this._payload = data.subarray(0, len); - } - return; - } - } while (true); - } - - _createClass(ID3, [{ - key: 'readUTF', - value: function readUTF(data, start, len) { - - var result = '', - offset = start, - end = start + len; - do { - result += String.fromCharCode(data[offset++]); - } while (offset < end); - return result; - } - }, { - key: '_parseID3Frames', - value: function _parseID3Frames(data, offset, endPos) { - var tagId, tagLen, tagStart, tagFlags, timestamp; - while (offset + 8 <= endPos) { - tagId = this.readUTF(data, offset, 4); - offset += 4; - - tagLen = data[offset++] << 24 + data[offset++] << 16 + data[offset++] << 8 + data[offset++]; - - tagFlags = data[offset++] << 8 + data[offset++]; - - tagStart = offset; - //logger.log("ID3 tag id:" + tagId); - switch (tagId) { - case 'PRIV': - //logger.log('parse frame:' + Hex.hexDump(data.subarray(offset,endPos))); - // owner should be "com.apple.streaming.transportStreamTimestamp" - if (this.readUTF(data, offset, 44) === 'com.apple.streaming.transportStreamTimestamp') { - offset += 44; - // smelling even better ! we found the right descriptor - // skip null character (string end) + 3 first bytes - offset += 4; - - // timestamp is 33 bit expressed as a big-endian eight-octet number, with the upper 31 bits set to zero. - var pts33Bit = data[offset++] & 0x1; - this._hasTimeStamp = true; - - timestamp = ((data[offset++] << 23) + (data[offset++] << 15) + (data[offset++] << 7) + data[offset++]) / 45; - - if (pts33Bit) { - timestamp += 47721858.84; // 2^32 / 90 - } - timestamp = Math.round(timestamp); - _logger.logger.trace('ID3 timestamp found: ' + timestamp); - this._timeStamp = timestamp; - } - break; - default: - break; - } - } - } - }, { - key: 'hasTimeStamp', - get: function get() { - return this._hasTimeStamp; - } - }, { - key: 'timeStamp', - get: function get() { - return this._timeStamp; - } - }, { - key: 'length', - get: function get() { - return this._length; - } - }, { - key: 'payload', - get: function get() { - return this._payload; - } - }]); - - return ID3; -}(); - -exports.default = ID3; - -},{"../utils/logger":38}],20:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * highly optimized TS demuxer: - * parse PAT, PMT - * extract PES packet from audio and video PIDs - * extract AVC/H264 NAL units and AAC/ADTS samples from PES packet - * trigger the remuxer upon parsing completion - * it also tries to workaround as best as it can audio codec switch (HE-AAC to AAC and vice versa), without having to restart the MediaSource. - * it also controls the remuxing process : - * upon discontinuity or level switch detection, it will also notifies the remuxer so that it can reset its state. - */ - -// import Hex from '../utils/hex'; - - -var _adts = require('./adts'); - -var _adts2 = _interopRequireDefault(_adts); - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -var _expGolomb = require('./exp-golomb'); - -var _expGolomb2 = _interopRequireDefault(_expGolomb); - -var _logger = require('../utils/logger'); - -var _errors = require('../errors'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var TSDemuxer = function () { - function TSDemuxer(observer, remuxerClass) { - _classCallCheck(this, TSDemuxer); - - this.observer = observer; - this.remuxerClass = remuxerClass; - this.lastCC = 0; - this.remuxer = new this.remuxerClass(observer); - } - - _createClass(TSDemuxer, [{ - key: 'switchLevel', - value: function switchLevel() { - this.pmtParsed = false; - this._pmtId = -1; - this._avcTrack = { container: 'video/mp2t', type: 'video', id: -1, sequenceNumber: 0, samples: [], len: 0, nbNalu: 0, dropped: 0 }; - this._aacTrack = { container: 'video/mp2t', type: 'audio', id: -1, sequenceNumber: 0, samples: [], len: 0 }; - this._id3Track = { type: 'id3', id: -1, sequenceNumber: 0, samples: [], len: 0 }; - this._txtTrack = { type: 'text', id: -1, sequenceNumber: 0, samples: [], len: 0 }; - // flush any partial content - this.aacOverFlow = null; - this.aacLastPTS = null; - this.avcNaluState = 0; - this.remuxer.switchLevel(); - } - }, { - key: 'insertDiscontinuity', - value: function insertDiscontinuity() { - this.switchLevel(); - this.remuxer.insertDiscontinuity(); - } - - // feed incoming data to the front of the parsing pipeline - - }, { - key: 'push', - value: function push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) { - var avcData, - aacData, - id3Data, - start, - len = data.length, - stt, - pid, - atf, - offset, - codecsOnly = this.remuxer.passthrough, - unknownPIDs = false; - - this.audioCodec = audioCodec; - this.videoCodec = videoCodec; - this.timeOffset = timeOffset; - this._duration = duration; - this.contiguous = false; - if (cc !== this.lastCC) { - _logger.logger.log('discontinuity detected'); - this.insertDiscontinuity(); - this.lastCC = cc; - } - if (level !== this.lastLevel) { - _logger.logger.log('level switch detected'); - this.switchLevel(); - this.lastLevel = level; - } else if (sn === this.lastSN + 1) { - this.contiguous = true; - } - this.lastSN = sn; - - var pmtParsed = this.pmtParsed, - avcId = this._avcTrack.id, - aacId = this._aacTrack.id, - id3Id = this._id3Track.id; - - // don't parse last TS packet if incomplete - len -= len % 188; - // loop through TS packets - for (start = 0; start < len; start += 188) { - if (data[start] === 0x47) { - stt = !!(data[start + 1] & 0x40); - // pid is a 13-bit field starting at the last bit of TS[1] - pid = ((data[start + 1] & 0x1f) << 8) + data[start + 2]; - atf = (data[start + 3] & 0x30) >> 4; - // if an adaption field is present, its length is specified by the fifth byte of the TS packet header. - if (atf > 1) { - offset = start + 5 + data[start + 4]; - // continue if there is only adaptation field - if (offset === start + 188) { - continue; - } - } else { - offset = start + 4; - } - if (pmtParsed) { - if (pid === avcId) { - if (stt) { - if (avcData) { - this._parseAVCPES(this._parsePES(avcData)); - if (codecsOnly) { - // if we have video codec info AND - // if audio PID is undefined OR if we have audio codec info, - // we have all codec info ! - if (this._avcTrack.codec && (aacId === -1 || this._aacTrack.codec)) { - this.remux(data); - return; - } - } - } - avcData = { data: [], size: 0 }; - } - if (avcData) { - avcData.data.push(data.subarray(offset, start + 188)); - avcData.size += start + 188 - offset; - } - } else if (pid === aacId) { - if (stt) { - if (aacData) { - this._parseAACPES(this._parsePES(aacData)); - if (codecsOnly) { - // here we now that we have audio codec info - // if video PID is undefined OR if we have video codec info, - // we have all codec infos ! - if (this._aacTrack.codec && (avcId === -1 || this._avcTrack.codec)) { - this.remux(data); - return; - } - } - } - aacData = { data: [], size: 0 }; - } - if (aacData) { - aacData.data.push(data.subarray(offset, start + 188)); - aacData.size += start + 188 - offset; - } - } else if (pid === id3Id) { - if (stt) { - if (id3Data) { - this._parseID3PES(this._parsePES(id3Data)); - } - id3Data = { data: [], size: 0 }; - } - if (id3Data) { - id3Data.data.push(data.subarray(offset, start + 188)); - id3Data.size += start + 188 - offset; - } - } - } else { - if (stt) { - offset += data[offset] + 1; - } - if (pid === 0) { - this._parsePAT(data, offset); - } else if (pid === this._pmtId) { - this._parsePMT(data, offset); - pmtParsed = this.pmtParsed = true; - avcId = this._avcTrack.id; - aacId = this._aacTrack.id; - id3Id = this._id3Track.id; - if (unknownPIDs) { - _logger.logger.log('reparse from beginning'); - unknownPIDs = false; - // we set it to -188, the += 188 in the for loop will reset start to 0 - start = -188; - } - } else { - _logger.logger.log('unknown PID found before PAT/PMT'); - unknownPIDs = true; - } - } - } else { - this.observer.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.FRAG_PARSING_ERROR, fatal: false, reason: 'TS packet did not start with 0x47' }); - } - } - // parse last PES packet - if (avcData) { - this._parseAVCPES(this._parsePES(avcData)); - } - if (aacData) { - this._parseAACPES(this._parsePES(aacData)); - } - if (id3Data) { - this._parseID3PES(this._parsePES(id3Data)); - } - this.remux(null); - } - }, { - key: 'remux', - value: function remux(data) { - this.remuxer.remux(this._aacTrack, this._avcTrack, this._id3Track, this._txtTrack, this.timeOffset, this.contiguous, data); - } - }, { - key: 'destroy', - value: function destroy() { - this.switchLevel(); - this._initPTS = this._initDTS = undefined; - this._duration = 0; - } - }, { - key: '_parsePAT', - value: function _parsePAT(data, offset) { - // skip the PSI header and parse the first PMT entry - this._pmtId = (data[offset + 10] & 0x1F) << 8 | data[offset + 11]; - //logger.log('PMT PID:' + this._pmtId); - } - }, { - key: '_parsePMT', - value: function _parsePMT(data, offset) { - var sectionLength, tableEnd, programInfoLength, pid; - sectionLength = (data[offset + 1] & 0x0f) << 8 | data[offset + 2]; - tableEnd = offset + 3 + sectionLength - 4; - // to determine where the table is, we have to figure out how - // long the program info descriptors are - programInfoLength = (data[offset + 10] & 0x0f) << 8 | data[offset + 11]; - // advance the offset to the first entry in the mapping table - offset += 12 + programInfoLength; - while (offset < tableEnd) { - pid = (data[offset + 1] & 0x1F) << 8 | data[offset + 2]; - switch (data[offset]) { - // ISO/IEC 13818-7 ADTS AAC (MPEG-2 lower bit-rate audio) - case 0x0f: - //logger.log('AAC PID:' + pid); - this._aacTrack.id = pid; - break; - // Packetized metadata (ID3) - case 0x15: - //logger.log('ID3 PID:' + pid); - this._id3Track.id = pid; - break; - // ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video) - case 0x1b: - //logger.log('AVC PID:' + pid); - this._avcTrack.id = pid; - break; - default: - _logger.logger.log('unkown stream type:' + data[offset]); - break; - } - // move to the next table entry - // skip past the elementary stream descriptors, if present - offset += ((data[offset + 3] & 0x0F) << 8 | data[offset + 4]) + 5; - } - } - }, { - key: '_parsePES', - value: function _parsePES(stream) { - var i = 0, - frag, - pesFlags, - pesPrefix, - pesLen, - pesHdrLen, - pesData, - pesPts, - pesDts, - payloadStartOffset, - data = stream.data; - //retrieve PTS/DTS from first fragment - frag = data[0]; - pesPrefix = (frag[0] << 16) + (frag[1] << 8) + frag[2]; - if (pesPrefix === 1) { - pesLen = (frag[4] << 8) + frag[5]; - pesFlags = frag[7]; - if (pesFlags & 0xC0) { - /* PES header described here : http://dvd.sourceforge.net/dvdinfo/pes-hdr.html - as PTS / DTS is 33 bit we cannot use bitwise operator in JS, - as Bitwise operators treat their operands as a sequence of 32 bits */ - pesPts = (frag[9] & 0x0E) * 536870912 + // 1 << 29 - (frag[10] & 0xFF) * 4194304 + // 1 << 22 - (frag[11] & 0xFE) * 16384 + // 1 << 14 - (frag[12] & 0xFF) * 128 + // 1 << 7 - (frag[13] & 0xFE) / 2; - // check if greater than 2^32 -1 - if (pesPts > 4294967295) { - // decrement 2^33 - pesPts -= 8589934592; - } - if (pesFlags & 0x40) { - pesDts = (frag[14] & 0x0E) * 536870912 + // 1 << 29 - (frag[15] & 0xFF) * 4194304 + // 1 << 22 - (frag[16] & 0xFE) * 16384 + // 1 << 14 - (frag[17] & 0xFF) * 128 + // 1 << 7 - (frag[18] & 0xFE) / 2; - // check if greater than 2^32 -1 - if (pesDts > 4294967295) { - // decrement 2^33 - pesDts -= 8589934592; - } - } else { - pesDts = pesPts; - } - } - pesHdrLen = frag[8]; - payloadStartOffset = pesHdrLen + 9; - - stream.size -= payloadStartOffset; - //reassemble PES packet - pesData = new Uint8Array(stream.size); - while (data.length) { - frag = data.shift(); - var len = frag.byteLength; - if (payloadStartOffset) { - if (payloadStartOffset > len) { - // trim full frag if PES header bigger than frag - payloadStartOffset -= len; - continue; - } else { - // trim partial frag if PES header smaller than frag - frag = frag.subarray(payloadStartOffset); - len -= payloadStartOffset; - payloadStartOffset = 0; - } - } - pesData.set(frag, i); - i += len; - } - return { data: pesData, pts: pesPts, dts: pesDts, len: pesLen }; - } else { - return null; - } - } - }, { - key: '_parseAVCPES', - value: function _parseAVCPES(pes) { - var _this = this; - - var track = this._avcTrack, - samples = track.samples, - units = this._parseAVCNALu(pes.data), - units2 = [], - debug = false, - key = false, - length = 0, - expGolombDecoder, - avcSample, - push, - i; - // no NALu found - if (units.length === 0 && samples.length > 0) { - // append pes.data to previous NAL unit - var lastavcSample = samples[samples.length - 1]; - var lastUnit = lastavcSample.units.units[lastavcSample.units.units.length - 1]; - var tmp = new Uint8Array(lastUnit.data.byteLength + pes.data.byteLength); - tmp.set(lastUnit.data, 0); - tmp.set(pes.data, lastUnit.data.byteLength); - lastUnit.data = tmp; - lastavcSample.units.length += pes.data.byteLength; - track.len += pes.data.byteLength; - } - //free pes.data to save up some memory - pes.data = null; - var debugString = ''; - - var pushAccesUnit = function () { - if (units2.length) { - // only push AVC sample if keyframe already found in this fragment OR - // keyframe found in last fragment (track.sps) AND - // samples already appended (we already found a keyframe in this fragment) OR fragment is contiguous - if (key === true || track.sps && (samples.length || this.contiguous)) { - avcSample = { units: { units: units2, length: length }, pts: pes.pts, dts: pes.dts, key: key }; - samples.push(avcSample); - track.len += length; - track.nbNalu += units2.length; - } else { - // dropped samples, track it - track.dropped++; - } - units2 = []; - length = 0; - } - }.bind(this); - - units.forEach(function (unit) { - switch (unit.type) { - //NDR - case 1: - push = true; - if (debug) { - debugString += 'NDR '; - } - break; - //IDR - case 5: - push = true; - if (debug) { - debugString += 'IDR '; - } - key = true; - break; - //SEI - case 6: - push = true; - if (debug) { - debugString += 'SEI '; - } - expGolombDecoder = new _expGolomb2.default(unit.data); - - // skip frameType - expGolombDecoder.readUByte(); - - var payloadType = expGolombDecoder.readUByte(); - - // TODO: there can be more than one payload in an SEI packet... - // TODO: need to read type and size in a while loop to get them all - if (payloadType === 4) { - var payloadSize = 0; - - do { - payloadSize = expGolombDecoder.readUByte(); - } while (payloadSize === 255); - - var countryCode = expGolombDecoder.readUByte(); - - if (countryCode === 181) { - var providerCode = expGolombDecoder.readUShort(); - - if (providerCode === 49) { - var userStructure = expGolombDecoder.readUInt(); - - if (userStructure === 0x47413934) { - var userDataType = expGolombDecoder.readUByte(); - - // Raw CEA-608 bytes wrapped in CEA-708 packet - if (userDataType === 3) { - var firstByte = expGolombDecoder.readUByte(); - var secondByte = expGolombDecoder.readUByte(); - - var totalCCs = 31 & firstByte; - var byteArray = [firstByte, secondByte]; - - for (i = 0; i < totalCCs; i++) { - // 3 bytes per CC - byteArray.push(expGolombDecoder.readUByte()); - byteArray.push(expGolombDecoder.readUByte()); - byteArray.push(expGolombDecoder.readUByte()); - } - - _this._txtTrack.samples.push({ type: 3, pts: pes.pts, bytes: byteArray }); - } - } - } - } - } - break; - //SPS - case 7: - push = true; - if (debug) { - debugString += 'SPS '; - } - if (!track.sps) { - expGolombDecoder = new _expGolomb2.default(unit.data); - var config = expGolombDecoder.readSPS(); - track.width = config.width; - track.height = config.height; - track.sps = [unit.data]; - track.duration = _this._duration; - var codecarray = unit.data.subarray(1, 4); - var codecstring = 'avc1.'; - for (i = 0; i < 3; i++) { - var h = codecarray[i].toString(16); - if (h.length < 2) { - h = '0' + h; - } - codecstring += h; - } - track.codec = codecstring; - } - break; - //PPS - case 8: - push = true; - if (debug) { - debugString += 'PPS '; - } - if (!track.pps) { - track.pps = [unit.data]; - } - break; - case 9: - push = false; - if (debug) { - debugString += 'AUD '; - } - pushAccesUnit(); - break; - default: - push = false; - debugString += 'unknown NAL ' + unit.type + ' '; - break; - } - if (push) { - units2.push(unit); - length += unit.data.byteLength; - } - }); - if (debug || debugString.length) { - _logger.logger.log(debugString); - } - pushAccesUnit(); - } - }, { - key: '_parseAVCNALu', - value: function _parseAVCNALu(array) { - var i = 0, - len = array.byteLength, - value, - overflow, - state = this.avcNaluState; - var units = [], - unit, - unitType, - lastUnitStart, - lastUnitType; - //logger.log('PES:' + Hex.hexDump(array)); - while (i < len) { - value = array[i++]; - // finding 3 or 4-byte start codes (00 00 01 OR 00 00 00 01) - switch (state) { - case 0: - if (value === 0) { - state = 1; - } - break; - case 1: - if (value === 0) { - state = 2; - } else { - state = 0; - } - break; - case 2: - case 3: - if (value === 0) { - state = 3; - } else if (value === 1 && i < len) { - unitType = array[i] & 0x1f; - //logger.log('find NALU @ offset:' + i + ',type:' + unitType); - if (lastUnitStart) { - unit = { data: array.subarray(lastUnitStart, i - state - 1), type: lastUnitType }; - //logger.log('pushing NALU, type/size:' + unit.type + '/' + unit.data.byteLength); - units.push(unit); - } else { - // lastUnitStart is undefined => this is the first start code found in this PES packet - // first check if start code delimiter is overlapping between 2 PES packets, - // ie it started in last packet (lastState not zero) - // and ended at the beginning of this PES packet (i <= 4 - lastState) - var lastState = this.avcNaluState; - if (lastState && i <= 4 - lastState) { - // start delimiter overlapping between PES packets - // strip start delimiter bytes from the end of last NAL unit - var track = this._avcTrack, - samples = track.samples; - if (samples.length) { - var lastavcSample = samples[samples.length - 1], - lastUnits = lastavcSample.units.units, - lastUnit = lastUnits[lastUnits.length - 1]; - // check if lastUnit had a state different from zero - if (lastUnit.state) { - // strip last bytes - lastUnit.data = lastUnit.data.subarray(0, lastUnit.data.byteLength - lastState); - lastavcSample.units.length -= lastState; - track.len -= lastState; - } - } - } - // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit. - overflow = i - state - 1; - if (overflow > 0) { - var _track = this._avcTrack, - _samples = _track.samples; - //logger.log('first NALU found with overflow:' + overflow); - if (_samples.length) { - var _lastavcSample = _samples[_samples.length - 1], - _lastUnits = _lastavcSample.units.units, - _lastUnit = _lastUnits[_lastUnits.length - 1], - tmp = new Uint8Array(_lastUnit.data.byteLength + overflow); - tmp.set(_lastUnit.data, 0); - tmp.set(array.subarray(0, overflow), _lastUnit.data.byteLength); - _lastUnit.data = tmp; - _lastavcSample.units.length += overflow; - _track.len += overflow; - } - } - } - lastUnitStart = i; - lastUnitType = unitType; - state = 0; - } else { - state = 0; - } - break; - default: - break; - } - } - if (lastUnitStart) { - unit = { data: array.subarray(lastUnitStart, len), type: lastUnitType, state: state }; - units.push(unit); - //logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state); - this.avcNaluState = state; - } - return units; - } - }, { - key: '_parseAACPES', - value: function _parseAACPES(pes) { - var track = this._aacTrack, - data = pes.data, - pts = pes.pts, - startOffset = 0, - duration = this._duration, - audioCodec = this.audioCodec, - aacOverFlow = this.aacOverFlow, - aacLastPTS = this.aacLastPTS, - config, - frameLength, - frameDuration, - frameIndex, - offset, - headerLength, - stamp, - len, - aacSample; - if (aacOverFlow) { - var tmp = new Uint8Array(aacOverFlow.byteLength + data.byteLength); - tmp.set(aacOverFlow, 0); - tmp.set(data, aacOverFlow.byteLength); - //logger.log(`AAC: append overflowing ${aacOverFlow.byteLength} bytes to beginning of new PES`); - data = tmp; - } - // look for ADTS header (0xFFFx) - for (offset = startOffset, len = data.length; offset < len - 1; offset++) { - if (data[offset] === 0xff && (data[offset + 1] & 0xf0) === 0xf0) { - break; - } - } - // if ADTS header does not start straight from the beginning of the PES payload, raise an error - if (offset) { - var reason, fatal; - if (offset < len - 1) { - reason = 'AAC PES did not start with ADTS header,offset:' + offset; - fatal = false; - } else { - reason = 'no ADTS header found in AAC PES'; - fatal = true; - } - this.observer.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.FRAG_PARSING_ERROR, fatal: fatal, reason: reason }); - if (fatal) { - return; - } - } - if (!track.audiosamplerate) { - config = _adts2.default.getAudioConfig(this.observer, data, offset, audioCodec); - track.config = config.config; - track.audiosamplerate = config.samplerate; - track.channelCount = config.channelCount; - track.codec = config.codec; - track.duration = duration; - _logger.logger.log('parsed codec:' + track.codec + ',rate:' + config.samplerate + ',nb channel:' + config.channelCount); - } - frameIndex = 0; - frameDuration = 1024 * 90000 / track.audiosamplerate; - - // if last AAC frame is overflowing, we should ensure timestamps are contiguous: - // first sample PTS should be equal to last sample PTS + frameDuration - if (aacOverFlow && aacLastPTS) { - var newPTS = aacLastPTS + frameDuration; - if (Math.abs(newPTS - pts) > 1) { - _logger.logger.log('AAC: align PTS for overlapping frames by ' + Math.round((newPTS - pts) / 90)); - pts = newPTS; - } - } - - while (offset + 5 < len) { - // The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header - headerLength = !!(data[offset + 1] & 0x01) ? 7 : 9; - // retrieve frame size - frameLength = (data[offset + 3] & 0x03) << 11 | data[offset + 4] << 3 | (data[offset + 5] & 0xE0) >>> 5; - frameLength -= headerLength; - //stamp = pes.pts; - - if (frameLength > 0 && offset + headerLength + frameLength <= len) { - stamp = pts + frameIndex * frameDuration; - //logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}/${(stamp/90).toFixed(0)}`); - aacSample = { unit: data.subarray(offset + headerLength, offset + headerLength + frameLength), pts: stamp, dts: stamp }; - track.samples.push(aacSample); - track.len += frameLength; - offset += frameLength + headerLength; - frameIndex++; - // look for ADTS header (0xFFFx) - for (; offset < len - 1; offset++) { - if (data[offset] === 0xff && (data[offset + 1] & 0xf0) === 0xf0) { - break; - } - } - } else { - break; - } - } - if (offset < len) { - aacOverFlow = data.subarray(offset, len); - //logger.log(`AAC: overflow detected:${len-offset}`); - } else { - aacOverFlow = null; - } - this.aacOverFlow = aacOverFlow; - this.aacLastPTS = stamp; - } - }, { - key: '_parseID3PES', - value: function _parseID3PES(pes) { - this._id3Track.samples.push(pes); - } - }], [{ - key: 'probe', - value: function probe(data) { - // a TS fragment should contain at least 3 TS packets, a PAT, a PMT, and one PID, each starting with 0x47 - if (data.length >= 3 * 188 && data[0] === 0x47 && data[188] === 0x47 && data[2 * 188] === 0x47) { - return true; - } else { - return false; - } - } - }]); - - return TSDemuxer; -}(); - -exports.default = TSDemuxer; - -},{"../errors":21,"../events":23,"../utils/logger":38,"./adts":14,"./exp-golomb":18}],21:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -var ErrorTypes = exports.ErrorTypes = { - // Identifier for a network error (loading error / timeout ...) - NETWORK_ERROR: 'networkError', - // Identifier for a media Error (video/parsing/mediasource error) - MEDIA_ERROR: 'mediaError', - // Identifier for all other errors - OTHER_ERROR: 'otherError' -}; - -var ErrorDetails = exports.ErrorDetails = { - // Identifier for a manifest load error - data: { url : faulty URL, response : XHR response} - MANIFEST_LOAD_ERROR: 'manifestLoadError', - // Identifier for a manifest load timeout - data: { url : faulty URL, response : XHR response} - MANIFEST_LOAD_TIMEOUT: 'manifestLoadTimeOut', - // Identifier for a manifest parsing error - data: { url : faulty URL, reason : error reason} - MANIFEST_PARSING_ERROR: 'manifestParsingError', - // Identifier for a manifest with only incompatible codecs error - data: { url : faulty URL, reason : error reason} - MANIFEST_INCOMPATIBLE_CODECS_ERROR: 'manifestIncompatibleCodecsError', - // Identifier for playlist load error - data: { url : faulty URL, response : XHR response} - LEVEL_LOAD_ERROR: 'levelLoadError', - // Identifier for playlist load timeout - data: { url : faulty URL, response : XHR response} - LEVEL_LOAD_TIMEOUT: 'levelLoadTimeOut', - // Identifier for a level switch error - data: { level : faulty level Id, event : error description} - LEVEL_SWITCH_ERROR: 'levelSwitchError', - // Identifier for fragment load error - data: { frag : fragment object, response : XHR response} - FRAG_LOAD_ERROR: 'fragLoadError', - // Identifier for fragment loop loading error - data: { frag : fragment object} - FRAG_LOOP_LOADING_ERROR: 'fragLoopLoadingError', - // Identifier for fragment load timeout error - data: { frag : fragment object} - FRAG_LOAD_TIMEOUT: 'fragLoadTimeOut', - // Identifier for a fragment decryption error event - data: parsing error description - FRAG_DECRYPT_ERROR: 'fragDecryptError', - // Identifier for a fragment parsing error event - data: parsing error description - FRAG_PARSING_ERROR: 'fragParsingError', - // Identifier for decrypt key load error - data: { frag : fragment object, response : XHR response} - KEY_LOAD_ERROR: 'keyLoadError', - // Identifier for decrypt key load timeout error - data: { frag : fragment object} - KEY_LOAD_TIMEOUT: 'keyLoadTimeOut', - // Identifier for a buffer append error - data: append error description - BUFFER_APPEND_ERROR: 'bufferAppendError', - // Identifier for a buffer appending error event - data: appending error description - BUFFER_APPENDING_ERROR: 'bufferAppendingError', - // Identifier for a buffer stalled error event - BUFFER_STALLED_ERROR: 'bufferStalledError', - // Identifier for a buffer full event - BUFFER_FULL_ERROR: 'bufferFullError', - // Identifier for a buffer seek over hole event - BUFFER_SEEK_OVER_HOLE: 'bufferSeekOverHole', - // Identifier for an internal exception happening inside hls.js while handling an event - INTERNAL_EXCEPTION: 'internalException' -}; - -},{}],22:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /* - * - * All objects in the event handling chain should inherit from this class - * - */ - -var _logger = require('./utils/logger'); - -var _errors = require('./errors'); - -var _events = require('./events'); - -var _events2 = _interopRequireDefault(_events); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var EventHandler = function () { - function EventHandler(hls) { - _classCallCheck(this, EventHandler); - - this.hls = hls; - this.onEvent = this.onEvent.bind(this); - - for (var _len = arguments.length, events = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - events[_key - 1] = arguments[_key]; - } - - this.handledEvents = events; - this.useGenericHandler = true; - - this.registerListeners(); - } - - _createClass(EventHandler, [{ - key: 'destroy', - value: function destroy() { - this.unregisterListeners(); - } - }, { - key: 'isEventHandler', - value: function isEventHandler() { - return _typeof(this.handledEvents) === 'object' && this.handledEvents.length && typeof this.onEvent === 'function'; - } - }, { - key: 'registerListeners', - value: function registerListeners() { - if (this.isEventHandler()) { - this.handledEvents.forEach(function (event) { - if (event === 'hlsEventGeneric') { - throw new Error('Forbidden event name: ' + event); - } - this.hls.on(event, this.onEvent); - }.bind(this)); - } - } - }, { - key: 'unregisterListeners', - value: function unregisterListeners() { - if (this.isEventHandler()) { - this.handledEvents.forEach(function (event) { - this.hls.off(event, this.onEvent); - }.bind(this)); - } - } - - /* - * arguments: event (string), data (any) - */ - - }, { - key: 'onEvent', - value: function onEvent(event, data) { - this.onEventGeneric(event, data); - } - }, { - key: 'onEventGeneric', - value: function onEventGeneric(event, data) { - var eventToFunction = function eventToFunction(event, data) { - var funcName = 'on' + event.replace('hls', ''); - if (typeof this[funcName] !== 'function') { - throw new Error('Event ' + event + ' has no generic handler in this ' + this.constructor.name + ' class (tried ' + funcName + ')'); - } - return this[funcName].bind(this, data); - }; - try { - eventToFunction.call(this, event, data).call(); - } catch (err) { - _logger.logger.error('internal error happened while processing ' + event + ':' + err.message); - this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.OTHER_ERROR, details: _errors.ErrorDetails.INTERNAL_EXCEPTION, fatal: false, event: event, err: err }); - } - } - }]); - - return EventHandler; -}(); - -exports.default = EventHandler; - -},{"./errors":21,"./events":23,"./utils/logger":38}],23:[function(require,module,exports){ -'use strict'; - -module.exports = { - // fired before MediaSource is attaching to media element - data: { media } - MEDIA_ATTACHING: 'hlsMediaAttaching', - // fired when MediaSource has been succesfully attached to media element - data: { } - MEDIA_ATTACHED: 'hlsMediaAttached', - // fired before detaching MediaSource from media element - data: { } - MEDIA_DETACHING: 'hlsMediaDetaching', - // fired when MediaSource has been detached from media element - data: { } - MEDIA_DETACHED: 'hlsMediaDetached', - // fired when we buffer is going to be resetted - BUFFER_RESET: 'hlsBufferReset', - // fired when we know about the codecs that we need buffers for to push into - data: {tracks : { container, codec, levelCodec, initSegment, metadata }} - BUFFER_CODECS: 'hlsBufferCodecs', - // fired when we append a segment to the buffer - data: { segment: segment object } - BUFFER_APPENDING: 'hlsBufferAppending', - // fired when we are done with appending a media segment to the buffer - BUFFER_APPENDED: 'hlsBufferAppended', - // fired when the stream is finished and we want to notify the media buffer that there will be no more data - BUFFER_EOS: 'hlsBufferEos', - // fired when the media buffer should be flushed - data {startOffset, endOffset} - BUFFER_FLUSHING: 'hlsBufferFlushing', - // fired when the media has been flushed - BUFFER_FLUSHED: 'hlsBufferFlushed', - // fired to signal that a manifest loading starts - data: { url : manifestURL} - MANIFEST_LOADING: 'hlsManifestLoading', - // fired after manifest has been loaded - data: { levels : [available quality levels] , url : manifestURL, stats : { trequest, tfirst, tload, mtime}} - MANIFEST_LOADED: 'hlsManifestLoaded', - // fired after manifest has been parsed - data: { levels : [available quality levels] , firstLevel : index of first quality level appearing in Manifest} - MANIFEST_PARSED: 'hlsManifestParsed', - // fired when a level playlist loading starts - data: { url : level URL level : id of level being loaded} - LEVEL_LOADING: 'hlsLevelLoading', - // fired when a level playlist loading finishes - data: { details : levelDetails object, level : id of loaded level, stats : { trequest, tfirst, tload, mtime} } - LEVEL_LOADED: 'hlsLevelLoaded', - // fired when a level's details have been updated based on previous details, after it has been loaded. - data: { details : levelDetails object, level : id of updated level } - LEVEL_UPDATED: 'hlsLevelUpdated', - // fired when a level's PTS information has been updated after parsing a fragment - data: { details : levelDetails object, level : id of updated level, drift: PTS drift observed when parsing last fragment } - LEVEL_PTS_UPDATED: 'hlsLevelPtsUpdated', - // fired when a level switch is requested - data: { level : id of new level } - LEVEL_SWITCH: 'hlsLevelSwitch', - // fired when a fragment loading starts - data: { frag : fragment object} - FRAG_LOADING: 'hlsFragLoading', - // fired when a fragment loading is progressing - data: { frag : fragment object, { trequest, tfirst, loaded}} - FRAG_LOAD_PROGRESS: 'hlsFragLoadProgress', - // Identifier for fragment load aborting for emergency switch down - data: {frag : fragment object} - FRAG_LOAD_EMERGENCY_ABORTED: 'hlsFragLoadEmergencyAborted', - // fired when a fragment loading is completed - data: { frag : fragment object, payload : fragment payload, stats : { trequest, tfirst, tload, length}} - FRAG_LOADED: 'hlsFragLoaded', - // fired when Init Segment has been extracted from fragment - data: { moov : moov MP4 box, codecs : codecs found while parsing fragment} - FRAG_PARSING_INIT_SEGMENT: 'hlsFragParsingInitSegment', - // fired when parsing sei text is completed - data: { samples : [ sei samples pes ] } - FRAG_PARSING_USERDATA: 'hlsFragParsingUserdata', - // fired when parsing id3 is completed - data: { samples : [ id3 samples pes ] } - FRAG_PARSING_METADATA: 'hlsFragParsingMetadata', - // fired when data have been extracted from fragment - data: { data1 : moof MP4 box or TS fragments, data2 : mdat MP4 box or null} - FRAG_PARSING_DATA: 'hlsFragParsingData', - // fired when fragment parsing is completed - data: undefined - FRAG_PARSED: 'hlsFragParsed', - // fired when fragment remuxed MP4 boxes have all been appended into SourceBuffer - data: { frag : fragment object, stats : { trequest, tfirst, tload, tparsed, tbuffered, length} } - FRAG_BUFFERED: 'hlsFragBuffered', - // fired when fragment matching with current media position is changing - data : { frag : fragment object } - FRAG_CHANGED: 'hlsFragChanged', - // Identifier for a FPS drop event - data: {curentDropped, currentDecoded, totalDroppedFrames} - FPS_DROP: 'hlsFpsDrop', - // Identifier for an error event - data: { type : error type, details : error details, fatal : if true, hls.js cannot/will not try to recover, if false, hls.js will try to recover,other error specific data} - ERROR: 'hlsError', - // fired when hls.js instance starts destroying. Different from MEDIA_DETACHED as one could want to detach and reattach a media to the instance of hls.js to handle mid-rolls for example - DESTROYING: 'hlsDestroying', - // fired when a decrypt key loading starts - data: { frag : fragment object} - KEY_LOADING: 'hlsKeyLoading', - // fired when a decrypt key loading is completed - data: { frag : fragment object, payload : key payload, stats : { trequest, tfirst, tload, length}} - KEY_LOADED: 'hlsKeyLoaded' -}; - -},{}],24:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * Buffer Helper class, providing methods dealing buffer length retrieval -*/ - -var BufferHelper = function () { - function BufferHelper() { - _classCallCheck(this, BufferHelper); - } - - _createClass(BufferHelper, null, [{ - key: "bufferInfo", - value: function bufferInfo(media, pos, maxHoleDuration) { - if (media) { - var vbuffered = media.buffered, - buffered = [], - i; - for (i = 0; i < vbuffered.length; i++) { - buffered.push({ start: vbuffered.start(i), end: vbuffered.end(i) }); - } - return this.bufferedInfo(buffered, pos, maxHoleDuration); - } else { - return { len: 0, start: 0, end: 0, nextStart: undefined }; - } - } - }, { - key: "bufferedInfo", - value: function bufferedInfo(buffered, pos, maxHoleDuration) { - var buffered2 = [], - - // bufferStart and bufferEnd are buffer boundaries around current video position - bufferLen, - bufferStart, - bufferEnd, - bufferStartNext, - i; - // sort on buffer.start/smaller end (IE does not always return sorted buffered range) - buffered.sort(function (a, b) { - var diff = a.start - b.start; - if (diff) { - return diff; - } else { - return b.end - a.end; - } - }); - // there might be some small holes between buffer time range - // consider that holes smaller than maxHoleDuration are irrelevant and build another - // buffer time range representations that discards those holes - for (i = 0; i < buffered.length; i++) { - var buf2len = buffered2.length; - if (buf2len) { - var buf2end = buffered2[buf2len - 1].end; - // if small hole (value between 0 or maxHoleDuration ) or overlapping (negative) - if (buffered[i].start - buf2end < maxHoleDuration) { - // merge overlapping time ranges - // update lastRange.end only if smaller than item.end - // e.g. [ 1, 15] with [ 2,8] => [ 1,15] (no need to modify lastRange.end) - // whereas [ 1, 8] with [ 2,15] => [ 1,15] ( lastRange should switch from [1,8] to [1,15]) - if (buffered[i].end > buf2end) { - buffered2[buf2len - 1].end = buffered[i].end; - } - } else { - // big hole - buffered2.push(buffered[i]); - } - } else { - // first value - buffered2.push(buffered[i]); - } - } - for (i = 0, bufferLen = 0, bufferStart = bufferEnd = pos; i < buffered2.length; i++) { - var start = buffered2[i].start, - end = buffered2[i].end; - //logger.log('buf start/end:' + buffered.start(i) + '/' + buffered.end(i)); - if (pos + maxHoleDuration >= start && pos < end) { - // play position is inside this buffer TimeRange, retrieve end of buffer position and buffer length - bufferStart = start; - bufferEnd = end; - bufferLen = bufferEnd - pos; - } else if (pos + maxHoleDuration < start) { - bufferStartNext = start; - break; - } - } - return { len: bufferLen, start: bufferStart, end: bufferEnd, nextStart: bufferStartNext }; - } - }]); - - return BufferHelper; -}(); - -exports.default = BufferHelper; - -},{}],25:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * Level Helper class, providing methods dealing with playlist sliding and drift - */ - -var _logger = require('../utils/logger'); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var LevelHelper = function () { - function LevelHelper() { - _classCallCheck(this, LevelHelper); - } - - _createClass(LevelHelper, null, [{ - key: 'mergeDetails', - value: function mergeDetails(oldDetails, newDetails) { - var start = Math.max(oldDetails.startSN, newDetails.startSN) - newDetails.startSN, - end = Math.min(oldDetails.endSN, newDetails.endSN) - newDetails.startSN, - delta = newDetails.startSN - oldDetails.startSN, - oldfragments = oldDetails.fragments, - newfragments = newDetails.fragments, - ccOffset = 0, - PTSFrag; - - // check if old/new playlists have fragments in common - if (end < start) { - newDetails.PTSKnown = false; - return; - } - // loop through overlapping SN and update startPTS , cc, and duration if any found - for (var i = start; i <= end; i++) { - var oldFrag = oldfragments[delta + i], - newFrag = newfragments[i]; - ccOffset = oldFrag.cc - newFrag.cc; - if (!isNaN(oldFrag.startPTS)) { - newFrag.start = newFrag.startPTS = oldFrag.startPTS; - newFrag.endPTS = oldFrag.endPTS; - newFrag.duration = oldFrag.duration; - PTSFrag = newFrag; - } - } - - if (ccOffset) { - _logger.logger.log('discontinuity sliding from playlist, take drift into account'); - for (i = 0; i < newfragments.length; i++) { - newfragments[i].cc += ccOffset; - } - } - - // if at least one fragment contains PTS info, recompute PTS information for all fragments - if (PTSFrag) { - LevelHelper.updateFragPTSDTS(newDetails, PTSFrag.sn, PTSFrag.startPTS, PTSFrag.endPTS, PTSFrag.startDTS, PTSFrag.endDTS); - } else { - // ensure that delta is within oldfragments range - // also adjust sliding in case delta is 0 (we could have old=[50-60] and new=old=[50-61]) - // in that case we also need to adjust start offset of all fragments - if (delta >= 0 && delta < oldfragments.length) { - // adjust start by sliding offset - var sliding = oldfragments[delta].start; - for (i = 0; i < newfragments.length; i++) { - newfragments[i].start += sliding; - } - } - } - // if we are here, it means we have fragments overlapping between - // old and new level. reliable PTS info is thus relying on old level - newDetails.PTSKnown = oldDetails.PTSKnown; - return; - } - }, { - key: 'updateFragPTSDTS', - value: function updateFragPTSDTS(details, sn, startPTS, endPTS, startDTS, endDTS) { - var fragIdx, fragments, frag, i; - // exit if sn out of range - if (sn < details.startSN || sn > details.endSN) { - return 0; - } - fragIdx = sn - details.startSN; - fragments = details.fragments; - frag = fragments[fragIdx]; - if (!isNaN(frag.startPTS)) { - // delta PTS between audio and video - var deltaPTS = Math.abs(frag.startPTS - startPTS); - if (isNaN(frag.deltaPTS)) { - frag.deltaPTS = deltaPTS; - } else { - frag.deltaPTS = Math.max(deltaPTS, frag.deltaPTS); - } - startPTS = Math.min(startPTS, frag.startPTS); - endPTS = Math.max(endPTS, frag.endPTS); - startDTS = Math.min(startDTS, frag.startDTS); - endDTS = Math.max(endDTS, frag.endDTS); - } - - var drift = startPTS - frag.start; - - frag.start = frag.startPTS = startPTS; - frag.endPTS = endPTS; - frag.startDTS = startDTS; - frag.endDTS = endDTS; - frag.duration = endPTS - startPTS; - // adjust fragment PTS/duration from seqnum-1 to frag 0 - for (i = fragIdx; i > 0; i--) { - LevelHelper.updatePTS(fragments, i, i - 1); - } - - // adjust fragment PTS/duration from seqnum to last frag - for (i = fragIdx; i < fragments.length - 1; i++) { - LevelHelper.updatePTS(fragments, i, i + 1); - } - details.PTSKnown = true; - //logger.log(` frag start/end:${startPTS.toFixed(3)}/${endPTS.toFixed(3)}`); - - return drift; - } - }, { - key: 'updatePTS', - value: function updatePTS(fragments, fromIdx, toIdx) { - var fragFrom = fragments[fromIdx], - fragTo = fragments[toIdx], - fragToPTS = fragTo.startPTS; - // if we know startPTS[toIdx] - if (!isNaN(fragToPTS)) { - // update fragment duration. - // it helps to fix drifts between playlist reported duration and fragment real duration - if (toIdx > fromIdx) { - fragFrom.duration = fragToPTS - fragFrom.start; - if (fragFrom.duration < 0) { - _logger.logger.error('negative duration computed for frag ' + fragFrom.sn + ',level ' + fragFrom.level + ', there should be some duration drift between playlist and fragment!'); - } - } else { - fragTo.duration = fragFrom.start - fragToPTS; - if (fragTo.duration < 0) { - _logger.logger.error('negative duration computed for frag ' + fragTo.sn + ',level ' + fragTo.level + ', there should be some duration drift between playlist and fragment!'); - } - } - } else { - // we dont know startPTS[toIdx] - if (toIdx > fromIdx) { - fragTo.start = fragFrom.start + fragFrom.duration; - } else { - fragTo.start = fragFrom.start - fragTo.duration; - } - } - } - }]); - - return LevelHelper; -}(); - -exports.default = LevelHelper; - -},{"../utils/logger":38}],26:[function(require,module,exports){ -/** - * HLS interface - */ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); -//import FPSController from './controller/fps-controller'; - - -var _events = require('./events'); - -var _events2 = _interopRequireDefault(_events); - -var _errors = require('./errors'); - -var _playlistLoader = require('./loader/playlist-loader'); - -var _playlistLoader2 = _interopRequireDefault(_playlistLoader); - -var _fragmentLoader = require('./loader/fragment-loader'); - -var _fragmentLoader2 = _interopRequireDefault(_fragmentLoader); - -var _abrController = require('./controller/abr-controller'); - -var _abrController2 = _interopRequireDefault(_abrController); - -var _bufferController = require('./controller/buffer-controller'); - -var _bufferController2 = _interopRequireDefault(_bufferController); - -var _capLevelController = require('./controller/cap-level-controller'); - -var _capLevelController2 = _interopRequireDefault(_capLevelController); - -var _streamController = require('./controller/stream-controller'); - -var _streamController2 = _interopRequireDefault(_streamController); - -var _levelController = require('./controller/level-controller'); - -var _levelController2 = _interopRequireDefault(_levelController); - -var _timelineController = require('./controller/timeline-controller'); - -var _timelineController2 = _interopRequireDefault(_timelineController); - -var _logger = require('./utils/logger'); - -var _xhrLoader = require('./utils/xhr-loader'); - -var _xhrLoader2 = _interopRequireDefault(_xhrLoader); - -var _events3 = require('events'); - -var _events4 = _interopRequireDefault(_events3); - -var _keyLoader = require('./loader/key-loader'); - -var _keyLoader2 = _interopRequireDefault(_keyLoader); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var Hls = function () { - _createClass(Hls, null, [{ - key: 'isSupported', - value: function isSupported() { - return window.MediaSource && typeof window.MediaSource.isTypeSupported === 'function' && window.MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"'); - } - }, { - key: 'Events', - get: function get() { - return _events2.default; - } - }, { - key: 'ErrorTypes', - get: function get() { - return _errors.ErrorTypes; - } - }, { - key: 'ErrorDetails', - get: function get() { - return _errors.ErrorDetails; - } - }, { - key: 'DefaultConfig', - get: function get() { - if (!Hls.defaultConfig) { - Hls.defaultConfig = { - autoStartLoad: true, - startPosition: -1, - debug: false, - capLevelToPlayerSize: false, - maxBufferLength: 30, - maxBufferSize: 60 * 1000 * 1000, - maxBufferHole: 0.5, - maxSeekHole: 2, - seekHoleNudgeDuration: 0.01, - stalledInBufferedNudgeThreshold: 10, - maxFragLookUpTolerance: 0.2, - liveSyncDurationCount: 3, - liveMaxLatencyDurationCount: Infinity, - liveSyncDuration: undefined, - liveMaxLatencyDuration: undefined, - maxMaxBufferLength: 600, - enableWorker: true, - enableSoftwareAES: true, - manifestLoadingTimeOut: 10000, - manifestLoadingMaxRetry: 1, - manifestLoadingRetryDelay: 1000, - levelLoadingTimeOut: 10000, - levelLoadingMaxRetry: 4, - levelLoadingRetryDelay: 1000, - fragLoadingTimeOut: 20000, - fragLoadingMaxRetry: 6, - fragLoadingRetryDelay: 1000, - fragLoadingLoopThreshold: 3, - startFragPrefetch: false, - // fpsDroppedMonitoringPeriod: 5000, - // fpsDroppedMonitoringThreshold: 0.2, - appendErrorMaxRetry: 3, - loader: _xhrLoader2.default, - fLoader: undefined, - pLoader: undefined, - abrController: _abrController2.default, - bufferController: _bufferController2.default, - capLevelController: _capLevelController2.default, - streamController: _streamController2.default, - timelineController: _timelineController2.default, - enableCEA708Captions: true, - enableMP2TPassThrough: false, - abrEwmaFastLive: 5, - abrEwmaSlowLive: 9, - abrEwmaFastVoD: 4, - abrEwmaSlowVoD: 15, - abrEwmaDefaultEstimate: 5e5, // 500 kbps - abrBandWidthFactor: 0.8, - abrBandWidthUpFactor: 0.7 - }; - } - return Hls.defaultConfig; - }, - set: function set(defaultConfig) { - Hls.defaultConfig = defaultConfig; - } - }]); - - function Hls() { - var config = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; - - _classCallCheck(this, Hls); - - var defaultConfig = Hls.DefaultConfig; - - if ((config.liveSyncDurationCount || config.liveMaxLatencyDurationCount) && (config.liveSyncDuration || config.liveMaxLatencyDuration)) { - throw new Error('Illegal hls.js config: don\'t mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration'); - } - - for (var prop in defaultConfig) { - if (prop in config) { - continue; - } - config[prop] = defaultConfig[prop]; - } - - if (config.liveMaxLatencyDurationCount !== undefined && config.liveMaxLatencyDurationCount <= config.liveSyncDurationCount) { - throw new Error('Illegal hls.js config: "liveMaxLatencyDurationCount" must be gt "liveSyncDurationCount"'); - } - - if (config.liveMaxLatencyDuration !== undefined && (config.liveMaxLatencyDuration <= config.liveSyncDuration || config.liveSyncDuration === undefined)) { - throw new Error('Illegal hls.js config: "liveMaxLatencyDuration" must be gt "liveSyncDuration"'); - } - - (0, _logger.enableLogs)(config.debug); - this.config = config; - // observer setup - var observer = this.observer = new _events4.default(); - observer.trigger = function trigger(event) { - for (var _len = arguments.length, data = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - data[_key - 1] = arguments[_key]; - } - - observer.emit.apply(observer, [event, event].concat(data)); - }; - - observer.off = function off(event) { - for (var _len2 = arguments.length, data = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { - data[_key2 - 1] = arguments[_key2]; - } - - observer.removeListener.apply(observer, [event].concat(data)); - }; - this.on = observer.on.bind(observer); - this.off = observer.off.bind(observer); - this.trigger = observer.trigger.bind(observer); - this.playlistLoader = new _playlistLoader2.default(this); - this.fragmentLoader = new _fragmentLoader2.default(this); - this.levelController = new _levelController2.default(this); - this.abrController = new config.abrController(this); - this.bufferController = new config.bufferController(this); - this.capLevelController = new config.capLevelController(this); - this.streamController = new config.streamController(this); - this.timelineController = new config.timelineController(this); - this.keyLoader = new _keyLoader2.default(this); - //this.fpsController = new FPSController(this); - } - - _createClass(Hls, [{ - key: 'destroy', - value: function destroy() { - _logger.logger.log('destroy'); - this.trigger(_events2.default.DESTROYING); - this.detachMedia(); - this.playlistLoader.destroy(); - this.fragmentLoader.destroy(); - this.levelController.destroy(); - this.abrController.destroy(); - this.bufferController.destroy(); - this.capLevelController.destroy(); - this.streamController.destroy(); - this.timelineController.destroy(); - this.keyLoader.destroy(); - //this.fpsController.destroy(); - this.url = null; - this.observer.removeAllListeners(); - } - }, { - key: 'attachMedia', - value: function attachMedia(media) { - _logger.logger.log('attachMedia'); - this.media = media; - this.trigger(_events2.default.MEDIA_ATTACHING, { media: media }); - } - }, { - key: 'detachMedia', - value: function detachMedia() { - _logger.logger.log('detachMedia'); - this.trigger(_events2.default.MEDIA_DETACHING); - this.media = null; - } - }, { - key: 'loadSource', - value: function loadSource(url) { - _logger.logger.log('loadSource:' + url); - this.url = url; - // when attaching to a source URL, trigger a playlist load - this.trigger(_events2.default.MANIFEST_LOADING, { url: url }); - } - }, { - key: 'startLoad', - value: function startLoad() { - var startPosition = arguments.length <= 0 || arguments[0] === undefined ? -1 : arguments[0]; - - _logger.logger.log('startLoad'); - this.levelController.startLoad(); - this.streamController.startLoad(startPosition); - } - }, { - key: 'stopLoad', - value: function stopLoad() { - _logger.logger.log('stopLoad'); - this.levelController.stopLoad(); - this.streamController.stopLoad(); - } - }, { - key: 'swapAudioCodec', - value: function swapAudioCodec() { - _logger.logger.log('swapAudioCodec'); - this.streamController.swapAudioCodec(); - } - }, { - key: 'recoverMediaError', - value: function recoverMediaError() { - _logger.logger.log('recoverMediaError'); - var media = this.media; - this.detachMedia(); - this.attachMedia(media); - } - - /** Return all quality levels **/ - - }, { - key: 'levels', - get: function get() { - return this.levelController.levels; - } - - /** Return current playback quality level **/ - - }, { - key: 'currentLevel', - get: function get() { - return this.streamController.currentLevel; - } - - /* set quality level immediately (-1 for automatic level selection) */ - , - set: function set(newLevel) { - _logger.logger.log('set currentLevel:' + newLevel); - this.loadLevel = newLevel; - this.streamController.immediateLevelSwitch(); - } - - /** Return next playback quality level (quality level of next fragment) **/ - - }, { - key: 'nextLevel', - get: function get() { - return this.streamController.nextLevel; - } - - /* set quality level for next fragment (-1 for automatic level selection) */ - , - set: function set(newLevel) { - _logger.logger.log('set nextLevel:' + newLevel); - this.levelController.manualLevel = newLevel; - this.streamController.nextLevelSwitch(); - } - - /** Return the quality level of current/last loaded fragment **/ - - }, { - key: 'loadLevel', - get: function get() { - return this.levelController.level; - } - - /* set quality level for current/next loaded fragment (-1 for automatic level selection) */ - , - set: function set(newLevel) { - _logger.logger.log('set loadLevel:' + newLevel); - this.levelController.manualLevel = newLevel; - } - - /** Return the quality level of next loaded fragment **/ - - }, { - key: 'nextLoadLevel', - get: function get() { - return this.levelController.nextLoadLevel; - } - - /** set quality level of next loaded fragment **/ - , - set: function set(level) { - this.levelController.nextLoadLevel = level; - } - - /** Return first level (index of first level referenced in manifest) - **/ - - }, { - key: 'firstLevel', - get: function get() { - return this.levelController.firstLevel; - } - - /** set first level (index of first level referenced in manifest) - **/ - , - set: function set(newLevel) { - _logger.logger.log('set firstLevel:' + newLevel); - this.levelController.firstLevel = newLevel; - } - - /** Return start level (level of first fragment that will be played back) - if not overrided by user, first level appearing in manifest will be used as start level - if -1 : automatic start level selection, playback will start from level matching download bandwidth (determined from download of first segment) - **/ - - }, { - key: 'startLevel', - get: function get() { - return this.levelController.startLevel; - } - - /** set start level (level of first fragment that will be played back) - if not overrided by user, first level appearing in manifest will be used as start level - if -1 : automatic start level selection, playback will start from level matching download bandwidth (determined from download of first segment) - **/ - , - set: function set(newLevel) { - _logger.logger.log('set startLevel:' + newLevel); - this.levelController.startLevel = newLevel; - } - - /** Return the capping/max level value that could be used by automatic level selection algorithm **/ - - }, { - key: 'autoLevelCapping', - get: function get() { - return this.abrController.autoLevelCapping; - } - - /** set the capping/max level value that could be used by automatic level selection algorithm **/ - , - set: function set(newLevel) { - _logger.logger.log('set autoLevelCapping:' + newLevel); - this.abrController.autoLevelCapping = newLevel; - } - - /* check if we are in automatic level selection mode */ - - }, { - key: 'autoLevelEnabled', - get: function get() { - return this.levelController.manualLevel === -1; - } - - /* return manual level */ - - }, { - key: 'manualLevel', - get: function get() { - return this.levelController.manualLevel; - } - }]); - - return Hls; -}(); - -exports.default = Hls; - -},{"./controller/abr-controller":3,"./controller/buffer-controller":4,"./controller/cap-level-controller":5,"./controller/level-controller":7,"./controller/stream-controller":8,"./controller/timeline-controller":9,"./errors":21,"./events":23,"./loader/fragment-loader":28,"./loader/key-loader":29,"./loader/playlist-loader":30,"./utils/logger":38,"./utils/xhr-loader":40,"events":1}],27:[function(require,module,exports){ -'use strict'; - -// This is mostly for support of the es6 module export -// syntax with the babel compiler, it looks like it doesnt support -// function exports like we are used to in node/commonjs -module.exports = require('./hls.js').default; - -},{"./hls.js":26}],28:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -var _eventHandler = require('../event-handler'); - -var _eventHandler2 = _interopRequireDefault(_eventHandler); - -var _errors = require('../errors'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* - * Fragment Loader - */ - -var FragmentLoader = function (_EventHandler) { - _inherits(FragmentLoader, _EventHandler); - - function FragmentLoader(hls) { - _classCallCheck(this, FragmentLoader); - - return _possibleConstructorReturn(this, Object.getPrototypeOf(FragmentLoader).call(this, hls, _events2.default.FRAG_LOADING)); - } - - _createClass(FragmentLoader, [{ - key: 'destroy', - value: function destroy() { - if (this.loader) { - this.loader.destroy(); - this.loader = null; - } - _eventHandler2.default.prototype.destroy.call(this); - } - }, { - key: 'onFragLoading', - value: function onFragLoading(data) { - var frag = data.frag; - this.frag = frag; - this.frag.loaded = 0; - var config = this.hls.config; - frag.loader = this.loader = typeof config.fLoader !== 'undefined' ? new config.fLoader(config) : new config.loader(config); - this.loader.load(frag.url, 'arraybuffer', this.loadsuccess.bind(this), this.loaderror.bind(this), this.loadtimeout.bind(this), config.fragLoadingTimeOut, 1, 0, this.loadprogress.bind(this), frag); - } - }, { - key: 'loadsuccess', - value: function loadsuccess(event, stats) { - var payload = event.currentTarget.response; - stats.length = payload.byteLength; - // detach fragment loader on load success - this.frag.loader = undefined; - this.hls.trigger(_events2.default.FRAG_LOADED, { payload: payload, frag: this.frag, stats: stats }); - } - }, { - key: 'loaderror', - value: function loaderror(event) { - if (this.loader) { - this.loader.abort(); - } - this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.NETWORK_ERROR, details: _errors.ErrorDetails.FRAG_LOAD_ERROR, fatal: false, frag: this.frag, response: event }); - } - }, { - key: 'loadtimeout', - value: function loadtimeout() { - if (this.loader) { - this.loader.abort(); - } - this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.NETWORK_ERROR, details: _errors.ErrorDetails.FRAG_LOAD_TIMEOUT, fatal: false, frag: this.frag }); - } - }, { - key: 'loadprogress', - value: function loadprogress(event, stats) { - this.frag.loaded = stats.loaded; - this.hls.trigger(_events2.default.FRAG_LOAD_PROGRESS, { frag: this.frag, stats: stats }); - } - }]); - - return FragmentLoader; -}(_eventHandler2.default); - -exports.default = FragmentLoader; - -},{"../errors":21,"../event-handler":22,"../events":23}],29:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -var _eventHandler = require('../event-handler'); - -var _eventHandler2 = _interopRequireDefault(_eventHandler); - -var _errors = require('../errors'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* - * Decrypt key Loader - */ - -var KeyLoader = function (_EventHandler) { - _inherits(KeyLoader, _EventHandler); - - function KeyLoader(hls) { - _classCallCheck(this, KeyLoader); - - var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(KeyLoader).call(this, hls, _events2.default.KEY_LOADING)); - - _this.decryptkey = null; - _this.decrypturl = null; - return _this; - } - - _createClass(KeyLoader, [{ - key: 'destroy', - value: function destroy() { - if (this.loader) { - this.loader.destroy(); - this.loader = null; - } - _eventHandler2.default.prototype.destroy.call(this); - } - }, { - key: 'onKeyLoading', - value: function onKeyLoading(data) { - var frag = this.frag = data.frag, - decryptdata = frag.decryptdata, - uri = decryptdata.uri; - // if uri is different from previous one or if decrypt key not retrieved yet - if (uri !== this.decrypturl || this.decryptkey === null) { - var config = this.hls.config; - frag.loader = this.loader = new config.loader(config); - this.decrypturl = uri; - this.decryptkey = null; - frag.loader.load(uri, 'arraybuffer', this.loadsuccess.bind(this), this.loaderror.bind(this), this.loadtimeout.bind(this), config.fragLoadingTimeOut, config.fragLoadingMaxRetry, config.fragLoadingRetryDelay, this.loadprogress.bind(this), frag); - } else if (this.decryptkey) { - // we already loaded this key, return it - decryptdata.key = this.decryptkey; - this.hls.trigger(_events2.default.KEY_LOADED, { frag: frag }); - } - } - }, { - key: 'loadsuccess', - value: function loadsuccess(event) { - var frag = this.frag; - this.decryptkey = frag.decryptdata.key = new Uint8Array(event.currentTarget.response); - // detach fragment loader on load success - frag.loader = undefined; - this.hls.trigger(_events2.default.KEY_LOADED, { frag: frag }); - } - }, { - key: 'loaderror', - value: function loaderror(event) { - if (this.loader) { - this.loader.abort(); - } - this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.NETWORK_ERROR, details: _errors.ErrorDetails.KEY_LOAD_ERROR, fatal: false, frag: this.frag, response: event }); - } - }, { - key: 'loadtimeout', - value: function loadtimeout() { - if (this.loader) { - this.loader.abort(); - } - this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.NETWORK_ERROR, details: _errors.ErrorDetails.KEY_LOAD_TIMEOUT, fatal: false, frag: this.frag }); - } - }, { - key: 'loadprogress', - value: function loadprogress() {} - }]); - - return KeyLoader; -}(_eventHandler2.default); - -exports.default = KeyLoader; - -},{"../errors":21,"../event-handler":22,"../events":23}],30:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -var _eventHandler = require('../event-handler'); - -var _eventHandler2 = _interopRequireDefault(_eventHandler); - -var _errors = require('../errors'); - -var _url = require('../utils/url'); - -var _url2 = _interopRequireDefault(_url); - -var _attrList = require('../utils/attr-list'); - -var _attrList2 = _interopRequireDefault(_attrList); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /** - * Playlist Loader - */ - -//import {logger} from '../utils/logger'; - -var PlaylistLoader = function (_EventHandler) { - _inherits(PlaylistLoader, _EventHandler); - - function PlaylistLoader(hls) { - _classCallCheck(this, PlaylistLoader); - - return _possibleConstructorReturn(this, Object.getPrototypeOf(PlaylistLoader).call(this, hls, _events2.default.MANIFEST_LOADING, _events2.default.LEVEL_LOADING)); - } - - _createClass(PlaylistLoader, [{ - key: 'destroy', - value: function destroy() { - if (this.loader) { - this.loader.destroy(); - this.loader = null; - } - this.url = this.id = null; - _eventHandler2.default.prototype.destroy.call(this); - } - }, { - key: 'onManifestLoading', - value: function onManifestLoading(data) { - this.load(data.url, null); - } - }, { - key: 'onLevelLoading', - value: function onLevelLoading(data) { - this.load(data.url, data.level, data.id); - } - }, { - key: 'load', - value: function load(url, id1, id2) { - var config = this.hls.config, - retry, - timeout, - retryDelay; - - if (this.loading && this.loader) { - if (this.url === url && this.id === id1 && this.id2 === id2) { - // same request than last pending one, don't do anything - return; - } else { - // one playlist load request is pending, but with different params, abort it before loading new playlist - this.loader.abort(); - } - } - - this.url = url; - this.id = id1; - this.id2 = id2; - if (this.id === null) { - retry = config.manifestLoadingMaxRetry; - timeout = config.manifestLoadingTimeOut; - retryDelay = config.manifestLoadingRetryDelay; - } else { - retry = config.levelLoadingMaxRetry; - timeout = config.levelLoadingTimeOut; - retryDelay = config.levelLoadingRetryDelay; - } - this.loader = typeof config.pLoader !== 'undefined' ? new config.pLoader(config) : new config.loader(config); - this.loading = true; - this.loader.load(url, '', this.loadsuccess.bind(this), this.loaderror.bind(this), this.loadtimeout.bind(this), timeout, retry, retryDelay); - } - }, { - key: 'resolve', - value: function resolve(url, baseUrl) { - return _url2.default.buildAbsoluteURL(baseUrl, url); - } - }, { - key: 'parseMasterPlaylist', - value: function parseMasterPlaylist(string, baseurl) { - var levels = [], - result = void 0; - - // https://regex101.com is your friend - var re = /#EXT-X-STREAM-INF:([^\n\r]*)[\r\n]+([^\r\n]+)/g; - while ((result = re.exec(string)) != null) { - var level = {}; - - var attrs = level.attrs = new _attrList2.default(result[1]); - level.url = this.resolve(result[2], baseurl); - - var resolution = attrs.decimalResolution('RESOLUTION'); - if (resolution) { - level.width = resolution.width; - level.height = resolution.height; - } - level.bitrate = attrs.decimalInteger('AVERAGE-BANDWIDTH') || attrs.decimalInteger('BANDWIDTH'); - level.name = attrs.NAME; - - var codecs = attrs.CODECS; - if (codecs) { - codecs = codecs.split(','); - for (var i = 0; i < codecs.length; i++) { - var codec = codecs[i]; - if (codec.indexOf('avc1') !== -1) { - level.videoCodec = this.avc1toavcoti(codec); - } else { - level.audioCodec = codec; - } - } - } - - levels.push(level); - } - return levels; - } - }, { - key: 'avc1toavcoti', - value: function avc1toavcoti(codec) { - var result, - avcdata = codec.split('.'); - if (avcdata.length > 2) { - result = avcdata.shift() + '.'; - result += parseInt(avcdata.shift()).toString(16); - result += ('000' + parseInt(avcdata.shift()).toString(16)).substr(-4); - } else { - result = codec; - } - return result; - } - }, { - key: 'cloneObj', - value: function cloneObj(obj) { - return JSON.parse(JSON.stringify(obj)); - } - }, { - key: 'parseLevelPlaylist', - value: function parseLevelPlaylist(string, baseurl, id) { - var currentSN = 0, - totalduration = 0, - level = { url: baseurl, fragments: [], live: true, startSN: 0 }, - levelkey = { method: null, key: null, iv: null, uri: null }, - cc = 0, - programDateTime = null, - frag = null, - result, - regexp, - byteRangeEndOffset, - byteRangeStartOffset; - - regexp = /(?:#EXT-X-(MEDIA-SEQUENCE):(\d+))|(?:#EXT-X-(TARGETDURATION):(\d+))|(?:#EXT-X-(KEY):(.*))|(?:#EXT-X-(START):(.*))|(?:#EXT(INF):([\d\.]+)[^\r\n]*([\r\n]+[^#|\r\n]+)?)|(?:#EXT-X-(BYTERANGE):([\d]+[@[\d]*)]*[\r\n]+([^#|\r\n]+)?|(?:#EXT-X-(ENDLIST))|(?:#EXT-X-(DIS)CONTINUITY))|(?:#EXT-X-(PROGRAM-DATE-TIME):(.*)[\r\n]+([^#|\r\n]+)?)/g; - while ((result = regexp.exec(string)) !== null) { - result.shift(); - result = result.filter(function (n) { - return n !== undefined; - }); - switch (result[0]) { - case 'MEDIA-SEQUENCE': - currentSN = level.startSN = parseInt(result[1]); - break; - case 'TARGETDURATION': - level.targetduration = parseFloat(result[1]); - break; - case 'ENDLIST': - level.live = false; - break; - case 'DIS': - cc++; - break; - case 'BYTERANGE': - var params = result[1].split('@'); - if (params.length === 1) { - byteRangeStartOffset = byteRangeEndOffset; - } else { - byteRangeStartOffset = parseInt(params[1]); - } - byteRangeEndOffset = parseInt(params[0]) + byteRangeStartOffset; - if (frag && !frag.url) { - frag.byteRangeStartOffset = byteRangeStartOffset; - frag.byteRangeEndOffset = byteRangeEndOffset; - frag.url = this.resolve(result[2], baseurl); - } - break; - case 'INF': - var duration = parseFloat(result[1]); - if (!isNaN(duration)) { - var fragdecryptdata, - sn = currentSN++; - if (levelkey.method && levelkey.uri && !levelkey.iv) { - fragdecryptdata = this.cloneObj(levelkey); - var uint8View = new Uint8Array(16); - for (var i = 12; i < 16; i++) { - uint8View[i] = sn >> 8 * (15 - i) & 0xff; - } - fragdecryptdata.iv = uint8View; - } else { - fragdecryptdata = levelkey; - } - var url = result[2] ? this.resolve(result[2], baseurl) : null; - frag = { url: url, duration: duration, start: totalduration, sn: sn, level: id, cc: cc, byteRangeStartOffset: byteRangeStartOffset, byteRangeEndOffset: byteRangeEndOffset, decryptdata: fragdecryptdata, programDateTime: programDateTime }; - level.fragments.push(frag); - totalduration += duration; - byteRangeStartOffset = null; - programDateTime = null; - } - break; - case 'KEY': - // https://tools.ietf.org/html/draft-pantos-http-live-streaming-08#section-3.4.4 - var decryptparams = result[1]; - var keyAttrs = new _attrList2.default(decryptparams); - var decryptmethod = keyAttrs.enumeratedString('METHOD'), - decrypturi = keyAttrs.URI, - decryptiv = keyAttrs.hexadecimalInteger('IV'); - if (decryptmethod) { - levelkey = { method: null, key: null, iv: null, uri: null }; - if (decrypturi && decryptmethod === 'AES-128') { - levelkey.method = decryptmethod; - // URI to get the key - levelkey.uri = this.resolve(decrypturi, baseurl); - levelkey.key = null; - // Initialization Vector (IV) - levelkey.iv = decryptiv; - } - } - break; - case 'START': - var startParams = result[1]; - var startAttrs = new _attrList2.default(startParams); - var startTimeOffset = startAttrs.decimalFloatingPoint('TIME-OFFSET'); - if (startTimeOffset) { - level.startTimeOffset = startTimeOffset; - } - break; - case 'PROGRAM-DATE-TIME': - programDateTime = new Date(Date.parse(result[1])); - if (frag && !frag.url && result.length >= 3) { - frag.url = this.resolve(result[2], baseurl); - frag.programDateTime = programDateTime; - } - break; - default: - break; - } - } - //logger.log('found ' + level.fragments.length + ' fragments'); - if (frag && !frag.url) { - level.fragments.pop(); - totalduration -= frag.duration; - } - level.totalduration = totalduration; - level.endSN = currentSN - 1; - return level; - } - }, { - key: 'loadsuccess', - value: function loadsuccess(event, stats) { - var target = event.currentTarget, - string = target.responseText, - url = target.responseURL, - id = this.id, - id2 = this.id2, - hls = this.hls, - levels; - - this.loading = false; - // responseURL not supported on some browsers (it is used to detect URL redirection) - if (url === undefined) { - // fallback to initial URL - url = this.url; - } - stats.tload = performance.now(); - stats.mtime = new Date(target.getResponseHeader('Last-Modified')); - if (string.indexOf('#EXTM3U') === 0) { - if (string.indexOf('#EXTINF:') > 0) { - // 1 level playlist - // if first request, fire manifest loaded event, level will be reloaded afterwards - // (this is to have a uniform logic for 1 level/multilevel playlists) - if (this.id === null) { - hls.trigger(_events2.default.MANIFEST_LOADED, { levels: [{ url: url }], url: url, stats: stats }); - } else { - var levelDetails = this.parseLevelPlaylist(string, url, id); - stats.tparsed = performance.now(); - hls.trigger(_events2.default.LEVEL_LOADED, { details: levelDetails, level: id, id: id2, stats: stats }); - } - } else { - levels = this.parseMasterPlaylist(string, url); - // multi level playlist, parse level info - if (levels.length) { - hls.trigger(_events2.default.MANIFEST_LOADED, { levels: levels, url: url, stats: stats }); - } else { - hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.NETWORK_ERROR, details: _errors.ErrorDetails.MANIFEST_PARSING_ERROR, fatal: true, url: url, reason: 'no level found in manifest' }); - } - } - } else { - hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.NETWORK_ERROR, details: _errors.ErrorDetails.MANIFEST_PARSING_ERROR, fatal: true, url: url, reason: 'no EXTM3U delimiter' }); - } - } - }, { - key: 'loaderror', - value: function loaderror(event) { - var details, fatal; - if (this.id === null) { - details = _errors.ErrorDetails.MANIFEST_LOAD_ERROR; - fatal = true; - } else { - details = _errors.ErrorDetails.LEVEL_LOAD_ERROR; - fatal = false; - } - if (this.loader) { - this.loader.abort(); - } - this.loading = false; - this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.NETWORK_ERROR, details: details, fatal: fatal, url: this.url, loader: this.loader, response: event.currentTarget, level: this.id, id: this.id2 }); - } - }, { - key: 'loadtimeout', - value: function loadtimeout() { - var details, fatal; - if (this.id === null) { - details = _errors.ErrorDetails.MANIFEST_LOAD_TIMEOUT; - fatal = true; - } else { - details = _errors.ErrorDetails.LEVEL_LOAD_TIMEOUT; - fatal = false; - } - if (this.loader) { - this.loader.abort(); - } - this.loading = false; - this.hls.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.NETWORK_ERROR, details: details, fatal: fatal, url: this.url, loader: this.loader, level: this.id, id: this.id2 }); - } - }]); - - return PlaylistLoader; -}(_eventHandler2.default); - -exports.default = PlaylistLoader; - -},{"../errors":21,"../event-handler":22,"../events":23,"../utils/attr-list":34,"../utils/url":39}],31:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * Generate MP4 Box -*/ - -//import Hex from '../utils/hex'; - -var MP4 = function () { - function MP4() { - _classCallCheck(this, MP4); - } - - _createClass(MP4, null, [{ - key: 'init', - value: function init() { - MP4.types = { - avc1: [], // codingname - avcC: [], - btrt: [], - dinf: [], - dref: [], - esds: [], - ftyp: [], - hdlr: [], - mdat: [], - mdhd: [], - mdia: [], - mfhd: [], - minf: [], - moof: [], - moov: [], - mp4a: [], - mvex: [], - mvhd: [], - sdtp: [], - stbl: [], - stco: [], - stsc: [], - stsd: [], - stsz: [], - stts: [], - tfdt: [], - tfhd: [], - traf: [], - trak: [], - trun: [], - trex: [], - tkhd: [], - vmhd: [], - smhd: [] - }; - - var i; - for (i in MP4.types) { - if (MP4.types.hasOwnProperty(i)) { - MP4.types[i] = [i.charCodeAt(0), i.charCodeAt(1), i.charCodeAt(2), i.charCodeAt(3)]; - } - } - - var videoHdlr = new Uint8Array([0x00, // version 0 - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x00, // pre_defined - 0x76, 0x69, 0x64, 0x65, // handler_type: 'vide' - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, 0x00, // reserved - 0x56, 0x69, 0x64, 0x65, 0x6f, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'VideoHandler' - ]); - - var audioHdlr = new Uint8Array([0x00, // version 0 - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x00, // pre_defined - 0x73, 0x6f, 0x75, 0x6e, // handler_type: 'soun' - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, 0x00, // reserved - 0x53, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'SoundHandler' - ]); - - MP4.HDLR_TYPES = { - 'video': videoHdlr, - 'audio': audioHdlr - }; - - var dref = new Uint8Array([0x00, // version 0 - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x01, // entry_count - 0x00, 0x00, 0x00, 0x0c, // entry_size - 0x75, 0x72, 0x6c, 0x20, // 'url' type - 0x00, // version 0 - 0x00, 0x00, 0x01 // entry_flags - ]); - - var stco = new Uint8Array([0x00, // version - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x00 // entry_count - ]); - - MP4.STTS = MP4.STSC = MP4.STCO = stco; - - MP4.STSZ = new Uint8Array([0x00, // version - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x00, // sample_size - 0x00, 0x00, 0x00, 0x00]); - // sample_count - MP4.VMHD = new Uint8Array([0x00, // version - 0x00, 0x00, 0x01, // flags - 0x00, 0x00, // graphicsmode - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // opcolor - ]); - MP4.SMHD = new Uint8Array([0x00, // version - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, // balance - 0x00, 0x00 // reserved - ]); - - MP4.STSD = new Uint8Array([0x00, // version 0 - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x01]); // entry_count - - var majorBrand = new Uint8Array([105, 115, 111, 109]); // isom - var avc1Brand = new Uint8Array([97, 118, 99, 49]); // avc1 - var minorVersion = new Uint8Array([0, 0, 0, 1]); - - MP4.FTYP = MP4.box(MP4.types.ftyp, majorBrand, minorVersion, majorBrand, avc1Brand); - MP4.DINF = MP4.box(MP4.types.dinf, MP4.box(MP4.types.dref, dref)); - } - }, { - key: 'box', - value: function box(type) { - var payload = Array.prototype.slice.call(arguments, 1), - size = 8, - i = payload.length, - len = i, - result; - // calculate the total size we need to allocate - while (i--) { - size += payload[i].byteLength; - } - result = new Uint8Array(size); - result[0] = size >> 24 & 0xff; - result[1] = size >> 16 & 0xff; - result[2] = size >> 8 & 0xff; - result[3] = size & 0xff; - result.set(type, 4); - // copy the payload into the result - for (i = 0, size = 8; i < len; i++) { - // copy payload[i] array @ offset size - result.set(payload[i], size); - size += payload[i].byteLength; - } - return result; - } - }, { - key: 'hdlr', - value: function hdlr(type) { - return MP4.box(MP4.types.hdlr, MP4.HDLR_TYPES[type]); - } - }, { - key: 'mdat', - value: function mdat(data) { - return MP4.box(MP4.types.mdat, data); - } - }, { - key: 'mdhd', - value: function mdhd(timescale, duration) { - duration *= timescale; - return MP4.box(MP4.types.mdhd, new Uint8Array([0x00, // version 0 - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x02, // creation_time - 0x00, 0x00, 0x00, 0x03, // modification_time - timescale >> 24 & 0xFF, timescale >> 16 & 0xFF, timescale >> 8 & 0xFF, timescale & 0xFF, // timescale - duration >> 24, duration >> 16 & 0xFF, duration >> 8 & 0xFF, duration & 0xFF, // duration - 0x55, 0xc4, // 'und' language (undetermined) - 0x00, 0x00])); - } - }, { - key: 'mdia', - value: function mdia(track) { - return MP4.box(MP4.types.mdia, MP4.mdhd(track.timescale, track.duration), MP4.hdlr(track.type), MP4.minf(track)); - } - }, { - key: 'mfhd', - value: function mfhd(sequenceNumber) { - return MP4.box(MP4.types.mfhd, new Uint8Array([0x00, 0x00, 0x00, 0x00, // flags - sequenceNumber >> 24, sequenceNumber >> 16 & 0xFF, sequenceNumber >> 8 & 0xFF, sequenceNumber & 0xFF])); - } - }, { - key: 'minf', - // sequence_number - value: function minf(track) { - if (track.type === 'audio') { - return MP4.box(MP4.types.minf, MP4.box(MP4.types.smhd, MP4.SMHD), MP4.DINF, MP4.stbl(track)); - } else { - return MP4.box(MP4.types.minf, MP4.box(MP4.types.vmhd, MP4.VMHD), MP4.DINF, MP4.stbl(track)); - } - } - }, { - key: 'moof', - value: function moof(sn, baseMediaDecodeTime, track) { - return MP4.box(MP4.types.moof, MP4.mfhd(sn), MP4.traf(track, baseMediaDecodeTime)); - } - /** - * @param tracks... (optional) {array} the tracks associated with this movie - */ - - }, { - key: 'moov', - value: function moov(tracks) { - var i = tracks.length, - boxes = []; - - while (i--) { - boxes[i] = MP4.trak(tracks[i]); - } - - return MP4.box.apply(null, [MP4.types.moov, MP4.mvhd(tracks[0].timescale, tracks[0].duration)].concat(boxes).concat(MP4.mvex(tracks))); - } - }, { - key: 'mvex', - value: function mvex(tracks) { - var i = tracks.length, - boxes = []; - - while (i--) { - boxes[i] = MP4.trex(tracks[i]); - } - return MP4.box.apply(null, [MP4.types.mvex].concat(boxes)); - } - }, { - key: 'mvhd', - value: function mvhd(timescale, duration) { - duration *= timescale; - var bytes = new Uint8Array([0x00, // version 0 - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x01, // creation_time - 0x00, 0x00, 0x00, 0x02, // modification_time - timescale >> 24 & 0xFF, timescale >> 16 & 0xFF, timescale >> 8 & 0xFF, timescale & 0xFF, // timescale - duration >> 24 & 0xFF, duration >> 16 & 0xFF, duration >> 8 & 0xFF, duration & 0xFF, // duration - 0x00, 0x01, 0x00, 0x00, // 1.0 rate - 0x01, 0x00, // 1.0 volume - 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pre_defined - 0xff, 0xff, 0xff, 0xff // next_track_ID - ]); - return MP4.box(MP4.types.mvhd, bytes); - } - }, { - key: 'sdtp', - value: function sdtp(track) { - var samples = track.samples || [], - bytes = new Uint8Array(4 + samples.length), - flags, - i; - // leave the full box header (4 bytes) all zero - // write the sample table - for (i = 0; i < samples.length; i++) { - flags = samples[i].flags; - bytes[i + 4] = flags.dependsOn << 4 | flags.isDependedOn << 2 | flags.hasRedundancy; - } - - return MP4.box(MP4.types.sdtp, bytes); - } - }, { - key: 'stbl', - value: function stbl(track) { - return MP4.box(MP4.types.stbl, MP4.stsd(track), MP4.box(MP4.types.stts, MP4.STTS), MP4.box(MP4.types.stsc, MP4.STSC), MP4.box(MP4.types.stsz, MP4.STSZ), MP4.box(MP4.types.stco, MP4.STCO)); - } - }, { - key: 'avc1', - value: function avc1(track) { - var sps = [], - pps = [], - i, - data, - len; - // assemble the SPSs - - for (i = 0; i < track.sps.length; i++) { - data = track.sps[i]; - len = data.byteLength; - sps.push(len >>> 8 & 0xFF); - sps.push(len & 0xFF); - sps = sps.concat(Array.prototype.slice.call(data)); // SPS - } - - // assemble the PPSs - for (i = 0; i < track.pps.length; i++) { - data = track.pps[i]; - len = data.byteLength; - pps.push(len >>> 8 & 0xFF); - pps.push(len & 0xFF); - pps = pps.concat(Array.prototype.slice.call(data)); - } - - var avcc = MP4.box(MP4.types.avcC, new Uint8Array([0x01, // version - sps[3], // profile - sps[4], // profile compat - sps[5], // level - 0xfc | 3, // lengthSizeMinusOne, hard-coded to 4 bytes - 0xE0 | track.sps.length // 3bit reserved (111) + numOfSequenceParameterSets - ].concat(sps).concat([track.pps.length // numOfPictureParameterSets - ]).concat(pps))), - // "PPS" - width = track.width, - height = track.height; - //console.log('avcc:' + Hex.hexDump(avcc)); - return MP4.box(MP4.types.avc1, new Uint8Array([0x00, 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, // reserved - 0x00, 0x01, // data_reference_index - 0x00, 0x00, // pre_defined - 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pre_defined - width >> 8 & 0xFF, width & 0xff, // width - height >> 8 & 0xFF, height & 0xff, // height - 0x00, 0x48, 0x00, 0x00, // horizresolution - 0x00, 0x48, 0x00, 0x00, // vertresolution - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x01, // frame_count - 0x12, 0x64, 0x61, 0x69, 0x6C, //dailymotion/hls.js - 0x79, 0x6D, 0x6F, 0x74, 0x69, 0x6F, 0x6E, 0x2F, 0x68, 0x6C, 0x73, 0x2E, 0x6A, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // compressorname - 0x00, 0x18, // depth = 24 - 0x11, 0x11]), // pre_defined = -1 - avcc, MP4.box(MP4.types.btrt, new Uint8Array([0x00, 0x1c, 0x9c, 0x80, // bufferSizeDB - 0x00, 0x2d, 0xc6, 0xc0, // maxBitrate - 0x00, 0x2d, 0xc6, 0xc0])) // avgBitrate - ); - } - }, { - key: 'esds', - value: function esds(track) { - var configlen = track.config.length; - return new Uint8Array([0x00, // version 0 - 0x00, 0x00, 0x00, // flags - - 0x03, // descriptor_type - 0x17 + configlen, // length - 0x00, 0x01, //es_id - 0x00, // stream_priority - - 0x04, // descriptor_type - 0x0f + configlen, // length - 0x40, //codec : mpeg4_audio - 0x15, // stream_type - 0x00, 0x00, 0x00, // buffer_size - 0x00, 0x00, 0x00, 0x00, // maxBitrate - 0x00, 0x00, 0x00, 0x00, // avgBitrate - - 0x05 // descriptor_type - ].concat([configlen]).concat(track.config).concat([0x06, 0x01, 0x02])); // GASpecificConfig)); // length + audio config descriptor - } - }, { - key: 'mp4a', - value: function mp4a(track) { - var audiosamplerate = track.audiosamplerate; - return MP4.box(MP4.types.mp4a, new Uint8Array([0x00, 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, // reserved - 0x00, 0x01, // data_reference_index - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, track.channelCount, // channelcount - 0x00, 0x10, // sampleSize:16bits - 0x00, 0x00, 0x00, 0x00, // reserved2 - audiosamplerate >> 8 & 0xFF, audiosamplerate & 0xff, // - 0x00, 0x00]), MP4.box(MP4.types.esds, MP4.esds(track))); - } - }, { - key: 'stsd', - value: function stsd(track) { - if (track.type === 'audio') { - return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track)); - } else { - return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track)); - } - } - }, { - key: 'tkhd', - value: function tkhd(track) { - var id = track.id, - duration = track.duration * track.timescale, - width = track.width, - height = track.height; - return MP4.box(MP4.types.tkhd, new Uint8Array([0x00, // version 0 - 0x00, 0x00, 0x07, // flags - 0x00, 0x00, 0x00, 0x00, // creation_time - 0x00, 0x00, 0x00, 0x00, // modification_time - id >> 24 & 0xFF, id >> 16 & 0xFF, id >> 8 & 0xFF, id & 0xFF, // track_ID - 0x00, 0x00, 0x00, 0x00, // reserved - duration >> 24, duration >> 16 & 0xFF, duration >> 8 & 0xFF, duration & 0xFF, // duration - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x00, // layer - 0x00, 0x00, // alternate_group - 0x00, 0x00, // non-audio track volume - 0x00, 0x00, // reserved - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix - width >> 8 & 0xFF, width & 0xFF, 0x00, 0x00, // width - height >> 8 & 0xFF, height & 0xFF, 0x00, 0x00 // height - ])); - } - }, { - key: 'traf', - value: function traf(track, baseMediaDecodeTime) { - var sampleDependencyTable = MP4.sdtp(track), - id = track.id; - return MP4.box(MP4.types.traf, MP4.box(MP4.types.tfhd, new Uint8Array([0x00, // version 0 - 0x00, 0x00, 0x00, // flags - id >> 24, id >> 16 & 0XFF, id >> 8 & 0XFF, id & 0xFF])), // track_ID - MP4.box(MP4.types.tfdt, new Uint8Array([0x00, // version 0 - 0x00, 0x00, 0x00, // flags - baseMediaDecodeTime >> 24, baseMediaDecodeTime >> 16 & 0XFF, baseMediaDecodeTime >> 8 & 0XFF, baseMediaDecodeTime & 0xFF])), // baseMediaDecodeTime - MP4.trun(track, sampleDependencyTable.length + 16 + // tfhd - 16 + // tfdt - 8 + // traf header - 16 + // mfhd - 8 + // moof header - 8), // mdat header - sampleDependencyTable); - } - - /** - * Generate a track box. - * @param track {object} a track definition - * @return {Uint8Array} the track box - */ - - }, { - key: 'trak', - value: function trak(track) { - track.duration = track.duration || 0xffffffff; - return MP4.box(MP4.types.trak, MP4.tkhd(track), MP4.mdia(track)); - } - }, { - key: 'trex', - value: function trex(track) { - var id = track.id; - return MP4.box(MP4.types.trex, new Uint8Array([0x00, // version 0 - 0x00, 0x00, 0x00, // flags - id >> 24, id >> 16 & 0XFF, id >> 8 & 0XFF, id & 0xFF, // track_ID - 0x00, 0x00, 0x00, 0x01, // default_sample_description_index - 0x00, 0x00, 0x00, 0x00, // default_sample_duration - 0x00, 0x00, 0x00, 0x00, // default_sample_size - 0x00, 0x01, 0x00, 0x01 // default_sample_flags - ])); - } - }, { - key: 'trun', - value: function trun(track, offset) { - var samples = track.samples || [], - len = samples.length, - arraylen = 12 + 16 * len, - array = new Uint8Array(arraylen), - i, - sample, - duration, - size, - flags, - cts; - offset += 8 + arraylen; - array.set([0x00, // version 0 - 0x00, 0x0f, 0x01, // flags - len >>> 24 & 0xFF, len >>> 16 & 0xFF, len >>> 8 & 0xFF, len & 0xFF, // sample_count - offset >>> 24 & 0xFF, offset >>> 16 & 0xFF, offset >>> 8 & 0xFF, offset & 0xFF // data_offset - ], 0); - for (i = 0; i < len; i++) { - sample = samples[i]; - duration = sample.duration; - size = sample.size; - flags = sample.flags; - cts = sample.cts; - array.set([duration >>> 24 & 0xFF, duration >>> 16 & 0xFF, duration >>> 8 & 0xFF, duration & 0xFF, // sample_duration - size >>> 24 & 0xFF, size >>> 16 & 0xFF, size >>> 8 & 0xFF, size & 0xFF, // sample_size - flags.isLeading << 2 | flags.dependsOn, flags.isDependedOn << 6 | flags.hasRedundancy << 4 | flags.paddingValue << 1 | flags.isNonSync, flags.degradPrio & 0xF0 << 8, flags.degradPrio & 0x0F, // sample_flags - cts >>> 24 & 0xFF, cts >>> 16 & 0xFF, cts >>> 8 & 0xFF, cts & 0xFF // sample_composition_time_offset - ], 12 + 16 * i); - } - return MP4.box(MP4.types.trun, array); - } - }, { - key: 'initSegment', - value: function initSegment(tracks) { - if (!MP4.types) { - MP4.init(); - } - var movie = MP4.moov(tracks), - result; - result = new Uint8Array(MP4.FTYP.byteLength + movie.byteLength); - result.set(MP4.FTYP); - result.set(movie, MP4.FTYP.byteLength); - return result; - } - }]); - - return MP4; -}(); - -exports.default = MP4; - -},{}],32:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * fMP4 remuxer - */ - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -var _logger = require('../utils/logger'); - -var _mp4Generator = require('../remux/mp4-generator'); - -var _mp4Generator2 = _interopRequireDefault(_mp4Generator); - -var _errors = require('../errors'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var MP4Remuxer = function () { - function MP4Remuxer(observer) { - _classCallCheck(this, MP4Remuxer); - - this.observer = observer; - this.ISGenerated = false; - this.PES2MP4SCALEFACTOR = 4; - this.PES_TIMESCALE = 90000; - this.MP4_TIMESCALE = this.PES_TIMESCALE / this.PES2MP4SCALEFACTOR; - } - - _createClass(MP4Remuxer, [{ - key: 'destroy', - value: function destroy() {} - }, { - key: 'insertDiscontinuity', - value: function insertDiscontinuity() { - this._initPTS = this._initDTS = undefined; - } - }, { - key: 'switchLevel', - value: function switchLevel() { - this.ISGenerated = false; - } - }, { - key: 'remux', - value: function remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, contiguous) { - // generate Init Segment if needed - if (!this.ISGenerated) { - this.generateIS(audioTrack, videoTrack, timeOffset); - } - if (this.ISGenerated) { - //logger.log('nb AVC samples:' + videoTrack.samples.length); - if (videoTrack.samples.length) { - this.remuxVideo(videoTrack, timeOffset, contiguous); - } - //logger.log('nb AAC samples:' + audioTrack.samples.length); - if (audioTrack.samples.length) { - this.remuxAudio(audioTrack, timeOffset, contiguous); - } - } - //logger.log('nb ID3 samples:' + audioTrack.samples.length); - if (id3Track.samples.length) { - this.remuxID3(id3Track, timeOffset); - } - //logger.log('nb ID3 samples:' + audioTrack.samples.length); - if (textTrack.samples.length) { - this.remuxText(textTrack, timeOffset); - } - //notify end of parsing - this.observer.trigger(_events2.default.FRAG_PARSED); - } - }, { - key: 'generateIS', - value: function generateIS(audioTrack, videoTrack, timeOffset) { - var observer = this.observer, - audioSamples = audioTrack.samples, - videoSamples = videoTrack.samples, - pesTimeScale = this.PES_TIMESCALE, - tracks = {}, - data = { tracks: tracks, unique: false }, - computePTSDTS = this._initPTS === undefined, - initPTS, - initDTS; - - if (computePTSDTS) { - initPTS = initDTS = Infinity; - } - if (audioTrack.config && audioSamples.length) { - audioTrack.timescale = audioTrack.audiosamplerate; - // MP4 duration (track duration in seconds multiplied by timescale) is coded on 32 bits - // we know that each AAC sample contains 1024 frames.... - // in order to avoid overflowing the 32 bit counter for large duration, we use smaller timescale (timescale/gcd) - // we just need to ensure that AAC sample duration will still be an integer (will be 1024/gcd) - if (audioTrack.timescale * audioTrack.duration > Math.pow(2, 32)) { - (function () { - var greatestCommonDivisor = function greatestCommonDivisor(a, b) { - if (!b) { - return a; - } - return greatestCommonDivisor(b, a % b); - }; - audioTrack.timescale = audioTrack.audiosamplerate / greatestCommonDivisor(audioTrack.audiosamplerate, 1024); - })(); - } - _logger.logger.log('audio mp4 timescale :' + audioTrack.timescale); - tracks.audio = { - container: 'audio/mp4', - codec: audioTrack.codec, - initSegment: _mp4Generator2.default.initSegment([audioTrack]), - metadata: { - channelCount: audioTrack.channelCount - } - }; - if (computePTSDTS) { - // remember first PTS of this demuxing context. for audio, PTS + DTS ... - initPTS = initDTS = audioSamples[0].pts - pesTimeScale * timeOffset; - } - } - - if (videoTrack.sps && videoTrack.pps && videoSamples.length) { - videoTrack.timescale = this.MP4_TIMESCALE; - tracks.video = { - container: 'video/mp4', - codec: videoTrack.codec, - initSegment: _mp4Generator2.default.initSegment([videoTrack]), - metadata: { - width: videoTrack.width, - height: videoTrack.height - } - }; - if (computePTSDTS) { - initPTS = Math.min(initPTS, videoSamples[0].pts - pesTimeScale * timeOffset); - initDTS = Math.min(initDTS, videoSamples[0].dts - pesTimeScale * timeOffset); - } - } - - if (Object.keys(tracks).length) { - observer.trigger(_events2.default.FRAG_PARSING_INIT_SEGMENT, data); - this.ISGenerated = true; - if (computePTSDTS) { - this._initPTS = initPTS; - this._initDTS = initDTS; - } - } else { - observer.trigger(_events2.default.ERROR, { type: _errors.ErrorTypes.MEDIA_ERROR, details: _errors.ErrorDetails.FRAG_PARSING_ERROR, fatal: false, reason: 'no audio/video samples found' }); - } - } - }, { - key: 'remuxVideo', - value: function remuxVideo(track, timeOffset, contiguous) { - var view, - offset = 8, - pesTimeScale = this.PES_TIMESCALE, - pes2mp4ScaleFactor = this.PES2MP4SCALEFACTOR, - avcSample, - mp4Sample, - mp4SampleLength, - unit, - mdat, - moof, - firstPTS, - firstDTS, - lastDTS, - pts, - dts, - ptsnorm, - dtsnorm, - flags, - samples = []; - - // handle broken streams with PTS < DTS, tolerance up 200ms (18000 in 90kHz timescale) - var PTSDTSshift = track.samples.reduce(function (prev, curr) { - return Math.max(Math.min(prev, curr.pts - curr.dts), -18000); - }, 0); - if (PTSDTSshift < 0) { - _logger.logger.warn('PTS < DTS detected in video samples, shifting DTS by ' + Math.round(PTSDTSshift / 90) + ' ms to overcome this issue'); - } - /* concatenate the video data and construct the mdat in place - (need 8 more bytes to fill length and mpdat type) */ - mdat = new Uint8Array(track.len + 4 * track.nbNalu + 8); - view = new DataView(mdat.buffer); - view.setUint32(0, mdat.byteLength); - mdat.set(_mp4Generator2.default.types.mdat, 4); - while (track.samples.length) { - avcSample = track.samples.shift(); - mp4SampleLength = 0; - // convert NALU bitstream to MP4 format (prepend NALU with size field) - while (avcSample.units.units.length) { - unit = avcSample.units.units.shift(); - view.setUint32(offset, unit.data.byteLength); - offset += 4; - mdat.set(unit.data, offset); - offset += unit.data.byteLength; - mp4SampleLength += 4 + unit.data.byteLength; - } - pts = avcSample.pts - this._initDTS; - // shift dts by PTSDTSshift, to ensure that PTS >= DTS - dts = avcSample.dts - this._initDTS + PTSDTSshift; - // ensure DTS is not bigger than PTS // strap belt !!! - dts = Math.min(pts, dts); - //logger.log(`Video/PTS/DTS/ptsnorm/DTSnorm:${Math.round(avcSample.pts/90)}/${Math.round(avcSample.dts/90)}/${Math.round(pts/90)}/${Math.round(dts/90)}`); - // if not first AVC sample of video track, normalize PTS/DTS with previous sample value - // and ensure that sample duration is positive - if (lastDTS !== undefined) { - ptsnorm = this._PTSNormalize(pts, lastDTS); - dtsnorm = this._PTSNormalize(dts, lastDTS); - var sampleDuration = (dtsnorm - lastDTS) / pes2mp4ScaleFactor; - if (sampleDuration <= 0) { - _logger.logger.log('invalid sample duration at PTS/DTS: ' + avcSample.pts + '/' + avcSample.dts + ':' + sampleDuration); - sampleDuration = 1; - } - mp4Sample.duration = sampleDuration; - } else { - var nextAvcDts = void 0, - delta = void 0; - if (contiguous) { - nextAvcDts = this.nextAvcDts; - } else { - nextAvcDts = timeOffset * pesTimeScale; - } - // first AVC sample of video track, normalize PTS/DTS - ptsnorm = this._PTSNormalize(pts, nextAvcDts); - dtsnorm = this._PTSNormalize(dts, nextAvcDts); - delta = Math.round((dtsnorm - nextAvcDts) / 90); - // if fragment are contiguous, detect hole/overlapping between fragments - if (contiguous) { - if (delta) { - if (delta > 1) { - _logger.logger.log('AVC:' + delta + ' ms hole between fragments detected,filling it'); - } else if (delta < -1) { - _logger.logger.log('AVC:' + -delta + ' ms overlapping between fragments detected'); - } - // set DTS to next DTS - dtsnorm = nextAvcDts; - // offset PTS as well, ensure that PTS is smaller or equal than new DTS - ptsnorm = Math.max(ptsnorm - delta, dtsnorm); - _logger.logger.log('Video/PTS/DTS adjusted: ' + ptsnorm + '/' + dtsnorm + ',delta:' + delta); - } - } - // remember first PTS of our avcSamples, ensure value is positive - firstPTS = Math.max(0, ptsnorm); - firstDTS = Math.max(0, dtsnorm); - } - //console.log(`PTS/DTS/initDTS/normPTS/normDTS/relative PTS : ${avcSample.pts}/${avcSample.dts}/${this._initDTS}/${ptsnorm}/${dtsnorm}/${(avcSample.pts/4294967296).toFixed(3)}); - mp4Sample = { - size: mp4SampleLength, - duration: 0, - cts: (ptsnorm - dtsnorm) / pes2mp4ScaleFactor, - flags: { - isLeading: 0, - isDependedOn: 0, - hasRedundancy: 0, - degradPrio: 0 - } - }; - flags = mp4Sample.flags; - if (avcSample.key === true) { - // the current sample is a key frame - flags.dependsOn = 2; - flags.isNonSync = 0; - } else { - flags.dependsOn = 1; - flags.isNonSync = 1; - } - samples.push(mp4Sample); - lastDTS = dtsnorm; - } - var lastSampleDuration = 0; - if (samples.length >= 2) { - lastSampleDuration = samples[samples.length - 2].duration; - mp4Sample.duration = lastSampleDuration; - } - // next AVC sample DTS should be equal to last sample DTS + last sample duration - this.nextAvcDts = dtsnorm + lastSampleDuration * pes2mp4ScaleFactor; - var dropped = track.dropped; - track.len = 0; - track.nbNalu = 0; - track.dropped = 0; - if (samples.length && navigator.userAgent.toLowerCase().indexOf('chrome') > -1) { - flags = samples[0].flags; - // chrome workaround, mark first sample as being a Random Access Point to avoid sourcebuffer append issue - // https://code.google.com/p/chromium/issues/detail?id=229412 - flags.dependsOn = 2; - flags.isNonSync = 0; - } - track.samples = samples; - moof = _mp4Generator2.default.moof(track.sequenceNumber++, firstDTS / pes2mp4ScaleFactor, track); - track.samples = []; - this.observer.trigger(_events2.default.FRAG_PARSING_DATA, { - data1: moof, - data2: mdat, - startPTS: firstPTS / pesTimeScale, - endPTS: (ptsnorm + pes2mp4ScaleFactor * lastSampleDuration) / pesTimeScale, - startDTS: firstDTS / pesTimeScale, - endDTS: this.nextAvcDts / pesTimeScale, - type: 'video', - nb: samples.length, - dropped: dropped - }); - } - }, { - key: 'remuxAudio', - value: function remuxAudio(track, timeOffset, contiguous) { - var view, - offset = 8, - pesTimeScale = this.PES_TIMESCALE, - mp4timeScale = track.timescale, - pes2mp4ScaleFactor = pesTimeScale / mp4timeScale, - expectedSampleDuration = track.timescale * 1024 / track.audiosamplerate, - aacSample, - mp4Sample, - unit, - mdat, - moof, - firstPTS, - firstDTS, - lastDTS, - pts, - dts, - ptsnorm, - dtsnorm, - samples = [], - samples0 = []; - - track.samples.sort(function (a, b) { - return a.pts - b.pts; - }); - samples0 = track.samples; - - while (samples0.length) { - aacSample = samples0.shift(); - unit = aacSample.unit; - pts = aacSample.pts - this._initDTS; - dts = aacSample.dts - this._initDTS; - //logger.log(`Audio/PTS:${Math.round(pts/90)}`); - // if not first sample - if (lastDTS !== undefined) { - ptsnorm = this._PTSNormalize(pts, lastDTS); - dtsnorm = this._PTSNormalize(dts, lastDTS); - // let's compute sample duration. - // sample Duration should be close to expectedSampleDuration - mp4Sample.duration = (dtsnorm - lastDTS) / pes2mp4ScaleFactor; - if (Math.abs(mp4Sample.duration - expectedSampleDuration) > expectedSampleDuration / 10) { - // more than 10% diff between sample duration and expectedSampleDuration .... lets log that - _logger.logger.log('invalid AAC sample duration at PTS ' + Math.round(pts / 90) + ',should be 1024,found :' + Math.round(mp4Sample.duration * track.audiosamplerate / track.timescale)); - } - // always adjust sample duration to avoid av sync issue - mp4Sample.duration = expectedSampleDuration; - ptsnorm = dtsnorm = expectedSampleDuration * pes2mp4ScaleFactor + lastDTS; - } else { - var nextAacPts = void 0, - delta = void 0; - if (contiguous) { - nextAacPts = this.nextAacPts; - } else { - nextAacPts = timeOffset * pesTimeScale; - } - ptsnorm = this._PTSNormalize(pts, nextAacPts); - dtsnorm = this._PTSNormalize(dts, nextAacPts); - delta = Math.round(1000 * (ptsnorm - nextAacPts) / pesTimeScale); - // if fragment are contiguous, detect hole/overlapping between fragments - if (contiguous) { - // log delta - if (delta) { - if (delta > 0) { - _logger.logger.log(delta + ' ms hole between AAC samples detected,filling it'); - // if we have frame overlap, overlapping for more than half a frame duration - } else if (delta < -12) { - // drop overlapping audio frames... browser will deal with it - _logger.logger.log(-delta + ' ms overlapping between AAC samples detected, drop frame'); - track.len -= unit.byteLength; - continue; - } - // set PTS/DTS to next PTS/DTS - ptsnorm = dtsnorm = nextAacPts; - } - } - // remember first PTS of our aacSamples, ensure value is positive - firstPTS = Math.max(0, ptsnorm); - firstDTS = Math.max(0, dtsnorm); - if (track.len > 0) { - /* concatenate the audio data and construct the mdat in place - (need 8 more bytes to fill length and mdat type) */ - mdat = new Uint8Array(track.len + 8); - view = new DataView(mdat.buffer); - view.setUint32(0, mdat.byteLength); - mdat.set(_mp4Generator2.default.types.mdat, 4); - } else { - // no audio samples - return; - } - } - mdat.set(unit, offset); - offset += unit.byteLength; - //console.log('PTS/DTS/initDTS/normPTS/normDTS/relative PTS : ${aacSample.pts}/${aacSample.dts}/${this._initDTS}/${ptsnorm}/${dtsnorm}/${(aacSample.pts/4294967296).toFixed(3)}'); - mp4Sample = { - size: unit.byteLength, - cts: 0, - duration: 0, - flags: { - isLeading: 0, - isDependedOn: 0, - hasRedundancy: 0, - degradPrio: 0, - dependsOn: 1 - } - }; - samples.push(mp4Sample); - lastDTS = dtsnorm; - } - var lastSampleDuration = 0; - var nbSamples = samples.length; - //set last sample duration as being identical to previous sample - if (nbSamples >= 2) { - lastSampleDuration = samples[nbSamples - 2].duration; - mp4Sample.duration = lastSampleDuration; - } - if (nbSamples) { - // next aac sample PTS should be equal to last sample PTS + duration - this.nextAacPts = ptsnorm + pes2mp4ScaleFactor * lastSampleDuration; - //logger.log('Audio/PTS/PTSend:' + aacSample.pts.toFixed(0) + '/' + this.nextAacDts.toFixed(0)); - track.len = 0; - track.samples = samples; - moof = _mp4Generator2.default.moof(track.sequenceNumber++, firstDTS / pes2mp4ScaleFactor, track); - track.samples = []; - this.observer.trigger(_events2.default.FRAG_PARSING_DATA, { - data1: moof, - data2: mdat, - startPTS: firstPTS / pesTimeScale, - endPTS: this.nextAacPts / pesTimeScale, - startDTS: firstDTS / pesTimeScale, - endDTS: (dtsnorm + pes2mp4ScaleFactor * lastSampleDuration) / pesTimeScale, - type: 'audio', - nb: nbSamples - }); - } - } - }, { - key: 'remuxID3', - value: function remuxID3(track, timeOffset) { - var length = track.samples.length, - sample; - // consume samples - if (length) { - for (var index = 0; index < length; index++) { - sample = track.samples[index]; - // setting id3 pts, dts to relative time - // using this._initPTS and this._initDTS to calculate relative time - sample.pts = (sample.pts - this._initPTS) / this.PES_TIMESCALE; - sample.dts = (sample.dts - this._initDTS) / this.PES_TIMESCALE; - } - this.observer.trigger(_events2.default.FRAG_PARSING_METADATA, { - samples: track.samples - }); - } - - track.samples = []; - timeOffset = timeOffset; - } - }, { - key: 'remuxText', - value: function remuxText(track, timeOffset) { - track.samples.sort(function (a, b) { - return a.pts - b.pts; - }); - - var length = track.samples.length, - sample; - // consume samples - if (length) { - for (var index = 0; index < length; index++) { - sample = track.samples[index]; - // setting text pts, dts to relative time - // using this._initPTS and this._initDTS to calculate relative time - sample.pts = (sample.pts - this._initPTS) / this.PES_TIMESCALE; - } - this.observer.trigger(_events2.default.FRAG_PARSING_USERDATA, { - samples: track.samples - }); - } - - track.samples = []; - timeOffset = timeOffset; - } - }, { - key: '_PTSNormalize', - value: function _PTSNormalize(value, reference) { - var offset; - if (reference === undefined) { - return value; - } - if (reference < value) { - // - 2^33 - offset = -8589934592; - } else { - // + 2^33 - offset = 8589934592; - } - /* PTS is 33bit (from 0 to 2^33 -1) - if diff between value and reference is bigger than half of the amplitude (2^32) then it means that - PTS looping occured. fill the gap */ - while (Math.abs(value - reference) > 4294967296) { - value += offset; - } - return value; - } - }, { - key: 'passthrough', - get: function get() { - return false; - } - }]); - - return MP4Remuxer; -}(); - -exports.default = MP4Remuxer; - -},{"../errors":21,"../events":23,"../remux/mp4-generator":31,"../utils/logger":38}],33:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * passthrough remuxer - */ - - -var _events = require('../events'); - -var _events2 = _interopRequireDefault(_events); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var PassThroughRemuxer = function () { - function PassThroughRemuxer(observer) { - _classCallCheck(this, PassThroughRemuxer); - - this.observer = observer; - this.ISGenerated = false; - } - - _createClass(PassThroughRemuxer, [{ - key: 'destroy', - value: function destroy() {} - }, { - key: 'insertDiscontinuity', - value: function insertDiscontinuity() {} - }, { - key: 'switchLevel', - value: function switchLevel() { - this.ISGenerated = false; - } - }, { - key: 'remux', - value: function remux(audioTrack, videoTrack, id3Track, textTrack, timeOffset, rawData) { - var observer = this.observer; - // generate Init Segment if needed - if (!this.ISGenerated) { - var tracks = {}, - data = { tracks: tracks, unique: true }, - track = videoTrack, - codec = track.codec; - - if (codec) { - data.tracks.video = { - container: track.container, - codec: codec, - metadata: { - width: track.width, - height: track.height - } - }; - } - - track = audioTrack; - codec = track.codec; - if (codec) { - data.tracks.audio = { - container: track.container, - codec: codec, - metadata: { - channelCount: track.channelCount - } - }; - } - this.ISGenerated = true; - observer.trigger(_events2.default.FRAG_PARSING_INIT_SEGMENT, data); - } - observer.trigger(_events2.default.FRAG_PARSING_DATA, { - data1: rawData, - startPTS: timeOffset, - startDTS: timeOffset, - type: 'audiovideo', - nb: 1, - dropped: 0 - }); - } - }, { - key: 'passthrough', - get: function get() { - return true; - } - }]); - - return PassThroughRemuxer; -}(); - -exports.default = PassThroughRemuxer; - -},{"../events":23}],34:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -// adapted from https://github.com/kanongil/node-m3u8parse/blob/master/attrlist.js - -var AttrList = function () { - function AttrList(attrs) { - _classCallCheck(this, AttrList); - - if (typeof attrs === 'string') { - attrs = AttrList.parseAttrList(attrs); - } - for (var attr in attrs) { - if (attrs.hasOwnProperty(attr)) { - this[attr] = attrs[attr]; - } - } - } - - _createClass(AttrList, [{ - key: 'decimalInteger', - value: function decimalInteger(attrName) { - var intValue = parseInt(this[attrName], 10); - if (intValue > Number.MAX_SAFE_INTEGER) { - return Infinity; - } - return intValue; - } - }, { - key: 'hexadecimalInteger', - value: function hexadecimalInteger(attrName) { - if (this[attrName]) { - var stringValue = (this[attrName] || '0x').slice(2); - stringValue = (stringValue.length & 1 ? '0' : '') + stringValue; - - var value = new Uint8Array(stringValue.length / 2); - for (var i = 0; i < stringValue.length / 2; i++) { - value[i] = parseInt(stringValue.slice(i * 2, i * 2 + 2), 16); - } - return value; - } else { - return null; - } - } - }, { - key: 'hexadecimalIntegerAsNumber', - value: function hexadecimalIntegerAsNumber(attrName) { - var intValue = parseInt(this[attrName], 16); - if (intValue > Number.MAX_SAFE_INTEGER) { - return Infinity; - } - return intValue; - } - }, { - key: 'decimalFloatingPoint', - value: function decimalFloatingPoint(attrName) { - return parseFloat(this[attrName]); - } - }, { - key: 'enumeratedString', - value: function enumeratedString(attrName) { - return this[attrName]; - } - }, { - key: 'decimalResolution', - value: function decimalResolution(attrName) { - var res = /^(\d+)x(\d+)$/.exec(this[attrName]); - if (res === null) { - return undefined; - } - return { - width: parseInt(res[1], 10), - height: parseInt(res[2], 10) - }; - } - }], [{ - key: 'parseAttrList', - value: function parseAttrList(input) { - var re = /\s*(.+?)\s*=((?:\".*?\")|.*?)(?:,|$)/g; - var match, - attrs = {}; - while ((match = re.exec(input)) !== null) { - var value = match[2], - quote = '"'; - - if (value.indexOf(quote) === 0 && value.lastIndexOf(quote) === value.length - 1) { - value = value.slice(1, -1); - } - attrs[match[1]] = value; - } - return attrs; - } - }]); - - return AttrList; -}(); - -exports.default = AttrList; - -},{}],35:[function(require,module,exports){ -"use strict"; - -var BinarySearch = { - /** - * Searches for an item in an array which matches a certain condition. - * This requires the condition to only match one item in the array, - * and for the array to be ordered. - * - * @param {Array} list The array to search. - * @param {Function} comparisonFunction - * Called and provided a candidate item as the first argument. - * Should return: - * > -1 if the item should be located at a lower index than the provided item. - * > 1 if the item should be located at a higher index than the provided item. - * > 0 if the item is the item you're looking for. - * - * @return {*} The object if it is found or null otherwise. - */ - search: function search(list, comparisonFunction) { - var minIndex = 0; - var maxIndex = list.length - 1; - var currentIndex = null; - var currentElement = null; - - while (minIndex <= maxIndex) { - currentIndex = (minIndex + maxIndex) / 2 | 0; - currentElement = list[currentIndex]; - - var comparisonResult = comparisonFunction(currentElement); - if (comparisonResult > 0) { - minIndex = currentIndex + 1; - } else if (comparisonResult < 0) { - maxIndex = currentIndex - 1; - } else { - return currentElement; - } - } - - return null; - } -}; - -module.exports = BinarySearch; - -},{}],36:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/* - * CEA-708 interpreter -*/ - -var CEA708Interpreter = function () { - function CEA708Interpreter() { - _classCallCheck(this, CEA708Interpreter); - } - - _createClass(CEA708Interpreter, [{ - key: 'attach', - value: function attach(media) { - this.media = media; - this.display = []; - this.memory = []; - } - }, { - key: 'detach', - value: function detach() { - this.clear(); - } - }, { - key: 'destroy', - value: function destroy() {} - }, { - key: '_createCue', - value: function _createCue() { - var VTTCue = window.VTTCue || window.TextTrackCue; - - var cue = this.cue = new VTTCue(-1, -1, ''); - cue.text = ''; - cue.pauseOnExit = false; - - // make sure it doesn't show up before it's ready - cue.startTime = Number.MAX_VALUE; - - // show it 'forever' once we do show it - // (we'll set the end time once we know it later) - cue.endTime = Number.MAX_VALUE; - - this.memory.push(cue); - } - }, { - key: 'clear', - value: function clear() { - var textTrack = this._textTrack; - if (textTrack && textTrack.cues) { - while (textTrack.cues.length > 0) { - textTrack.removeCue(textTrack.cues[0]); - } - } - } - }, { - key: 'push', - value: function push(timestamp, bytes) { - if (!this.cue) { - this._createCue(); - } - - var count = bytes[0] & 31; - var position = 2; - var tmpByte, ccbyte1, ccbyte2, ccValid, ccType; - - for (var j = 0; j < count; j++) { - tmpByte = bytes[position++]; - ccbyte1 = 0x7F & bytes[position++]; - ccbyte2 = 0x7F & bytes[position++]; - ccValid = (4 & tmpByte) === 0 ? false : true; - ccType = 3 & tmpByte; - - if (ccbyte1 === 0 && ccbyte2 === 0) { - continue; - } - - if (ccValid) { - if (ccType === 0) // || ccType === 1 - { - // Standard Characters - if (0x20 & ccbyte1 || 0x40 & ccbyte1) { - this.cue.text += this._fromCharCode(ccbyte1) + this._fromCharCode(ccbyte2); - } - // Special Characters - else if ((ccbyte1 === 0x11 || ccbyte1 === 0x19) && ccbyte2 >= 0x30 && ccbyte2 <= 0x3F) { - // extended chars, e.g. musical note, accents - switch (ccbyte2) { - case 48: - this.cue.text += '®'; - break; - case 49: - this.cue.text += '°'; - break; - case 50: - this.cue.text += '½'; - break; - case 51: - this.cue.text += '¿'; - break; - case 52: - this.cue.text += '™'; - break; - case 53: - this.cue.text += '¢'; - break; - case 54: - this.cue.text += ''; - break; - case 55: - this.cue.text += '£'; - break; - case 56: - this.cue.text += '♪'; - break; - case 57: - this.cue.text += ' '; - break; - case 58: - this.cue.text += 'è'; - break; - case 59: - this.cue.text += 'â'; - break; - case 60: - this.cue.text += 'ê'; - break; - case 61: - this.cue.text += 'î'; - break; - case 62: - this.cue.text += 'ô'; - break; - case 63: - this.cue.text += 'û'; - break; - } - } - if ((ccbyte1 === 0x11 || ccbyte1 === 0x19) && ccbyte2 >= 0x20 && ccbyte2 <= 0x2F) { - // Mid-row codes: color/underline - switch (ccbyte2) { - case 0x20: - // White - break; - case 0x21: - // White Underline - break; - case 0x22: - // Green - break; - case 0x23: - // Green Underline - break; - case 0x24: - // Blue - break; - case 0x25: - // Blue Underline - break; - case 0x26: - // Cyan - break; - case 0x27: - // Cyan Underline - break; - case 0x28: - // Red - break; - case 0x29: - // Red Underline - break; - case 0x2A: - // Yellow - break; - case 0x2B: - // Yellow Underline - break; - case 0x2C: - // Magenta - break; - case 0x2D: - // Magenta Underline - break; - case 0x2E: - // Italics - break; - case 0x2F: - // Italics Underline - break; - } - } - if ((ccbyte1 === 0x14 || ccbyte1 === 0x1C) && ccbyte2 >= 0x20 && ccbyte2 <= 0x2F) { - // Mid-row codes: color/underline - switch (ccbyte2) { - case 0x20: - // TODO: shouldn't affect roll-ups... - this._clearActiveCues(timestamp); - // RCL: Resume Caption Loading - // begin pop on - break; - case 0x21: - // BS: Backspace - this.cue.text = this.cue.text.substr(0, this.cue.text.length - 1); - break; - case 0x22: - // AOF: reserved (formerly alarm off) - break; - case 0x23: - // AON: reserved (formerly alarm on) - break; - case 0x24: - // DER: Delete to end of row - break; - case 0x25: - // RU2: roll-up 2 rows - //this._rollup(2); - break; - case 0x26: - // RU3: roll-up 3 rows - //this._rollup(3); - break; - case 0x27: - // RU4: roll-up 4 rows - //this._rollup(4); - break; - case 0x28: - // FON: Flash on - break; - case 0x29: - // RDC: Resume direct captioning - this._clearActiveCues(timestamp); - break; - case 0x2A: - // TR: Text Restart - break; - case 0x2B: - // RTD: Resume Text Display - break; - case 0x2C: - // EDM: Erase Displayed Memory - this._clearActiveCues(timestamp); - break; - case 0x2D: - // CR: Carriage Return - // only affects roll-up - //this._rollup(1); - break; - case 0x2E: - // ENM: Erase non-displayed memory - this._text = ''; - break; - case 0x2F: - this._flipMemory(timestamp); - // EOC: End of caption - // hide any displayed captions and show any hidden one - break; - } - } - if ((ccbyte1 === 0x17 || ccbyte1 === 0x1F) && ccbyte2 >= 0x21 && ccbyte2 <= 0x23) { - // Mid-row codes: color/underline - switch (ccbyte2) { - case 0x21: - // TO1: tab offset 1 column - break; - case 0x22: - // TO1: tab offset 2 column - break; - case 0x23: - // TO1: tab offset 3 column - break; - } - } else { - // Probably a pre-amble address code - } - } - } - } - } - }, { - key: '_fromCharCode', - value: function _fromCharCode(tmpByte) { - switch (tmpByte) { - case 42: - return 'á'; - - case 2: - return 'á'; - - case 2: - return 'é'; - - case 4: - return 'í'; - - case 5: - return 'ó'; - - case 6: - return 'ú'; - - case 3: - return 'ç'; - - case 4: - return '÷'; - - case 5: - return 'Ñ'; - - case 6: - return 'ñ'; - - case 7: - return '█'; - - default: - return String.fromCharCode(tmpByte); - } - } - }, { - key: '_flipMemory', - value: function _flipMemory(timestamp) { - this._clearActiveCues(timestamp); - this._flushCaptions(timestamp); - } - }, { - key: '_flushCaptions', - value: function _flushCaptions(timestamp) { - if (!this._has708) { - this._textTrack = this.media.addTextTrack('captions', 'English', 'en'); - this._has708 = true; - } - - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = this.memory[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var memoryItem = _step.value; - - memoryItem.startTime = timestamp; - this._textTrack.addCue(memoryItem); - this.display.push(memoryItem); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - - this.memory = []; - this.cue = null; - } - }, { - key: '_clearActiveCues', - value: function _clearActiveCues(timestamp) { - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - for (var _iterator2 = this.display[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - var displayItem = _step2.value; - - displayItem.endTime = timestamp; - } - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - - this.display = []; - } - - /* _rollUp(n) - { - // TODO: implement roll-up captions - } - */ - - }, { - key: '_clearBufferedCues', - value: function _clearBufferedCues() { - //remove them all... - } - }]); - - return CEA708Interpreter; -}(); - -exports.default = CEA708Interpreter; - -},{}],37:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/* - * compute an Exponential Weighted moving average - * - https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average - * - heavily inspired from shaka-player - */ - -var EWMA = function () { - - // About half of the estimated value will be from the last |halfLife| samples by weight. - - function EWMA(halfLife) { - _classCallCheck(this, EWMA); - - // Larger values of alpha expire historical data more slowly. - this.alpha_ = halfLife ? Math.exp(Math.log(0.5) / halfLife) : 0; - this.estimate_ = 0; - this.totalWeight_ = 0; - } - - _createClass(EWMA, [{ - key: "sample", - value: function sample(weight, value) { - var adjAlpha = Math.pow(this.alpha_, weight); - this.estimate_ = value * (1 - adjAlpha) + adjAlpha * this.estimate_; - this.totalWeight_ += weight; - } - }, { - key: "getTotalWeight", - value: function getTotalWeight() { - return this.totalWeight_; - } - }, { - key: "getEstimate", - value: function getEstimate() { - if (this.alpha_) { - var zeroFactor = 1 - Math.pow(this.alpha_, this.totalWeight_); - return this.estimate_ / zeroFactor; - } else { - return this.estimate_; - } - } - }]); - - return EWMA; -}(); - -exports.default = EWMA; - -},{}],38:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; - -function noop() {} - -var fakeLogger = { - trace: noop, - debug: noop, - log: noop, - warn: noop, - info: noop, - error: noop -}; - -var exportedLogger = fakeLogger; - -//let lastCallTime; -// function formatMsgWithTimeInfo(type, msg) { -// const now = Date.now(); -// const diff = lastCallTime ? '+' + (now - lastCallTime) : '0'; -// lastCallTime = now; -// msg = (new Date(now)).toISOString() + ' | [' + type + '] > ' + msg + ' ( ' + diff + ' ms )'; -// return msg; -// } - -function formatMsg(type, msg) { - msg = '[' + type + '] > ' + msg; - return msg; -} - -function consolePrintFn(type) { - var func = window.console[type]; - if (func) { - return function () { - for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - if (args[0]) { - args[0] = formatMsg(type, args[0]); - } - func.apply(window.console, args); - }; - } - return noop; -} - -function exportLoggerFunctions(debugConfig) { - for (var _len2 = arguments.length, functions = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { - functions[_key2 - 1] = arguments[_key2]; - } - - functions.forEach(function (type) { - exportedLogger[type] = debugConfig[type] ? debugConfig[type].bind(debugConfig) : consolePrintFn(type); - }); -} - -var enableLogs = exports.enableLogs = function enableLogs(debugConfig) { - if (debugConfig === true || (typeof debugConfig === 'undefined' ? 'undefined' : _typeof(debugConfig)) === 'object') { - exportLoggerFunctions(debugConfig, - // Remove out from list here to hard-disable a log-level - //'trace', - 'debug', 'log', 'info', 'warn', 'error'); - // Some browsers don't allow to use bind on console object anyway - // fallback to default if needed - try { - exportedLogger.log(); - } catch (e) { - exportedLogger = fakeLogger; - } - } else { - exportedLogger = fakeLogger; - } -}; - -var logger = exports.logger = exportedLogger; - -},{}],39:[function(require,module,exports){ -'use strict'; - -var URLHelper = { - // build an absolute URL from a relative one using the provided baseURL - // if relativeURL is an absolute URL it will be returned as is. - buildAbsoluteURL: function buildAbsoluteURL(baseURL, relativeURL) { - // remove any remaining space and CRLF - relativeURL = relativeURL.trim(); - if (/^[a-z]+:/i.test(relativeURL)) { - // complete url, not relative - return relativeURL; - } - - var relativeURLQuery = null; - var relativeURLHash = null; - - var relativeURLHashSplit = /^([^#]*)(.*)$/.exec(relativeURL); - if (relativeURLHashSplit) { - relativeURLHash = relativeURLHashSplit[2]; - relativeURL = relativeURLHashSplit[1]; - } - var relativeURLQuerySplit = /^([^\?]*)(.*)$/.exec(relativeURL); - if (relativeURLQuerySplit) { - relativeURLQuery = relativeURLQuerySplit[2]; - relativeURL = relativeURLQuerySplit[1]; - } - - var baseURLHashSplit = /^([^#]*)(.*)$/.exec(baseURL); - if (baseURLHashSplit) { - baseURL = baseURLHashSplit[1]; - } - var baseURLQuerySplit = /^([^\?]*)(.*)$/.exec(baseURL); - if (baseURLQuerySplit) { - baseURL = baseURLQuerySplit[1]; - } - - var baseURLDomainSplit = /^(([a-z]+:)?\/\/[a-z0-9\.\-_~]+(:[0-9]+)?)?(\/.*)$/i.exec(baseURL); - if (!baseURLDomainSplit) { - throw new Error('Error trying to parse base URL.'); - } - - // e.g. 'http:', 'https:', '' - var baseURLProtocol = baseURLDomainSplit[2] || ''; - // e.g. 'http://example.com', '//example.com', '' - var baseURLProtocolDomain = baseURLDomainSplit[1] || ''; - // e.g. '/a/b/c/playlist.m3u8' - var baseURLPath = baseURLDomainSplit[4]; - - var builtURL = null; - if (/^\/\//.test(relativeURL)) { - // relative url starts wth '//' so copy protocol (which may be '' if baseUrl didn't provide one) - builtURL = baseURLProtocol + '//' + URLHelper.buildAbsolutePath('', relativeURL.substring(2)); - } else if (/^\//.test(relativeURL)) { - // relative url starts with '/' so start from root of domain - builtURL = baseURLProtocolDomain + '/' + URLHelper.buildAbsolutePath('', relativeURL.substring(1)); - } else { - builtURL = URLHelper.buildAbsolutePath(baseURLProtocolDomain + baseURLPath, relativeURL); - } - - // put the query and hash parts back - if (relativeURLQuery) { - builtURL += relativeURLQuery; - } - if (relativeURLHash) { - builtURL += relativeURLHash; - } - return builtURL; - }, - - // build an absolute path using the provided basePath - // adapted from https://developer.mozilla.org/en-US/docs/Web/API/document/cookie#Using_relative_URLs_in_the_path_parameter - // this does not handle the case where relativePath is "/" or "//". These cases should be handled outside this. - buildAbsolutePath: function buildAbsolutePath(basePath, relativePath) { - var sRelPath = relativePath; - var nUpLn, - sDir = '', - sPath = basePath.replace(/[^\/]*$/, sRelPath.replace(/(\/|^)(?:\.?\/+)+/g, '$1')); - for (var nEnd, nStart = 0; nEnd = sPath.indexOf('/../', nStart), nEnd > -1; nStart = nEnd + nUpLn) { - nUpLn = /^\/(?:\.\.\/)*/.exec(sPath.slice(nEnd))[0].length; - sDir = (sDir + sPath.substring(nStart, nEnd)).replace(new RegExp('(?:\\\/+[^\\\/]*){0,' + (nUpLn - 1) / 3 + '}$'), '/'); - } - return sDir + sPath.substr(nStart); - } -}; - -module.exports = URLHelper; - -},{}],40:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /** - * XHR based logger - */ - -var _logger = require('../utils/logger'); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var XhrLoader = function () { - function XhrLoader(config) { - _classCallCheck(this, XhrLoader); - - if (config && config.xhrSetup) { - this.xhrSetup = config.xhrSetup; - } - } - - _createClass(XhrLoader, [{ - key: 'destroy', - value: function destroy() { - this.abort(); - this.loader = null; - } - }, { - key: 'abort', - value: function abort() { - var loader = this.loader, - timeoutHandle = this.timeoutHandle; - if (loader && loader.readyState !== 4) { - this.stats.aborted = true; - loader.abort(); - } - if (timeoutHandle) { - window.clearTimeout(timeoutHandle); - } - } - }, { - key: 'load', - value: function load(url, responseType, onSuccess, onError, onTimeout, timeout, maxRetry, retryDelay) { - var onProgress = arguments.length <= 8 || arguments[8] === undefined ? null : arguments[8]; - var frag = arguments.length <= 9 || arguments[9] === undefined ? null : arguments[9]; - - this.url = url; - if (frag && !isNaN(frag.byteRangeStartOffset) && !isNaN(frag.byteRangeEndOffset)) { - this.byteRange = frag.byteRangeStartOffset + '-' + (frag.byteRangeEndOffset - 1); - } - this.responseType = responseType; - this.onSuccess = onSuccess; - this.onProgress = onProgress; - this.onTimeout = onTimeout; - this.onError = onError; - this.stats = { trequest: performance.now(), retry: 0 }; - this.timeout = timeout; - this.maxRetry = maxRetry; - this.retryDelay = retryDelay; - this.loadInternal(); - } - }, { - key: 'loadInternal', - value: function loadInternal() { - var xhr; - - if (typeof XDomainRequest !== 'undefined') { - xhr = this.loader = new XDomainRequest(); - } else { - xhr = this.loader = new XMLHttpRequest(); - } - - xhr.onloadend = this.loadend.bind(this); - xhr.onprogress = this.loadprogress.bind(this); - - xhr.open('GET', this.url, true); - if (this.byteRange) { - xhr.setRequestHeader('Range', 'bytes=' + this.byteRange); - } - xhr.responseType = this.responseType; - var stats = this.stats; - stats.tfirst = 0; - stats.loaded = 0; - if (this.xhrSetup) { - this.xhrSetup(xhr, this.url); - } - this.timeoutHandle = window.setTimeout(this.loadtimeout.bind(this), this.timeout); - xhr.send(); - } - }, { - key: 'loadend', - value: function loadend(event) { - var xhr = event.currentTarget, - status = xhr.status, - stats = this.stats; - // don't proceed if xhr has been aborted - if (!stats.aborted) { - // http status between 200 to 299 are all successful - if (status >= 200 && status < 300) { - window.clearTimeout(this.timeoutHandle); - stats.tload = Math.max(stats.tfirst, performance.now()); - this.onSuccess(event, stats); - } else { - // error ... - if (stats.retry < this.maxRetry) { - _logger.logger.warn(status + ' while loading ' + this.url + ', retrying in ' + this.retryDelay + '...'); - this.destroy(); - window.setTimeout(this.loadInternal.bind(this), this.retryDelay); - // exponential backoff - this.retryDelay = Math.min(2 * this.retryDelay, 64000); - stats.retry++; - } else { - window.clearTimeout(this.timeoutHandle); - _logger.logger.error(status + ' while loading ' + this.url); - this.onError(event); - } - } - } - } - }, { - key: 'loadtimeout', - value: function loadtimeout(event) { - _logger.logger.warn('timeout while loading ' + this.url); - this.onTimeout(event, this.stats); - } - }, { - key: 'loadprogress', - value: function loadprogress(event) { - var stats = this.stats; - if (stats.tfirst === 0) { - stats.tfirst = Math.max(performance.now(), stats.trequest); - } - stats.loaded = event.loaded; - if (this.onProgress) { - this.onProgress(event, stats); - } - } - }]); - - return XhrLoader; -}(); - -exports.default = XhrLoader; - -},{"../utils/logger":38}]},{},[27])(27) -}); -//# sourceMappingURL=hls.js.map diff --git a/dashboard-ui/bower_components/hls.js/dist/hls.js.map b/dashboard-ui/bower_components/hls.js/dist/hls.js.map deleted file mode 100644 index 6e910b17d..000000000 --- a/dashboard-ui/bower_components/hls.js/dist/hls.js.map +++ /dev/null @@ -1,93 +0,0 @@ -{ - "version": 3, - "sources": [ - "node_modules/browser-pack/_prelude.js", - "node_modules/events/events.js", - "node_modules/webworkify/index.js", - "src/controller/abr-controller.js", - "src/controller/buffer-controller.js", - "src/controller/cap-level-controller.js", - "src/controller/ewma-bandwidth-estimator.js", - "src/controller/level-controller.js", - "src/controller/stream-controller.js", - "src/controller/timeline-controller.js", - "src/crypt/aes.js", - "src/crypt/aes128-decrypter.js", - "src/crypt/decrypter.js", - "src/demux/aacdemuxer.js", - "src/demux/adts.js", - "src/demux/demuxer-inline.js", - "src/demux/demuxer-worker.js", - "src/demux/demuxer.js", - "src/demux/exp-golomb.js", - "src/demux/id3.js", - "src/demux/tsdemuxer.js", - "src/errors.js", - "src/event-handler.js", - "src/events.js", - "src/helper/buffer-helper.js", - "src/helper/level-helper.js", - "src/hls.js", - "src/index.js", - "src/loader/fragment-loader.js", - "src/loader/key-loader.js", - "src/loader/playlist-loader.js", - "src/remux/mp4-generator.js", - "src/remux/mp4-remuxer.js", - "src/remux/passthrough-remuxer.js", - "src/utils/attr-list.js", - "src/utils/binary-search.js", - "src/utils/cea-708-interpreter.js", - "src/utils/ewma.js", - "src/utils/logger.js", - "src/utils/url.js", - "src/utils/xhr-loader.js" - ], - "names": [], - "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1SA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;AC3DA;;;;AACA;;;;AACA;;;;AACA;;AACA;;AACA;;;;;;;;;;;;;;;;IAEM,a;;;AAEJ,yBAAY,GAAZ,EAAiB;AAAA;;AAAA,iGACT,GADS,EACJ,iBAAM,YADF,EAEJ,iBAAM,WAFF,EAGJ,iBAAM,KAHF;;AAIf,UAAK,mBAAL,GAA2B,CAA3B;AACA,UAAK,iBAAL,GAAyB,CAAC,CAA1B;AACA,UAAK,cAAL,GAAsB,CAAC,CAAvB;AACA,UAAK,GAAL,GAAW,GAAX;AACA,UAAK,OAAL,GAAe,MAAK,iBAAL,CAAuB,IAAvB,OAAf;AARe;AAShB;;;;8BAES;AACR,WAAK,UAAL;AACA,6BAAa,SAAb,CAAuB,OAAvB,CAA+B,IAA/B,CAAoC,IAApC;AACD;;;kCAEa,I,EAAM;AAClB,UAAI,CAAC,KAAK,KAAV,EAAiB;AACf,aAAK,KAAL,GAAa,YAAY,KAAK,OAAjB,EAA0B,GAA1B,CAAb;AACD;;;;AAID,UAAI,CAAC,KAAK,WAAV,EAAuB;AAC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", - "file": "generated.js", - "sourceRoot": "", - "sourcesContent": [ - "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o 0 && this._events[type].length > m) {\n this._events[type].warned = true;\n console.error('(node) warning: possible EventEmitter memory ' +\n 'leak detected. %d listeners added. ' +\n 'Use emitter.setMaxListeners() to increase limit.',\n this._events[type].length);\n if (typeof console.trace === 'function') {\n // not supported in IE 10\n console.trace();\n }\n }\n }\n\n return this;\n};\n\nEventEmitter.prototype.on = EventEmitter.prototype.addListener;\n\nEventEmitter.prototype.once = function(type, listener) {\n if (!isFunction(listener))\n throw TypeError('listener must be a function');\n\n var fired = false;\n\n function g() {\n this.removeListener(type, g);\n\n if (!fired) {\n fired = true;\n listener.apply(this, arguments);\n }\n }\n\n g.listener = listener;\n this.on(type, g);\n\n return this;\n};\n\n// emits a 'removeListener' event iff the listener was removed\nEventEmitter.prototype.removeListener = function(type, listener) {\n var list, position, length, i;\n\n if (!isFunction(listener))\n throw TypeError('listener must be a function');\n\n if (!this._events || !this._events[type])\n return this;\n\n list = this._events[type];\n length = list.length;\n position = -1;\n\n if (list === listener ||\n (isFunction(list.listener) && list.listener === listener)) {\n delete this._events[type];\n if (this._events.removeListener)\n this.emit('removeListener', type, listener);\n\n } else if (isObject(list)) {\n for (i = length; i-- > 0;) {\n if (list[i] === listener ||\n (list[i].listener && list[i].listener === listener)) {\n position = i;\n break;\n }\n }\n\n if (position < 0)\n return this;\n\n if (list.length === 1) {\n list.length = 0;\n delete this._events[type];\n } else {\n list.splice(position, 1);\n }\n\n if (this._events.removeListener)\n this.emit('removeListener', type, listener);\n }\n\n return this;\n};\n\nEventEmitter.prototype.removeAllListeners = function(type) {\n var key, listeners;\n\n if (!this._events)\n return this;\n\n // not listening for removeListener, no need to emit\n if (!this._events.removeListener) {\n if (arguments.length === 0)\n this._events = {};\n else if (this._events[type])\n delete this._events[type];\n return this;\n }\n\n // emit removeListener for all listeners on all events\n if (arguments.length === 0) {\n for (key in this._events) {\n if (key === 'removeListener') continue;\n this.removeAllListeners(key);\n }\n this.removeAllListeners('removeListener');\n this._events = {};\n return this;\n }\n\n listeners = this._events[type];\n\n if (isFunction(listeners)) {\n this.removeListener(type, listeners);\n } else if (listeners) {\n // LIFO order\n while (listeners.length)\n this.removeListener(type, listeners[listeners.length - 1]);\n }\n delete this._events[type];\n\n return this;\n};\n\nEventEmitter.prototype.listeners = function(type) {\n var ret;\n if (!this._events || !this._events[type])\n ret = [];\n else if (isFunction(this._events[type]))\n ret = [this._events[type]];\n else\n ret = this._events[type].slice();\n return ret;\n};\n\nEventEmitter.prototype.listenerCount = function(type) {\n if (this._events) {\n var evlistener = this._events[type];\n\n if (isFunction(evlistener))\n return 1;\n else if (evlistener)\n return evlistener.length;\n }\n return 0;\n};\n\nEventEmitter.listenerCount = function(emitter, type) {\n return emitter.listenerCount(type);\n};\n\nfunction isFunction(arg) {\n return typeof arg === 'function';\n}\n\nfunction isNumber(arg) {\n return typeof arg === 'number';\n}\n\nfunction isObject(arg) {\n return typeof arg === 'object' && arg !== null;\n}\n\nfunction isUndefined(arg) {\n return arg === void 0;\n}\n", - "var bundleFn = arguments[3];\nvar sources = arguments[4];\nvar cache = arguments[5];\n\nvar stringify = JSON.stringify;\n\nmodule.exports = function (fn) {\n var keys = [];\n var wkey;\n var cacheKeys = Object.keys(cache);\n\n for (var i = 0, l = cacheKeys.length; i < l; i++) {\n var key = cacheKeys[i];\n var exp = cache[key].exports;\n // Using babel as a transpiler to use esmodule, the export will always\n // be an object with the default export as a property of it. To ensure\n // the existing api and babel esmodule exports are both supported we\n // check for both\n if (exp === fn || exp.default === fn) {\n wkey = key;\n break;\n }\n }\n\n if (!wkey) {\n wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);\n var wcache = {};\n for (var i = 0, l = cacheKeys.length; i < l; i++) {\n var key = cacheKeys[i];\n wcache[key] = key;\n }\n sources[wkey] = [\n Function(['require','module','exports'], '(' + fn + ')(self)'),\n wcache\n ];\n }\n var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);\n\n var scache = {}; scache[wkey] = wkey;\n sources[skey] = [\n Function(['require'], (\n // try to call default if defined to also support babel esmodule\n // exports\n 'var f = require(' + stringify(wkey) + ');' +\n '(f.default ? f.default : f)(self);'\n )),\n scache\n ];\n\n var src = '(' + bundleFn + ')({'\n + Object.keys(sources).map(function (key) {\n return stringify(key) + ':['\n + sources[key][0]\n + ',' + stringify(sources[key][1]) + ']'\n ;\n }).join(',')\n + '},{},[' + stringify(skey) + '])'\n ;\n\n var URL = window.URL || window.webkitURL || window.mozURL || window.msURL;\n\n return new Worker(URL.createObjectURL(\n new Blob([src], { type: 'text/javascript' })\n ));\n};\n", - "/*\n * simple ABR Controller\n * - compute next level based on last fragment bw heuristics\n * - implement an abandon rules triggered if we have less than 2 frag buffered and if computed bw shows that we risk buffer stalling\n */\n\nimport Event from '../events';\nimport EventHandler from '../event-handler';\nimport BufferHelper from '../helper/buffer-helper';\nimport {ErrorDetails} from '../errors';\nimport {logger} from '../utils/logger';\nimport EwmaBandWidthEstimator from './ewma-bandwidth-estimator';\n\nclass AbrController extends EventHandler {\n\n constructor(hls) {\n super(hls, Event.FRAG_LOADING,\n Event.FRAG_LOADED,\n Event.ERROR);\n this.lastLoadedFragLevel = 0;\n this._autoLevelCapping = -1;\n this._nextAutoLevel = -1;\n this.hls = hls;\n this.onCheck = this.abandonRulesCheck.bind(this);\n }\n\n destroy() {\n this.clearTimer();\n EventHandler.prototype.destroy.call(this);\n }\n\n onFragLoading(data) {\n if (!this.timer) {\n this.timer = setInterval(this.onCheck, 100);\n }\n\n // lazy init of bw Estimator, rationale is that we use different params for Live/VoD\n // so we need to wait for stream manifest / playlist type to instantiate it.\n if (!this.bwEstimator) {\n let hls = this.hls,\n level = data.frag.level,\n isLive = hls.levels[level].details.live,\n config = hls.config,\n ewmaFast, ewmaSlow;\n\n if (isLive) {\n ewmaFast = config.abrEwmaFastLive;\n ewmaSlow = config.abrEwmaSlowLive;\n } else {\n ewmaFast = config.abrEwmaFastVoD;\n ewmaSlow = config.abrEwmaSlowVoD;\n }\n this.bwEstimator = new EwmaBandWidthEstimator(hls,ewmaSlow,ewmaFast,config.abrEwmaDefaultEstimate);\n }\n\n let frag = data.frag;\n frag.trequest = performance.now();\n this.fragCurrent = frag;\n }\n\n abandonRulesCheck() {\n /*\n monitor fragment retrieval time...\n we compute expected time of arrival of the complete fragment.\n we compare it to expected time of buffer starvation\n */\n let hls = this.hls, v = hls.media,frag = this.fragCurrent;\n\n // if loader has been destroyed or loading has been aborted, stop timer and return\n if(!frag.loader || ( frag.loader.stats && frag.loader.stats.aborted)) {\n logger.warn(`frag loader destroy or aborted, disarm abandonRulesCheck`);\n this.clearTimer();\n return;\n }\n /* only monitor frag retrieval time if\n (video not paused OR first fragment being loaded(ready state === HAVE_NOTHING = 0)) AND autoswitching enabled AND not lowest level (=> means that we have several levels) */\n if (v && (!v.paused || !v.readyState) && frag.autoLevel && frag.level) {\n let requestDelay = performance.now() - frag.trequest;\n // monitor fragment load progress after half of expected fragment duration,to stabilize bitrate\n if (requestDelay > (500 * frag.duration)) {\n let levels = hls.levels,\n loadRate = Math.max(1,frag.loaded * 1000 / requestDelay), // byte/s; at least 1 byte/s to avoid division by zero\n // compute expected fragment length using frag duration and level bitrate. also ensure that expected len is gte than already loaded size\n expectedLen = Math.max(frag.loaded, Math.round(frag.duration * levels[frag.level].bitrate / 8));\n\n let pos = v.currentTime;\n let fragLoadedDelay = (expectedLen - frag.loaded) / loadRate;\n let bufferStarvationDelay = BufferHelper.bufferInfo(v,pos,hls.config.maxBufferHole).end - pos;\n // consider emergency switch down only if we have less than 2 frag buffered AND\n // time to finish loading current fragment is bigger than buffer starvation delay\n // ie if we risk buffer starvation if bw does not increase quickly\n if (bufferStarvationDelay < 2*frag.duration && fragLoadedDelay > bufferStarvationDelay) {\n let fragLevelNextLoadedDelay, nextLoadLevel;\n // lets iterate through lower level and try to find the biggest one that could avoid rebuffering\n // we start from current level - 1 and we step down , until we find a matching level\n for (nextLoadLevel = frag.level - 1 ; nextLoadLevel >=0 ; nextLoadLevel--) {\n // compute time to load next fragment at lower level\n // 0.8 : consider only 80% of current bw to be conservative\n // 8 = bits per byte (bps/Bps)\n fragLevelNextLoadedDelay = frag.duration * levels[nextLoadLevel].bitrate / (8 * 0.8 * loadRate);\n logger.log(`fragLoadedDelay/bufferStarvationDelay/fragLevelNextLoadedDelay[${nextLoadLevel}] :${fragLoadedDelay.toFixed(1)}/${bufferStarvationDelay.toFixed(1)}/${fragLevelNextLoadedDelay.toFixed(1)}`);\n if (fragLevelNextLoadedDelay < bufferStarvationDelay) {\n // we found a lower level that be rebuffering free with current estimated bw !\n break;\n }\n }\n // only emergency switch down if it takes less time to load new fragment at lowest level instead\n // of finishing loading current one ...\n if (fragLevelNextLoadedDelay < fragLoadedDelay) {\n // ensure nextLoadLevel is not negative\n nextLoadLevel = Math.max(0,nextLoadLevel);\n // force next load level in auto mode\n hls.nextLoadLevel = nextLoadLevel;\n // update bw estimate for this fragment before cancelling load (this will help reducing the bw)\n this.bwEstimator.sample(requestDelay,frag.loaded);\n // abort fragment loading ...\n logger.warn(`loading too slow, abort fragment loading and switch to level ${nextLoadLevel}`);\n //abort fragment loading\n frag.loader.abort();\n this.clearTimer();\n hls.trigger(Event.FRAG_LOAD_EMERGENCY_ABORTED, {frag: frag});\n }\n }\n }\n }\n }\n\n onFragLoaded(data) {\n var stats = data.stats;\n // only update stats on first frag loading\n // if same frag is loaded multiple times, it might be in browser cache, and loaded quickly\n // and leading to wrong bw estimation\n if (stats.aborted === undefined && data.frag.loadCounter === 1) {\n this.bwEstimator.sample(performance.now() - stats.trequest,stats.loaded);\n }\n\n // stop monitoring bw once frag loaded\n this.clearTimer();\n // store level id after successful fragment load\n this.lastLoadedFragLevel = data.frag.level;\n // reset forced auto level value so that next level will be selected\n this._nextAutoLevel = -1;\n }\n\n onError(data) {\n // stop timer in case of frag loading error\n switch(data.details) {\n case ErrorDetails.FRAG_LOAD_ERROR:\n case ErrorDetails.FRAG_LOAD_TIMEOUT:\n this.clearTimer();\n break;\n default:\n break;\n }\n }\n\n clearTimer() {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n }\n\n /** Return the capping/max level value that could be used by automatic level selection algorithm **/\n get autoLevelCapping() {\n return this._autoLevelCapping;\n }\n\n /** set the capping/max level value that could be used by automatic level selection algorithm **/\n set autoLevelCapping(newLevel) {\n this._autoLevelCapping = newLevel;\n }\n\n get nextAutoLevel() {\n var hls = this.hls, i, maxAutoLevel, levels = hls.levels, config = hls.config;\n if (this._autoLevelCapping === -1 && levels && levels.length) {\n maxAutoLevel = levels.length - 1;\n } else {\n maxAutoLevel = this._autoLevelCapping;\n }\n\n // in case next auto level has been forced, return it straight-away (but capped)\n if (this._nextAutoLevel !== -1) {\n return Math.min(this._nextAutoLevel,maxAutoLevel);\n }\n\n let avgbw = this.bwEstimator ? this.bwEstimator.getEstimate() : config.abrEwmaDefaultEstimate,\n adjustedbw;\n // follow algorithm captured from stagefright :\n // https://android.googlesource.com/platform/frameworks/av/+/master/media/libstagefright/httplive/LiveSession.cpp\n // Pick the highest bandwidth stream below or equal to estimated bandwidth.\n for (i = 0; i <= maxAutoLevel; i++) {\n // consider only 80% of the available bandwidth, but if we are switching up,\n // be even more conservative (70%) to avoid overestimating and immediately\n // switching back.\n if (i <= this.lastLoadedFragLevel) {\n adjustedbw = config.abrBandWidthFactor * avgbw;\n } else {\n adjustedbw = config.abrBandWidthUpFactor * avgbw;\n }\n if (adjustedbw < levels[i].bitrate) {\n return Math.max(0, i - 1);\n }\n }\n return i - 1;\n }\n\n set nextAutoLevel(nextLevel) {\n this._nextAutoLevel = nextLevel;\n }\n}\n\nexport default AbrController;\n\n", - "/*\n * Buffer Controller\n*/\n\nimport Event from '../events';\nimport EventHandler from '../event-handler';\nimport {logger} from '../utils/logger';\nimport {ErrorTypes, ErrorDetails} from '../errors';\n\n\nclass BufferController extends EventHandler {\n\n constructor(hls) {\n super(hls,\n Event.MEDIA_ATTACHING,\n Event.MEDIA_DETACHING,\n Event.BUFFER_RESET,\n Event.BUFFER_APPENDING,\n Event.BUFFER_CODECS,\n Event.BUFFER_EOS,\n Event.BUFFER_FLUSHING,\n Event.LEVEL_UPDATED);\n\n // the value that we have set mediasource.duration to\n // (the actual duration may be tweaked slighly by the browser)\n this._msDuration = null;\n // the value that we want to set mediaSource.duration to\n this._levelDuration = null;\n\n // Source Buffer listeners\n this.onsbue = this.onSBUpdateEnd.bind(this);\n this.onsbe = this.onSBUpdateError.bind(this);\n }\n\n destroy() {\n EventHandler.prototype.destroy.call(this);\n }\n\n onMediaAttaching(data) {\n let media = this.media = data.media;\n if (media) {\n // setup the media source\n var ms = this.mediaSource = new MediaSource();\n //Media Source listeners\n this.onmso = this.onMediaSourceOpen.bind(this);\n this.onmse = this.onMediaSourceEnded.bind(this);\n this.onmsc = this.onMediaSourceClose.bind(this);\n ms.addEventListener('sourceopen', this.onmso);\n ms.addEventListener('sourceended', this.onmse);\n ms.addEventListener('sourceclose', this.onmsc);\n // link video and media Source\n media.src = URL.createObjectURL(ms);\n }\n }\n\n onMediaDetaching() {\n var ms = this.mediaSource;\n if (ms) {\n if (ms.readyState === 'open') {\n try {\n // endOfStream could trigger exception if any sourcebuffer is in updating state\n // we don't really care about checking sourcebuffer state here,\n // as we are anyway detaching the MediaSource\n // let's just avoid this exception to propagate\n ms.endOfStream();\n } catch(err) {\n logger.warn(`onMediaDetaching:${err.message} while calling endOfStream`);\n }\n }\n ms.removeEventListener('sourceopen', this.onmso);\n ms.removeEventListener('sourceended', this.onmse);\n ms.removeEventListener('sourceclose', this.onmsc);\n\n try {\n // unlink MediaSource from video tag\n this.media.src = '';\n this.media.removeAttribute('src');\n } catch(err) {\n logger.warn(`onMediaDetaching:${err.message} while unlinking video.src`);\n }\n this.mediaSource = null;\n this.media = null;\n this.pendingTracks = null;\n this.sourceBuffer = null;\n }\n this.onmso = this.onmse = this.onmsc = null;\n this.hls.trigger(Event.MEDIA_DETACHED);\n }\n\n onMediaSourceOpen() {\n logger.log('media source opened');\n this.hls.trigger(Event.MEDIA_ATTACHED, { media : this.media });\n // once received, don't listen anymore to sourceopen event\n this.mediaSource.removeEventListener('sourceopen', this.onmso);\n // if any buffer codecs pending, treat it here.\n var pendingTracks = this.pendingTracks;\n if (pendingTracks) {\n this.onBufferCodecs(pendingTracks);\n this.pendingTracks = null;\n this.doAppending();\n }\n }\n\n onMediaSourceClose() {\n logger.log('media source closed');\n }\n\n onMediaSourceEnded() {\n logger.log('media source ended');\n }\n\n\n onSBUpdateEnd() {\n\n if (this._needsFlush) {\n this.doFlush();\n }\n\n if (this._needsEos) {\n this.onBufferEos();\n }\n\n this.hls.trigger(Event.BUFFER_APPENDED);\n\n this.doAppending();\n }\n\n onSBUpdateError(event) {\n logger.error(`sourceBuffer error:${event}`);\n // according to http://www.w3.org/TR/media-source/#sourcebuffer-append-error\n // this error might not always be fatal (it is fatal if decode error is set, in that case\n // it will be followed by a mediaElement error ...)\n this.hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.BUFFER_APPENDING_ERROR, fatal: false});\n // we don't need to do more than that, as accordin to the spec, updateend will be fired just after\n }\n\n onBufferReset() {\n var sourceBuffer = this.sourceBuffer;\n if (sourceBuffer) {\n for(var type in sourceBuffer) {\n var sb = sourceBuffer[type];\n try {\n this.mediaSource.removeSourceBuffer(sb);\n sb.removeEventListener('updateend', this.onsbue);\n sb.removeEventListener('error', this.onsbe);\n } catch(err) {\n }\n }\n this.sourceBuffer = null;\n }\n this.flushRange = [];\n this.appended = 0;\n }\n\n onBufferCodecs(tracks) {\n let mediaSource = this.mediaSource;\n\n // delay sourcebuffer creation if media source not opened yet\n if(!mediaSource || mediaSource.readyState !== 'open') {\n this.pendingTracks = tracks;\n return;\n }\n\n if (!this.sourceBuffer) {\n let sourceBuffer = {};\n for (let trackName in tracks) {\n let track = tracks[trackName];\n // use levelCodec as first priority\n let codec = track.levelCodec || track.codec;\n let mimeType = `${track.container};codecs=${codec}`;\n logger.log(`creating sourceBuffer with mimeType:${mimeType}`);\n let sb = sourceBuffer[trackName] = mediaSource.addSourceBuffer(mimeType);\n sb.addEventListener('updateend', this.onsbue);\n sb.addEventListener('error', this.onsbe);\n }\n this.sourceBuffer = sourceBuffer;\n }\n }\n\n onBufferAppending(data) {\n if (!this.segments) {\n this.segments = [ data ];\n } else {\n this.segments.push(data);\n }\n this.doAppending();\n }\n\n onBufferAppendFail(data) {\n logger.error(`sourceBuffer error:${data.event}`);\n // according to http://www.w3.org/TR/media-source/#sourcebuffer-append-error\n // this error might not always be fatal (it is fatal if decode error is set, in that case\n // it will be followed by a mediaElement error ...)\n this.hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.BUFFER_APPENDING_ERROR, fatal: false, frag: this.fragCurrent});\n }\n\n onBufferEos() {\n var sb = this.sourceBuffer, mediaSource = this.mediaSource;\n if (!mediaSource || mediaSource.readyState !== 'open') {\n return;\n }\n if (!((sb.audio && sb.audio.updating) || (sb.video && sb.video.updating))) {\n logger.log('all media data available, signal endOfStream() to MediaSource and stop loading fragment');\n //Notify the media element that it now has all of the media data\n mediaSource.endOfStream();\n this._needsEos = false;\n } else {\n this._needsEos = true;\n }\n }\n\n onBufferFlushing(data) {\n this.flushRange.push({start: data.startOffset, end: data.endOffset});\n // attempt flush immediatly\n this.flushBufferCounter = 0;\n this.doFlush();\n }\n\n onLevelUpdated(event) {\n let details = event.details;\n if (details.fragments.length === 0) {\n return;\n }\n this._levelDuration = details.totalduration + details.fragments[0].start;\n this.updateMediaElementDuration();\n }\n\n // https://github.com/dailymotion/hls.js/issues/355\n updateMediaElementDuration() {\n if (this._levelDuration === null) {\n return;\n }\n let media = this.media;\n let mediaSource = this.mediaSource;\n if (!media || !mediaSource || media.readyState === 0 || mediaSource.readyState !== 'open') {\n return;\n }\n for (let type in mediaSource.sourceBuffers) {\n if (mediaSource.sourceBuffers[type].updating) {\n // can't set duration whilst a buffer is updating\n return;\n }\n }\n if (this._msDuration === null) {\n // initialise to the value that the media source is reporting\n this._msDuration = mediaSource.duration;\n }\n // this._levelDuration was the last value we set.\n // not using mediaSource.duration as the browser may tweak this value\n // only update mediasource duration if its value increase, this is to avoid\n // flushing already buffered portion when switching between quality level, as they\n if (this._levelDuration > this._msDuration) {\n logger.log(`Updating mediasource duration to ${this._levelDuration}`);\n mediaSource.duration = this._levelDuration;\n this._msDuration = this._levelDuration;\n }\n }\n\n doFlush() {\n // loop through all buffer ranges to flush\n while(this.flushRange.length) {\n var range = this.flushRange[0];\n // flushBuffer will abort any buffer append in progress and flush Audio/Video Buffer\n if (this.flushBuffer(range.start, range.end)) {\n // range flushed, remove from flush array\n this.flushRange.shift();\n this.flushBufferCounter = 0;\n } else {\n this._needsFlush = true;\n // avoid looping, wait for SB update end to retrigger a flush\n return;\n }\n }\n if (this.flushRange.length === 0) {\n // everything flushed\n this._needsFlush = false;\n\n // let's recompute this.appended, which is used to avoid flush looping\n var appended = 0;\n var sourceBuffer = this.sourceBuffer;\n if (sourceBuffer) {\n for (var type in sourceBuffer) {\n appended += sourceBuffer[type].buffered.length;\n }\n }\n this.appended = appended;\n this.hls.trigger(Event.BUFFER_FLUSHED);\n }\n }\n\n doAppending() {\n var hls = this.hls, sourceBuffer = this.sourceBuffer, segments = this.segments;\n if (sourceBuffer) {\n if (this.media.error) {\n segments = [];\n logger.error('trying to append although a media error occured, flush segment and abort');\n return;\n }\n for (var type in sourceBuffer) {\n if (sourceBuffer[type].updating) {\n //logger.log('sb update in progress');\n return;\n }\n }\n if (segments.length) {\n var segment = segments.shift();\n try {\n //logger.log(`appending ${segment.type} SB, size:${segment.data.length});\n sourceBuffer[segment.type].appendBuffer(segment.data);\n this.appendError = 0;\n this.appended++;\n } catch(err) {\n // in case any error occured while appending, put back segment in segments table\n logger.error(`error while trying to append buffer:${err.message}`);\n segments.unshift(segment);\n var event = {type: ErrorTypes.MEDIA_ERROR};\n if(err.code !== 22) {\n if (this.appendError) {\n this.appendError++;\n } else {\n this.appendError = 1;\n }\n event.details = ErrorDetails.BUFFER_APPEND_ERROR;\n event.frag = this.fragCurrent;\n /* with UHD content, we could get loop of quota exceeded error until\n browser is able to evict some data from sourcebuffer. retrying help recovering this\n */\n if (this.appendError > hls.config.appendErrorMaxRetry) {\n logger.log(`fail ${hls.config.appendErrorMaxRetry} times to append segment in sourceBuffer`);\n segments = [];\n event.fatal = true;\n hls.trigger(Event.ERROR, event);\n return;\n } else {\n event.fatal = false;\n hls.trigger(Event.ERROR, event);\n }\n } else {\n // QuotaExceededError: http://www.w3.org/TR/html5/infrastructure.html#quotaexceedederror\n // let's stop appending any segments, and report BUFFER_FULL_ERROR error\n this.segments = [];\n event.details = ErrorDetails.BUFFER_FULL_ERROR;\n hls.trigger(Event.ERROR,event);\n return;\n }\n }\n }\n }\n }\n\n /*\n flush specified buffered range,\n return true once range has been flushed.\n as sourceBuffer.remove() is asynchronous, flushBuffer will be retriggered on sourceBuffer update end\n */\n flushBuffer(startOffset, endOffset) {\n var sb, i, bufStart, bufEnd, flushStart, flushEnd;\n //logger.log('flushBuffer,pos/start/end: ' + this.media.currentTime + '/' + startOffset + '/' + endOffset);\n // safeguard to avoid infinite looping : don't try to flush more than the nb of appended segments\n if (this.flushBufferCounter < this.appended && this.sourceBuffer) {\n for (var type in this.sourceBuffer) {\n sb = this.sourceBuffer[type];\n if (!sb.updating) {\n for (i = 0; i < sb.buffered.length; i++) {\n bufStart = sb.buffered.start(i);\n bufEnd = sb.buffered.end(i);\n // workaround firefox not able to properly flush multiple buffered range.\n if (navigator.userAgent.toLowerCase().indexOf('firefox') !== -1 && endOffset === Number.POSITIVE_INFINITY) {\n flushStart = startOffset;\n flushEnd = endOffset;\n } else {\n flushStart = Math.max(bufStart, startOffset);\n flushEnd = Math.min(bufEnd, endOffset);\n }\n /* sometimes sourcebuffer.remove() does not flush\n the exact expected time range.\n to avoid rounding issues/infinite loop,\n only flush buffer range of length greater than 500ms.\n */\n if (Math.min(flushEnd,bufEnd) - flushStart > 0.5 ) {\n this.flushBufferCounter++;\n logger.log(`flush ${type} [${flushStart},${flushEnd}], of [${bufStart},${bufEnd}], pos:${this.media.currentTime}`);\n sb.remove(flushStart, flushEnd);\n return false;\n }\n }\n } else {\n //logger.log('abort ' + type + ' append in progress');\n // this will abort any appending in progress\n //sb.abort();\n logger.warn('cannot flush, sb updating in progress');\n return false;\n }\n }\n } else {\n logger.warn('abort flushing too many retries');\n }\n logger.log('buffer flushed');\n // everything flushed !\n return true;\n }\n}\n\nexport default BufferController;\n", - "/*\n * cap stream level to media size dimension controller\n*/\n\nimport Event from '../events';\nimport EventHandler from '../event-handler';\n\nclass CapLevelController extends EventHandler {\n\tconstructor(hls) {\n super(hls,\n Event.MEDIA_ATTACHING,\n Event.MANIFEST_PARSED); \n\t}\n\t\n\tdestroy() {\n if (this.hls.config.capLevelToPlayerSize) {\n this.media = null;\n this.autoLevelCapping = Number.POSITIVE_INFINITY;\n if (this.timer) {\n this.timer = clearInterval(this.timer);\n }\n }\n }\n\t \n\tonMediaAttaching(data) {\n this.media = data.media instanceof HTMLVideoElement ? data.media : null; \n }\n\n onManifestParsed(data) {\n if (this.hls.config.capLevelToPlayerSize) {\n this.autoLevelCapping = Number.POSITIVE_INFINITY;\n this.levels = data.levels;\n this.hls.firstLevel = this.getMaxLevel(data.firstLevel);\n clearInterval(this.timer);\n this.timer = setInterval(this.detectPlayerSize.bind(this), 1000);\n this.detectPlayerSize();\n }\n }\n \n detectPlayerSize() {\n if (this.media) {\n let levelsLength = this.levels ? this.levels.length : 0;\n if (levelsLength) {\n this.hls.autoLevelCapping = this.getMaxLevel(levelsLength - 1);\n if (this.hls.autoLevelCapping > this.autoLevelCapping) {\n // if auto level capping has a higher value for the previous one, flush the buffer using nextLevelSwitch\n // usually happen when the user go to the fullscreen mode.\n this.hls.streamController.nextLevelSwitch();\n }\n this.autoLevelCapping = this.hls.autoLevelCapping; \n } \n }\n }\n \n /*\n * returns level should be the one with the dimensions equal or greater than the media (player) dimensions (so the video will be downscaled)\n */\n getMaxLevel(capLevelIndex) {\n let result,\n i,\n level,\n mWidth = this.mediaWidth,\n mHeight = this.mediaHeight,\n lWidth = 0,\n lHeight = 0;\n \n for (i = 0; i <= capLevelIndex; i++) {\n level = this.levels[i];\n result = i;\n lWidth = level.width;\n lHeight = level.height;\n if (mWidth <= lWidth || mHeight <= lHeight) {\n break;\n }\n } \n return result;\n }\n \n get contentScaleFactor() {\n let pixelRatio = 1;\n try {\n pixelRatio = window.devicePixelRatio;\n } catch(e) {}\n return pixelRatio;\n }\n \n get mediaWidth() {\n let width;\n if (this.media) {\n width = this.media.width || this.media.clientWidth || this.media.offsetWidth;\n width *= this.contentScaleFactor;\n }\n return width;\n }\n \n get mediaHeight() {\n let height;\n if (this.media) {\n height = this.media.height || this.media.clientHeight || this.media.offsetHeight;\n height *= this.contentScaleFactor; \n }\n return height;\n }\n}\n\nexport default CapLevelController;", - "/*\n * EWMA Bandwidth Estimator\n * - heavily inspired from shaka-player\n * Tracks bandwidth samples and estimates available bandwidth.\n * Based on the minimum of two exponentially-weighted moving averages with\n * different half-lives.\n */\n\nimport EWMA from '../utils/ewma';\n\n\nclass EwmaBandWidthEstimator {\n\n constructor(hls,slow,fast,defaultEstimate) {\n this.hls = hls;\n this.defaultEstimate_ = defaultEstimate;\n this.minWeight_ = 0.001;\n this.minDelayMs_ = 50;\n this.slow_ = new EWMA(slow);\n this.fast_ = new EWMA(fast);\n }\n\n sample(durationMs,numBytes) {\n durationMs = Math.max(durationMs, this.minDelayMs_);\n var bandwidth = 8000* numBytes / durationMs,\n //console.log('instant bw:'+ Math.round(bandwidth));\n // we weight sample using loading duration....\n weight = durationMs / 1000;\n this.fast_.sample(weight,bandwidth);\n this.slow_.sample(weight,bandwidth);\n }\n\n\n getEstimate() {\n if (!this.fast_ || !this.slow_ || this.fast_.getTotalWeight() < this.minWeight_) {\n return this.defaultEstimate_;\n }\n //console.log('slow estimate:'+ Math.round(this.slow_.getEstimate()));\n //console.log('fast estimate:'+ Math.round(this.fast_.getEstimate()));\n // Take the minimum of these two estimates. This should have the effect of\n // adapting down quickly, but up more slowly.\n return Math.min(this.fast_.getEstimate(),this.slow_.getEstimate());\n }\n\n destroy() {\n }\n}\nexport default EwmaBandWidthEstimator;\n\n", - "/*\n * Level Controller\n*/\n\nimport Event from '../events';\nimport EventHandler from '../event-handler';\nimport {logger} from '../utils/logger';\nimport {ErrorTypes, ErrorDetails} from '../errors';\n\nclass LevelController extends EventHandler {\n\n constructor(hls) {\n super(hls,\n Event.MANIFEST_LOADED,\n Event.LEVEL_LOADED,\n Event.ERROR);\n this.ontick = this.tick.bind(this);\n this._manualLevel = this._autoLevelCapping = -1;\n }\n\n destroy() {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n this._manualLevel = -1;\n }\n\n startLoad() {\n this.canload = true;\n // speed up live playlist refresh if timer exists\n if (this.timer) {\n this.tick();\n }\n }\n\n stopLoad() {\n this.canload = false;\n }\n\n onManifestLoaded(data) {\n var levels0 = [], levels = [], bitrateStart, i, bitrateSet = {}, videoCodecFound = false, audioCodecFound = false, hls = this.hls;\n\n // regroup redundant level together\n data.levels.forEach(level => {\n if(level.videoCodec) {\n videoCodecFound = true;\n }\n if(level.audioCodec) {\n audioCodecFound = true;\n }\n var redundantLevelId = bitrateSet[level.bitrate];\n if (redundantLevelId === undefined) {\n bitrateSet[level.bitrate] = levels0.length;\n level.url = [level.url];\n level.urlId = 0;\n levels0.push(level);\n } else {\n levels0[redundantLevelId].url.push(level.url);\n }\n });\n\n // remove audio-only level if we also have levels with audio+video codecs signalled\n if(videoCodecFound && audioCodecFound) {\n levels0.forEach(level => {\n if(level.videoCodec) {\n levels.push(level);\n }\n });\n } else {\n levels = levels0;\n }\n\n // only keep level with supported audio/video codecs\n levels = levels.filter(function(level) {\n var checkSupportedAudio = function(codec) { return MediaSource.isTypeSupported(`audio/mp4;codecs=${codec}`);};\n var checkSupportedVideo = function(codec) { return MediaSource.isTypeSupported(`video/mp4;codecs=${codec}`);};\n var audioCodec = level.audioCodec, videoCodec = level.videoCodec;\n\n return (!audioCodec || checkSupportedAudio(audioCodec)) &&\n (!videoCodec || checkSupportedVideo(videoCodec));\n });\n\n if(levels.length) {\n // start bitrate is the first bitrate of the manifest\n bitrateStart = levels[0].bitrate;\n // sort level on bitrate\n levels.sort(function (a, b) {\n return a.bitrate - b.bitrate;\n });\n this._levels = levels;\n // find index of first level in sorted levels\n for (i = 0; i < levels.length; i++) {\n if (levels[i].bitrate === bitrateStart) {\n this._firstLevel = i;\n logger.log(`manifest loaded,${levels.length} level(s) found, first bitrate:${bitrateStart}`);\n break;\n }\n }\n hls.trigger(Event.MANIFEST_PARSED, {levels: this._levels, firstLevel: this._firstLevel, stats: data.stats});\n } else {\n hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.MANIFEST_INCOMPATIBLE_CODECS_ERROR, fatal: true, url: hls.url, reason: 'no level with compatible codecs found in manifest'});\n }\n return;\n }\n\n get levels() {\n return this._levels;\n }\n\n get level() {\n return this._level;\n }\n\n set level(newLevel) {\n let levels = this._levels;\n if (levels && levels.length > newLevel) {\n if (this._level !== newLevel || levels[newLevel].details === undefined) {\n this.setLevelInternal(newLevel);\n }\n }\n }\n\n setLevelInternal(newLevel) {\n let levels = this._levels;\n // check if level idx is valid\n if (newLevel >= 0 && newLevel < levels.length) {\n // stopping live reloading timer if any\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n this._level = newLevel;\n logger.log(`switching to level ${newLevel}`);\n this.hls.trigger(Event.LEVEL_SWITCH, {level: newLevel});\n var level = levels[newLevel];\n // check if we need to load playlist for this level\n if (level.details === undefined || level.details.live === true) {\n // level not retrieved yet, or live playlist we need to (re)load it\n logger.log(`(re)loading playlist for level ${newLevel}`);\n var urlId = level.urlId;\n this.hls.trigger(Event.LEVEL_LOADING, {url: level.url[urlId], level: newLevel, id: urlId});\n }\n } else {\n // invalid level id given, trigger error\n this.hls.trigger(Event.ERROR, {type : ErrorTypes.OTHER_ERROR, details: ErrorDetails.LEVEL_SWITCH_ERROR, level: newLevel, fatal: false, reason: 'invalid level idx'});\n }\n }\n\n get manualLevel() {\n return this._manualLevel;\n }\n\n set manualLevel(newLevel) {\n this._manualLevel = newLevel;\n if (this._startLevel === undefined) {\n this._startLevel = newLevel;\n }\n if (newLevel !== -1) {\n this.level = newLevel;\n }\n }\n\n get firstLevel() {\n return this._firstLevel;\n }\n\n set firstLevel(newLevel) {\n this._firstLevel = newLevel;\n }\n\n get startLevel() {\n if (this._startLevel === undefined) {\n return this._firstLevel;\n } else {\n return this._startLevel;\n }\n }\n\n set startLevel(newLevel) {\n this._startLevel = newLevel;\n }\n\n onError(data) {\n if(data.fatal) {\n return;\n }\n\n let details = data.details, hls = this.hls, levelId, level, levelError = false;\n // try to recover not fatal errors\n switch(details) {\n case ErrorDetails.FRAG_LOAD_ERROR:\n case ErrorDetails.FRAG_LOAD_TIMEOUT:\n case ErrorDetails.FRAG_LOOP_LOADING_ERROR:\n case ErrorDetails.KEY_LOAD_ERROR:\n case ErrorDetails.KEY_LOAD_TIMEOUT:\n levelId = data.frag.level;\n break;\n case ErrorDetails.LEVEL_LOAD_ERROR:\n case ErrorDetails.LEVEL_LOAD_TIMEOUT:\n levelId = data.level;\n levelError = true;\n break;\n default:\n break;\n }\n /* try to switch to a redundant stream if any available.\n * if no redundant stream available, emergency switch down (if in auto mode and current level not 0)\n * otherwise, we cannot recover this network error ...\n * don't raise FRAG_LOAD_ERROR and FRAG_LOAD_TIMEOUT as fatal, as it is handled by mediaController\n */\n if (levelId !== undefined) {\n level = this._levels[levelId];\n if (level.urlId < (level.url.length - 1)) {\n level.urlId++;\n level.details = undefined;\n logger.warn(`level controller,${details} for level ${levelId}: switching to redundant stream id ${level.urlId}`);\n } else {\n // we could try to recover if in auto mode and current level not lowest level (0)\n let recoverable = ((this._manualLevel === -1) && levelId);\n if (recoverable) {\n logger.warn(`level controller,${details}: emergency switch-down for next fragment`);\n hls.abrController.nextAutoLevel = 0;\n } else if(level && level.details && level.details.live) {\n logger.warn(`level controller,${details} on live stream, discard`);\n if (levelError) {\n // reset this._level so that another call to set level() will retrigger a frag load\n this._level = undefined;\n }\n // FRAG_LOAD_ERROR and FRAG_LOAD_TIMEOUT are handled by mediaController\n } else if (details !== ErrorDetails.FRAG_LOAD_ERROR && details !== ErrorDetails.FRAG_LOAD_TIMEOUT) {\n logger.error(`cannot recover ${details} error`);\n this._level = undefined;\n // stopping live reloading timer if any\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n // redispatch same error but with fatal set to true\n data.fatal = true;\n hls.trigger(Event.ERROR, data);\n }\n }\n }\n }\n\n onLevelLoaded(data) {\n // only process level loaded events matching with expected level\n if (data.level === this._level) {\n let newDetails = data.details;\n // if current playlist is a live playlist, arm a timer to reload it\n if (newDetails.live) {\n let reloadInterval = 1000*newDetails.targetduration,\n curLevel = this._levels[data.level],\n curDetails = curLevel.details;\n if (curDetails && newDetails.endSN === curDetails.endSN) {\n // follow HLS Spec, If the client reloads a Playlist file and finds that it has not\n // changed then it MUST wait for a period of one-half the target\n // duration before retrying.\n reloadInterval /=2;\n logger.log(`same live playlist, reload twice faster`);\n }\n // decrement reloadInterval with level loading delay\n reloadInterval -= performance.now() - data.stats.trequest;\n // in any case, don't reload more than every second\n reloadInterval = Math.max(1000,Math.round(reloadInterval));\n logger.log(`live playlist, reload in ${reloadInterval} ms`);\n this.timer = setTimeout(this.ontick,reloadInterval);\n } else {\n this.timer = null;\n }\n }\n }\n\n tick() {\n var levelId = this._level;\n if (levelId !== undefined && this.canload) {\n var level = this._levels[levelId], urlId = level.urlId;\n this.hls.trigger(Event.LEVEL_LOADING, {url: level.url[urlId], level: levelId, id: urlId});\n }\n }\n\n get nextLoadLevel() {\n if (this._manualLevel !== -1) {\n return this._manualLevel;\n } else {\n return this.hls.abrController.nextAutoLevel;\n }\n }\n\n set nextLoadLevel(nextLevel) {\n this.level = nextLevel;\n if (this._manualLevel === -1) {\n this.hls.abrController.nextAutoLevel = nextLevel;\n }\n }\n}\n\nexport default LevelController;\n\n", - "/*\n * Stream Controller\n*/\n\nimport Demuxer from '../demux/demuxer';\nimport Event from '../events';\nimport EventHandler from '../event-handler';\nimport {logger} from '../utils/logger';\nimport BinarySearch from '../utils/binary-search';\nimport BufferHelper from '../helper/buffer-helper';\nimport LevelHelper from '../helper/level-helper';\nimport {ErrorTypes, ErrorDetails} from '../errors';\n\nconst State = {\n STOPPED : 'STOPPED',\n STARTING : 'STARTING',\n IDLE : 'IDLE',\n PAUSED : 'PAUSED',\n KEY_LOADING : 'KEY_LOADING',\n FRAG_LOADING : 'FRAG_LOADING',\n FRAG_LOADING_WAITING_RETRY : 'FRAG_LOADING_WAITING_RETRY',\n WAITING_LEVEL : 'WAITING_LEVEL',\n PARSING : 'PARSING',\n PARSED : 'PARSED',\n ENDED : 'ENDED',\n ERROR : 'ERROR'\n};\n\nclass StreamController extends EventHandler {\n\n constructor(hls) {\n super(hls,\n Event.MEDIA_ATTACHED,\n Event.MEDIA_DETACHING,\n Event.MANIFEST_LOADING,\n Event.MANIFEST_PARSED,\n Event.LEVEL_LOADED,\n Event.KEY_LOADED,\n Event.FRAG_LOADED,\n Event.FRAG_LOAD_EMERGENCY_ABORTED,\n Event.FRAG_PARSING_INIT_SEGMENT,\n Event.FRAG_PARSING_DATA,\n Event.FRAG_PARSED,\n Event.ERROR,\n Event.BUFFER_APPENDED,\n Event.BUFFER_FLUSHED);\n\n this.config = hls.config;\n this.audioCodecSwap = false;\n this.ticks = 0;\n this.ontick = this.tick.bind(this);\n }\n\n destroy() {\n this.stopLoad();\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n EventHandler.prototype.destroy.call(this);\n this.state = State.STOPPED;\n }\n\n startLoad(startPosition) {\n if (this.levels) {\n var media = this.media, lastCurrentTime = this.lastCurrentTime;\n this.stopLoad();\n this.demuxer = new Demuxer(this.hls);\n if (!this.timer) {\n this.timer = setInterval(this.ontick, 100);\n }\n this.level = -1;\n this.fragLoadError = 0;\n if (media && lastCurrentTime > 0) {\n logger.log(`configure startPosition @${lastCurrentTime}`);\n if (!this.lastPaused) {\n logger.log('resuming video');\n media.play();\n }\n this.state = State.IDLE;\n } else {\n this.lastCurrentTime = this.startPosition ? this.startPosition : startPosition;\n this.state = State.STARTING;\n }\n this.nextLoadPosition = this.startPosition = this.lastCurrentTime;\n this.tick();\n } else {\n logger.warn('cannot start loading as manifest not parsed yet');\n this.state = State.STOPPED;\n }\n }\n\n stopLoad() {\n var frag = this.fragCurrent;\n if (frag) {\n if (frag.loader) {\n frag.loader.abort();\n }\n this.fragCurrent = null;\n }\n this.fragPrevious = null;\n if (this.demuxer) {\n this.demuxer.destroy();\n this.demuxer = null;\n }\n this.state = State.STOPPED;\n }\n\n tick() {\n this.ticks++;\n if (this.ticks === 1) {\n this.doTick();\n if (this.ticks > 1) {\n setTimeout(this.tick, 1);\n }\n this.ticks = 0;\n }\n }\n\n doTick() {\n var pos, level, levelDetails, hls = this.hls, config = hls.config, media = this.media, isSeeking = media && media.seeking;\n //logger.log(this.state);\n switch(this.state) {\n case State.ERROR:\n //don't do anything in error state to avoid breaking further ...\n case State.PAUSED:\n //don't do anything in paused state either ...\n break;\n case State.STARTING:\n // determine load level\n let startLevel = hls.startLevel;\n if (startLevel === -1) {\n // -1 : guess start Level by doing a bitrate test by loading first fragment of lowest quality level\n startLevel = 0;\n this.fragBitrateTest = true;\n }\n // set new level to playlist loader : this will trigger start level load\n // hls.nextLoadLevel remains until it is set to a new value or until a new frag is successfully loaded\n this.level = hls.nextLoadLevel = startLevel;\n this.state = State.WAITING_LEVEL;\n this.loadedmetadata = false;\n break;\n case State.IDLE:\n // if video not attached AND\n // start fragment already requested OR start frag prefetch disable\n // exit loop\n // => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop\n if (!media &&\n (this.startFragRequested || !config.startFragPrefetch)) {\n break;\n }\n // determine next candidate fragment to be loaded, based on current position and\n // end of buffer position\n // ensure 60s of buffer upfront\n // if we have not yet loaded any fragment, start loading from start position\n if (this.loadedmetadata) {\n pos = media.currentTime;\n } else {\n pos = this.nextLoadPosition;\n }\n level = hls.nextLoadLevel;\n var bufferInfo = BufferHelper.bufferInfo(media,pos,config.maxBufferHole),\n bufferLen = bufferInfo.len,\n bufferEnd = bufferInfo.end,\n fragPrevious = this.fragPrevious,\n maxBufLen;\n // compute max Buffer Length that we could get from this load level, based on level bitrate. don't buffer more than 60 MB and more than 30s\n if ((this.levels[level]).hasOwnProperty('bitrate')) {\n maxBufLen = Math.max(8 * config.maxBufferSize / this.levels[level].bitrate, config.maxBufferLength);\n maxBufLen = Math.min(maxBufLen, config.maxMaxBufferLength);\n } else {\n maxBufLen = config.maxBufferLength;\n }\n // if buffer length is less than maxBufLen try to load a new fragment\n if (bufferLen < maxBufLen) {\n // set next load level : this will trigger a playlist load if needed\n hls.nextLoadLevel = level;\n this.level = level;\n levelDetails = this.levels[level].details;\n // if level info not retrieved yet, switch state and wait for level retrieval\n // if live playlist, ensure that new playlist has been refreshed to avoid loading/try to load\n // a useless and outdated fragment (that might even introduce load error if it is already out of the live playlist)\n if (typeof levelDetails === 'undefined' || levelDetails.live && this.levelLastLoaded !== level) {\n this.state = State.WAITING_LEVEL;\n break;\n }\n // find fragment index, contiguous with end of buffer position\n let fragments = levelDetails.fragments,\n fragLen = fragments.length,\n start = fragments[0].start,\n end = fragments[fragLen-1].start + fragments[fragLen-1].duration,\n frag;\n\n // in case of live playlist we need to ensure that requested position is not located before playlist start\n if (levelDetails.live) {\n // check if requested position is within seekable boundaries :\n //logger.log(`start/pos/bufEnd/seeking:${start.toFixed(3)}/${pos.toFixed(3)}/${bufferEnd.toFixed(3)}/${media.seeking}`);\n let maxLatency = config.liveMaxLatencyDuration !== undefined ? config.liveMaxLatencyDuration : config.liveMaxLatencyDurationCount*levelDetails.targetduration;\n\n if (bufferEnd < Math.max(start, end - maxLatency)) {\n let targetLatency = config.liveSyncDuration !== undefined ? config.liveSyncDuration : config.liveSyncDurationCount * levelDetails.targetduration;\n let liveSyncPosition = start + Math.max(0, levelDetails.totalduration - targetLatency);\n logger.log(`buffer end: ${bufferEnd} is located too far from the end of live sliding playlist, reset currentTime to : ${liveSyncPosition.toFixed(3)}`);\n bufferEnd = liveSyncPosition;\n if (media && media.readyState && media.duration > liveSyncPosition) {\n media.currentTime = liveSyncPosition;\n }\n }\n\n // if end of buffer greater than live edge, don't load any fragment\n // this could happen if live playlist intermittently slides in the past.\n // level 1 loaded [182580161,182580167]\n // level 1 loaded [182580162,182580169]\n // Loading 182580168 of [182580162 ,182580169],level 1 ..\n // Loading 182580169 of [182580162 ,182580169],level 1 ..\n // level 1 loaded [182580162,182580168] <============= here we should have bufferEnd > end. in that case break to avoid reloading 182580168\n // level 1 loaded [182580164,182580171]\n //\n if (levelDetails.PTSKnown && bufferEnd > end) {\n break;\n }\n\n if (this.startFragRequested && !levelDetails.PTSKnown) {\n /* we are switching level on live playlist, but we don't have any PTS info for that quality level ...\n try to load frag matching with next SN.\n even if SN are not synchronized between playlists, loading this frag will help us\n compute playlist sliding and find the right one after in case it was not the right consecutive one */\n if (fragPrevious) {\n var targetSN = fragPrevious.sn + 1;\n if (targetSN >= levelDetails.startSN && targetSN <= levelDetails.endSN) {\n frag = fragments[targetSN - levelDetails.startSN];\n logger.log(`live playlist, switching playlist, load frag with next SN: ${frag.sn}`);\n }\n }\n if (!frag) {\n /* we have no idea about which fragment should be loaded.\n so let's load mid fragment. it will help computing playlist sliding and find the right one\n */\n frag = fragments[Math.min(fragLen - 1, Math.round(fragLen / 2))];\n logger.log(`live playlist, switching playlist, unknown, load middle frag : ${frag.sn}`);\n }\n }\n } else {\n // VoD playlist: if bufferEnd before start of playlist, load first fragment\n if (bufferEnd < start) {\n frag = fragments[0];\n }\n }\n if (!frag) {\n let maxFragLookUpTolerance = config.maxFragLookUpTolerance;\n if (bufferEnd < end) {\n // no frag look up tolerance in case bufferEnd close to end, or media seeking\n if (bufferEnd > end - maxFragLookUpTolerance || isSeeking) {\n maxFragLookUpTolerance = 0;\n }\n frag = BinarySearch.search(fragments, (candidate) => {\n // offset should be within fragment boundary - config.maxFragLookUpTolerance\n // this is to cope with situations like\n // bufferEnd = 9.991\n // frag[Ø] : [0,10]\n // frag[1] : [10,20]\n // bufferEnd is within frag[0] range ... although what we are expecting is to return frag[1] here\n // frag start frag start+duration\n // |-----------------------------|\n // <---> <--->\n // ...--------><-----------------------------><---------....\n // previous frag matching fragment next frag\n // return -1 return 0 return 1\n //logger.log(`level/sn/start/end/bufEnd:${level}/${candidate.sn}/${candidate.start}/${(candidate.start+candidate.duration)}/${bufferEnd}`);\n if ((candidate.start + candidate.duration - maxFragLookUpTolerance) <= bufferEnd) {\n return 1;\n }\n else if (candidate.start - maxFragLookUpTolerance > bufferEnd) {\n return -1;\n }\n return 0;\n });\n } else {\n // reach end of playlist\n frag = fragments[fragLen-1];\n }\n }\n if(frag) {\n start = frag.start;\n //logger.log('find SN matching with pos:' + bufferEnd + ':' + frag.sn);\n if (fragPrevious && frag.level === fragPrevious.level && frag.sn === fragPrevious.sn) {\n if (frag.sn < levelDetails.endSN) {\n let deltaPTS = fragPrevious.deltaPTS,\n curSNIdx = frag.sn - levelDetails.startSN;\n // if there is a significant delta between audio and video, larger than max allowed hole,\n // and if previous remuxed fragment did not start with a keyframe. (fragPrevious.dropped)\n // let's try to load previous fragment again to get last keyframe\n // then we will reload again current fragment (that way we should be able to fill the buffer hole ...)\n if (deltaPTS && deltaPTS > config.maxBufferHole && fragPrevious.dropped) {\n frag = fragments[curSNIdx-1];\n logger.warn(`SN just loaded, with large PTS gap between audio and video, maybe frag is not starting with a keyframe ? load previous one to try to overcome this`);\n // decrement previous frag load counter to avoid frag loop loading error when next fragment will get reloaded\n fragPrevious.loadCounter--;\n } else {\n frag = fragments[curSNIdx+1];\n logger.log(`SN just loaded, load next one: ${frag.sn}`);\n }\n // ensure frag is not undefined\n if(!frag) {\n break;\n }\n } else {\n // have we reached end of VOD playlist ?\n if (!levelDetails.live) {\n // Finalize the media stream\n this.hls.trigger(Event.BUFFER_EOS);\n // We might be loading the last fragment but actually the media\n // is currently processing a seek command and waiting for new data to resume at another point.\n // Going to ended state while media is seeking can spawn an infinite buffering broken state.\n if (!isSeeking) {\n this.state = State.ENDED;\n }\n }\n break;\n }\n }\n //logger.log(' loading frag ' + i +',pos/bufEnd:' + pos.toFixed(3) + '/' + bufferEnd.toFixed(3));\n if ((frag.decryptdata.uri != null) && (frag.decryptdata.key == null)) {\n logger.log(`Loading key for ${frag.sn} of [${levelDetails.startSN} ,${levelDetails.endSN}],level ${level}`);\n this.state = State.KEY_LOADING;\n hls.trigger(Event.KEY_LOADING, {frag: frag});\n } else {\n logger.log(`Loading ${frag.sn} of [${levelDetails.startSN} ,${levelDetails.endSN}],level ${level}, currentTime:${pos},bufferEnd:${bufferEnd.toFixed(3)}`);\n // ensure that we are not reloading the same fragments in loop ...\n if (this.fragLoadIdx !== undefined) {\n this.fragLoadIdx++;\n } else {\n this.fragLoadIdx = 0;\n }\n if (frag.loadCounter) {\n frag.loadCounter++;\n let maxThreshold = config.fragLoadingLoopThreshold;\n // if this frag has already been loaded 3 times, and if it has been reloaded recently\n if (frag.loadCounter > maxThreshold && (Math.abs(this.fragLoadIdx - frag.loadIdx) < maxThreshold)) {\n hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_LOOP_LOADING_ERROR, fatal: false, frag: frag});\n return;\n }\n } else {\n frag.loadCounter = 1;\n }\n frag.loadIdx = this.fragLoadIdx;\n this.fragCurrent = frag;\n this.startFragRequested = true;\n frag.autoLevel = hls.autoLevelEnabled;\n hls.trigger(Event.FRAG_LOADING, {frag: frag});\n this.state = State.FRAG_LOADING;\n }\n }\n }\n break;\n case State.WAITING_LEVEL:\n level = this.levels[this.level];\n // check if playlist is already loaded\n if (level && level.details) {\n this.state = State.IDLE;\n }\n break;\n case State.FRAG_LOADING_WAITING_RETRY:\n var now = performance.now();\n var retryDate = this.retryDate;\n // if current time is gt than retryDate, or if media seeking let's switch to IDLE state to retry loading\n if(!retryDate || (now >= retryDate) || isSeeking) {\n logger.log(`mediaController: retryDate reached, switch back to IDLE state`);\n this.state = State.IDLE;\n }\n break;\n case State.STOPPED:\n case State.FRAG_LOADING:\n case State.PARSING:\n case State.PARSED:\n case State.ENDED:\n break;\n default:\n break;\n }\n // check buffer\n this._checkBuffer();\n // check/update current fragment\n this._checkFragmentChanged();\n }\n\n\n\n\n getBufferRange(position) {\n var i, range,\n bufferRange = this.bufferRange;\n if (bufferRange) {\n for (i = bufferRange.length - 1; i >=0; i--) {\n range = bufferRange[i];\n if (position >= range.start && position <= range.end) {\n return range;\n }\n }\n }\n return null;\n }\n\n get currentLevel() {\n if (this.media) {\n var range = this.getBufferRange(this.media.currentTime);\n if (range) {\n return range.frag.level;\n }\n }\n return -1;\n }\n\n get nextBufferRange() {\n if (this.media) {\n // first get end range of current fragment\n return this.followingBufferRange(this.getBufferRange(this.media.currentTime));\n } else {\n return null;\n }\n }\n\n followingBufferRange(range) {\n if (range) {\n // try to get range of next fragment (500ms after this range)\n return this.getBufferRange(range.end + 0.5);\n }\n return null;\n }\n\n get nextLevel() {\n var range = this.nextBufferRange;\n if (range) {\n return range.frag.level;\n } else {\n return -1;\n }\n }\n\n isBuffered(position) {\n let media = this.media;\n if (media) {\n let buffered = media.buffered;\n for (let i = 0; i < buffered.length; i++) {\n if (position >= buffered.start(i) && position <= buffered.end(i)) {\n return true;\n }\n }\n }\n return false;\n }\n\n _checkFragmentChanged() {\n var rangeCurrent, currentTime, video = this.media;\n if (video && video.seeking === false) {\n currentTime = video.currentTime;\n /* if video element is in seeked state, currentTime can only increase.\n (assuming that playback rate is positive ...)\n As sometimes currentTime jumps back to zero after a\n media decode error, check this, to avoid seeking back to\n wrong position after a media decode error\n */\n if(currentTime > video.playbackRate*this.lastCurrentTime) {\n this.lastCurrentTime = currentTime;\n }\n if (this.isBuffered(currentTime)) {\n rangeCurrent = this.getBufferRange(currentTime);\n } else if (this.isBuffered(currentTime + 0.1)) {\n /* ensure that FRAG_CHANGED event is triggered at startup,\n when first video frame is displayed and playback is paused.\n add a tolerance of 100ms, in case current position is not buffered,\n check if current pos+100ms is buffered and use that buffer range\n for FRAG_CHANGED event reporting */\n rangeCurrent = this.getBufferRange(currentTime + 0.1);\n }\n if (rangeCurrent) {\n var fragPlaying = rangeCurrent.frag;\n if (fragPlaying !== this.fragPlaying) {\n this.fragPlaying = fragPlaying;\n this.hls.trigger(Event.FRAG_CHANGED, {frag: fragPlaying});\n }\n }\n }\n }\n\n /*\n on immediate level switch :\n - pause playback if playing\n - cancel any pending load request\n - and trigger a buffer flush\n */\n immediateLevelSwitch() {\n logger.log('immediateLevelSwitch');\n if (!this.immediateSwitch) {\n this.immediateSwitch = true;\n let media = this.media, previouslyPaused;\n if (media) {\n previouslyPaused = media.paused;\n media.pause();\n } else {\n // don't restart playback after instant level switch in case media not attached\n previouslyPaused = true;\n }\n this.previouslyPaused = previouslyPaused;\n }\n var fragCurrent = this.fragCurrent;\n if (fragCurrent && fragCurrent.loader) {\n fragCurrent.loader.abort();\n }\n this.fragCurrent = null;\n // increase fragment load Index to avoid frag loop loading error after buffer flush\n this.fragLoadIdx += 2 * this.config.fragLoadingLoopThreshold;\n this.state = State.PAUSED;\n // flush everything\n this.hls.trigger(Event.BUFFER_FLUSHING, {startOffset: 0, endOffset: Number.POSITIVE_INFINITY});\n }\n\n /*\n on immediate level switch end, after new fragment has been buffered :\n - nudge video decoder by slightly adjusting video currentTime\n - resume the playback if needed\n */\n immediateLevelSwitchEnd() {\n this.immediateSwitch = false;\n let media = this.media;\n if (media && media.readyState) {\n media.currentTime -= 0.0001;\n if (!this.previouslyPaused) {\n media.play();\n }\n }\n }\n\n nextLevelSwitch() {\n /* try to switch ASAP without breaking video playback :\n in order to ensure smooth but quick level switching,\n we need to find the next flushable buffer range\n we should take into account new segment fetch time\n */\n let media = this.media;\n // ensure that media is defined and that metadata are available (to retrieve currentTime)\n if (media && media.readyState) {\n let fetchdelay, currentRange, nextRange;\n // increase fragment load Index to avoid frag loop loading error after buffer flush\n this.fragLoadIdx += 2 * this.config.fragLoadingLoopThreshold;\n currentRange = this.getBufferRange(media.currentTime);\n if (currentRange && currentRange.start > 1) {\n // flush buffer preceding current fragment (flush until current fragment start offset)\n // minus 1s to avoid video freezing, that could happen if we flush keyframe of current video ...\n this.state = State.PAUSED;\n this.hls.trigger(Event.BUFFER_FLUSHING, {startOffset: 0, endOffset: currentRange.start - 1});\n }\n if (!media.paused) {\n // add a safety delay of 1s\n var nextLevelId = this.hls.nextLoadLevel,nextLevel = this.levels[nextLevelId], fragLastKbps = this.fragLastKbps;\n if (fragLastKbps && this.fragCurrent) {\n fetchdelay = this.fragCurrent.duration * nextLevel.bitrate / (1000 * fragLastKbps) + 1;\n } else {\n fetchdelay = 0;\n }\n } else {\n fetchdelay = 0;\n }\n //logger.log('fetchdelay:'+fetchdelay);\n // find buffer range that will be reached once new fragment will be fetched\n nextRange = this.getBufferRange(media.currentTime + fetchdelay);\n if (nextRange) {\n // we can flush buffer range following this one without stalling playback\n nextRange = this.followingBufferRange(nextRange);\n if (nextRange) {\n // if we are here, we can also cancel any loading/demuxing in progress, as they are useless\n var fragCurrent = this.fragCurrent;\n if (fragCurrent && fragCurrent.loader) {\n fragCurrent.loader.abort();\n }\n this.fragCurrent = null;\n // flush position is the start position of this new buffer\n this.state = State.PAUSED;\n this.hls.trigger(Event.BUFFER_FLUSHING, {startOffset: nextRange.start, endOffset: Number.POSITIVE_INFINITY});\n }\n }\n }\n }\n\n onMediaAttached(data) {\n var media = this.media = data.media;\n this.onvseeking = this.onMediaSeeking.bind(this);\n this.onvseeked = this.onMediaSeeked.bind(this);\n this.onvended = this.onMediaEnded.bind(this);\n media.addEventListener('seeking', this.onvseeking);\n media.addEventListener('seeked', this.onvseeked);\n media.addEventListener('ended', this.onvended);\n let config = this.config;\n if(this.levels && config.autoStartLoad) {\n this.hls.startLoad(config.startPosition);\n }\n }\n\n onMediaDetaching() {\n var media = this.media;\n if (media && media.ended) {\n logger.log('MSE detaching and video ended, reset startPosition');\n this.startPosition = this.lastCurrentTime = 0;\n }\n\n // reset fragment loading counter on MSE detaching to avoid reporting FRAG_LOOP_LOADING_ERROR after error recovery\n var levels = this.levels;\n if (levels) {\n // reset fragment load counter\n levels.forEach(level => {\n if(level.details) {\n level.details.fragments.forEach(fragment => {\n fragment.loadCounter = undefined;\n });\n }\n });\n }\n // remove video listeners\n if (media) {\n media.removeEventListener('seeking', this.onvseeking);\n media.removeEventListener('seeked', this.onvseeked);\n media.removeEventListener('ended', this.onvended);\n this.onvseeking = this.onvseeked = this.onvended = null;\n }\n this.media = null;\n this.loadedmetadata = false;\n this.stopLoad();\n }\n\n onMediaSeeking() {\n if (this.state === State.FRAG_LOADING) {\n // check if currently loaded fragment is inside buffer.\n //if outside, cancel fragment loading, otherwise do nothing\n if (BufferHelper.bufferInfo(this.media,this.media.currentTime,this.config.maxBufferHole).len === 0) {\n logger.log('seeking outside of buffer while fragment load in progress, cancel fragment load');\n var fragCurrent = this.fragCurrent;\n if (fragCurrent) {\n if (fragCurrent.loader) {\n fragCurrent.loader.abort();\n }\n this.fragCurrent = null;\n }\n this.fragPrevious = null;\n // switch to IDLE state to load new fragment\n this.state = State.IDLE;\n }\n } else if (this.state === State.ENDED) {\n // switch to IDLE state to check for potential new fragment\n this.state = State.IDLE;\n }\n if (this.media) {\n this.lastCurrentTime = this.media.currentTime;\n }\n // avoid reporting fragment loop loading error in case user is seeking several times on same position\n if (this.fragLoadIdx !== undefined) {\n this.fragLoadIdx += 2 * this.config.fragLoadingLoopThreshold;\n }\n // tick to speed up processing\n this.tick();\n }\n\n onMediaSeeked() {\n // tick to speed up FRAGMENT_PLAYING triggering\n this.tick();\n }\n\n onMediaEnded() {\n logger.log('media ended');\n // reset startPosition and lastCurrentTime to restart playback @ stream beginning\n this.startPosition = this.lastCurrentTime = 0;\n }\n\n\n onManifestLoading() {\n // reset buffer on manifest loading\n logger.log('trigger BUFFER_RESET');\n this.hls.trigger(Event.BUFFER_RESET);\n this.bufferRange = [];\n this.stalled = false;\n }\n\n onManifestParsed(data) {\n var aac = false, heaac = false, codec;\n data.levels.forEach(level => {\n // detect if we have different kind of audio codecs used amongst playlists\n codec = level.audioCodec;\n if (codec) {\n if (codec.indexOf('mp4a.40.2') !== -1) {\n aac = true;\n }\n if (codec.indexOf('mp4a.40.5') !== -1) {\n heaac = true;\n }\n }\n });\n this.audioCodecSwitch = (aac && heaac);\n if (this.audioCodecSwitch) {\n logger.log('both AAC/HE-AAC audio found in levels; declaring level codec as HE-AAC');\n }\n this.levels = data.levels;\n this.startLevelLoaded = false;\n this.startFragRequested = false;\n let config = this.config;\n if (config.autoStartLoad) {\n this.hls.startLoad(config.startPosition);\n }\n }\n\n onLevelLoaded(data) {\n var newDetails = data.details,\n newLevelId = data.level,\n curLevel = this.levels[newLevelId],\n duration = newDetails.totalduration,\n sliding = 0;\n\n logger.log(`level ${newLevelId} loaded [${newDetails.startSN},${newDetails.endSN}],duration:${duration}`);\n this.levelLastLoaded = newLevelId;\n\n if (newDetails.live) {\n var curDetails = curLevel.details;\n if (curDetails) {\n // we already have details for that level, merge them\n LevelHelper.mergeDetails(curDetails,newDetails);\n sliding = newDetails.fragments[0].start;\n if (newDetails.PTSKnown) {\n logger.log(`live playlist sliding:${sliding.toFixed(3)}`);\n } else {\n logger.log('live playlist - outdated PTS, unknown sliding');\n }\n } else {\n newDetails.PTSKnown = false;\n logger.log('live playlist - first load, unknown sliding');\n }\n } else {\n newDetails.PTSKnown = false;\n }\n // override level info\n curLevel.details = newDetails;\n this.hls.trigger(Event.LEVEL_UPDATED, { details: newDetails, level: newLevelId });\n\n if (this.startFragRequested === false) {\n // compute start position if set to -1. use it straight away if value is defined\n if (this.startPosition === -1) {\n // first, check if start time offset has been set in playlist, if yes, use this value\n let startTimeOffset = newDetails.startTimeOffset;\n if(!isNaN(startTimeOffset)) {\n logger.log(`start time offset found in playlist, adjust startPosition to ${startTimeOffset}`);\n this.startPosition = startTimeOffset;\n } else {\n // if live playlist, set start position to be fragment N-this.config.liveSyncDurationCount (usually 3)\n if (newDetails.live) {\n let targetLatency = this.config.liveSyncDuration !== undefined ? this.config.liveSyncDuration : this.config.liveSyncDurationCount * newDetails.targetduration;\n this.startPosition = Math.max(0, sliding + duration - targetLatency);\n } else {\n this.startPosition = 0;\n }\n }\n }\n this.nextLoadPosition = this.startPosition;\n }\n // only switch batck to IDLE state if we were waiting for level to start downloading a new fragment\n if (this.state === State.WAITING_LEVEL) {\n this.state = State.IDLE;\n }\n //trigger handler right now\n this.tick();\n }\n\n onKeyLoaded() {\n if (this.state === State.KEY_LOADING) {\n this.state = State.IDLE;\n this.tick();\n }\n }\n\n onFragLoaded(data) {\n var fragCurrent = this.fragCurrent;\n if (this.state === State.FRAG_LOADING &&\n fragCurrent &&\n data.frag.level === fragCurrent.level &&\n data.frag.sn === fragCurrent.sn) {\n\n logger.log(`Loaded ${fragCurrent.sn} of level ${fragCurrent.level}`);\n if (this.fragBitrateTest === true) {\n // switch back to IDLE state ... we just loaded a fragment to determine adequate start bitrate and initialize autoswitch algo\n this.state = State.IDLE;\n this.fragBitrateTest = false;\n this.startFragRequested = false;\n data.stats.tparsed = data.stats.tbuffered = performance.now();\n this.hls.trigger(Event.FRAG_BUFFERED, {stats: data.stats, frag: fragCurrent});\n } else {\n this.state = State.PARSING;\n // transmux the MPEG-TS data to ISO-BMFF segments\n this.stats = data.stats;\n var currentLevel = this.levels[this.level],\n details = currentLevel.details,\n duration = details.totalduration,\n start = fragCurrent.startDTS !== undefined ? fragCurrent.startDTS : fragCurrent.start,\n level = fragCurrent.level,\n sn = fragCurrent.sn,\n audioCodec = currentLevel.audioCodec || this.config.defaultAudioCodec;\n if(this.audioCodecSwap) {\n logger.log('swapping playlist audio codec');\n if(audioCodec === undefined) {\n audioCodec = this.lastAudioCodec;\n }\n if(audioCodec) {\n if(audioCodec.indexOf('mp4a.40.5') !==-1) {\n audioCodec = 'mp4a.40.2';\n } else {\n audioCodec = 'mp4a.40.5';\n }\n }\n }\n this.pendingAppending = 0;\n logger.log(`Demuxing ${sn} of [${details.startSN} ,${details.endSN}],level ${level}, cc ${fragCurrent.cc}`);\n let demuxer = this.demuxer;\n if (demuxer) {\n demuxer.push(data.payload, audioCodec, currentLevel.videoCodec, start, fragCurrent.cc, level, sn, duration, fragCurrent.decryptdata);\n }\n }\n }\n this.fragLoadError = 0;\n }\n\n onFragParsingInitSegment(data) {\n if (this.state === State.PARSING) {\n var tracks = data.tracks, trackName, track;\n\n // include levelCodec in audio and video tracks\n track = tracks.audio;\n if(track) {\n var audioCodec = this.levels[this.level].audioCodec,\n ua = navigator.userAgent.toLowerCase();\n if(audioCodec && this.audioCodecSwap) {\n logger.log('swapping playlist audio codec');\n if(audioCodec.indexOf('mp4a.40.5') !==-1) {\n audioCodec = 'mp4a.40.2';\n } else {\n audioCodec = 'mp4a.40.5';\n }\n }\n // in case AAC and HE-AAC audio codecs are signalled in manifest\n // force HE-AAC , as it seems that most browsers prefers that way,\n // except for mono streams OR on FF\n // these conditions might need to be reviewed ...\n if (this.audioCodecSwitch) {\n // don't force HE-AAC if mono stream\n if(track.metadata.channelCount !== 1 &&\n // don't force HE-AAC if firefox\n ua.indexOf('firefox') === -1) {\n audioCodec = 'mp4a.40.5';\n }\n }\n // HE-AAC is broken on Android, always signal audio codec as AAC even if variant manifest states otherwise\n if(ua.indexOf('android') !== -1) {\n audioCodec = 'mp4a.40.2';\n logger.log(`Android: force audio codec to` + audioCodec);\n }\n track.levelCodec = audioCodec;\n }\n track = tracks.video;\n if(track) {\n track.levelCodec = this.levels[this.level].videoCodec;\n }\n\n // if remuxer specify that a unique track needs to generated,\n // let's merge all tracks together\n if (data.unique) {\n var mergedTrack = {\n codec : '',\n levelCodec : ''\n };\n for (trackName in data.tracks) {\n track = tracks[trackName];\n mergedTrack.container = track.container;\n if (mergedTrack.codec) {\n mergedTrack.codec += ',';\n mergedTrack.levelCodec += ',';\n }\n if(track.codec) {\n mergedTrack.codec += track.codec;\n }\n if (track.levelCodec) {\n mergedTrack.levelCodec += track.levelCodec;\n }\n }\n tracks = { audiovideo : mergedTrack };\n }\n this.hls.trigger(Event.BUFFER_CODECS,tracks);\n // loop through tracks that are going to be provided to bufferController\n for (trackName in tracks) {\n track = tracks[trackName];\n logger.log(`track:${trackName},container:${track.container},codecs[level/parsed]=[${track.levelCodec}/${track.codec}]`);\n var initSegment = track.initSegment;\n if (initSegment) {\n this.pendingAppending++;\n this.hls.trigger(Event.BUFFER_APPENDING, {type: trackName, data: initSegment});\n }\n }\n //trigger handler right now\n this.tick();\n }\n }\n\n onFragParsingData(data) {\n if (this.state === State.PARSING) {\n this.tparse2 = Date.now();\n var level = this.levels[this.level],\n frag = this.fragCurrent;\n\n logger.log(`parsed ${data.type},PTS:[${data.startPTS.toFixed(3)},${data.endPTS.toFixed(3)}],DTS:[${data.startDTS.toFixed(3)}/${data.endDTS.toFixed(3)}],nb:${data.nb},dropped:${data.dropped || 0}`);\n\n var drift = LevelHelper.updateFragPTSDTS(level.details,frag.sn,data.startPTS,data.endPTS,data.startDTS,data.endDTS),\n hls = this.hls;\n hls.trigger(Event.LEVEL_PTS_UPDATED, {details: level.details, level: this.level, drift: drift});\n\n // has remuxer dropped video frames located before first keyframe ?\n if(data.type === 'video') {\n frag.dropped = data.dropped;\n }\n\n [data.data1, data.data2].forEach(buffer => {\n if (buffer) {\n this.pendingAppending++;\n hls.trigger(Event.BUFFER_APPENDING, {type: data.type, data: buffer});\n }\n });\n\n this.nextLoadPosition = data.endPTS;\n this.bufferRange.push({type: data.type, start: data.startPTS, end: data.endPTS, frag: frag});\n\n //trigger handler right now\n this.tick();\n } else {\n logger.warn(`not in PARSING state but ${this.state}, ignoring FRAG_PARSING_DATA event`);\n }\n }\n\n onFragParsed() {\n if (this.state === State.PARSING) {\n this.stats.tparsed = performance.now();\n this.state = State.PARSED;\n this._checkAppendedParsed();\n }\n }\n\n onBufferAppended() {\n switch (this.state) {\n case State.PARSING:\n case State.PARSED:\n this.pendingAppending--;\n this._checkAppendedParsed();\n break;\n default:\n break;\n }\n }\n\n _checkAppendedParsed() {\n //trigger handler right now\n if (this.state === State.PARSED && this.pendingAppending === 0) {\n var frag = this.fragCurrent, stats = this.stats;\n if (frag) {\n this.fragPrevious = frag;\n stats.tbuffered = performance.now();\n this.fragLastKbps = Math.round(8 * stats.length / (stats.tbuffered - stats.tfirst));\n this.hls.trigger(Event.FRAG_BUFFERED, {stats: stats, frag: frag});\n logger.log(`media buffered : ${this.timeRangesToString(this.media.buffered)}`);\n this.state = State.IDLE;\n }\n this.tick();\n }\n }\n\n onError(data) {\n switch(data.details) {\n case ErrorDetails.FRAG_LOAD_ERROR:\n case ErrorDetails.FRAG_LOAD_TIMEOUT:\n if(!data.fatal) {\n var loadError = this.fragLoadError;\n if(loadError) {\n loadError++;\n } else {\n loadError=1;\n }\n if (loadError <= this.config.fragLoadingMaxRetry) {\n this.fragLoadError = loadError;\n // reset load counter to avoid frag loop loading error\n data.frag.loadCounter = 0;\n // exponential backoff capped to 64s\n var delay = Math.min(Math.pow(2,loadError-1)*this.config.fragLoadingRetryDelay,64000);\n logger.warn(`mediaController: frag loading failed, retry in ${delay} ms`);\n this.retryDate = performance.now() + delay;\n // retry loading state\n this.state = State.FRAG_LOADING_WAITING_RETRY;\n } else {\n logger.error(`mediaController: ${data.details} reaches max retry, redispatch as fatal ...`);\n // redispatch same error but with fatal set to true\n data.fatal = true;\n this.hls.trigger(Event.ERROR, data);\n this.state = State.ERROR;\n }\n }\n break;\n case ErrorDetails.FRAG_LOOP_LOADING_ERROR:\n case ErrorDetails.LEVEL_LOAD_ERROR:\n case ErrorDetails.LEVEL_LOAD_TIMEOUT:\n case ErrorDetails.KEY_LOAD_ERROR:\n case ErrorDetails.KEY_LOAD_TIMEOUT:\n // when in ERROR state, don't switch back to IDLE state in case a non-fatal error is received\n if(this.state !== State.ERROR) {\n // if fatal error, stop processing, otherwise move to IDLE to retry loading\n this.state = data.fatal ? State.ERROR : State.IDLE;\n logger.warn(`mediaController: ${data.details} while loading frag,switch to ${this.state} state ...`);\n }\n break;\n case ErrorDetails.BUFFER_FULL_ERROR:\n // only reduce max buf len if in appending state\n if (this.state === State.PARSING || this.state === State.PARSED) {\n // reduce max buffer length as it might be too high. we do this to avoid loop flushing ...\n this.config.maxMaxBufferLength/=2;\n logger.warn(`reduce max buffer length to ${this.config.maxMaxBufferLength}s and switch to IDLE state`);\n // increase fragment load Index to avoid frag loop loading error after buffer flush\n this.fragLoadIdx += 2 * this.config.fragLoadingLoopThreshold;\n this.state = State.IDLE;\n }\n break;\n default:\n break;\n }\n }\n\n_checkBuffer() {\n var media = this.media;\n // if ready state different from HAVE_NOTHING (numeric value 0), we are allowed to seek\n if(media && media.readyState) {\n let currentTime = media.currentTime,\n buffered = media.buffered;\n // adjust currentTime to start position on loaded metadata\n if(!this.loadedmetadata && buffered.length) {\n this.loadedmetadata = true;\n // only adjust currentTime if startPosition not equal to 0\n let startPosition = this.startPosition;\n // if currentTime === 0 AND not matching with expected startPosition\n if (!currentTime && currentTime !== startPosition) {\n if (startPosition) {\n logger.log(`target start position:${startPosition}`);\n // at that stage, there should be only one buffered range, as we reach that code after first fragment has been\n let bufferStart = buffered.start(0),\n bufferEnd = buffered.end(0);\n // if startPosition not buffered, let's seek to buffered.start(0)\n if(startPosition < bufferStart || startPosition > bufferEnd) {\n startPosition = bufferStart;\n logger.log(`target start position not buffered, seek to buffered.start(0) ${bufferStart}`);\n }\n logger.log(`adjust currentTime from ${currentTime} to ${startPosition}`);\n media.currentTime = startPosition;\n }\n }\n } else {\n let bufferInfo = BufferHelper.bufferInfo(media,currentTime,0),\n expectedPlaying = !(media.paused || // not playing when media is paused\n media.ended || // not playing when media is ended\n media.buffered.length === 0), // not playing if nothing buffered\n jumpThreshold = 0.4, // tolerance needed as some browsers stalls playback before reaching buffered range end\n playheadMoving = currentTime > media.playbackRate*this.lastCurrentTime;\n\n if (this.stalled && playheadMoving) {\n this.stalled = false;\n logger.log(`playback not stuck anymore @${currentTime}`);\n }\n // check buffer upfront\n // if less than jumpThreshold second is buffered, let's check in more details\n if(expectedPlaying && bufferInfo.len <= jumpThreshold) {\n if(playheadMoving) {\n // playhead moving\n jumpThreshold = 0;\n this.seekHoleNudgeDuration = 0;\n } else {\n // playhead not moving AND media expected to play\n if(!this.stalled) {\n this.seekHoleNudgeDuration = 0;\n logger.log(`playback seems stuck @${currentTime}`);\n this.hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.BUFFER_STALLED_ERROR, fatal: false});\n this.stalled = true;\n } else {\n this.seekHoleNudgeDuration += this.config.seekHoleNudgeDuration;\n }\n }\n // if we are below threshold, try to jump to start of next buffer range if close\n if(bufferInfo.len <= jumpThreshold) {\n // no buffer available @ currentTime, check if next buffer is close (within a config.maxSeekHole second range)\n var nextBufferStart = bufferInfo.nextStart, delta = nextBufferStart-currentTime;\n if(nextBufferStart &&\n (delta < this.config.maxSeekHole) &&\n (delta > 0)) {\n // next buffer is close ! adjust currentTime to nextBufferStart\n // this will ensure effective video decoding\n logger.log(`adjust currentTime from ${media.currentTime} to next buffered @ ${nextBufferStart} + nudge ${this.seekHoleNudgeDuration}`);\n let hole = nextBufferStart + this.seekHoleNudgeDuration - media.currentTime;\n media.currentTime = nextBufferStart + this.seekHoleNudgeDuration;\n this.hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.BUFFER_SEEK_OVER_HOLE, fatal: false, hole : hole});\n }\n }\n }\n }\n }\n }\n\n onFragLoadEmergencyAborted() {\n this.state = State.IDLE;\n this.tick();\n }\n\n onBufferFlushed() {\n /* after successful buffer flushing, rebuild buffer Range array\n loop through existing buffer range and check if\n corresponding range is still buffered. only push to new array already buffered range\n */\n var newRange = [],range,i;\n for (i = 0; i < this.bufferRange.length; i++) {\n range = this.bufferRange[i];\n if (this.isBuffered((range.start + range.end) / 2)) {\n newRange.push(range);\n }\n }\n this.bufferRange = newRange;\n\n // handle end of immediate switching if needed\n if (this.immediateSwitch) {\n this.immediateLevelSwitchEnd();\n }\n // move to IDLE once flush complete. this should trigger new fragment loading\n this.state = State.IDLE;\n // reset reference to frag\n this.fragPrevious = null;\n }\n\n swapAudioCodec() {\n this.audioCodecSwap = !this.audioCodecSwap;\n }\n\n timeRangesToString(r) {\n var log = '', len = r.length;\n for (var i=0; i OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\n * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\n * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN\n * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * The views and conclusions contained in the software and documentation\n * are those of the authors and should not be interpreted as representing\n * official policies, either expressed or implied, of the authors.\n */\nclass AES {\n\n /**\n * Schedule out an AES key for both encryption and decryption. This\n * is a low-level class. Use a cipher mode to do bulk encryption.\n *\n * @constructor\n * @param key {Array} The key as an array of 4, 6 or 8 words.\n */\n constructor(key) {\n /**\n * The expanded S-box and inverse S-box tables. These will be computed\n * on the client so that we don't have to send them down the wire.\n *\n * There are two tables, _tables[0] is for encryption and\n * _tables[1] is for decryption.\n *\n * The first 4 sub-tables are the expanded S-box with MixColumns. The\n * last (_tables[01][4]) is the S-box itself.\n *\n * @private\n */\n this._tables = [[[],[],[],[],[]],[[],[],[],[],[]]];\n\n this._precompute();\n\n var i, j, tmp,\n encKey, decKey,\n sbox = this._tables[0][4], decTable = this._tables[1],\n keyLen = key.length, rcon = 1;\n\n if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) {\n throw new Error('Invalid aes key size=' + keyLen);\n }\n\n encKey = key.slice(0);\n decKey = [];\n this._key = [encKey, decKey];\n\n // schedule encryption keys\n for (i = keyLen; i < 4 * keyLen + 28; i++) {\n tmp = encKey[i-1];\n\n // apply sbox\n if (i%keyLen === 0 || (keyLen === 8 && i%keyLen === 4)) {\n tmp = sbox[tmp>>>24]<<24 ^ sbox[tmp>>16&255]<<16 ^ sbox[tmp>>8&255]<<8 ^ sbox[tmp&255];\n\n // shift rows and add rcon\n if (i%keyLen === 0) {\n tmp = tmp<<8 ^ tmp>>>24 ^ rcon<<24;\n rcon = rcon<<1 ^ (rcon>>7)*283;\n }\n }\n\n encKey[i] = encKey[i-keyLen] ^ tmp;\n }\n\n // schedule decryption keys\n for (j = 0; i; j++, i--) {\n tmp = encKey[j&3 ? i : i - 4];\n if (i<=4 || j<4) {\n decKey[j] = tmp;\n } else {\n decKey[j] = decTable[0][sbox[tmp>>>24 ]] ^\n decTable[1][sbox[tmp>>16 & 255]] ^\n decTable[2][sbox[tmp>>8 & 255]] ^\n decTable[3][sbox[tmp & 255]];\n }\n }\n }\n\n /**\n * Expand the S-box tables.\n *\n * @private\n */\n _precompute() {\n var encTable = this._tables[0], decTable = this._tables[1],\n sbox = encTable[4], sboxInv = decTable[4],\n i, x, xInv, d=[], th=[], x2, x4, x8, s, tEnc, tDec;\n\n // Compute double and third tables\n for (i = 0; i < 256; i++) {\n th[( d[i] = i<<1 ^ (i>>7)*283 )^i]=i;\n }\n\n for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) {\n // Compute sbox\n s = xInv ^ xInv<<1 ^ xInv<<2 ^ xInv<<3 ^ xInv<<4;\n s = s>>8 ^ s&255 ^ 99;\n sbox[x] = s;\n sboxInv[s] = x;\n\n // Compute MixColumns\n x8 = d[x4 = d[x2 = d[x]]];\n tDec = x8*0x1010101 ^ x4*0x10001 ^ x2*0x101 ^ x*0x1010100;\n tEnc = d[s]*0x101 ^ s*0x1010100;\n\n for (i = 0; i < 4; i++) {\n encTable[i][x] = tEnc = tEnc<<24 ^ tEnc>>>8;\n decTable[i][s] = tDec = tDec<<24 ^ tDec>>>8;\n }\n }\n\n // Compactify. Considerable speedup on Firefox.\n for (i = 0; i < 5; i++) {\n encTable[i] = encTable[i].slice(0);\n decTable[i] = decTable[i].slice(0);\n }\n }\n\n /**\n * Decrypt 16 bytes, specified as four 32-bit words.\n * @param encrypted0 {number} the first word to decrypt\n * @param encrypted1 {number} the second word to decrypt\n * @param encrypted2 {number} the third word to decrypt\n * @param encrypted3 {number} the fourth word to decrypt\n * @param out {Int32Array} the array to write the decrypted words\n * into\n * @param offset {number} the offset into the output array to start\n * writing results\n * @return {Array} The plaintext.\n */\n decrypt(encrypted0, encrypted1, encrypted2, encrypted3, out, offset) {\n var key = this._key[1],\n // state variables a,b,c,d are loaded with pre-whitened data\n a = encrypted0 ^ key[0],\n b = encrypted3 ^ key[1],\n c = encrypted2 ^ key[2],\n d = encrypted1 ^ key[3],\n a2, b2, c2,\n\n nInnerRounds = key.length / 4 - 2, // key.length === 2 ?\n i,\n kIndex = 4,\n table = this._tables[1],\n\n // load up the tables\n table0 = table[0],\n table1 = table[1],\n table2 = table[2],\n table3 = table[3],\n sbox = table[4];\n\n // Inner rounds. Cribbed from OpenSSL.\n for (i = 0; i < nInnerRounds; i++) {\n a2 = table0[a>>>24] ^ table1[b>>16 & 255] ^ table2[c>>8 & 255] ^ table3[d & 255] ^ key[kIndex];\n b2 = table0[b>>>24] ^ table1[c>>16 & 255] ^ table2[d>>8 & 255] ^ table3[a & 255] ^ key[kIndex + 1];\n c2 = table0[c>>>24] ^ table1[d>>16 & 255] ^ table2[a>>8 & 255] ^ table3[b & 255] ^ key[kIndex + 2];\n d = table0[d>>>24] ^ table1[a>>16 & 255] ^ table2[b>>8 & 255] ^ table3[c & 255] ^ key[kIndex + 3];\n kIndex += 4;\n a=a2; b=b2; c=c2;\n }\n\n // Last round.\n for (i = 0; i < 4; i++) {\n out[(3 & -i) + offset] =\n sbox[a>>>24 ]<<24 ^\n sbox[b>>16 & 255]<<16 ^\n sbox[c>>8 & 255]<<8 ^\n sbox[d & 255] ^\n key[kIndex++];\n a2=a; a=b; b=c; c=d; d=a2;\n }\n }\n}\n\nexport default AES;\n", - "/*\n *\n * This file contains an adaptation of the AES decryption algorithm\n * from the Standford Javascript Cryptography Library. That work is\n * covered by the following copyright and permissions notice:\n *\n * Copyright 2009-2010 Emily Stark, Mike Hamburg, Dan Boneh.\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following\n * disclaimer in the documentation and/or other materials provided\n * with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\n * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\n * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN\n * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n * The views and conclusions contained in the software and documentation\n * are those of the authors and should not be interpreted as representing\n * official policies, either expressed or implied, of the authors.\n */\n\nimport AES from './aes';\n\nclass AES128Decrypter {\n\n constructor(key, initVector) {\n this.key = key;\n this.iv = initVector;\n }\n\n /**\n * Convert network-order (big-endian) bytes into their little-endian\n * representation.\n */\n ntoh(word) {\n return (word << 24) |\n ((word & 0xff00) << 8) |\n ((word & 0xff0000) >> 8) |\n (word >>> 24);\n }\n\n\n /**\n * Decrypt bytes using AES-128 with CBC and PKCS#7 padding.\n * @param encrypted {Uint8Array} the encrypted bytes\n * @param key {Uint32Array} the bytes of the decryption key\n * @param initVector {Uint32Array} the initialization vector (IV) to\n * use for the first round of CBC.\n * @return {Uint8Array} the decrypted bytes\n *\n * @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard\n * @see http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29\n * @see https://tools.ietf.org/html/rfc2315\n */\n doDecrypt(encrypted, key, initVector) {\n var\n // word-level access to the encrypted bytes\n encrypted32 = new Int32Array(encrypted.buffer, encrypted.byteOffset, encrypted.byteLength >> 2),\n\n decipher = new AES(Array.prototype.slice.call(key)),\n\n // byte and word-level access for the decrypted output\n decrypted = new Uint8Array(encrypted.byteLength),\n decrypted32 = new Int32Array(decrypted.buffer),\n\n // temporary variables for working with the IV, encrypted, and\n // decrypted data\n init0, init1, init2, init3,\n encrypted0, encrypted1, encrypted2, encrypted3,\n\n // iteration variable\n wordIx;\n\n // pull out the words of the IV to ensure we don't modify the\n // passed-in reference and easier access\n init0 = ~~initVector[0];\n init1 = ~~initVector[1];\n init2 = ~~initVector[2];\n init3 = ~~initVector[3];\n\n // decrypt four word sequences, applying cipher-block chaining (CBC)\n // to each decrypted block\n for (wordIx = 0; wordIx < encrypted32.length; wordIx += 4) {\n // convert big-endian (network order) words into little-endian\n // (javascript order)\n encrypted0 = ~~this.ntoh(encrypted32[wordIx]);\n encrypted1 = ~~this.ntoh(encrypted32[wordIx + 1]);\n encrypted2 = ~~this.ntoh(encrypted32[wordIx + 2]);\n encrypted3 = ~~this.ntoh(encrypted32[wordIx + 3]);\n\n // decrypt the block\n decipher.decrypt(encrypted0,\n encrypted1,\n encrypted2,\n encrypted3,\n decrypted32,\n wordIx);\n\n // XOR with the IV, and restore network byte-order to obtain the\n // plaintext\n decrypted32[wordIx] = this.ntoh(decrypted32[wordIx] ^ init0);\n decrypted32[wordIx + 1] = this.ntoh(decrypted32[wordIx + 1] ^ init1);\n decrypted32[wordIx + 2] = this.ntoh(decrypted32[wordIx + 2] ^ init2);\n decrypted32[wordIx + 3] = this.ntoh(decrypted32[wordIx + 3] ^ init3);\n\n // setup the IV for the next round\n init0 = encrypted0;\n init1 = encrypted1;\n init2 = encrypted2;\n init3 = encrypted3;\n }\n\n return decrypted;\n }\n\n localDecrypt(encrypted, key, initVector, decrypted) {\n var bytes = this.doDecrypt(encrypted,\n key,\n initVector);\n decrypted.set(bytes, encrypted.byteOffset);\n }\n\n decrypt(encrypted) {\n var\n step = 4 * 8000,\n //encrypted32 = new Int32Array(encrypted.buffer),\n encrypted32 = new Int32Array(encrypted),\n decrypted = new Uint8Array(encrypted.byteLength),\n i = 0;\n\n // split up the encryption job and do the individual chunks asynchronously\n var key = this.key;\n var initVector = this.iv;\n this.localDecrypt(encrypted32.subarray(i, i + step), key, initVector, decrypted);\n\n for (i = step; i < encrypted32.length; i += step) {\n initVector = new Uint32Array([\n this.ntoh(encrypted32[i - 4]),\n this.ntoh(encrypted32[i - 3]),\n this.ntoh(encrypted32[i - 2]),\n this.ntoh(encrypted32[i - 1])\n ]);\n this.localDecrypt(encrypted32.subarray(i, i + step), key, initVector, decrypted);\n }\n\n return decrypted;\n }\n}\n\nexport default AES128Decrypter;\n", - "/*\n * AES128 decryption.\n */\n\nimport AES128Decrypter from './aes128-decrypter';\nimport {ErrorTypes, ErrorDetails} from '../errors';\nimport {logger} from '../utils/logger';\n\nclass Decrypter {\n\n constructor(hls) {\n this.hls = hls;\n try {\n const browserCrypto = window ? window.crypto : crypto;\n this.subtle = browserCrypto.subtle || browserCrypto.webkitSubtle;\n this.disableWebCrypto = !this.subtle;\n } catch (e) {\n this.disableWebCrypto = true;\n }\n }\n\n destroy() {\n }\n\n decrypt(data, key, iv, callback) {\n if (this.disableWebCrypto && this.hls.config.enableSoftwareAES) {\n this.decryptBySoftware(data, key, iv, callback);\n } else {\n this.decryptByWebCrypto(data, key, iv, callback);\n }\n }\n\n decryptByWebCrypto(data, key, iv, callback) {\n logger.log('decrypting by WebCrypto API');\n\n this.subtle.importKey('raw', key, { name : 'AES-CBC', length : 128 }, false, ['decrypt']).\n then((importedKey) => {\n this.subtle.decrypt({ name : 'AES-CBC', iv : iv.buffer }, importedKey, data).\n then(callback).\n catch ((err) => {\n this.onWebCryptoError(err, data, key, iv, callback);\n });\n }).\n catch ((err) => {\n this.onWebCryptoError(err, data, key, iv, callback);\n });\n }\n\n decryptBySoftware(data, key8, iv8, callback) {\n logger.log('decrypting by JavaScript Implementation');\n\n var view = new DataView(key8.buffer);\n var key = new Uint32Array([\n view.getUint32(0),\n view.getUint32(4),\n view.getUint32(8),\n view.getUint32(12)\n ]);\n\n view = new DataView(iv8.buffer);\n var iv = new Uint32Array([\n view.getUint32(0),\n view.getUint32(4),\n view.getUint32(8),\n view.getUint32(12)\n ]);\n\n var decrypter = new AES128Decrypter(key, iv);\n callback(decrypter.decrypt(data).buffer);\n }\n\n onWebCryptoError(err, data, key, iv, callback) {\n if (this.hls.config.enableSoftwareAES) {\n logger.log('disabling to use WebCrypto API');\n this.disableWebCrypto = true;\n this.decryptBySoftware(data, key, iv, callback);\n }\n else {\n logger.error(`decrypting error : ${err.message}`);\n this.hls.trigger(Event.ERROR, {type : ErrorTypes.MEDIA_ERROR, details : ErrorDetails.FRAG_DECRYPT_ERROR, fatal : true, reason : err.message});\n }\n }\n\n}\n\nexport default Decrypter;\n", - "/**\n * AAC demuxer\n */\nimport ADTS from './adts';\nimport {logger} from '../utils/logger';\nimport ID3 from '../demux/id3';\n\n class AACDemuxer {\n\n constructor(observer,remuxerClass) {\n this.observer = observer;\n this.remuxerClass = remuxerClass;\n this.remuxer = new this.remuxerClass(observer);\n this._aacTrack = {container : 'audio/adts', type: 'audio', id :-1, sequenceNumber: 0, samples : [], len : 0};\n }\n\n static probe(data) {\n // check if data contains ID3 timestamp and ADTS sync worc\n var id3 = new ID3(data), offset,len;\n if(id3.hasTimeStamp) {\n // look for ADTS header (0xFFFx)\n for (offset = id3.length, len = data.length; offset < len - 1; offset++) {\n if ((data[offset] === 0xff) && (data[offset+1] & 0xf0) === 0xf0) {\n //logger.log('ADTS sync word found !');\n return true;\n }\n }\n }\n return false;\n }\n\n\n // feed incoming data to the front of the parsing pipeline\n push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) {\n var track = this._aacTrack,\n id3 = new ID3(data),\n pts = 90*id3.timeStamp,\n config, frameLength, frameDuration, frameIndex, offset, headerLength, stamp, len, aacSample;\n // look for ADTS header (0xFFFx)\n for (offset = id3.length, len = data.length; offset < len - 1; offset++) {\n if ((data[offset] === 0xff) && (data[offset+1] & 0xf0) === 0xf0) {\n break;\n }\n }\n\n if (!track.audiosamplerate) {\n config = ADTS.getAudioConfig(this.observer,data, offset, audioCodec);\n track.config = config.config;\n track.audiosamplerate = config.samplerate;\n track.channelCount = config.channelCount;\n track.codec = config.codec;\n track.duration = duration;\n logger.log(`parsed codec:${track.codec},rate:${config.samplerate},nb channel:${config.channelCount}`);\n }\n frameIndex = 0;\n frameDuration = 1024 * 90000 / track.audiosamplerate;\n while ((offset + 5) < len) {\n // The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header\n headerLength = (!!(data[offset + 1] & 0x01) ? 7 : 9);\n // retrieve frame size\n frameLength = ((data[offset + 3] & 0x03) << 11) |\n (data[offset + 4] << 3) |\n ((data[offset + 5] & 0xE0) >>> 5);\n frameLength -= headerLength;\n //stamp = pes.pts;\n\n if ((frameLength > 0) && ((offset + headerLength + frameLength) <= len)) {\n stamp = pts + frameIndex * frameDuration;\n //logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}/${(stamp/90).toFixed(0)}`);\n aacSample = {unit: data.subarray(offset + headerLength, offset + headerLength + frameLength), pts: stamp, dts: stamp};\n track.samples.push(aacSample);\n track.len += frameLength;\n offset += frameLength + headerLength;\n frameIndex++;\n // look for ADTS header (0xFFFx)\n for ( ; offset < (len - 1); offset++) {\n if ((data[offset] === 0xff) && ((data[offset + 1] & 0xf0) === 0xf0)) {\n break;\n }\n }\n } else {\n break;\n }\n }\n this.remuxer.remux(this._aacTrack,{samples : []}, {samples : [ { pts: pts, dts : pts, unit : id3.payload} ]}, { samples: [] }, timeOffset);\n }\n\n destroy() {\n }\n\n}\n\nexport default AACDemuxer;\n", - "/**\n * ADTS parser helper\n */\nimport {logger} from '../utils/logger';\nimport {ErrorTypes, ErrorDetails} from '../errors';\n\n class ADTS {\n\n static getAudioConfig(observer, data, offset, audioCodec) {\n var adtsObjectType, // :int\n adtsSampleingIndex, // :int\n adtsExtensionSampleingIndex, // :int\n adtsChanelConfig, // :int\n config,\n userAgent = navigator.userAgent.toLowerCase(),\n adtsSampleingRates = [\n 96000, 88200,\n 64000, 48000,\n 44100, 32000,\n 24000, 22050,\n 16000, 12000,\n 11025, 8000,\n 7350];\n // byte 2\n adtsObjectType = ((data[offset + 2] & 0xC0) >>> 6) + 1;\n adtsSampleingIndex = ((data[offset + 2] & 0x3C) >>> 2);\n if(adtsSampleingIndex > adtsSampleingRates.length-1) {\n observer.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_PARSING_ERROR, fatal: true, reason: `invalid ADTS sampling index:${adtsSampleingIndex}`});\n return;\n }\n adtsChanelConfig = ((data[offset + 2] & 0x01) << 2);\n // byte 3\n adtsChanelConfig |= ((data[offset + 3] & 0xC0) >>> 6);\n logger.log(`manifest codec:${audioCodec},ADTS data:type:${adtsObjectType},sampleingIndex:${adtsSampleingIndex}[${adtsSampleingRates[adtsSampleingIndex]}Hz],channelConfig:${adtsChanelConfig}`);\n // firefox: freq less than 24kHz = AAC SBR (HE-AAC)\n if (userAgent.indexOf('firefox') !== -1) {\n if (adtsSampleingIndex >= 6) {\n adtsObjectType = 5;\n config = new Array(4);\n // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies\n // there is a factor 2 between frame sample rate and output sample rate\n // multiply frequency by 2 (see table below, equivalent to substract 3)\n adtsExtensionSampleingIndex = adtsSampleingIndex - 3;\n } else {\n adtsObjectType = 2;\n config = new Array(2);\n adtsExtensionSampleingIndex = adtsSampleingIndex;\n }\n // Android : always use AAC\n } else if (userAgent.indexOf('android') !== -1) {\n adtsObjectType = 2;\n config = new Array(2);\n adtsExtensionSampleingIndex = adtsSampleingIndex;\n } else {\n /* for other browsers (chrome ...)\n always force audio type to be HE-AAC SBR, as some browsers do not support audio codec switch properly (like Chrome ...)\n */\n adtsObjectType = 5;\n config = new Array(4);\n // if (manifest codec is HE-AAC or HE-AACv2) OR (manifest codec not specified AND frequency less than 24kHz)\n if ((audioCodec && ((audioCodec.indexOf('mp4a.40.29') !== -1) ||\n (audioCodec.indexOf('mp4a.40.5') !== -1))) ||\n (!audioCodec && adtsSampleingIndex >= 6)) {\n // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies\n // there is a factor 2 between frame sample rate and output sample rate\n // multiply frequency by 2 (see table below, equivalent to substract 3)\n adtsExtensionSampleingIndex = adtsSampleingIndex - 3;\n } else {\n // if (manifest codec is AAC) AND (frequency less than 24kHz AND nb channel is 1) OR (manifest codec not specified and mono audio)\n // Chrome fails to play back with low frequency AAC LC mono when initialized with HE-AAC. This is not a problem with stereo.\n if (audioCodec && audioCodec.indexOf('mp4a.40.2') !== -1 && (adtsSampleingIndex >= 6 && adtsChanelConfig === 1) ||\n (!audioCodec && adtsChanelConfig === 1)) {\n adtsObjectType = 2;\n config = new Array(2);\n }\n adtsExtensionSampleingIndex = adtsSampleingIndex;\n }\n }\n /* refer to http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Audio_Specific_Config\n ISO 14496-3 (AAC).pdf - Table 1.13 — Syntax of AudioSpecificConfig()\n Audio Profile / Audio Object Type\n 0: Null\n 1: AAC Main\n 2: AAC LC (Low Complexity)\n 3: AAC SSR (Scalable Sample Rate)\n 4: AAC LTP (Long Term Prediction)\n 5: SBR (Spectral Band Replication)\n 6: AAC Scalable\n sampling freq\n 0: 96000 Hz\n 1: 88200 Hz\n 2: 64000 Hz\n 3: 48000 Hz\n 4: 44100 Hz\n 5: 32000 Hz\n 6: 24000 Hz\n 7: 22050 Hz\n 8: 16000 Hz\n 9: 12000 Hz\n 10: 11025 Hz\n 11: 8000 Hz\n 12: 7350 Hz\n 13: Reserved\n 14: Reserved\n 15: frequency is written explictly\n Channel Configurations\n These are the channel configurations:\n 0: Defined in AOT Specifc Config\n 1: 1 channel: front-center\n 2: 2 channels: front-left, front-right\n */\n // audioObjectType = profile => profile, the MPEG-4 Audio Object Type minus 1\n config[0] = adtsObjectType << 3;\n // samplingFrequencyIndex\n config[0] |= (adtsSampleingIndex & 0x0E) >> 1;\n config[1] |= (adtsSampleingIndex & 0x01) << 7;\n // channelConfiguration\n config[1] |= adtsChanelConfig << 3;\n if (adtsObjectType === 5) {\n // adtsExtensionSampleingIndex\n config[1] |= (adtsExtensionSampleingIndex & 0x0E) >> 1;\n config[2] = (adtsExtensionSampleingIndex & 0x01) << 7;\n // adtsObjectType (force to 2, chrome is checking that object type is less than 5 ???\n // https://chromium.googlesource.com/chromium/src.git/+/master/media/formats/mp4/aac.cc\n config[2] |= 2 << 2;\n config[3] = 0;\n }\n return {config: config, samplerate: adtsSampleingRates[adtsSampleingIndex], channelCount: adtsChanelConfig, codec: ('mp4a.40.' + adtsObjectType)};\n }\n}\n\nexport default ADTS;\n", - "/* inline demuxer.\n * probe fragments and instantiate appropriate demuxer depending on content type (TSDemuxer, AACDemuxer, ...)\n */\n\nimport Event from '../events';\nimport {ErrorTypes, ErrorDetails} from '../errors';\nimport AACDemuxer from '../demux/aacdemuxer';\nimport TSDemuxer from '../demux/tsdemuxer';\nimport MP4Remuxer from '../remux/mp4-remuxer';\nimport PassThroughRemuxer from '../remux/passthrough-remuxer';\n\nclass DemuxerInline {\n\n constructor(hls,typeSupported) {\n this.hls = hls;\n this.typeSupported = typeSupported;\n }\n\n destroy() {\n var demuxer = this.demuxer;\n if (demuxer) {\n demuxer.destroy();\n }\n }\n\n push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) {\n var demuxer = this.demuxer;\n if (!demuxer) {\n var hls = this.hls;\n // probe for content type\n if (TSDemuxer.probe(data)) {\n if (this.typeSupported.mp2t === true) {\n demuxer = new TSDemuxer(hls,PassThroughRemuxer);\n } else {\n demuxer = new TSDemuxer(hls,MP4Remuxer);\n }\n } else if(AACDemuxer.probe(data)) {\n demuxer = new AACDemuxer(hls,MP4Remuxer);\n } else {\n hls.trigger(Event.ERROR, {type : ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_PARSING_ERROR, fatal: true, reason: 'no demux matching with content found'});\n return;\n }\n this.demuxer = demuxer;\n }\n demuxer.push(data,audioCodec,videoCodec,timeOffset,cc,level,sn,duration);\n }\n}\n\nexport default DemuxerInline;\n", - "/* demuxer web worker.\n * - listen to worker message, and trigger DemuxerInline upon reception of Fragments.\n * - provides MP4 Boxes back to main thread using [transferable objects](https://developers.google.com/web/updates/2011/12/Transferable-Objects-Lightning-Fast) in order to minimize message passing overhead.\n */\n\n import DemuxerInline from '../demux/demuxer-inline';\n import Event from '../events';\n import EventEmitter from 'events';\n\nvar DemuxerWorker = function (self) {\n // observer setup\n var observer = new EventEmitter();\n observer.trigger = function trigger (event, ...data) {\n observer.emit(event, event, ...data);\n };\n\n observer.off = function off (event, ...data) {\n observer.removeListener(event, ...data);\n };\n self.addEventListener('message', function (ev) {\n var data = ev.data;\n //console.log('demuxer cmd:' + data.cmd);\n switch (data.cmd) {\n case 'init':\n self.demuxer = new DemuxerInline(observer, data.typeSupported);\n break;\n case 'demux':\n self.demuxer.push(new Uint8Array(data.data), data.audioCodec, data.videoCodec, data.timeOffset, data.cc, data.level, data.sn, data.duration);\n break;\n default:\n break;\n }\n });\n\n // listen to events triggered by Demuxer\n observer.on(Event.FRAG_PARSING_INIT_SEGMENT, function(ev, data) {\n self.postMessage({event: ev, tracks : data.tracks, unique : data.unique });\n });\n\n observer.on(Event.FRAG_PARSING_DATA, function(ev, data) {\n var objData = {event: ev, type: data.type, startPTS: data.startPTS, endPTS: data.endPTS, startDTS: data.startDTS, endDTS: data.endDTS, data1: data.data1.buffer, data2: data.data2.buffer, nb: data.nb, dropped : data.dropped};\n // pass data1/data2 as transferable object (no copy)\n self.postMessage(objData, [objData.data1, objData.data2]);\n });\n\n observer.on(Event.FRAG_PARSED, function(event) {\n self.postMessage({event: event});\n });\n\n observer.on(Event.ERROR, function(event, data) {\n self.postMessage({event: event, data: data});\n });\n\n observer.on(Event.FRAG_PARSING_METADATA, function(event, data) {\n var objData = {event: event, samples: data.samples};\n self.postMessage(objData);\n });\n\n observer.on(Event.FRAG_PARSING_USERDATA, function(event, data) {\n var objData = {event: event, samples: data.samples};\n self.postMessage(objData);\n });\n\n};\n\nexport default DemuxerWorker;\n\n", - "import Event from '../events';\nimport DemuxerInline from '../demux/demuxer-inline';\nimport DemuxerWorker from '../demux/demuxer-worker';\nimport {logger} from '../utils/logger';\nimport Decrypter from '../crypt/decrypter';\n\nclass Demuxer {\n\n constructor(hls) {\n this.hls = hls;\n var typeSupported = {\n mp4 : MediaSource.isTypeSupported('video/mp4'),\n mp2t : hls.config.enableMP2TPassThrough && MediaSource.isTypeSupported('video/mp2t')\n };\n if (hls.config.enableWorker && (typeof(Worker) !== 'undefined')) {\n logger.log('demuxing in webworker');\n try {\n var work = require('webworkify');\n this.w = work(DemuxerWorker);\n this.onwmsg = this.onWorkerMessage.bind(this);\n this.w.addEventListener('message', this.onwmsg);\n this.w.postMessage({cmd: 'init', typeSupported : typeSupported});\n } catch(err) {\n logger.error('error while initializing DemuxerWorker, fallback on DemuxerInline');\n this.demuxer = new DemuxerInline(hls,typeSupported);\n }\n } else {\n this.demuxer = new DemuxerInline(hls,typeSupported);\n }\n this.demuxInitialized = true;\n }\n\n destroy() {\n if (this.w) {\n this.w.removeEventListener('message', this.onwmsg);\n this.w.terminate();\n this.w = null;\n } else {\n this.demuxer.destroy();\n this.demuxer = null;\n }\n if (this.decrypter) {\n this.decrypter.destroy();\n this.decrypter = null;\n }\n }\n\n pushDecrypted(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) {\n if (this.w) {\n // post fragment payload as transferable objects (no copy)\n this.w.postMessage({cmd: 'demux', data: data, audioCodec: audioCodec, videoCodec: videoCodec, timeOffset: timeOffset, cc: cc, level: level, sn : sn, duration: duration}, [data]);\n } else {\n this.demuxer.push(new Uint8Array(data), audioCodec, videoCodec, timeOffset, cc, level, sn, duration);\n }\n }\n\n push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration, decryptdata) {\n if ((data.byteLength > 0) && (decryptdata != null) && (decryptdata.key != null) && (decryptdata.method === 'AES-128')) {\n if (this.decrypter == null) {\n this.decrypter = new Decrypter(this.hls);\n }\n\n var localthis = this;\n this.decrypter.decrypt(data, decryptdata.key, decryptdata.iv, function(decryptedData){\n localthis.pushDecrypted(decryptedData, audioCodec, videoCodec, timeOffset, cc, level, sn, duration);\n });\n } else {\n this.pushDecrypted(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration);\n }\n }\n\n onWorkerMessage(ev) {\n var data = ev.data;\n //console.log('onWorkerMessage:' + data.event);\n switch(data.event) {\n case Event.FRAG_PARSING_INIT_SEGMENT:\n var obj = {};\n obj.tracks = data.tracks;\n obj.unique = data.unique;\n this.hls.trigger(Event.FRAG_PARSING_INIT_SEGMENT, obj);\n break;\n case Event.FRAG_PARSING_DATA:\n this.hls.trigger(Event.FRAG_PARSING_DATA,{\n data1: new Uint8Array(data.data1),\n data2: new Uint8Array(data.data2),\n startPTS: data.startPTS,\n endPTS: data.endPTS,\n startDTS: data.startDTS,\n endDTS: data.endDTS,\n type: data.type,\n nb: data.nb,\n dropped: data.dropped,\n });\n break;\n case Event.FRAG_PARSING_METADATA:\n this.hls.trigger(Event.FRAG_PARSING_METADATA, {\n samples: data.samples\n });\n break;\n case Event.FRAG_PARSING_USERDATA:\n this.hls.trigger(Event.FRAG_PARSING_USERDATA, {\n samples: data.samples\n });\n break;\n default:\n this.hls.trigger(data.event, data.data);\n break;\n }\n }\n}\n\nexport default Demuxer;\n\n", - "/**\n * Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264.\n*/\n\nimport {logger} from '../utils/logger';\n\nclass ExpGolomb {\n\n constructor(data) {\n this.data = data;\n // the number of bytes left to examine in this.data\n this.bytesAvailable = this.data.byteLength;\n // the current word being examined\n this.word = 0; // :uint\n // the number of bits left to examine in the current word\n this.bitsAvailable = 0; // :uint\n }\n\n // ():void\n loadWord() {\n var\n position = this.data.byteLength - this.bytesAvailable,\n workingBytes = new Uint8Array(4),\n availableBytes = Math.min(4, this.bytesAvailable);\n if (availableBytes === 0) {\n throw new Error('no bytes available');\n }\n workingBytes.set(this.data.subarray(position, position + availableBytes));\n this.word = new DataView(workingBytes.buffer).getUint32(0);\n // track the amount of this.data that has been processed\n this.bitsAvailable = availableBytes * 8;\n this.bytesAvailable -= availableBytes;\n }\n\n // (count:int):void\n skipBits(count) {\n var skipBytes; // :int\n if (this.bitsAvailable > count) {\n this.word <<= count;\n this.bitsAvailable -= count;\n } else {\n count -= this.bitsAvailable;\n skipBytes = count >> 3;\n count -= (skipBytes >> 3);\n this.bytesAvailable -= skipBytes;\n this.loadWord();\n this.word <<= count;\n this.bitsAvailable -= count;\n }\n }\n\n // (size:int):uint\n readBits(size) {\n var\n bits = Math.min(this.bitsAvailable, size), // :uint\n valu = this.word >>> (32 - bits); // :uint\n if (size > 32) {\n logger.error('Cannot read more than 32 bits at a time');\n }\n this.bitsAvailable -= bits;\n if (this.bitsAvailable > 0) {\n this.word <<= bits;\n } else if (this.bytesAvailable > 0) {\n this.loadWord();\n }\n bits = size - bits;\n if (bits > 0) {\n return valu << bits | this.readBits(bits);\n } else {\n return valu;\n }\n }\n\n // ():uint\n skipLZ() {\n var leadingZeroCount; // :uint\n for (leadingZeroCount = 0; leadingZeroCount < this.bitsAvailable; ++leadingZeroCount) {\n if (0 !== (this.word & (0x80000000 >>> leadingZeroCount))) {\n // the first bit of working word is 1\n this.word <<= leadingZeroCount;\n this.bitsAvailable -= leadingZeroCount;\n return leadingZeroCount;\n }\n }\n // we exhausted word and still have not found a 1\n this.loadWord();\n return leadingZeroCount + this.skipLZ();\n }\n\n // ():void\n skipUEG() {\n this.skipBits(1 + this.skipLZ());\n }\n\n // ():void\n skipEG() {\n this.skipBits(1 + this.skipLZ());\n }\n\n // ():uint\n readUEG() {\n var clz = this.skipLZ(); // :uint\n return this.readBits(clz + 1) - 1;\n }\n\n // ():int\n readEG() {\n var valu = this.readUEG(); // :int\n if (0x01 & valu) {\n // the number is odd if the low order bit is set\n return (1 + valu) >>> 1; // add 1 to make it even, and divide by 2\n } else {\n return -1 * (valu >>> 1); // divide by two then make it negative\n }\n }\n\n // Some convenience functions\n // :Boolean\n readBoolean() {\n return 1 === this.readBits(1);\n }\n\n // ():int\n readUByte() {\n return this.readBits(8);\n }\n\n // ():int\n readUShort() {\n return this.readBits(16);\n }\n // ():int\n readUInt() {\n return this.readBits(32);\n }\n\n /**\n * Advance the ExpGolomb decoder past a scaling list. The scaling\n * list is optionally transmitted as part of a sequence parameter\n * set and is not relevant to transmuxing.\n * @param count {number} the number of entries in this scaling list\n * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1\n */\n skipScalingList(count) {\n var\n lastScale = 8,\n nextScale = 8,\n j,\n deltaScale;\n for (j = 0; j < count; j++) {\n if (nextScale !== 0) {\n deltaScale = this.readEG();\n nextScale = (lastScale + deltaScale + 256) % 256;\n }\n lastScale = (nextScale === 0) ? lastScale : nextScale;\n }\n }\n\n /**\n * Read a sequence parameter set and return some interesting video\n * properties. A sequence parameter set is the H264 metadata that\n * describes the properties of upcoming video frames.\n * @param data {Uint8Array} the bytes of a sequence parameter set\n * @return {object} an object with configuration parsed from the\n * sequence parameter set, including the dimensions of the\n * associated video frames.\n */\n readSPS() {\n var\n frameCropLeftOffset = 0,\n frameCropRightOffset = 0,\n frameCropTopOffset = 0,\n frameCropBottomOffset = 0,\n sarScale = 1,\n profileIdc,profileCompat,levelIdc,\n numRefFramesInPicOrderCntCycle, picWidthInMbsMinus1,\n picHeightInMapUnitsMinus1,\n frameMbsOnlyFlag,\n scalingListCount,\n i;\n this.readUByte();\n profileIdc = this.readUByte(); // profile_idc\n profileCompat = this.readBits(5); // constraint_set[0-4]_flag, u(5)\n this.skipBits(3); // reserved_zero_3bits u(3),\n levelIdc = this.readUByte(); //level_idc u(8)\n this.skipUEG(); // seq_parameter_set_id\n // some profiles have more optional data we don't need\n if (profileIdc === 100 ||\n profileIdc === 110 ||\n profileIdc === 122 ||\n profileIdc === 244 ||\n profileIdc === 44 ||\n profileIdc === 83 ||\n profileIdc === 86 ||\n profileIdc === 118 ||\n profileIdc === 128) {\n var chromaFormatIdc = this.readUEG();\n if (chromaFormatIdc === 3) {\n this.skipBits(1); // separate_colour_plane_flag\n }\n this.skipUEG(); // bit_depth_luma_minus8\n this.skipUEG(); // bit_depth_chroma_minus8\n this.skipBits(1); // qpprime_y_zero_transform_bypass_flag\n if (this.readBoolean()) { // seq_scaling_matrix_present_flag\n scalingListCount = (chromaFormatIdc !== 3) ? 8 : 12;\n for (i = 0; i < scalingListCount; i++) {\n if (this.readBoolean()) { // seq_scaling_list_present_flag[ i ]\n if (i < 6) {\n this.skipScalingList(16);\n } else {\n this.skipScalingList(64);\n }\n }\n }\n }\n }\n this.skipUEG(); // log2_max_frame_num_minus4\n var picOrderCntType = this.readUEG();\n if (picOrderCntType === 0) {\n this.readUEG(); //log2_max_pic_order_cnt_lsb_minus4\n } else if (picOrderCntType === 1) {\n this.skipBits(1); // delta_pic_order_always_zero_flag\n this.skipEG(); // offset_for_non_ref_pic\n this.skipEG(); // offset_for_top_to_bottom_field\n numRefFramesInPicOrderCntCycle = this.readUEG();\n for(i = 0; i < numRefFramesInPicOrderCntCycle; i++) {\n this.skipEG(); // offset_for_ref_frame[ i ]\n }\n }\n this.skipUEG(); // max_num_ref_frames\n this.skipBits(1); // gaps_in_frame_num_value_allowed_flag\n picWidthInMbsMinus1 = this.readUEG();\n picHeightInMapUnitsMinus1 = this.readUEG();\n frameMbsOnlyFlag = this.readBits(1);\n if (frameMbsOnlyFlag === 0) {\n this.skipBits(1); // mb_adaptive_frame_field_flag\n }\n this.skipBits(1); // direct_8x8_inference_flag\n if (this.readBoolean()) { // frame_cropping_flag\n frameCropLeftOffset = this.readUEG();\n frameCropRightOffset = this.readUEG();\n frameCropTopOffset = this.readUEG();\n frameCropBottomOffset = this.readUEG();\n }\n if (this.readBoolean()) {\n // vui_parameters_present_flag\n if (this.readBoolean()) {\n // aspect_ratio_info_present_flag\n let sarRatio;\n const aspectRatioIdc = this.readUByte();\n switch (aspectRatioIdc) {\n case 1: sarRatio = [1,1]; break;\n case 2: sarRatio = [12,11]; break;\n case 3: sarRatio = [10,11]; break;\n case 4: sarRatio = [16,11]; break;\n case 5: sarRatio = [40,33]; break;\n case 6: sarRatio = [24,11]; break;\n case 7: sarRatio = [20,11]; break;\n case 8: sarRatio = [32,11]; break;\n case 9: sarRatio = [80,33]; break;\n case 10: sarRatio = [18,11]; break;\n case 11: sarRatio = [15,11]; break;\n case 12: sarRatio = [64,33]; break;\n case 13: sarRatio = [160,99]; break;\n case 14: sarRatio = [4,3]; break;\n case 15: sarRatio = [3,2]; break;\n case 16: sarRatio = [2,1]; break;\n case 255: {\n sarRatio = [this.readUByte() << 8 | this.readUByte(), this.readUByte() << 8 | this.readUByte()];\n break;\n }\n }\n if (sarRatio) {\n sarScale = sarRatio[0] / sarRatio[1];\n }\n }\n }\n return {\n width: Math.ceil((((picWidthInMbsMinus1 + 1) * 16) - frameCropLeftOffset * 2 - frameCropRightOffset * 2) * sarScale),\n height: ((2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16) - ((frameMbsOnlyFlag? 2 : 4) * (frameCropTopOffset + frameCropBottomOffset))\n };\n }\n\n readSliceType() {\n // skip NALu type\n this.readUByte();\n // discard first_mb_in_slice\n this.readUEG();\n // return slice_type\n return this.readUEG();\n }\n}\n\nexport default ExpGolomb;\n", - "/**\n * ID3 parser\n */\nimport {logger} from '../utils/logger';\n//import Hex from '../utils/hex';\n\n class ID3 {\n\n constructor(data) {\n this._hasTimeStamp = false;\n var offset = 0, byte1,byte2,byte3,byte4,tagSize,endPos,header,len;\n do {\n header = this.readUTF(data,offset,3);\n offset+=3;\n // first check for ID3 header\n if (header === 'ID3') {\n // skip 24 bits\n offset += 3;\n // retrieve tag(s) length\n byte1 = data[offset++] & 0x7f;\n byte2 = data[offset++] & 0x7f;\n byte3 = data[offset++] & 0x7f;\n byte4 = data[offset++] & 0x7f;\n tagSize = (byte1 << 21) + (byte2 << 14) + (byte3 << 7) + byte4;\n endPos = offset + tagSize;\n //logger.log(`ID3 tag found, size/end: ${tagSize}/${endPos}`);\n\n // read ID3 tags\n this._parseID3Frames(data, offset,endPos);\n offset = endPos;\n } else if (header === '3DI') {\n // http://id3.org/id3v2.4.0-structure chapter 3.4. ID3v2 footer\n offset += 7;\n logger.log(`3DI footer found, end: ${offset}`);\n } else {\n offset -= 3;\n len = offset;\n if (len) {\n //logger.log(`ID3 len: ${len}`);\n if (!this.hasTimeStamp) {\n logger.warn('ID3 tag found, but no timestamp');\n }\n this._length = len;\n this._payload = data.subarray(0,len);\n }\n return;\n }\n } while (true);\n }\n\n readUTF(data,start,len) {\n\n var result = '',offset = start, end = start + len;\n do {\n result += String.fromCharCode(data[offset++]);\n } while(offset < end);\n return result;\n }\n\n _parseID3Frames(data,offset,endPos) {\n var tagId,tagLen,tagStart,tagFlags,timestamp;\n while(offset + 8 <= endPos) {\n tagId = this.readUTF(data,offset,4);\n offset +=4;\n\n tagLen = data[offset++] << 24 +\n data[offset++] << 16 +\n data[offset++] << 8 +\n data[offset++];\n\n tagFlags = data[offset++] << 8 +\n data[offset++];\n\n tagStart = offset;\n //logger.log(\"ID3 tag id:\" + tagId);\n switch(tagId) {\n case 'PRIV':\n //logger.log('parse frame:' + Hex.hexDump(data.subarray(offset,endPos)));\n // owner should be \"com.apple.streaming.transportStreamTimestamp\"\n if (this.readUTF(data,offset,44) === 'com.apple.streaming.transportStreamTimestamp') {\n offset+=44;\n // smelling even better ! we found the right descriptor\n // skip null character (string end) + 3 first bytes\n offset+= 4;\n\n // timestamp is 33 bit expressed as a big-endian eight-octet number, with the upper 31 bits set to zero.\n var pts33Bit = data[offset++] & 0x1;\n this._hasTimeStamp = true;\n\n timestamp = ((data[offset++] << 23) +\n (data[offset++] << 15) +\n (data[offset++] << 7) +\n data[offset++]) /45;\n\n if (pts33Bit) {\n timestamp += 47721858.84; // 2^32 / 90\n }\n timestamp = Math.round(timestamp);\n logger.trace(`ID3 timestamp found: ${timestamp}`);\n this._timeStamp = timestamp;\n }\n break;\n default:\n break;\n }\n }\n }\n\n get hasTimeStamp() {\n return this._hasTimeStamp;\n }\n\n get timeStamp() {\n return this._timeStamp;\n }\n\n get length() {\n return this._length;\n }\n\n get payload() {\n return this._payload;\n }\n\n}\n\nexport default ID3;\n\n", - "/**\n * highly optimized TS demuxer:\n * parse PAT, PMT\n * extract PES packet from audio and video PIDs\n * extract AVC/H264 NAL units and AAC/ADTS samples from PES packet\n * trigger the remuxer upon parsing completion\n * it also tries to workaround as best as it can audio codec switch (HE-AAC to AAC and vice versa), without having to restart the MediaSource.\n * it also controls the remuxing process :\n * upon discontinuity or level switch detection, it will also notifies the remuxer so that it can reset its state.\n*/\n\n import ADTS from './adts';\n import Event from '../events';\n import ExpGolomb from './exp-golomb';\n// import Hex from '../utils/hex';\n import {logger} from '../utils/logger';\n import {ErrorTypes, ErrorDetails} from '../errors';\n\n class TSDemuxer {\n\n constructor(observer,remuxerClass) {\n this.observer = observer;\n this.remuxerClass = remuxerClass;\n this.lastCC = 0;\n this.remuxer = new this.remuxerClass(observer);\n }\n\n static probe(data) {\n // a TS fragment should contain at least 3 TS packets, a PAT, a PMT, and one PID, each starting with 0x47\n if (data.length >= 3*188 && data[0] === 0x47 && data[188] === 0x47 && data[2*188] === 0x47) {\n return true;\n } else {\n return false;\n }\n }\n\n switchLevel() {\n this.pmtParsed = false;\n this._pmtId = -1;\n this._avcTrack = {container : 'video/mp2t', type: 'video', id :-1, sequenceNumber: 0, samples : [], len : 0, nbNalu : 0, dropped : 0};\n this._aacTrack = {container : 'video/mp2t', type: 'audio', id :-1, sequenceNumber: 0, samples : [], len : 0};\n this._id3Track = {type: 'id3', id :-1, sequenceNumber: 0, samples : [], len : 0};\n this._txtTrack = {type: 'text', id: -1, sequenceNumber: 0, samples: [], len: 0};\n // flush any partial content\n this.aacOverFlow = null;\n this.aacLastPTS = null;\n this.avcNaluState = 0;\n this.remuxer.switchLevel();\n }\n\n insertDiscontinuity() {\n this.switchLevel();\n this.remuxer.insertDiscontinuity();\n }\n\n // feed incoming data to the front of the parsing pipeline\n push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) {\n var avcData, aacData, id3Data,\n start, len = data.length, stt, pid, atf, offset,\n codecsOnly = this.remuxer.passthrough,\n unknownPIDs = false;\n\n this.audioCodec = audioCodec;\n this.videoCodec = videoCodec;\n this.timeOffset = timeOffset;\n this._duration = duration;\n this.contiguous = false;\n if (cc !== this.lastCC) {\n logger.log('discontinuity detected');\n this.insertDiscontinuity();\n this.lastCC = cc;\n }\n if (level !== this.lastLevel) {\n logger.log('level switch detected');\n this.switchLevel();\n this.lastLevel = level;\n } else if (sn === (this.lastSN+1)) {\n this.contiguous = true;\n }\n this.lastSN = sn;\n\n var pmtParsed = this.pmtParsed,\n avcId = this._avcTrack.id,\n aacId = this._aacTrack.id,\n id3Id = this._id3Track.id;\n\n // don't parse last TS packet if incomplete\n len -= len % 188;\n // loop through TS packets\n for (start = 0; start < len; start += 188) {\n if (data[start] === 0x47) {\n stt = !!(data[start + 1] & 0x40);\n // pid is a 13-bit field starting at the last bit of TS[1]\n pid = ((data[start + 1] & 0x1f) << 8) + data[start + 2];\n atf = (data[start + 3] & 0x30) >> 4;\n // if an adaption field is present, its length is specified by the fifth byte of the TS packet header.\n if (atf > 1) {\n offset = start + 5 + data[start + 4];\n // continue if there is only adaptation field\n if (offset === (start + 188)) {\n continue;\n }\n } else {\n offset = start + 4;\n }\n if (pmtParsed) {\n if (pid === avcId) {\n if (stt) {\n if (avcData) {\n this._parseAVCPES(this._parsePES(avcData));\n if (codecsOnly) {\n // if we have video codec info AND\n // if audio PID is undefined OR if we have audio codec info,\n // we have all codec info !\n if (this._avcTrack.codec && (aacId === -1 || this._aacTrack.codec)) {\n this.remux(data);\n return;\n }\n }\n }\n avcData = {data: [], size: 0};\n }\n if (avcData) {\n avcData.data.push(data.subarray(offset, start + 188));\n avcData.size += start + 188 - offset;\n }\n } else if (pid === aacId) {\n if (stt) {\n if (aacData) {\n this._parseAACPES(this._parsePES(aacData));\n if (codecsOnly) {\n // here we now that we have audio codec info\n // if video PID is undefined OR if we have video codec info,\n // we have all codec infos !\n if (this._aacTrack.codec && (avcId === -1 || this._avcTrack.codec)) {\n this.remux(data);\n return;\n }\n }\n }\n aacData = {data: [], size: 0};\n }\n if (aacData) {\n aacData.data.push(data.subarray(offset, start + 188));\n aacData.size += start + 188 - offset;\n }\n } else if (pid === id3Id) {\n if (stt) {\n if (id3Data) {\n this._parseID3PES(this._parsePES(id3Data));\n }\n id3Data = {data: [], size: 0};\n }\n if (id3Data) {\n id3Data.data.push(data.subarray(offset, start + 188));\n id3Data.size += start + 188 - offset;\n }\n }\n } else {\n if (stt) {\n offset += data[offset] + 1;\n }\n if (pid === 0) {\n this._parsePAT(data, offset);\n } else if (pid === this._pmtId) {\n this._parsePMT(data, offset);\n pmtParsed = this.pmtParsed = true;\n avcId = this._avcTrack.id;\n aacId = this._aacTrack.id;\n id3Id = this._id3Track.id;\n if (unknownPIDs) {\n logger.log('reparse from beginning');\n unknownPIDs = false;\n // we set it to -188, the += 188 in the for loop will reset start to 0\n start = -188;\n }\n } else {\n logger.log('unknown PID found before PAT/PMT');\n unknownPIDs = true;\n }\n }\n } else {\n this.observer.trigger(Event.ERROR, {type : ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_PARSING_ERROR, fatal: false, reason: 'TS packet did not start with 0x47'});\n }\n }\n // parse last PES packet\n if (avcData) {\n this._parseAVCPES(this._parsePES(avcData));\n }\n if (aacData) {\n this._parseAACPES(this._parsePES(aacData));\n }\n if (id3Data) {\n this._parseID3PES(this._parsePES(id3Data));\n }\n this.remux(null);\n }\n\n remux(data) {\n this.remuxer.remux(this._aacTrack, this._avcTrack, this._id3Track, this._txtTrack, this.timeOffset, this.contiguous, data);\n }\n\n destroy() {\n this.switchLevel();\n this._initPTS = this._initDTS = undefined;\n this._duration = 0;\n }\n\n _parsePAT(data, offset) {\n // skip the PSI header and parse the first PMT entry\n this._pmtId = (data[offset + 10] & 0x1F) << 8 | data[offset + 11];\n //logger.log('PMT PID:' + this._pmtId);\n }\n\n _parsePMT(data, offset) {\n var sectionLength, tableEnd, programInfoLength, pid;\n sectionLength = (data[offset + 1] & 0x0f) << 8 | data[offset + 2];\n tableEnd = offset + 3 + sectionLength - 4;\n // to determine where the table is, we have to figure out how\n // long the program info descriptors are\n programInfoLength = (data[offset + 10] & 0x0f) << 8 | data[offset + 11];\n // advance the offset to the first entry in the mapping table\n offset += 12 + programInfoLength;\n while (offset < tableEnd) {\n pid = (data[offset + 1] & 0x1F) << 8 | data[offset + 2];\n switch(data[offset]) {\n // ISO/IEC 13818-7 ADTS AAC (MPEG-2 lower bit-rate audio)\n case 0x0f:\n //logger.log('AAC PID:' + pid);\n this._aacTrack.id = pid;\n break;\n // Packetized metadata (ID3)\n case 0x15:\n //logger.log('ID3 PID:' + pid);\n this._id3Track.id = pid;\n break;\n // ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video)\n case 0x1b:\n //logger.log('AVC PID:' + pid);\n this._avcTrack.id = pid;\n break;\n default:\n logger.log('unkown stream type:' + data[offset]);\n break;\n }\n // move to the next table entry\n // skip past the elementary stream descriptors, if present\n offset += ((data[offset + 3] & 0x0F) << 8 | data[offset + 4]) + 5;\n }\n }\n\n _parsePES(stream) {\n var i = 0, frag, pesFlags, pesPrefix, pesLen, pesHdrLen, pesData, pesPts, pesDts, payloadStartOffset, data = stream.data;\n //retrieve PTS/DTS from first fragment\n frag = data[0];\n pesPrefix = (frag[0] << 16) + (frag[1] << 8) + frag[2];\n if (pesPrefix === 1) {\n pesLen = (frag[4] << 8) + frag[5];\n pesFlags = frag[7];\n if (pesFlags & 0xC0) {\n /* PES header described here : http://dvd.sourceforge.net/dvdinfo/pes-hdr.html\n as PTS / DTS is 33 bit we cannot use bitwise operator in JS,\n as Bitwise operators treat their operands as a sequence of 32 bits */\n pesPts = (frag[9] & 0x0E) * 536870912 +// 1 << 29\n (frag[10] & 0xFF) * 4194304 +// 1 << 22\n (frag[11] & 0xFE) * 16384 +// 1 << 14\n (frag[12] & 0xFF) * 128 +// 1 << 7\n (frag[13] & 0xFE) / 2;\n // check if greater than 2^32 -1\n if (pesPts > 4294967295) {\n // decrement 2^33\n pesPts -= 8589934592;\n }\n if (pesFlags & 0x40) {\n pesDts = (frag[14] & 0x0E ) * 536870912 +// 1 << 29\n (frag[15] & 0xFF ) * 4194304 +// 1 << 22\n (frag[16] & 0xFE ) * 16384 +// 1 << 14\n (frag[17] & 0xFF ) * 128 +// 1 << 7\n (frag[18] & 0xFE ) / 2;\n // check if greater than 2^32 -1\n if (pesDts > 4294967295) {\n // decrement 2^33\n pesDts -= 8589934592;\n }\n } else {\n pesDts = pesPts;\n }\n }\n pesHdrLen = frag[8];\n payloadStartOffset = pesHdrLen + 9;\n\n stream.size -= payloadStartOffset;\n //reassemble PES packet\n pesData = new Uint8Array(stream.size);\n while (data.length) {\n frag = data.shift();\n var len = frag.byteLength;\n if (payloadStartOffset) {\n if (payloadStartOffset > len) {\n // trim full frag if PES header bigger than frag\n payloadStartOffset-=len;\n continue;\n } else {\n // trim partial frag if PES header smaller than frag\n frag = frag.subarray(payloadStartOffset);\n len-=payloadStartOffset;\n payloadStartOffset = 0;\n }\n }\n pesData.set(frag, i);\n i+=len;\n }\n return {data: pesData, pts: pesPts, dts: pesDts, len: pesLen};\n } else {\n return null;\n }\n }\n\n _parseAVCPES(pes) {\n var track = this._avcTrack,\n samples = track.samples,\n units = this._parseAVCNALu(pes.data),\n units2 = [],\n debug = false,\n key = false,\n length = 0,\n expGolombDecoder,\n avcSample,\n push,\n i;\n // no NALu found\n if (units.length === 0 && samples.length > 0) {\n // append pes.data to previous NAL unit\n var lastavcSample = samples[samples.length - 1];\n var lastUnit = lastavcSample.units.units[lastavcSample.units.units.length - 1];\n var tmp = new Uint8Array(lastUnit.data.byteLength + pes.data.byteLength);\n tmp.set(lastUnit.data, 0);\n tmp.set(pes.data, lastUnit.data.byteLength);\n lastUnit.data = tmp;\n lastavcSample.units.length += pes.data.byteLength;\n track.len += pes.data.byteLength;\n }\n //free pes.data to save up some memory\n pes.data = null;\n var debugString = '';\n\n var pushAccesUnit = function() {\n if (units2.length) {\n // only push AVC sample if keyframe already found in this fragment OR\n // keyframe found in last fragment (track.sps) AND\n // samples already appended (we already found a keyframe in this fragment) OR fragment is contiguous\n if (key === true ||\n (track.sps && (samples.length || this.contiguous))) {\n avcSample = {units: { units : units2, length : length}, pts: pes.pts, dts: pes.dts, key: key};\n samples.push(avcSample);\n track.len += length;\n track.nbNalu += units2.length;\n } else {\n // dropped samples, track it\n track.dropped++;\n }\n units2 = [];\n length = 0;\n }\n }.bind(this);\n\n units.forEach(unit => {\n switch(unit.type) {\n //NDR\n case 1:\n push = true;\n if(debug) {\n debugString += 'NDR ';\n }\n break;\n //IDR\n case 5:\n push = true;\n if(debug) {\n debugString += 'IDR ';\n }\n key = true;\n break;\n //SEI\n case 6:\n push = true;\n if(debug) {\n debugString += 'SEI ';\n }\n expGolombDecoder = new ExpGolomb(unit.data);\n\n // skip frameType\n expGolombDecoder.readUByte();\n\n var payloadType = expGolombDecoder.readUByte();\n\n // TODO: there can be more than one payload in an SEI packet...\n // TODO: need to read type and size in a while loop to get them all\n if (payloadType === 4)\n {\n var payloadSize = 0;\n\n do {\n payloadSize = expGolombDecoder.readUByte();\n }\n while (payloadSize === 255);\n\n var countryCode = expGolombDecoder.readUByte();\n\n if (countryCode === 181)\n {\n var providerCode = expGolombDecoder.readUShort();\n\n if (providerCode === 49)\n {\n var userStructure = expGolombDecoder.readUInt();\n\n if (userStructure === 0x47413934)\n {\n var userDataType = expGolombDecoder.readUByte();\n\n // Raw CEA-608 bytes wrapped in CEA-708 packet\n if (userDataType === 3)\n {\n var firstByte = expGolombDecoder.readUByte();\n var secondByte = expGolombDecoder.readUByte();\n\n var totalCCs = 31 & firstByte;\n var byteArray = [firstByte, secondByte];\n\n for (i=0; i this is the first start code found in this PES packet\n // first check if start code delimiter is overlapping between 2 PES packets,\n // ie it started in last packet (lastState not zero)\n // and ended at the beginning of this PES packet (i <= 4 - lastState)\n let lastState = this.avcNaluState;\n if(lastState && (i <= 4 - lastState)) {\n // start delimiter overlapping between PES packets\n // strip start delimiter bytes from the end of last NAL unit\n let track = this._avcTrack,\n samples = track.samples;\n if (samples.length) {\n let lastavcSample = samples[samples.length - 1],\n lastUnits = lastavcSample.units.units,\n lastUnit = lastUnits[lastUnits.length - 1];\n // check if lastUnit had a state different from zero\n if (lastUnit.state) {\n // strip last bytes\n lastUnit.data = lastUnit.data.subarray(0,lastUnit.data.byteLength - lastState);\n lastavcSample.units.length -= lastState;\n track.len -= lastState;\n }\n }\n }\n // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit.\n overflow = i - state - 1;\n if (overflow > 0) {\n let track = this._avcTrack,\n samples = track.samples;\n //logger.log('first NALU found with overflow:' + overflow);\n if (samples.length) {\n let lastavcSample = samples[samples.length - 1],\n lastUnits = lastavcSample.units.units,\n lastUnit = lastUnits[lastUnits.length - 1],\n tmp = new Uint8Array(lastUnit.data.byteLength + overflow);\n tmp.set(lastUnit.data, 0);\n tmp.set(array.subarray(0, overflow), lastUnit.data.byteLength);\n lastUnit.data = tmp;\n lastavcSample.units.length += overflow;\n track.len += overflow;\n }\n }\n }\n lastUnitStart = i;\n lastUnitType = unitType;\n state = 0;\n } else {\n state = 0;\n }\n break;\n default:\n break;\n }\n }\n if (lastUnitStart) {\n unit = {data: array.subarray(lastUnitStart, len), type: lastUnitType, state : state};\n units.push(unit);\n //logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state);\n this.avcNaluState = state;\n }\n return units;\n }\n\n _parseAACPES(pes) {\n var track = this._aacTrack,\n data = pes.data,\n pts = pes.pts,\n startOffset = 0,\n duration = this._duration,\n audioCodec = this.audioCodec,\n aacOverFlow = this.aacOverFlow,\n aacLastPTS = this.aacLastPTS,\n config, frameLength, frameDuration, frameIndex, offset, headerLength, stamp, len, aacSample;\n if (aacOverFlow) {\n var tmp = new Uint8Array(aacOverFlow.byteLength + data.byteLength);\n tmp.set(aacOverFlow, 0);\n tmp.set(data, aacOverFlow.byteLength);\n //logger.log(`AAC: append overflowing ${aacOverFlow.byteLength} bytes to beginning of new PES`);\n data = tmp;\n }\n // look for ADTS header (0xFFFx)\n for (offset = startOffset, len = data.length; offset < len - 1; offset++) {\n if ((data[offset] === 0xff) && (data[offset+1] & 0xf0) === 0xf0) {\n break;\n }\n }\n // if ADTS header does not start straight from the beginning of the PES payload, raise an error\n if (offset) {\n var reason, fatal;\n if (offset < len - 1) {\n reason = `AAC PES did not start with ADTS header,offset:${offset}`;\n fatal = false;\n } else {\n reason = 'no ADTS header found in AAC PES';\n fatal = true;\n }\n this.observer.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_PARSING_ERROR, fatal: fatal, reason: reason});\n if (fatal) {\n return;\n }\n }\n if (!track.audiosamplerate) {\n config = ADTS.getAudioConfig(this.observer,data, offset, audioCodec);\n track.config = config.config;\n track.audiosamplerate = config.samplerate;\n track.channelCount = config.channelCount;\n track.codec = config.codec;\n track.duration = duration;\n logger.log(`parsed codec:${track.codec},rate:${config.samplerate},nb channel:${config.channelCount}`);\n }\n frameIndex = 0;\n frameDuration = 1024 * 90000 / track.audiosamplerate;\n\n // if last AAC frame is overflowing, we should ensure timestamps are contiguous:\n // first sample PTS should be equal to last sample PTS + frameDuration\n if(aacOverFlow && aacLastPTS) {\n var newPTS = aacLastPTS+frameDuration;\n if(Math.abs(newPTS-pts) > 1) {\n logger.log(`AAC: align PTS for overlapping frames by ${Math.round((newPTS-pts)/90)}`);\n pts=newPTS;\n }\n }\n\n while ((offset + 5) < len) {\n // The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header\n headerLength = (!!(data[offset + 1] & 0x01) ? 7 : 9);\n // retrieve frame size\n frameLength = ((data[offset + 3] & 0x03) << 11) |\n (data[offset + 4] << 3) |\n ((data[offset + 5] & 0xE0) >>> 5);\n frameLength -= headerLength;\n //stamp = pes.pts;\n\n if ((frameLength > 0) && ((offset + headerLength + frameLength) <= len)) {\n stamp = pts + frameIndex * frameDuration;\n //logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}/${(stamp/90).toFixed(0)}`);\n aacSample = {unit: data.subarray(offset + headerLength, offset + headerLength + frameLength), pts: stamp, dts: stamp};\n track.samples.push(aacSample);\n track.len += frameLength;\n offset += frameLength + headerLength;\n frameIndex++;\n // look for ADTS header (0xFFFx)\n for ( ; offset < (len - 1); offset++) {\n if ((data[offset] === 0xff) && ((data[offset + 1] & 0xf0) === 0xf0)) {\n break;\n }\n }\n } else {\n break;\n }\n }\n if (offset < len) {\n aacOverFlow = data.subarray(offset, len);\n //logger.log(`AAC: overflow detected:${len-offset}`);\n } else {\n aacOverFlow = null;\n }\n this.aacOverFlow = aacOverFlow;\n this.aacLastPTS = stamp;\n }\n\n _parseID3PES(pes) {\n this._id3Track.samples.push(pes);\n }\n}\n\nexport default TSDemuxer;\n\n", - "export const ErrorTypes = {\n // Identifier for a network error (loading error / timeout ...)\n NETWORK_ERROR: 'networkError',\n // Identifier for a media Error (video/parsing/mediasource error)\n MEDIA_ERROR: 'mediaError',\n // Identifier for all other errors\n OTHER_ERROR: 'otherError'\n};\n\nexport const ErrorDetails = {\n // Identifier for a manifest load error - data: { url : faulty URL, response : XHR response}\n MANIFEST_LOAD_ERROR: 'manifestLoadError',\n // Identifier for a manifest load timeout - data: { url : faulty URL, response : XHR response}\n MANIFEST_LOAD_TIMEOUT: 'manifestLoadTimeOut',\n // Identifier for a manifest parsing error - data: { url : faulty URL, reason : error reason}\n MANIFEST_PARSING_ERROR: 'manifestParsingError',\n // Identifier for a manifest with only incompatible codecs error - data: { url : faulty URL, reason : error reason}\n MANIFEST_INCOMPATIBLE_CODECS_ERROR: 'manifestIncompatibleCodecsError',\n // Identifier for playlist load error - data: { url : faulty URL, response : XHR response}\n LEVEL_LOAD_ERROR: 'levelLoadError',\n // Identifier for playlist load timeout - data: { url : faulty URL, response : XHR response}\n LEVEL_LOAD_TIMEOUT: 'levelLoadTimeOut',\n // Identifier for a level switch error - data: { level : faulty level Id, event : error description}\n LEVEL_SWITCH_ERROR: 'levelSwitchError',\n // Identifier for fragment load error - data: { frag : fragment object, response : XHR response}\n FRAG_LOAD_ERROR: 'fragLoadError',\n // Identifier for fragment loop loading error - data: { frag : fragment object}\n FRAG_LOOP_LOADING_ERROR: 'fragLoopLoadingError',\n // Identifier for fragment load timeout error - data: { frag : fragment object}\n FRAG_LOAD_TIMEOUT: 'fragLoadTimeOut',\n // Identifier for a fragment decryption error event - data: parsing error description\n FRAG_DECRYPT_ERROR: 'fragDecryptError',\n // Identifier for a fragment parsing error event - data: parsing error description\n FRAG_PARSING_ERROR: 'fragParsingError',\n // Identifier for decrypt key load error - data: { frag : fragment object, response : XHR response}\n KEY_LOAD_ERROR: 'keyLoadError',\n // Identifier for decrypt key load timeout error - data: { frag : fragment object}\n KEY_LOAD_TIMEOUT: 'keyLoadTimeOut',\n // Identifier for a buffer append error - data: append error description\n BUFFER_APPEND_ERROR: 'bufferAppendError',\n // Identifier for a buffer appending error event - data: appending error description\n BUFFER_APPENDING_ERROR: 'bufferAppendingError',\n // Identifier for a buffer stalled error event\n BUFFER_STALLED_ERROR: 'bufferStalledError',\n // Identifier for a buffer full event\n BUFFER_FULL_ERROR: 'bufferFullError',\n // Identifier for a buffer seek over hole event\n BUFFER_SEEK_OVER_HOLE: 'bufferSeekOverHole',\n // Identifier for an internal exception happening inside hls.js while handling an event\n INTERNAL_EXCEPTION: 'internalException'\n};\n", - "/*\n*\n* All objects in the event handling chain should inherit from this class\n*\n*/\n\nimport {logger} from './utils/logger';\nimport {ErrorTypes, ErrorDetails} from './errors';\nimport Event from './events';\n\nclass EventHandler {\n\n constructor(hls, ...events) {\n this.hls = hls;\n this.onEvent = this.onEvent.bind(this);\n this.handledEvents = events;\n this.useGenericHandler = true;\n\n this.registerListeners();\n }\n\n destroy() {\n this.unregisterListeners();\n }\n\n isEventHandler() {\n return typeof this.handledEvents === 'object' && this.handledEvents.length && typeof this.onEvent === 'function';\n }\n\n registerListeners() {\n if (this.isEventHandler()) {\n this.handledEvents.forEach(function(event) {\n if (event === 'hlsEventGeneric') {\n throw new Error('Forbidden event name: ' + event);\n }\n this.hls.on(event, this.onEvent);\n }.bind(this));\n }\n }\n\n unregisterListeners() {\n if (this.isEventHandler()) {\n this.handledEvents.forEach(function(event) {\n this.hls.off(event, this.onEvent);\n }.bind(this));\n }\n }\n\n /*\n * arguments: event (string), data (any)\n */\n onEvent(event, data) {\n this.onEventGeneric(event, data);\n }\n\n onEventGeneric(event, data) {\n var eventToFunction = function(event, data) {\n var funcName = 'on' + event.replace('hls', '');\n if (typeof this[funcName] !== 'function') {\n throw new Error(`Event ${event} has no generic handler in this ${this.constructor.name} class (tried ${funcName})`);\n }\n return this[funcName].bind(this, data);\n };\n try {\n eventToFunction.call(this, event, data).call();\n } catch (err) {\n logger.error(`internal error happened while processing ${event}:${err.message}`);\n this.hls.trigger(Event.ERROR, {type: ErrorTypes.OTHER_ERROR, details: ErrorDetails.INTERNAL_EXCEPTION, fatal: false, event : event, err : err});\n }\n }\n}\n\nexport default EventHandler;\n", - "module.exports = {\n // fired before MediaSource is attaching to media element - data: { media }\n MEDIA_ATTACHING: 'hlsMediaAttaching',\n // fired when MediaSource has been succesfully attached to media element - data: { }\n MEDIA_ATTACHED: 'hlsMediaAttached',\n // fired before detaching MediaSource from media element - data: { }\n MEDIA_DETACHING: 'hlsMediaDetaching',\n // fired when MediaSource has been detached from media element - data: { }\n MEDIA_DETACHED: 'hlsMediaDetached',\n // fired when we buffer is going to be resetted\n BUFFER_RESET: 'hlsBufferReset',\n // fired when we know about the codecs that we need buffers for to push into - data: {tracks : { container, codec, levelCodec, initSegment, metadata }}\n BUFFER_CODECS: 'hlsBufferCodecs',\n // fired when we append a segment to the buffer - data: { segment: segment object }\n BUFFER_APPENDING: 'hlsBufferAppending',\n // fired when we are done with appending a media segment to the buffer\n BUFFER_APPENDED: 'hlsBufferAppended',\n // fired when the stream is finished and we want to notify the media buffer that there will be no more data\n BUFFER_EOS: 'hlsBufferEos',\n // fired when the media buffer should be flushed - data {startOffset, endOffset}\n BUFFER_FLUSHING: 'hlsBufferFlushing',\n // fired when the media has been flushed\n BUFFER_FLUSHED: 'hlsBufferFlushed',\n // fired to signal that a manifest loading starts - data: { url : manifestURL}\n MANIFEST_LOADING: 'hlsManifestLoading',\n // fired after manifest has been loaded - data: { levels : [available quality levels] , url : manifestURL, stats : { trequest, tfirst, tload, mtime}}\n MANIFEST_LOADED: 'hlsManifestLoaded',\n // fired after manifest has been parsed - data: { levels : [available quality levels] , firstLevel : index of first quality level appearing in Manifest}\n MANIFEST_PARSED: 'hlsManifestParsed',\n // fired when a level playlist loading starts - data: { url : level URL level : id of level being loaded}\n LEVEL_LOADING: 'hlsLevelLoading',\n // fired when a level playlist loading finishes - data: { details : levelDetails object, level : id of loaded level, stats : { trequest, tfirst, tload, mtime} }\n LEVEL_LOADED: 'hlsLevelLoaded',\n // fired when a level's details have been updated based on previous details, after it has been loaded. - data: { details : levelDetails object, level : id of updated level }\n LEVEL_UPDATED: 'hlsLevelUpdated',\n // fired when a level's PTS information has been updated after parsing a fragment - data: { details : levelDetails object, level : id of updated level, drift: PTS drift observed when parsing last fragment }\n LEVEL_PTS_UPDATED: 'hlsLevelPtsUpdated',\n // fired when a level switch is requested - data: { level : id of new level }\n LEVEL_SWITCH: 'hlsLevelSwitch',\n // fired when a fragment loading starts - data: { frag : fragment object}\n FRAG_LOADING: 'hlsFragLoading',\n // fired when a fragment loading is progressing - data: { frag : fragment object, { trequest, tfirst, loaded}}\n FRAG_LOAD_PROGRESS: 'hlsFragLoadProgress',\n // Identifier for fragment load aborting for emergency switch down - data: {frag : fragment object}\n FRAG_LOAD_EMERGENCY_ABORTED: 'hlsFragLoadEmergencyAborted',\n // fired when a fragment loading is completed - data: { frag : fragment object, payload : fragment payload, stats : { trequest, tfirst, tload, length}}\n FRAG_LOADED: 'hlsFragLoaded',\n // fired when Init Segment has been extracted from fragment - data: { moov : moov MP4 box, codecs : codecs found while parsing fragment}\n FRAG_PARSING_INIT_SEGMENT: 'hlsFragParsingInitSegment',\n // fired when parsing sei text is completed - data: { samples : [ sei samples pes ] }\n FRAG_PARSING_USERDATA: 'hlsFragParsingUserdata',\n // fired when parsing id3 is completed - data: { samples : [ id3 samples pes ] }\n FRAG_PARSING_METADATA: 'hlsFragParsingMetadata',\n // fired when data have been extracted from fragment - data: { data1 : moof MP4 box or TS fragments, data2 : mdat MP4 box or null}\n FRAG_PARSING_DATA: 'hlsFragParsingData',\n // fired when fragment parsing is completed - data: undefined\n FRAG_PARSED: 'hlsFragParsed',\n // fired when fragment remuxed MP4 boxes have all been appended into SourceBuffer - data: { frag : fragment object, stats : { trequest, tfirst, tload, tparsed, tbuffered, length} }\n FRAG_BUFFERED: 'hlsFragBuffered',\n // fired when fragment matching with current media position is changing - data : { frag : fragment object }\n FRAG_CHANGED: 'hlsFragChanged',\n // Identifier for a FPS drop event - data: {curentDropped, currentDecoded, totalDroppedFrames}\n FPS_DROP: 'hlsFpsDrop',\n // Identifier for an error event - data: { type : error type, details : error details, fatal : if true, hls.js cannot/will not try to recover, if false, hls.js will try to recover,other error specific data}\n ERROR: 'hlsError',\n // fired when hls.js instance starts destroying. Different from MEDIA_DETACHED as one could want to detach and reattach a media to the instance of hls.js to handle mid-rolls for example\n DESTROYING: 'hlsDestroying',\n // fired when a decrypt key loading starts - data: { frag : fragment object}\n KEY_LOADING: 'hlsKeyLoading',\n // fired when a decrypt key loading is completed - data: { frag : fragment object, payload : key payload, stats : { trequest, tfirst, tload, length}}\n KEY_LOADED: 'hlsKeyLoaded',\n};\n", - "/**\n * Buffer Helper class, providing methods dealing buffer length retrieval\n*/\n\n\nclass BufferHelper {\n\n static bufferInfo(media, pos,maxHoleDuration) {\n if (media) {\n var vbuffered = media.buffered, buffered = [],i;\n for (i = 0; i < vbuffered.length; i++) {\n buffered.push({start: vbuffered.start(i), end: vbuffered.end(i)});\n }\n return this.bufferedInfo(buffered,pos,maxHoleDuration);\n } else {\n return {len: 0, start: 0, end: 0, nextStart : undefined} ;\n }\n }\n\n static bufferedInfo(buffered,pos,maxHoleDuration) {\n var buffered2 = [],\n // bufferStart and bufferEnd are buffer boundaries around current video position\n bufferLen,bufferStart, bufferEnd,bufferStartNext,i;\n // sort on buffer.start/smaller end (IE does not always return sorted buffered range)\n buffered.sort(function (a, b) {\n var diff = a.start - b.start;\n if (diff) {\n return diff;\n } else {\n return b.end - a.end;\n }\n });\n // there might be some small holes between buffer time range\n // consider that holes smaller than maxHoleDuration are irrelevant and build another\n // buffer time range representations that discards those holes\n for (i = 0; i < buffered.length; i++) {\n var buf2len = buffered2.length;\n if(buf2len) {\n var buf2end = buffered2[buf2len - 1].end;\n // if small hole (value between 0 or maxHoleDuration ) or overlapping (negative)\n if((buffered[i].start - buf2end) < maxHoleDuration) {\n // merge overlapping time ranges\n // update lastRange.end only if smaller than item.end\n // e.g. [ 1, 15] with [ 2,8] => [ 1,15] (no need to modify lastRange.end)\n // whereas [ 1, 8] with [ 2,15] => [ 1,15] ( lastRange should switch from [1,8] to [1,15])\n if(buffered[i].end > buf2end) {\n buffered2[buf2len - 1].end = buffered[i].end;\n }\n } else {\n // big hole\n buffered2.push(buffered[i]);\n }\n } else {\n // first value\n buffered2.push(buffered[i]);\n }\n }\n for (i = 0, bufferLen = 0, bufferStart = bufferEnd = pos; i < buffered2.length; i++) {\n var start = buffered2[i].start,\n end = buffered2[i].end;\n //logger.log('buf start/end:' + buffered.start(i) + '/' + buffered.end(i));\n if ((pos + maxHoleDuration) >= start && pos < end) {\n // play position is inside this buffer TimeRange, retrieve end of buffer position and buffer length\n bufferStart = start;\n bufferEnd = end;\n bufferLen = bufferEnd - pos;\n } else if ((pos + maxHoleDuration) < start) {\n bufferStartNext = start;\n break;\n }\n }\n return {len: bufferLen, start: bufferStart, end: bufferEnd, nextStart : bufferStartNext};\n }\n\n}\n\nexport default BufferHelper;\n", - "/**\n * Level Helper class, providing methods dealing with playlist sliding and drift\n*/\n\nimport {logger} from '../utils/logger';\n\nclass LevelHelper {\n\n static mergeDetails(oldDetails,newDetails) {\n var start = Math.max(oldDetails.startSN,newDetails.startSN)-newDetails.startSN,\n end = Math.min(oldDetails.endSN,newDetails.endSN)-newDetails.startSN,\n delta = newDetails.startSN - oldDetails.startSN,\n oldfragments = oldDetails.fragments,\n newfragments = newDetails.fragments,\n ccOffset =0,\n PTSFrag;\n\n // check if old/new playlists have fragments in common\n if ( end < start) {\n newDetails.PTSKnown = false;\n return;\n }\n // loop through overlapping SN and update startPTS , cc, and duration if any found\n for(var i = start ; i <= end ; i++) {\n var oldFrag = oldfragments[delta+i],\n newFrag = newfragments[i];\n ccOffset = oldFrag.cc - newFrag.cc;\n if (!isNaN(oldFrag.startPTS)) {\n newFrag.start = newFrag.startPTS = oldFrag.startPTS;\n newFrag.endPTS = oldFrag.endPTS;\n newFrag.duration = oldFrag.duration;\n PTSFrag = newFrag;\n }\n }\n\n if(ccOffset) {\n logger.log(`discontinuity sliding from playlist, take drift into account`);\n for(i = 0 ; i < newfragments.length ; i++) {\n newfragments[i].cc += ccOffset;\n }\n }\n\n // if at least one fragment contains PTS info, recompute PTS information for all fragments\n if(PTSFrag) {\n LevelHelper.updateFragPTSDTS(newDetails,PTSFrag.sn,PTSFrag.startPTS,PTSFrag.endPTS,PTSFrag.startDTS,PTSFrag.endDTS);\n } else {\n // ensure that delta is within oldfragments range\n // also adjust sliding in case delta is 0 (we could have old=[50-60] and new=old=[50-61])\n // in that case we also need to adjust start offset of all fragments\n if (delta >= 0 && delta < oldfragments.length) {\n // adjust start by sliding offset\n var sliding = oldfragments[delta].start;\n for(i = 0 ; i < newfragments.length ; i++) {\n newfragments[i].start += sliding;\n }\n }\n }\n // if we are here, it means we have fragments overlapping between\n // old and new level. reliable PTS info is thus relying on old level\n newDetails.PTSKnown = oldDetails.PTSKnown;\n return;\n }\n\n static updateFragPTSDTS(details,sn,startPTS,endPTS,startDTS,endDTS) {\n var fragIdx, fragments, frag, i;\n // exit if sn out of range\n if (sn < details.startSN || sn > details.endSN) {\n return 0;\n }\n fragIdx = sn - details.startSN;\n fragments = details.fragments;\n frag = fragments[fragIdx];\n if(!isNaN(frag.startPTS)) {\n // delta PTS between audio and video\n let deltaPTS = Math.abs(frag.startPTS-startPTS);\n if (isNaN(frag.deltaPTS)) {\n frag.deltaPTS = deltaPTS;\n } else {\n frag.deltaPTS = Math.max(deltaPTS,frag.deltaPTS);\n }\n startPTS = Math.min(startPTS,frag.startPTS);\n endPTS = Math.max(endPTS, frag.endPTS);\n startDTS = Math.min(startDTS,frag.startDTS);\n endDTS = Math.max(endDTS, frag.endDTS);\n }\n\n var drift = startPTS - frag.start;\n\n frag.start = frag.startPTS = startPTS;\n frag.endPTS = endPTS;\n frag.startDTS = startDTS;\n frag.endDTS = endDTS;\n frag.duration = endPTS - startPTS;\n // adjust fragment PTS/duration from seqnum-1 to frag 0\n for(i = fragIdx ; i > 0 ; i--) {\n LevelHelper.updatePTS(fragments,i,i-1);\n }\n\n // adjust fragment PTS/duration from seqnum to last frag\n for(i = fragIdx ; i < fragments.length - 1 ; i++) {\n LevelHelper.updatePTS(fragments,i,i+1);\n }\n details.PTSKnown = true;\n //logger.log(` frag start/end:${startPTS.toFixed(3)}/${endPTS.toFixed(3)}`);\n\n return drift;\n }\n\n static updatePTS(fragments,fromIdx, toIdx) {\n var fragFrom = fragments[fromIdx],fragTo = fragments[toIdx], fragToPTS = fragTo.startPTS;\n // if we know startPTS[toIdx]\n if(!isNaN(fragToPTS)) {\n // update fragment duration.\n // it helps to fix drifts between playlist reported duration and fragment real duration\n if (toIdx > fromIdx) {\n fragFrom.duration = fragToPTS-fragFrom.start;\n if(fragFrom.duration < 0) {\n logger.error(`negative duration computed for frag ${fragFrom.sn},level ${fragFrom.level}, there should be some duration drift between playlist and fragment!`);\n }\n } else {\n fragTo.duration = fragFrom.start - fragToPTS;\n if(fragTo.duration < 0) {\n logger.error(`negative duration computed for frag ${fragTo.sn},level ${fragTo.level}, there should be some duration drift between playlist and fragment!`);\n }\n }\n } else {\n // we dont know startPTS[toIdx]\n if (toIdx > fromIdx) {\n fragTo.start = fragFrom.start + fragFrom.duration;\n } else {\n fragTo.start = fragFrom.start - fragTo.duration;\n }\n }\n }\n}\n\nexport default LevelHelper;\n", - "/**\n * HLS interface\n */\n'use strict';\n\nimport Event from './events';\nimport {ErrorTypes, ErrorDetails} from './errors';\nimport PlaylistLoader from './loader/playlist-loader';\nimport FragmentLoader from './loader/fragment-loader';\nimport AbrController from './controller/abr-controller';\nimport BufferController from './controller/buffer-controller';\nimport CapLevelController from './controller/cap-level-controller';\nimport StreamController from './controller/stream-controller';\nimport LevelController from './controller/level-controller';\nimport TimelineController from './controller/timeline-controller';\n//import FPSController from './controller/fps-controller';\nimport {logger, enableLogs} from './utils/logger';\nimport XhrLoader from './utils/xhr-loader';\nimport EventEmitter from 'events';\nimport KeyLoader from './loader/key-loader';\n\nclass Hls {\n\n static isSupported() {\n return (window.MediaSource &&\n typeof window.MediaSource.isTypeSupported === 'function' &&\n window.MediaSource.isTypeSupported('video/mp4; codecs=\"avc1.42E01E,mp4a.40.2\"'));\n }\n\n static get Events() {\n return Event;\n }\n\n static get ErrorTypes() {\n return ErrorTypes;\n }\n\n static get ErrorDetails() {\n return ErrorDetails;\n }\n\n static get DefaultConfig() {\n if(!Hls.defaultConfig) {\n Hls.defaultConfig = {\n autoStartLoad: true,\n startPosition: -1,\n debug: false,\n capLevelToPlayerSize: false,\n maxBufferLength: 30,\n maxBufferSize: 60 * 1000 * 1000,\n maxBufferHole: 0.5,\n maxSeekHole: 2,\n seekHoleNudgeDuration : 0.01,\n stalledInBufferedNudgeThreshold: 10,\n maxFragLookUpTolerance : 0.2,\n liveSyncDurationCount:3,\n liveMaxLatencyDurationCount: Infinity,\n liveSyncDuration: undefined,\n liveMaxLatencyDuration: undefined,\n maxMaxBufferLength: 600,\n enableWorker: true,\n enableSoftwareAES: true,\n manifestLoadingTimeOut: 10000,\n manifestLoadingMaxRetry: 1,\n manifestLoadingRetryDelay: 1000,\n levelLoadingTimeOut: 10000,\n levelLoadingMaxRetry: 4,\n levelLoadingRetryDelay: 1000,\n fragLoadingTimeOut: 20000,\n fragLoadingMaxRetry: 6,\n fragLoadingRetryDelay: 1000,\n fragLoadingLoopThreshold: 3,\n startFragPrefetch : false,\n // fpsDroppedMonitoringPeriod: 5000,\n // fpsDroppedMonitoringThreshold: 0.2,\n appendErrorMaxRetry: 3,\n loader: XhrLoader,\n fLoader: undefined,\n pLoader: undefined,\n abrController : AbrController,\n bufferController : BufferController,\n capLevelController : CapLevelController,\n streamController: StreamController,\n timelineController: TimelineController,\n enableCEA708Captions: true,\n enableMP2TPassThrough : false,\n abrEwmaFastLive: 5,\n abrEwmaSlowLive: 9,\n abrEwmaFastVoD: 4,\n abrEwmaSlowVoD: 15,\n abrEwmaDefaultEstimate: 5e5, // 500 kbps\n abrBandWidthFactor : 0.8,\n abrBandWidthUpFactor : 0.7\n };\n }\n return Hls.defaultConfig;\n }\n\n static set DefaultConfig(defaultConfig) {\n Hls.defaultConfig = defaultConfig;\n }\n\n constructor(config = {}) {\n var defaultConfig = Hls.DefaultConfig;\n\n if ((config.liveSyncDurationCount || config.liveMaxLatencyDurationCount) && (config.liveSyncDuration || config.liveMaxLatencyDuration)) {\n throw new Error('Illegal hls.js config: don\\'t mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration');\n }\n\n for (var prop in defaultConfig) {\n if (prop in config) { continue; }\n config[prop] = defaultConfig[prop];\n }\n\n if (config.liveMaxLatencyDurationCount !== undefined && config.liveMaxLatencyDurationCount <= config.liveSyncDurationCount) {\n throw new Error('Illegal hls.js config: \"liveMaxLatencyDurationCount\" must be gt \"liveSyncDurationCount\"');\n }\n\n if (config.liveMaxLatencyDuration !== undefined && (config.liveMaxLatencyDuration <= config.liveSyncDuration || config.liveSyncDuration === undefined)) {\n throw new Error('Illegal hls.js config: \"liveMaxLatencyDuration\" must be gt \"liveSyncDuration\"');\n }\n\n enableLogs(config.debug);\n this.config = config;\n // observer setup\n var observer = this.observer = new EventEmitter();\n observer.trigger = function trigger (event, ...data) {\n observer.emit(event, event, ...data);\n };\n\n observer.off = function off (event, ...data) {\n observer.removeListener(event, ...data);\n };\n this.on = observer.on.bind(observer);\n this.off = observer.off.bind(observer);\n this.trigger = observer.trigger.bind(observer);\n this.playlistLoader = new PlaylistLoader(this);\n this.fragmentLoader = new FragmentLoader(this);\n this.levelController = new LevelController(this);\n this.abrController = new config.abrController(this);\n this.bufferController = new config.bufferController(this);\n this.capLevelController = new config.capLevelController(this);\n this.streamController = new config.streamController(this);\n this.timelineController = new config.timelineController(this);\n this.keyLoader = new KeyLoader(this);\n //this.fpsController = new FPSController(this);\n }\n\n destroy() {\n logger.log('destroy');\n this.trigger(Event.DESTROYING);\n this.detachMedia();\n this.playlistLoader.destroy();\n this.fragmentLoader.destroy();\n this.levelController.destroy();\n this.abrController.destroy();\n this.bufferController.destroy();\n this.capLevelController.destroy();\n this.streamController.destroy();\n this.timelineController.destroy();\n this.keyLoader.destroy();\n //this.fpsController.destroy();\n this.url = null;\n this.observer.removeAllListeners();\n }\n\n attachMedia(media) {\n logger.log('attachMedia');\n this.media = media;\n this.trigger(Event.MEDIA_ATTACHING, {media: media});\n }\n\n detachMedia() {\n logger.log('detachMedia');\n this.trigger(Event.MEDIA_DETACHING);\n this.media = null;\n }\n\n loadSource(url) {\n logger.log(`loadSource:${url}`);\n this.url = url;\n // when attaching to a source URL, trigger a playlist load\n this.trigger(Event.MANIFEST_LOADING, {url: url});\n }\n\n startLoad(startPosition=-1) {\n logger.log('startLoad');\n this.levelController.startLoad();\n this.streamController.startLoad(startPosition);\n }\n\n stopLoad() {\n logger.log('stopLoad');\n this.levelController.stopLoad();\n this.streamController.stopLoad();\n }\n\n swapAudioCodec() {\n logger.log('swapAudioCodec');\n this.streamController.swapAudioCodec();\n }\n\n recoverMediaError() {\n logger.log('recoverMediaError');\n var media = this.media;\n this.detachMedia();\n this.attachMedia(media);\n }\n\n /** Return all quality levels **/\n get levels() {\n return this.levelController.levels;\n }\n\n /** Return current playback quality level **/\n get currentLevel() {\n return this.streamController.currentLevel;\n }\n\n /* set quality level immediately (-1 for automatic level selection) */\n set currentLevel(newLevel) {\n logger.log(`set currentLevel:${newLevel}`);\n this.loadLevel = newLevel;\n this.streamController.immediateLevelSwitch();\n }\n\n /** Return next playback quality level (quality level of next fragment) **/\n get nextLevel() {\n return this.streamController.nextLevel;\n }\n\n /* set quality level for next fragment (-1 for automatic level selection) */\n set nextLevel(newLevel) {\n logger.log(`set nextLevel:${newLevel}`);\n this.levelController.manualLevel = newLevel;\n this.streamController.nextLevelSwitch();\n }\n\n /** Return the quality level of current/last loaded fragment **/\n get loadLevel() {\n return this.levelController.level;\n }\n\n /* set quality level for current/next loaded fragment (-1 for automatic level selection) */\n set loadLevel(newLevel) {\n logger.log(`set loadLevel:${newLevel}`);\n this.levelController.manualLevel = newLevel;\n }\n\n /** Return the quality level of next loaded fragment **/\n get nextLoadLevel() {\n return this.levelController.nextLoadLevel;\n }\n\n /** set quality level of next loaded fragment **/\n set nextLoadLevel(level) {\n this.levelController.nextLoadLevel = level;\n }\n\n /** Return first level (index of first level referenced in manifest)\n **/\n get firstLevel() {\n return this.levelController.firstLevel;\n }\n\n /** set first level (index of first level referenced in manifest)\n **/\n set firstLevel(newLevel) {\n logger.log(`set firstLevel:${newLevel}`);\n this.levelController.firstLevel = newLevel;\n }\n\n /** Return start level (level of first fragment that will be played back)\n if not overrided by user, first level appearing in manifest will be used as start level\n if -1 : automatic start level selection, playback will start from level matching download bandwidth (determined from download of first segment)\n **/\n get startLevel() {\n return this.levelController.startLevel;\n }\n\n /** set start level (level of first fragment that will be played back)\n if not overrided by user, first level appearing in manifest will be used as start level\n if -1 : automatic start level selection, playback will start from level matching download bandwidth (determined from download of first segment)\n **/\n set startLevel(newLevel) {\n logger.log(`set startLevel:${newLevel}`);\n this.levelController.startLevel = newLevel;\n }\n\n /** Return the capping/max level value that could be used by automatic level selection algorithm **/\n get autoLevelCapping() {\n return this.abrController.autoLevelCapping;\n }\n\n /** set the capping/max level value that could be used by automatic level selection algorithm **/\n set autoLevelCapping(newLevel) {\n logger.log(`set autoLevelCapping:${newLevel}`);\n this.abrController.autoLevelCapping = newLevel;\n }\n\n /* check if we are in automatic level selection mode */\n get autoLevelEnabled() {\n return (this.levelController.manualLevel === -1);\n }\n\n /* return manual level */\n get manualLevel() {\n return this.levelController.manualLevel;\n }\n}\n\nexport default Hls;\n", - "// This is mostly for support of the es6 module export\n// syntax with the babel compiler, it looks like it doesnt support\n// function exports like we are used to in node/commonjs\nmodule.exports = require('./hls.js').default;\n", - "/*\n * Fragment Loader\n*/\n\nimport Event from '../events';\nimport EventHandler from '../event-handler';\nimport {ErrorTypes, ErrorDetails} from '../errors';\n\nclass FragmentLoader extends EventHandler {\n\n constructor(hls) {\n super(hls, Event.FRAG_LOADING);\n }\n\n destroy() {\n if (this.loader) {\n this.loader.destroy();\n this.loader = null;\n }\n EventHandler.prototype.destroy.call(this);\n }\n\n onFragLoading(data) {\n var frag = data.frag;\n this.frag = frag;\n this.frag.loaded = 0;\n var config = this.hls.config;\n frag.loader = this.loader = typeof(config.fLoader) !== 'undefined' ? new config.fLoader(config) : new config.loader(config);\n this.loader.load(frag.url, 'arraybuffer', this.loadsuccess.bind(this), this.loaderror.bind(this), this.loadtimeout.bind(this), config.fragLoadingTimeOut, 1, 0, this.loadprogress.bind(this), frag);\n }\n\n loadsuccess(event, stats) {\n var payload = event.currentTarget.response;\n stats.length = payload.byteLength;\n // detach fragment loader on load success\n this.frag.loader = undefined;\n this.hls.trigger(Event.FRAG_LOADED, {payload: payload, frag: this.frag, stats: stats});\n }\n\n loaderror(event) {\n if (this.loader) {\n this.loader.abort();\n }\n this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.FRAG_LOAD_ERROR, fatal: false, frag: this.frag, response: event});\n }\n\n loadtimeout() {\n if (this.loader) {\n this.loader.abort();\n }\n this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.FRAG_LOAD_TIMEOUT, fatal: false, frag: this.frag});\n }\n\n loadprogress(event, stats) {\n this.frag.loaded = stats.loaded;\n this.hls.trigger(Event.FRAG_LOAD_PROGRESS, {frag: this.frag, stats: stats});\n }\n}\n\nexport default FragmentLoader;\n", - "/*\n * Decrypt key Loader\n*/\n\nimport Event from '../events';\nimport EventHandler from '../event-handler';\nimport {ErrorTypes, ErrorDetails} from '../errors';\n\nclass KeyLoader extends EventHandler {\n\n constructor(hls) {\n super(hls, Event.KEY_LOADING);\n this.decryptkey = null;\n this.decrypturl = null;\n }\n\n destroy() {\n if (this.loader) {\n this.loader.destroy();\n this.loader = null;\n }\n EventHandler.prototype.destroy.call(this);\n }\n\n onKeyLoading(data) {\n var frag = this.frag = data.frag,\n decryptdata = frag.decryptdata,\n uri = decryptdata.uri;\n // if uri is different from previous one or if decrypt key not retrieved yet\n if (uri !== this.decrypturl || this.decryptkey === null) {\n var config = this.hls.config;\n frag.loader = this.loader = new config.loader(config);\n this.decrypturl = uri;\n this.decryptkey = null;\n frag.loader.load(uri, 'arraybuffer', this.loadsuccess.bind(this), this.loaderror.bind(this), this.loadtimeout.bind(this), config.fragLoadingTimeOut, config.fragLoadingMaxRetry, config.fragLoadingRetryDelay, this.loadprogress.bind(this), frag);\n } else if (this.decryptkey) {\n // we already loaded this key, return it\n decryptdata.key = this.decryptkey;\n this.hls.trigger(Event.KEY_LOADED, {frag: frag});\n }\n }\n\n loadsuccess(event) {\n var frag = this.frag;\n this.decryptkey = frag.decryptdata.key = new Uint8Array(event.currentTarget.response);\n // detach fragment loader on load success\n frag.loader = undefined;\n this.hls.trigger(Event.KEY_LOADED, {frag: frag});\n }\n\n loaderror(event) {\n if (this.loader) {\n this.loader.abort();\n }\n this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.KEY_LOAD_ERROR, fatal: false, frag: this.frag, response: event});\n }\n\n loadtimeout() {\n if (this.loader) {\n this.loader.abort();\n }\n this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.KEY_LOAD_TIMEOUT, fatal: false, frag: this.frag});\n }\n\n loadprogress() {\n\n }\n}\n\nexport default KeyLoader;\n", - "/**\n * Playlist Loader\n*/\n\nimport Event from '../events';\nimport EventHandler from '../event-handler';\nimport {ErrorTypes, ErrorDetails} from '../errors';\nimport URLHelper from '../utils/url';\nimport AttrList from '../utils/attr-list';\n//import {logger} from '../utils/logger';\n\nclass PlaylistLoader extends EventHandler {\n\n constructor(hls) {\n super(hls,\n Event.MANIFEST_LOADING,\n Event.LEVEL_LOADING);\n }\n\n destroy() {\n if (this.loader) {\n this.loader.destroy();\n this.loader = null;\n }\n this.url = this.id = null;\n EventHandler.prototype.destroy.call(this);\n }\n\n onManifestLoading(data) {\n this.load(data.url, null);\n }\n\n onLevelLoading(data) {\n this.load(data.url, data.level, data.id);\n }\n\n load(url, id1, id2) {\n var config = this.hls.config,\n retry,\n timeout,\n retryDelay;\n\n if (this.loading && this.loader) {\n if (this.url === url && this.id === id1 && this.id2 === id2) {\n // same request than last pending one, don't do anything\n return;\n } else {\n // one playlist load request is pending, but with different params, abort it before loading new playlist\n this.loader.abort();\n }\n }\n\n this.url = url;\n this.id = id1;\n this.id2 = id2;\n if(this.id === null) {\n retry = config.manifestLoadingMaxRetry;\n timeout = config.manifestLoadingTimeOut;\n retryDelay = config.manifestLoadingRetryDelay;\n } else {\n retry = config.levelLoadingMaxRetry;\n timeout = config.levelLoadingTimeOut;\n retryDelay = config.levelLoadingRetryDelay;\n }\n this.loader = typeof(config.pLoader) !== 'undefined' ? new config.pLoader(config) : new config.loader(config);\n this.loading = true;\n this.loader.load(url, '', this.loadsuccess.bind(this), this.loaderror.bind(this), this.loadtimeout.bind(this), timeout, retry, retryDelay);\n }\n\n resolve(url, baseUrl) {\n return URLHelper.buildAbsoluteURL(baseUrl, url);\n }\n\n parseMasterPlaylist(string, baseurl) {\n let levels = [], result;\n\n // https://regex101.com is your friend\n const re = /#EXT-X-STREAM-INF:([^\\n\\r]*)[\\r\\n]+([^\\r\\n]+)/g;\n while ((result = re.exec(string)) != null){\n const level = {};\n\n var attrs = level.attrs = new AttrList(result[1]);\n level.url = this.resolve(result[2], baseurl);\n\n var resolution = attrs.decimalResolution('RESOLUTION');\n if(resolution) {\n level.width = resolution.width;\n level.height = resolution.height;\n }\n level.bitrate = attrs.decimalInteger('AVERAGE-BANDWIDTH') || attrs.decimalInteger('BANDWIDTH');\n level.name = attrs.NAME;\n\n var codecs = attrs.CODECS;\n if(codecs) {\n codecs = codecs.split(',');\n for (let i = 0; i < codecs.length; i++) {\n const codec = codecs[i];\n if (codec.indexOf('avc1') !== -1) {\n level.videoCodec = this.avc1toavcoti(codec);\n } else {\n level.audioCodec = codec;\n }\n }\n }\n\n levels.push(level);\n }\n return levels;\n }\n\n avc1toavcoti(codec) {\n var result, avcdata = codec.split('.');\n if (avcdata.length > 2) {\n result = avcdata.shift() + '.';\n result += parseInt(avcdata.shift()).toString(16);\n result += ('000' + parseInt(avcdata.shift()).toString(16)).substr(-4);\n } else {\n result = codec;\n }\n return result;\n }\n\n cloneObj(obj) {\n return JSON.parse(JSON.stringify(obj));\n }\n\n parseLevelPlaylist(string, baseurl, id) {\n var currentSN = 0,\n totalduration = 0,\n level = {url: baseurl, fragments: [], live: true, startSN: 0},\n levelkey = {method : null, key : null, iv : null, uri : null},\n cc = 0,\n programDateTime = null,\n frag = null,\n result,\n regexp,\n byteRangeEndOffset,\n byteRangeStartOffset;\n\n regexp = /(?:#EXT-X-(MEDIA-SEQUENCE):(\\d+))|(?:#EXT-X-(TARGETDURATION):(\\d+))|(?:#EXT-X-(KEY):(.*))|(?:#EXT-X-(START):(.*))|(?:#EXT(INF):([\\d\\.]+)[^\\r\\n]*([\\r\\n]+[^#|\\r\\n]+)?)|(?:#EXT-X-(BYTERANGE):([\\d]+[@[\\d]*)]*[\\r\\n]+([^#|\\r\\n]+)?|(?:#EXT-X-(ENDLIST))|(?:#EXT-X-(DIS)CONTINUITY))|(?:#EXT-X-(PROGRAM-DATE-TIME):(.*)[\\r\\n]+([^#|\\r\\n]+)?)/g;\n while ((result = regexp.exec(string)) !== null) {\n result.shift();\n result = result.filter(function(n) { return (n !== undefined); });\n switch (result[0]) {\n case 'MEDIA-SEQUENCE':\n currentSN = level.startSN = parseInt(result[1]);\n break;\n case 'TARGETDURATION':\n level.targetduration = parseFloat(result[1]);\n break;\n case 'ENDLIST':\n level.live = false;\n break;\n case 'DIS':\n cc++;\n break;\n case 'BYTERANGE':\n var params = result[1].split('@');\n if (params.length === 1) {\n byteRangeStartOffset = byteRangeEndOffset;\n } else {\n byteRangeStartOffset = parseInt(params[1]);\n }\n byteRangeEndOffset = parseInt(params[0]) + byteRangeStartOffset;\n if (frag && !frag.url) {\n frag.byteRangeStartOffset = byteRangeStartOffset;\n frag.byteRangeEndOffset = byteRangeEndOffset;\n frag.url = this.resolve(result[2], baseurl);\n }\n break;\n case 'INF':\n var duration = parseFloat(result[1]);\n if (!isNaN(duration)) {\n var fragdecryptdata,\n sn = currentSN++;\n if (levelkey.method && levelkey.uri && !levelkey.iv) {\n fragdecryptdata = this.cloneObj(levelkey);\n var uint8View = new Uint8Array(16);\n for (var i = 12; i < 16; i++) {\n uint8View[i] = (sn >> 8*(15-i)) & 0xff;\n }\n fragdecryptdata.iv = uint8View;\n } else {\n fragdecryptdata = levelkey;\n }\n var url = result[2] ? this.resolve(result[2], baseurl) : null;\n frag = {url: url, duration: duration, start: totalduration, sn: sn, level: id, cc: cc, byteRangeStartOffset: byteRangeStartOffset, byteRangeEndOffset: byteRangeEndOffset, decryptdata : fragdecryptdata, programDateTime: programDateTime};\n level.fragments.push(frag);\n totalduration += duration;\n byteRangeStartOffset = null;\n programDateTime = null;\n }\n break;\n case 'KEY':\n // https://tools.ietf.org/html/draft-pantos-http-live-streaming-08#section-3.4.4\n var decryptparams = result[1];\n var keyAttrs = new AttrList(decryptparams);\n var decryptmethod = keyAttrs.enumeratedString('METHOD'),\n decrypturi = keyAttrs.URI,\n decryptiv = keyAttrs.hexadecimalInteger('IV');\n if (decryptmethod) {\n levelkey = { method: null, key: null, iv: null, uri: null };\n if ((decrypturi) && (decryptmethod === 'AES-128')) {\n levelkey.method = decryptmethod;\n // URI to get the key\n levelkey.uri = this.resolve(decrypturi, baseurl);\n levelkey.key = null;\n // Initialization Vector (IV)\n levelkey.iv = decryptiv;\n }\n }\n break;\n case 'START':\n let startParams = result[1];\n let startAttrs = new AttrList(startParams);\n let startTimeOffset = startAttrs.decimalFloatingPoint('TIME-OFFSET');\n if (startTimeOffset) {\n level.startTimeOffset = startTimeOffset;\n }\n break;\n case 'PROGRAM-DATE-TIME':\n programDateTime = new Date(Date.parse(result[1]));\n if (frag && !frag.url && result.length >= 3) {\n frag.url = this.resolve(result[2], baseurl);\n frag.programDateTime = programDateTime;\n }\n break;\n default:\n break;\n }\n }\n //logger.log('found ' + level.fragments.length + ' fragments');\n if(frag && !frag.url) {\n level.fragments.pop();\n totalduration-=frag.duration;\n }\n level.totalduration = totalduration;\n level.endSN = currentSN - 1;\n return level;\n }\n\n loadsuccess(event, stats) {\n var target = event.currentTarget,\n string = target.responseText,\n url = target.responseURL,\n id = this.id,\n id2 = this.id2,\n hls = this.hls,\n levels;\n\n this.loading = false;\n // responseURL not supported on some browsers (it is used to detect URL redirection)\n if (url === undefined) {\n // fallback to initial URL\n url = this.url;\n }\n stats.tload = performance.now();\n stats.mtime = new Date(target.getResponseHeader('Last-Modified'));\n if (string.indexOf('#EXTM3U') === 0) {\n if (string.indexOf('#EXTINF:') > 0) {\n // 1 level playlist\n // if first request, fire manifest loaded event, level will be reloaded afterwards\n // (this is to have a uniform logic for 1 level/multilevel playlists)\n if (this.id === null) {\n hls.trigger(Event.MANIFEST_LOADED, {levels: [{url: url}], url: url, stats: stats});\n } else {\n var levelDetails = this.parseLevelPlaylist(string, url, id);\n stats.tparsed = performance.now();\n hls.trigger(Event.LEVEL_LOADED, {details: levelDetails, level: id, id: id2, stats: stats});\n }\n } else {\n levels = this.parseMasterPlaylist(string, url);\n // multi level playlist, parse level info\n if (levels.length) {\n hls.trigger(Event.MANIFEST_LOADED, {levels: levels, url: url, stats: stats});\n } else {\n hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.MANIFEST_PARSING_ERROR, fatal: true, url: url, reason: 'no level found in manifest'});\n }\n }\n } else {\n hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.MANIFEST_PARSING_ERROR, fatal: true, url: url, reason: 'no EXTM3U delimiter'});\n }\n }\n\n loaderror(event) {\n var details, fatal;\n if (this.id === null) {\n details = ErrorDetails.MANIFEST_LOAD_ERROR;\n fatal = true;\n } else {\n details = ErrorDetails.LEVEL_LOAD_ERROR;\n fatal = false;\n }\n if (this.loader) {\n this.loader.abort();\n }\n this.loading = false;\n this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: details, fatal: fatal, url: this.url, loader: this.loader, response: event.currentTarget, level: this.id, id: this.id2});\n }\n\n loadtimeout() {\n var details, fatal;\n if (this.id === null) {\n details = ErrorDetails.MANIFEST_LOAD_TIMEOUT;\n fatal = true;\n } else {\n details = ErrorDetails.LEVEL_LOAD_TIMEOUT;\n fatal = false;\n }\n if (this.loader) {\n this.loader.abort();\n }\n this.loading = false;\n this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: details, fatal: fatal, url: this.url, loader: this.loader, level: this.id, id: this.id2});\n }\n}\n\nexport default PlaylistLoader;\n", - "/**\n * Generate MP4 Box\n*/\n\n//import Hex from '../utils/hex';\nclass MP4 {\n static init() {\n MP4.types = {\n avc1: [], // codingname\n avcC: [],\n btrt: [],\n dinf: [],\n dref: [],\n esds: [],\n ftyp: [],\n hdlr: [],\n mdat: [],\n mdhd: [],\n mdia: [],\n mfhd: [],\n minf: [],\n moof: [],\n moov: [],\n mp4a: [],\n mvex: [],\n mvhd: [],\n sdtp: [],\n stbl: [],\n stco: [],\n stsc: [],\n stsd: [],\n stsz: [],\n stts: [],\n tfdt: [],\n tfhd: [],\n traf: [],\n trak: [],\n trun: [],\n trex: [],\n tkhd: [],\n vmhd: [],\n smhd: []\n };\n\n var i;\n for (i in MP4.types) {\n if (MP4.types.hasOwnProperty(i)) {\n MP4.types[i] = [\n i.charCodeAt(0),\n i.charCodeAt(1),\n i.charCodeAt(2),\n i.charCodeAt(3)\n ];\n }\n }\n\n var videoHdlr = new Uint8Array([\n 0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x00, // pre_defined\n 0x76, 0x69, 0x64, 0x65, // handler_type: 'vide'\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x56, 0x69, 0x64, 0x65,\n 0x6f, 0x48, 0x61, 0x6e,\n 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'VideoHandler'\n ]);\n\n var audioHdlr = new Uint8Array([\n 0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x00, // pre_defined\n 0x73, 0x6f, 0x75, 0x6e, // handler_type: 'soun'\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x53, 0x6f, 0x75, 0x6e,\n 0x64, 0x48, 0x61, 0x6e,\n 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'SoundHandler'\n ]);\n\n MP4.HDLR_TYPES = {\n 'video': videoHdlr,\n 'audio': audioHdlr\n };\n\n var dref = new Uint8Array([\n 0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x01, // entry_count\n 0x00, 0x00, 0x00, 0x0c, // entry_size\n 0x75, 0x72, 0x6c, 0x20, // 'url' type\n 0x00, // version 0\n 0x00, 0x00, 0x01 // entry_flags\n ]);\n\n var stco = new Uint8Array([\n 0x00, // version\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x00 // entry_count\n ]);\n\n MP4.STTS = MP4.STSC = MP4.STCO = stco;\n\n MP4.STSZ = new Uint8Array([\n 0x00, // version\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x00, // sample_size\n 0x00, 0x00, 0x00, 0x00, // sample_count\n ]);\n MP4.VMHD = new Uint8Array([\n 0x00, // version\n 0x00, 0x00, 0x01, // flags\n 0x00, 0x00, // graphicsmode\n 0x00, 0x00,\n 0x00, 0x00,\n 0x00, 0x00 // opcolor\n ]);\n MP4.SMHD = new Uint8Array([\n 0x00, // version\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, // balance\n 0x00, 0x00 // reserved\n ]);\n\n MP4.STSD = new Uint8Array([\n 0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x01]);// entry_count\n\n var majorBrand = new Uint8Array([105,115,111,109]); // isom\n var avc1Brand = new Uint8Array([97,118,99,49]); // avc1\n var minorVersion = new Uint8Array([0, 0, 0, 1]);\n\n MP4.FTYP = MP4.box(MP4.types.ftyp, majorBrand, minorVersion, majorBrand, avc1Brand);\n MP4.DINF = MP4.box(MP4.types.dinf, MP4.box(MP4.types.dref, dref));\n }\n\n static box(type) {\n var\n payload = Array.prototype.slice.call(arguments, 1),\n size = 8,\n i = payload.length,\n len = i,\n result;\n // calculate the total size we need to allocate\n while (i--) {\n size += payload[i].byteLength;\n }\n result = new Uint8Array(size);\n result[0] = (size >> 24) & 0xff;\n result[1] = (size >> 16) & 0xff;\n result[2] = (size >> 8) & 0xff;\n result[3] = size & 0xff;\n result.set(type, 4);\n // copy the payload into the result\n for (i = 0, size = 8; i < len; i++) {\n // copy payload[i] array @ offset size\n result.set(payload[i], size);\n size += payload[i].byteLength;\n }\n return result;\n }\n\n static hdlr(type) {\n return MP4.box(MP4.types.hdlr, MP4.HDLR_TYPES[type]);\n }\n\n static mdat(data) {\n return MP4.box(MP4.types.mdat, data);\n }\n\n static mdhd(timescale, duration) {\n duration *= timescale;\n return MP4.box(MP4.types.mdhd, new Uint8Array([\n 0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x02, // creation_time\n 0x00, 0x00, 0x00, 0x03, // modification_time\n (timescale >> 24) & 0xFF,\n (timescale >> 16) & 0xFF,\n (timescale >> 8) & 0xFF,\n timescale & 0xFF, // timescale\n (duration >> 24),\n (duration >> 16) & 0xFF,\n (duration >> 8) & 0xFF,\n duration & 0xFF, // duration\n 0x55, 0xc4, // 'und' language (undetermined)\n 0x00, 0x00\n ]));\n }\n\n static mdia(track) {\n return MP4.box(MP4.types.mdia, MP4.mdhd(track.timescale, track.duration), MP4.hdlr(track.type), MP4.minf(track));\n }\n\n static mfhd(sequenceNumber) {\n return MP4.box(MP4.types.mfhd, new Uint8Array([\n 0x00,\n 0x00, 0x00, 0x00, // flags\n (sequenceNumber >> 24),\n (sequenceNumber >> 16) & 0xFF,\n (sequenceNumber >> 8) & 0xFF,\n sequenceNumber & 0xFF, // sequence_number\n ]));\n }\n\n static minf(track) {\n if (track.type === 'audio') {\n return MP4.box(MP4.types.minf, MP4.box(MP4.types.smhd, MP4.SMHD), MP4.DINF, MP4.stbl(track));\n } else {\n return MP4.box(MP4.types.minf, MP4.box(MP4.types.vmhd, MP4.VMHD), MP4.DINF, MP4.stbl(track));\n }\n }\n\n static moof(sn, baseMediaDecodeTime, track) {\n return MP4.box(MP4.types.moof, MP4.mfhd(sn), MP4.traf(track,baseMediaDecodeTime));\n }\n/**\n * @param tracks... (optional) {array} the tracks associated with this movie\n */\n static moov(tracks) {\n var\n i = tracks.length,\n boxes = [];\n\n while (i--) {\n boxes[i] = MP4.trak(tracks[i]);\n }\n\n return MP4.box.apply(null, [MP4.types.moov, MP4.mvhd(tracks[0].timescale, tracks[0].duration)].concat(boxes).concat(MP4.mvex(tracks)));\n }\n\n static mvex(tracks) {\n var\n i = tracks.length,\n boxes = [];\n\n while (i--) {\n boxes[i] = MP4.trex(tracks[i]);\n }\n return MP4.box.apply(null, [MP4.types.mvex].concat(boxes));\n }\n\n static mvhd(timescale,duration) {\n duration*=timescale;\n var\n bytes = new Uint8Array([\n 0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n 0x00, 0x00, 0x00, 0x01, // creation_time\n 0x00, 0x00, 0x00, 0x02, // modification_time\n (timescale >> 24) & 0xFF,\n (timescale >> 16) & 0xFF,\n (timescale >> 8) & 0xFF,\n timescale & 0xFF, // timescale\n (duration >> 24) & 0xFF,\n (duration >> 16) & 0xFF,\n (duration >> 8) & 0xFF,\n duration & 0xFF, // duration\n 0x00, 0x01, 0x00, 0x00, // 1.0 rate\n 0x01, 0x00, // 1.0 volume\n 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x01, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x01, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00, // pre_defined\n 0xff, 0xff, 0xff, 0xff // next_track_ID\n ]);\n return MP4.box(MP4.types.mvhd, bytes);\n }\n\n static sdtp(track) {\n var\n samples = track.samples || [],\n bytes = new Uint8Array(4 + samples.length),\n flags,\n i;\n // leave the full box header (4 bytes) all zero\n // write the sample table\n for (i = 0; i < samples.length; i++) {\n flags = samples[i].flags;\n bytes[i + 4] = (flags.dependsOn << 4) |\n (flags.isDependedOn << 2) |\n (flags.hasRedundancy);\n }\n\n return MP4.box(MP4.types.sdtp, bytes);\n }\n\n static stbl(track) {\n return MP4.box(MP4.types.stbl, MP4.stsd(track), MP4.box(MP4.types.stts, MP4.STTS), MP4.box(MP4.types.stsc, MP4.STSC), MP4.box(MP4.types.stsz, MP4.STSZ), MP4.box(MP4.types.stco, MP4.STCO));\n }\n\n static avc1(track) {\n var sps = [], pps = [], i, data, len;\n // assemble the SPSs\n\n for (i = 0; i < track.sps.length; i++) {\n data = track.sps[i];\n len = data.byteLength;\n sps.push((len >>> 8) & 0xFF);\n sps.push((len & 0xFF));\n sps = sps.concat(Array.prototype.slice.call(data)); // SPS\n }\n\n // assemble the PPSs\n for (i = 0; i < track.pps.length; i++) {\n data = track.pps[i];\n len = data.byteLength;\n pps.push((len >>> 8) & 0xFF);\n pps.push((len & 0xFF));\n pps = pps.concat(Array.prototype.slice.call(data));\n }\n\n var avcc = MP4.box(MP4.types.avcC, new Uint8Array([\n 0x01, // version\n sps[3], // profile\n sps[4], // profile compat\n sps[5], // level\n 0xfc | 3, // lengthSizeMinusOne, hard-coded to 4 bytes\n 0xE0 | track.sps.length // 3bit reserved (111) + numOfSequenceParameterSets\n ].concat(sps).concat([\n track.pps.length // numOfPictureParameterSets\n ]).concat(pps))), // \"PPS\"\n width = track.width,\n height = track.height;\n //console.log('avcc:' + Hex.hexDump(avcc));\n return MP4.box(MP4.types.avc1, new Uint8Array([\n 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, // reserved\n 0x00, 0x01, // data_reference_index\n 0x00, 0x00, // pre_defined\n 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00, // pre_defined\n (width >> 8) & 0xFF,\n width & 0xff, // width\n (height >> 8) & 0xFF,\n height & 0xff, // height\n 0x00, 0x48, 0x00, 0x00, // horizresolution\n 0x00, 0x48, 0x00, 0x00, // vertresolution\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x01, // frame_count\n 0x12,\n 0x64, 0x61, 0x69, 0x6C, //dailymotion/hls.js\n 0x79, 0x6D, 0x6F, 0x74,\n 0x69, 0x6F, 0x6E, 0x2F,\n 0x68, 0x6C, 0x73, 0x2E,\n 0x6A, 0x73, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, // compressorname\n 0x00, 0x18, // depth = 24\n 0x11, 0x11]), // pre_defined = -1\n avcc,\n MP4.box(MP4.types.btrt, new Uint8Array([\n 0x00, 0x1c, 0x9c, 0x80, // bufferSizeDB\n 0x00, 0x2d, 0xc6, 0xc0, // maxBitrate\n 0x00, 0x2d, 0xc6, 0xc0])) // avgBitrate\n );\n }\n\n static esds(track) {\n var configlen = track.config.length;\n return new Uint8Array([\n 0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n\n 0x03, // descriptor_type\n 0x17+configlen, // length\n 0x00, 0x01, //es_id\n 0x00, // stream_priority\n\n 0x04, // descriptor_type\n 0x0f+configlen, // length\n 0x40, //codec : mpeg4_audio\n 0x15, // stream_type\n 0x00, 0x00, 0x00, // buffer_size\n 0x00, 0x00, 0x00, 0x00, // maxBitrate\n 0x00, 0x00, 0x00, 0x00, // avgBitrate\n\n 0x05 // descriptor_type\n ].concat([configlen]).concat(track.config).concat([0x06, 0x01, 0x02])); // GASpecificConfig)); // length + audio config descriptor\n }\n\n static mp4a(track) {\n var audiosamplerate = track.audiosamplerate;\n return MP4.box(MP4.types.mp4a, new Uint8Array([\n 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, 0x00, // reserved\n 0x00, 0x01, // data_reference_index\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, track.channelCount, // channelcount\n 0x00, 0x10, // sampleSize:16bits\n 0x00, 0x00, 0x00, 0x00, // reserved2\n (audiosamplerate >> 8) & 0xFF,\n audiosamplerate & 0xff, //\n 0x00, 0x00]),\n MP4.box(MP4.types.esds, MP4.esds(track)));\n }\n\n static stsd(track) {\n if (track.type === 'audio') {\n return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));\n } else {\n return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track));\n }\n }\n\n static tkhd(track) {\n var id = track.id,\n duration = track.duration*track.timescale,\n width = track.width,\n height = track.height;\n return MP4.box(MP4.types.tkhd, new Uint8Array([\n 0x00, // version 0\n 0x00, 0x00, 0x07, // flags\n 0x00, 0x00, 0x00, 0x00, // creation_time\n 0x00, 0x00, 0x00, 0x00, // modification_time\n (id >> 24) & 0xFF,\n (id >> 16) & 0xFF,\n (id >> 8) & 0xFF,\n id & 0xFF, // track_ID\n 0x00, 0x00, 0x00, 0x00, // reserved\n (duration >> 24),\n (duration >> 16) & 0xFF,\n (duration >> 8) & 0xFF,\n duration & 0xFF, // duration\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00, // reserved\n 0x00, 0x00, // layer\n 0x00, 0x00, // alternate_group\n 0x00, 0x00, // non-audio track volume\n 0x00, 0x00, // reserved\n 0x00, 0x01, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x01, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x00, 0x00, 0x00, 0x00,\n 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix\n (width >> 8) & 0xFF,\n width & 0xFF,\n 0x00, 0x00, // width\n (height >> 8) & 0xFF,\n height & 0xFF,\n 0x00, 0x00 // height\n ]));\n }\n\n static traf(track,baseMediaDecodeTime) {\n var sampleDependencyTable = MP4.sdtp(track),\n id = track.id;\n return MP4.box(MP4.types.traf,\n MP4.box(MP4.types.tfhd, new Uint8Array([\n 0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n (id >> 24),\n (id >> 16) & 0XFF,\n (id >> 8) & 0XFF,\n (id & 0xFF) // track_ID\n ])),\n MP4.box(MP4.types.tfdt, new Uint8Array([\n 0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n (baseMediaDecodeTime >>24),\n (baseMediaDecodeTime >> 16) & 0XFF,\n (baseMediaDecodeTime >> 8) & 0XFF,\n (baseMediaDecodeTime & 0xFF) // baseMediaDecodeTime\n ])),\n MP4.trun(track,\n sampleDependencyTable.length +\n 16 + // tfhd\n 16 + // tfdt\n 8 + // traf header\n 16 + // mfhd\n 8 + // moof header\n 8), // mdat header\n sampleDependencyTable);\n }\n\n /**\n * Generate a track box.\n * @param track {object} a track definition\n * @return {Uint8Array} the track box\n */\n static trak(track) {\n track.duration = track.duration || 0xffffffff;\n return MP4.box(MP4.types.trak, MP4.tkhd(track), MP4.mdia(track));\n }\n\n static trex(track) {\n var id = track.id;\n return MP4.box(MP4.types.trex, new Uint8Array([\n 0x00, // version 0\n 0x00, 0x00, 0x00, // flags\n (id >> 24),\n (id >> 16) & 0XFF,\n (id >> 8) & 0XFF,\n (id & 0xFF), // track_ID\n 0x00, 0x00, 0x00, 0x01, // default_sample_description_index\n 0x00, 0x00, 0x00, 0x00, // default_sample_duration\n 0x00, 0x00, 0x00, 0x00, // default_sample_size\n 0x00, 0x01, 0x00, 0x01 // default_sample_flags\n ]));\n }\n\n static trun(track, offset) {\n var samples= track.samples || [],\n len = samples.length,\n arraylen = 12 + (16 * len),\n array = new Uint8Array(arraylen),\n i,sample,duration,size,flags,cts;\n offset += 8 + arraylen;\n array.set([\n 0x00, // version 0\n 0x00, 0x0f, 0x01, // flags\n (len >>> 24) & 0xFF,\n (len >>> 16) & 0xFF,\n (len >>> 8) & 0xFF,\n len & 0xFF, // sample_count\n (offset >>> 24) & 0xFF,\n (offset >>> 16) & 0xFF,\n (offset >>> 8) & 0xFF,\n offset & 0xFF // data_offset\n ],0);\n for (i = 0; i < len; i++) {\n sample = samples[i];\n duration = sample.duration;\n size = sample.size;\n flags = sample.flags;\n cts = sample.cts;\n array.set([\n (duration >>> 24) & 0xFF,\n (duration >>> 16) & 0xFF,\n (duration >>> 8) & 0xFF,\n duration & 0xFF, // sample_duration\n (size >>> 24) & 0xFF,\n (size >>> 16) & 0xFF,\n (size >>> 8) & 0xFF,\n size & 0xFF, // sample_size\n (flags.isLeading << 2) | flags.dependsOn,\n (flags.isDependedOn << 6) |\n (flags.hasRedundancy << 4) |\n (flags.paddingValue << 1) |\n flags.isNonSync,\n flags.degradPrio & 0xF0 << 8,\n flags.degradPrio & 0x0F, // sample_flags\n (cts >>> 24) & 0xFF,\n (cts >>> 16) & 0xFF,\n (cts >>> 8) & 0xFF,\n cts & 0xFF // sample_composition_time_offset\n ],12+16*i);\n }\n return MP4.box(MP4.types.trun, array);\n }\n\n static initSegment(tracks) {\n if (!MP4.types) {\n MP4.init();\n }\n var movie = MP4.moov(tracks), result;\n result = new Uint8Array(MP4.FTYP.byteLength + movie.byteLength);\n result.set(MP4.FTYP);\n result.set(movie, MP4.FTYP.byteLength);\n return result;\n }\n}\n\nexport default MP4;\n", - "/**\n * fMP4 remuxer\n*/\n\n\nimport Event from '../events';\nimport {logger} from '../utils/logger';\nimport MP4 from '../remux/mp4-generator';\nimport {ErrorTypes, ErrorDetails} from '../errors';\n\nclass MP4Remuxer {\n constructor(observer) {\n this.observer = observer;\n this.ISGenerated = false;\n this.PES2MP4SCALEFACTOR = 4;\n this.PES_TIMESCALE = 90000;\n this.MP4_TIMESCALE = this.PES_TIMESCALE / this.PES2MP4SCALEFACTOR;\n }\n\n get passthrough() {\n return false;\n }\n\n destroy() {\n }\n\n insertDiscontinuity() {\n this._initPTS = this._initDTS = undefined;\n }\n\n switchLevel() {\n this.ISGenerated = false;\n }\n\n remux(audioTrack,videoTrack,id3Track,textTrack,timeOffset, contiguous) {\n // generate Init Segment if needed\n if (!this.ISGenerated) {\n this.generateIS(audioTrack,videoTrack,timeOffset);\n }\n if (this.ISGenerated) {\n //logger.log('nb AVC samples:' + videoTrack.samples.length);\n if (videoTrack.samples.length) {\n this.remuxVideo(videoTrack,timeOffset,contiguous);\n }\n //logger.log('nb AAC samples:' + audioTrack.samples.length);\n if (audioTrack.samples.length) {\n this.remuxAudio(audioTrack,timeOffset,contiguous);\n }\n }\n //logger.log('nb ID3 samples:' + audioTrack.samples.length);\n if (id3Track.samples.length) {\n this.remuxID3(id3Track,timeOffset);\n }\n //logger.log('nb ID3 samples:' + audioTrack.samples.length);\n if (textTrack.samples.length) {\n this.remuxText(textTrack,timeOffset);\n }\n //notify end of parsing\n this.observer.trigger(Event.FRAG_PARSED);\n }\n\n generateIS(audioTrack,videoTrack,timeOffset) {\n var observer = this.observer,\n audioSamples = audioTrack.samples,\n videoSamples = videoTrack.samples,\n pesTimeScale = this.PES_TIMESCALE,\n tracks = {},\n data = { tracks : tracks, unique : false },\n computePTSDTS = (this._initPTS === undefined),\n initPTS, initDTS;\n\n if (computePTSDTS) {\n initPTS = initDTS = Infinity;\n }\n if (audioTrack.config && audioSamples.length) {\n audioTrack.timescale = audioTrack.audiosamplerate;\n // MP4 duration (track duration in seconds multiplied by timescale) is coded on 32 bits\n // we know that each AAC sample contains 1024 frames....\n // in order to avoid overflowing the 32 bit counter for large duration, we use smaller timescale (timescale/gcd)\n // we just need to ensure that AAC sample duration will still be an integer (will be 1024/gcd)\n if (audioTrack.timescale * audioTrack.duration > Math.pow(2, 32)) {\n let greatestCommonDivisor = function(a, b) {\n if ( ! b) {\n return a;\n }\n return greatestCommonDivisor(b, a % b);\n };\n audioTrack.timescale = audioTrack.audiosamplerate / greatestCommonDivisor(audioTrack.audiosamplerate,1024);\n }\n logger.log ('audio mp4 timescale :'+ audioTrack.timescale);\n tracks.audio = {\n container : 'audio/mp4',\n codec : audioTrack.codec,\n initSegment : MP4.initSegment([audioTrack]),\n metadata : {\n channelCount : audioTrack.channelCount\n }\n };\n if (computePTSDTS) {\n // remember first PTS of this demuxing context. for audio, PTS + DTS ...\n initPTS = initDTS = audioSamples[0].pts - pesTimeScale * timeOffset;\n }\n }\n\n if (videoTrack.sps && videoTrack.pps && videoSamples.length) {\n videoTrack.timescale = this.MP4_TIMESCALE;\n tracks.video = {\n container : 'video/mp4',\n codec : videoTrack.codec,\n initSegment : MP4.initSegment([videoTrack]),\n metadata : {\n width : videoTrack.width,\n height : videoTrack.height\n }\n };\n if (computePTSDTS) {\n initPTS = Math.min(initPTS,videoSamples[0].pts - pesTimeScale * timeOffset);\n initDTS = Math.min(initDTS,videoSamples[0].dts - pesTimeScale * timeOffset);\n }\n }\n\n if(Object.keys(tracks).length) {\n observer.trigger(Event.FRAG_PARSING_INIT_SEGMENT,data);\n this.ISGenerated = true;\n if (computePTSDTS) {\n this._initPTS = initPTS;\n this._initDTS = initDTS;\n }\n } else {\n observer.trigger(Event.ERROR, {type : ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_PARSING_ERROR, fatal: false, reason: 'no audio/video samples found'});\n }\n }\n\n remuxVideo(track, timeOffset, contiguous) {\n var view,\n offset = 8,\n pesTimeScale = this.PES_TIMESCALE,\n pes2mp4ScaleFactor = this.PES2MP4SCALEFACTOR,\n avcSample,\n mp4Sample,\n mp4SampleLength,\n unit,\n mdat, moof,\n firstPTS, firstDTS, lastDTS,\n pts, dts, ptsnorm, dtsnorm,\n flags,\n samples = [];\n\n // handle broken streams with PTS < DTS, tolerance up 200ms (18000 in 90kHz timescale)\n let PTSDTSshift = track.samples.reduce( (prev, curr) => Math.max(Math.min(prev,curr.pts-curr.dts),-18000),0);\n if (PTSDTSshift < 0) {\n logger.warn(`PTS < DTS detected in video samples, shifting DTS by ${Math.round(PTSDTSshift/90)} ms to overcome this issue`);\n }\n /* concatenate the video data and construct the mdat in place\n (need 8 more bytes to fill length and mpdat type) */\n mdat = new Uint8Array(track.len + (4 * track.nbNalu) + 8);\n view = new DataView(mdat.buffer);\n view.setUint32(0, mdat.byteLength);\n mdat.set(MP4.types.mdat, 4);\n while (track.samples.length) {\n avcSample = track.samples.shift();\n mp4SampleLength = 0;\n // convert NALU bitstream to MP4 format (prepend NALU with size field)\n while (avcSample.units.units.length) {\n unit = avcSample.units.units.shift();\n view.setUint32(offset, unit.data.byteLength);\n offset += 4;\n mdat.set(unit.data, offset);\n offset += unit.data.byteLength;\n mp4SampleLength += 4 + unit.data.byteLength;\n }\n pts = avcSample.pts - this._initDTS;\n // shift dts by PTSDTSshift, to ensure that PTS >= DTS\n dts = avcSample.dts - this._initDTS + PTSDTSshift;\n // ensure DTS is not bigger than PTS // strap belt !!!\n dts = Math.min(pts,dts);\n //logger.log(`Video/PTS/DTS/ptsnorm/DTSnorm:${Math.round(avcSample.pts/90)}/${Math.round(avcSample.dts/90)}/${Math.round(pts/90)}/${Math.round(dts/90)}`);\n // if not first AVC sample of video track, normalize PTS/DTS with previous sample value\n // and ensure that sample duration is positive\n if (lastDTS !== undefined) {\n ptsnorm = this._PTSNormalize(pts, lastDTS);\n dtsnorm = this._PTSNormalize(dts, lastDTS);\n var sampleDuration = (dtsnorm - lastDTS) / pes2mp4ScaleFactor;\n if (sampleDuration <= 0) {\n logger.log(`invalid sample duration at PTS/DTS: ${avcSample.pts}/${avcSample.dts}:${sampleDuration}`);\n sampleDuration = 1;\n }\n mp4Sample.duration = sampleDuration;\n } else {\n let nextAvcDts, delta;\n if (contiguous) {\n nextAvcDts = this.nextAvcDts;\n } else {\n nextAvcDts = timeOffset*pesTimeScale;\n }\n // first AVC sample of video track, normalize PTS/DTS\n ptsnorm = this._PTSNormalize(pts, nextAvcDts);\n dtsnorm = this._PTSNormalize(dts, nextAvcDts);\n delta = Math.round((dtsnorm - nextAvcDts) / 90);\n // if fragment are contiguous, detect hole/overlapping between fragments\n if (contiguous) {\n if (delta) {\n if (delta > 1) {\n logger.log(`AVC:${delta} ms hole between fragments detected,filling it`);\n } else if (delta < -1) {\n logger.log(`AVC:${(-delta)} ms overlapping between fragments detected`);\n }\n // set DTS to next DTS\n dtsnorm = nextAvcDts;\n // offset PTS as well, ensure that PTS is smaller or equal than new DTS\n ptsnorm = Math.max(ptsnorm - delta, dtsnorm);\n logger.log(`Video/PTS/DTS adjusted: ${ptsnorm}/${dtsnorm},delta:${delta}`);\n }\n }\n // remember first PTS of our avcSamples, ensure value is positive\n firstPTS = Math.max(0, ptsnorm);\n firstDTS = Math.max(0, dtsnorm);\n }\n //console.log(`PTS/DTS/initDTS/normPTS/normDTS/relative PTS : ${avcSample.pts}/${avcSample.dts}/${this._initDTS}/${ptsnorm}/${dtsnorm}/${(avcSample.pts/4294967296).toFixed(3)});\n mp4Sample = {\n size: mp4SampleLength,\n duration: 0,\n cts: (ptsnorm - dtsnorm) / pes2mp4ScaleFactor,\n flags: {\n isLeading: 0,\n isDependedOn: 0,\n hasRedundancy: 0,\n degradPrio: 0\n }\n };\n flags = mp4Sample.flags;\n if (avcSample.key === true) {\n // the current sample is a key frame\n flags.dependsOn = 2;\n flags.isNonSync = 0;\n } else {\n flags.dependsOn = 1;\n flags.isNonSync = 1;\n }\n samples.push(mp4Sample);\n lastDTS = dtsnorm;\n }\n var lastSampleDuration = 0;\n if (samples.length >= 2) {\n lastSampleDuration = samples[samples.length - 2].duration;\n mp4Sample.duration = lastSampleDuration;\n }\n // next AVC sample DTS should be equal to last sample DTS + last sample duration\n this.nextAvcDts = dtsnorm + lastSampleDuration * pes2mp4ScaleFactor;\n let dropped = track.dropped;\n track.len = 0;\n track.nbNalu = 0;\n track.dropped = 0;\n if(samples.length && navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {\n flags = samples[0].flags;\n // chrome workaround, mark first sample as being a Random Access Point to avoid sourcebuffer append issue\n // https://code.google.com/p/chromium/issues/detail?id=229412\n flags.dependsOn = 2;\n flags.isNonSync = 0;\n }\n track.samples = samples;\n moof = MP4.moof(track.sequenceNumber++, firstDTS / pes2mp4ScaleFactor, track);\n track.samples = [];\n this.observer.trigger(Event.FRAG_PARSING_DATA, {\n data1: moof,\n data2: mdat,\n startPTS: firstPTS / pesTimeScale,\n endPTS: (ptsnorm + pes2mp4ScaleFactor * lastSampleDuration) / pesTimeScale,\n startDTS: firstDTS / pesTimeScale,\n endDTS: this.nextAvcDts / pesTimeScale,\n type: 'video',\n nb: samples.length,\n dropped : dropped\n });\n }\n\n remuxAudio(track,timeOffset, contiguous) {\n var view,\n offset = 8,\n pesTimeScale = this.PES_TIMESCALE,\n mp4timeScale = track.timescale,\n pes2mp4ScaleFactor = pesTimeScale/mp4timeScale,\n expectedSampleDuration = track.timescale * 1024 / track.audiosamplerate,\n aacSample, mp4Sample,\n unit,\n mdat, moof,\n firstPTS, firstDTS, lastDTS,\n pts, dts, ptsnorm, dtsnorm,\n samples = [],\n samples0 = [];\n\n track.samples.sort(function(a, b) {\n return (a.pts-b.pts);\n });\n samples0 = track.samples;\n\n while (samples0.length) {\n aacSample = samples0.shift();\n unit = aacSample.unit;\n pts = aacSample.pts - this._initDTS;\n dts = aacSample.dts - this._initDTS;\n //logger.log(`Audio/PTS:${Math.round(pts/90)}`);\n // if not first sample\n if (lastDTS !== undefined) {\n ptsnorm = this._PTSNormalize(pts, lastDTS);\n dtsnorm = this._PTSNormalize(dts, lastDTS);\n // let's compute sample duration.\n // sample Duration should be close to expectedSampleDuration\n mp4Sample.duration = (dtsnorm - lastDTS) / pes2mp4ScaleFactor;\n if(Math.abs(mp4Sample.duration - expectedSampleDuration) > expectedSampleDuration/10) {\n // more than 10% diff between sample duration and expectedSampleDuration .... lets log that\n logger.log(`invalid AAC sample duration at PTS ${Math.round(pts/90)},should be 1024,found :${Math.round(mp4Sample.duration*track.audiosamplerate/track.timescale)}`);\n }\n // always adjust sample duration to avoid av sync issue\n mp4Sample.duration = expectedSampleDuration;\n ptsnorm = dtsnorm = expectedSampleDuration * pes2mp4ScaleFactor + lastDTS;\n } else {\n let nextAacPts, delta;\n if (contiguous) {\n nextAacPts = this.nextAacPts;\n } else {\n nextAacPts = timeOffset*pesTimeScale;\n }\n ptsnorm = this._PTSNormalize(pts, nextAacPts);\n dtsnorm = this._PTSNormalize(dts, nextAacPts);\n delta = Math.round(1000 * (ptsnorm - nextAacPts) / pesTimeScale);\n // if fragment are contiguous, detect hole/overlapping between fragments\n if (contiguous) {\n // log delta\n if (delta) {\n if (delta > 0) {\n logger.log(`${delta} ms hole between AAC samples detected,filling it`);\n // if we have frame overlap, overlapping for more than half a frame duration\n } else if (delta < -12) {\n // drop overlapping audio frames... browser will deal with it\n logger.log(`${(-delta)} ms overlapping between AAC samples detected, drop frame`);\n track.len -= unit.byteLength;\n continue;\n }\n // set PTS/DTS to next PTS/DTS\n ptsnorm = dtsnorm = nextAacPts;\n }\n }\n // remember first PTS of our aacSamples, ensure value is positive\n firstPTS = Math.max(0, ptsnorm);\n firstDTS = Math.max(0, dtsnorm);\n if(track.len > 0) {\n /* concatenate the audio data and construct the mdat in place\n (need 8 more bytes to fill length and mdat type) */\n mdat = new Uint8Array(track.len + 8);\n view = new DataView(mdat.buffer);\n view.setUint32(0, mdat.byteLength);\n mdat.set(MP4.types.mdat, 4);\n } else {\n // no audio samples\n return;\n }\n }\n mdat.set(unit, offset);\n offset += unit.byteLength;\n //console.log('PTS/DTS/initDTS/normPTS/normDTS/relative PTS : ${aacSample.pts}/${aacSample.dts}/${this._initDTS}/${ptsnorm}/${dtsnorm}/${(aacSample.pts/4294967296).toFixed(3)}');\n mp4Sample = {\n size: unit.byteLength,\n cts: 0,\n duration:0,\n flags: {\n isLeading: 0,\n isDependedOn: 0,\n hasRedundancy: 0,\n degradPrio: 0,\n dependsOn: 1,\n }\n };\n samples.push(mp4Sample);\n lastDTS = dtsnorm;\n }\n var lastSampleDuration = 0;\n var nbSamples = samples.length;\n //set last sample duration as being identical to previous sample\n if (nbSamples >= 2) {\n lastSampleDuration = samples[nbSamples - 2].duration;\n mp4Sample.duration = lastSampleDuration;\n }\n if (nbSamples) {\n // next aac sample PTS should be equal to last sample PTS + duration\n this.nextAacPts = ptsnorm + pes2mp4ScaleFactor * lastSampleDuration;\n //logger.log('Audio/PTS/PTSend:' + aacSample.pts.toFixed(0) + '/' + this.nextAacDts.toFixed(0));\n track.len = 0;\n track.samples = samples;\n moof = MP4.moof(track.sequenceNumber++, firstDTS / pes2mp4ScaleFactor, track);\n track.samples = [];\n this.observer.trigger(Event.FRAG_PARSING_DATA, {\n data1: moof,\n data2: mdat,\n startPTS: firstPTS / pesTimeScale,\n endPTS: this.nextAacPts / pesTimeScale,\n startDTS: firstDTS / pesTimeScale,\n endDTS: (dtsnorm + pes2mp4ScaleFactor * lastSampleDuration) / pesTimeScale,\n type: 'audio',\n nb: nbSamples\n });\n }\n }\n\n remuxID3(track,timeOffset) {\n var length = track.samples.length, sample;\n // consume samples\n if(length) {\n for(var index = 0; index < length; index++) {\n sample = track.samples[index];\n // setting id3 pts, dts to relative time\n // using this._initPTS and this._initDTS to calculate relative time\n sample.pts = ((sample.pts - this._initPTS) / this.PES_TIMESCALE);\n sample.dts = ((sample.dts - this._initDTS) / this.PES_TIMESCALE);\n }\n this.observer.trigger(Event.FRAG_PARSING_METADATA, {\n samples:track.samples\n });\n }\n\n track.samples = [];\n timeOffset = timeOffset;\n }\n\n remuxText(track,timeOffset) {\n track.samples.sort(function(a, b) {\n return (a.pts-b.pts);\n });\n\n var length = track.samples.length, sample;\n // consume samples\n if(length) {\n for(var index = 0; index < length; index++) {\n sample = track.samples[index];\n // setting text pts, dts to relative time\n // using this._initPTS and this._initDTS to calculate relative time\n sample.pts = ((sample.pts - this._initPTS) / this.PES_TIMESCALE);\n }\n this.observer.trigger(Event.FRAG_PARSING_USERDATA, {\n samples:track.samples\n });\n }\n\n track.samples = [];\n timeOffset = timeOffset;\n }\n\n _PTSNormalize(value, reference) {\n var offset;\n if (reference === undefined) {\n return value;\n }\n if (reference < value) {\n // - 2^33\n offset = -8589934592;\n } else {\n // + 2^33\n offset = 8589934592;\n }\n /* PTS is 33bit (from 0 to 2^33 -1)\n if diff between value and reference is bigger than half of the amplitude (2^32) then it means that\n PTS looping occured. fill the gap */\n while (Math.abs(value - reference) > 4294967296) {\n value += offset;\n }\n return value;\n }\n\n}\n\nexport default MP4Remuxer;\n", - "/**\n * passthrough remuxer\n*/\nimport Event from '../events';\n\nclass PassThroughRemuxer {\n constructor(observer) {\n this.observer = observer;\n this.ISGenerated = false;\n }\n\n get passthrough() {\n return true;\n }\n\n destroy() {\n }\n\n insertDiscontinuity() {\n }\n\n switchLevel() {\n this.ISGenerated = false;\n }\n\n remux(audioTrack,videoTrack,id3Track,textTrack,timeOffset,rawData) {\n var observer = this.observer;\n // generate Init Segment if needed\n if (!this.ISGenerated) {\n var tracks = {},\n data = { tracks : tracks, unique : true },\n track = videoTrack,\n codec = track.codec;\n\n if (codec) {\n data.tracks.video = {\n container : track.container,\n codec : codec,\n metadata : {\n width : track.width,\n height : track.height\n }\n };\n }\n\n track = audioTrack;\n codec = track.codec;\n if (codec) {\n data.tracks.audio = {\n container : track.container,\n codec : codec,\n metadata : {\n channelCount : track.channelCount\n }\n };\n }\n this.ISGenerated = true;\n observer.trigger(Event.FRAG_PARSING_INIT_SEGMENT,data);\n }\n observer.trigger(Event.FRAG_PARSING_DATA, {\n data1: rawData,\n startPTS: timeOffset,\n startDTS: timeOffset,\n type: 'audiovideo',\n nb: 1,\n dropped : 0\n });\n }\n}\n\nexport default PassThroughRemuxer;\n", - "\n// adapted from https://github.com/kanongil/node-m3u8parse/blob/master/attrlist.js\nclass AttrList {\n\n constructor(attrs) {\n if (typeof attrs === 'string') {\n attrs = AttrList.parseAttrList(attrs);\n }\n for(var attr in attrs){\n if(attrs.hasOwnProperty(attr)) {\n this[attr] = attrs[attr];\n }\n }\n }\n\n decimalInteger(attrName) {\n const intValue = parseInt(this[attrName], 10);\n if (intValue > Number.MAX_SAFE_INTEGER) {\n return Infinity;\n }\n return intValue;\n }\n\n hexadecimalInteger(attrName) {\n if(this[attrName]) {\n let stringValue = (this[attrName] || '0x').slice(2);\n stringValue = ((stringValue.length & 1) ? '0' : '') + stringValue;\n\n const value = new Uint8Array(stringValue.length / 2);\n for (let i = 0; i < stringValue.length / 2; i++) {\n value[i] = parseInt(stringValue.slice(i * 2, i * 2 + 2), 16);\n }\n return value;\n } else {\n return null;\n }\n }\n\n hexadecimalIntegerAsNumber(attrName) {\n const intValue = parseInt(this[attrName], 16);\n if (intValue > Number.MAX_SAFE_INTEGER) {\n return Infinity;\n }\n return intValue;\n }\n\n decimalFloatingPoint(attrName) {\n return parseFloat(this[attrName]);\n }\n\n enumeratedString(attrName) {\n return this[attrName];\n }\n\n decimalResolution(attrName) {\n const res = /^(\\d+)x(\\d+)$/.exec(this[attrName]);\n if (res === null) {\n return undefined;\n }\n return {\n width: parseInt(res[1], 10),\n height: parseInt(res[2], 10)\n };\n }\n\n static parseAttrList(input) {\n const re = /\\s*(.+?)\\s*=((?:\\\".*?\\\")|.*?)(?:,|$)/g;\n var match, attrs = {};\n while ((match = re.exec(input)) !== null) {\n var value = match[2], quote = '\"';\n\n if (value.indexOf(quote) === 0 &&\n value.lastIndexOf(quote) === (value.length-1)) {\n value = value.slice(1, -1);\n }\n attrs[match[1]] = value;\n }\n return attrs;\n }\n\n}\n\nexport default AttrList;\n", - "var BinarySearch = {\n /**\n * Searches for an item in an array which matches a certain condition.\n * This requires the condition to only match one item in the array,\n * and for the array to be ordered.\n *\n * @param {Array} list The array to search.\n * @param {Function} comparisonFunction\n * Called and provided a candidate item as the first argument.\n * Should return:\n * > -1 if the item should be located at a lower index than the provided item.\n * > 1 if the item should be located at a higher index than the provided item.\n * > 0 if the item is the item you're looking for.\n *\n * @return {*} The object if it is found or null otherwise.\n */\n search: function(list, comparisonFunction) {\n var minIndex = 0;\n var maxIndex = list.length - 1;\n var currentIndex = null;\n var currentElement = null;\n \n while (minIndex <= maxIndex) {\n currentIndex = (minIndex + maxIndex) / 2 | 0;\n currentElement = list[currentIndex];\n \n var comparisonResult = comparisonFunction(currentElement);\n if (comparisonResult > 0) {\n minIndex = currentIndex + 1;\n }\n else if (comparisonResult < 0) {\n maxIndex = currentIndex - 1;\n }\n else {\n return currentElement;\n }\n }\n \n return null;\n }\n};\n\nmodule.exports = BinarySearch;\n", - "/*\n * CEA-708 interpreter\n*/\n\nclass CEA708Interpreter {\n\n constructor() {\n }\n\n attach(media) {\n this.media = media;\n this.display = [];\n this.memory = [];\n }\n\n detach()\n {\n this.clear();\n }\n\n destroy() {\n }\n\n _createCue()\n {\n var VTTCue = window.VTTCue || window.TextTrackCue;\n\n var cue = this.cue = new VTTCue(-1, -1, '');\n cue.text = '';\n cue.pauseOnExit = false;\n\n // make sure it doesn't show up before it's ready\n cue.startTime = Number.MAX_VALUE;\n\n // show it 'forever' once we do show it\n // (we'll set the end time once we know it later)\n cue.endTime = Number.MAX_VALUE;\n\n this.memory.push(cue);\n }\n\n clear()\n {\n var textTrack = this._textTrack;\n if (textTrack && textTrack.cues)\n {\n while (textTrack.cues.length > 0)\n {\n textTrack.removeCue(textTrack.cues[0]);\n }\n }\n }\n\n push(timestamp, bytes)\n {\n if (!this.cue)\n {\n this._createCue();\n }\n\n var count = bytes[0] & 31;\n var position = 2;\n var tmpByte, ccbyte1, ccbyte2, ccValid, ccType;\n\n for (var j=0; j= 0x30 && ccbyte2 <= 0x3F)\n {\n // extended chars, e.g. musical note, accents\n switch (ccbyte2)\n {\n case 48:\n this.cue.text += '®';\n break;\n case 49:\n this.cue.text += '°';\n break;\n case 50:\n this.cue.text += '½';\n break;\n case 51:\n this.cue.text += '¿';\n break;\n case 52:\n this.cue.text += '™';\n break;\n case 53:\n this.cue.text += '¢';\n break;\n case 54:\n this.cue.text += '';\n break;\n case 55:\n this.cue.text += '£';\n break;\n case 56:\n this.cue.text += '♪';\n break;\n case 57:\n this.cue.text += ' ';\n break;\n case 58:\n this.cue.text += 'è';\n break;\n case 59:\n this.cue.text += 'â';\n break;\n case 60:\n this.cue.text += 'ê';\n break;\n case 61:\n this.cue.text += 'î';\n break;\n case 62:\n this.cue.text += 'ô';\n break;\n case 63:\n this.cue.text += 'û';\n break;\n }\n }\n if ((ccbyte1 === 0x11 || ccbyte1 === 0x19) && ccbyte2 >= 0x20 && ccbyte2 <= 0x2F)\n {\n // Mid-row codes: color/underline\n switch (ccbyte2)\n {\n case 0x20:\n // White\n break;\n case 0x21:\n // White Underline\n break;\n case 0x22:\n // Green\n break;\n case 0x23:\n // Green Underline\n break;\n case 0x24:\n // Blue\n break;\n case 0x25:\n // Blue Underline\n break;\n case 0x26:\n // Cyan\n break;\n case 0x27:\n // Cyan Underline\n break;\n case 0x28:\n // Red\n break;\n case 0x29:\n // Red Underline\n break;\n case 0x2A:\n // Yellow\n break;\n case 0x2B:\n // Yellow Underline\n break;\n case 0x2C:\n // Magenta\n break;\n case 0x2D:\n // Magenta Underline\n break;\n case 0x2E:\n // Italics\n break;\n case 0x2F:\n // Italics Underline\n break;\n }\n }\n if ((ccbyte1 === 0x14 || ccbyte1 === 0x1C) && ccbyte2 >= 0x20 && ccbyte2 <= 0x2F)\n {\n // Mid-row codes: color/underline\n switch (ccbyte2)\n {\n case 0x20:\n // TODO: shouldn't affect roll-ups...\n this._clearActiveCues(timestamp);\n // RCL: Resume Caption Loading\n // begin pop on\n break;\n case 0x21:\n // BS: Backspace\n this.cue.text = this.cue.text.substr(0, this.cue.text.length-1);\n break;\n case 0x22:\n // AOF: reserved (formerly alarm off)\n break;\n case 0x23:\n // AON: reserved (formerly alarm on)\n break;\n case 0x24:\n // DER: Delete to end of row\n break;\n case 0x25:\n // RU2: roll-up 2 rows\n //this._rollup(2);\n break;\n case 0x26:\n // RU3: roll-up 3 rows\n //this._rollup(3);\n break;\n case 0x27:\n // RU4: roll-up 4 rows\n //this._rollup(4);\n break;\n case 0x28:\n // FON: Flash on\n break;\n case 0x29:\n // RDC: Resume direct captioning\n this._clearActiveCues(timestamp);\n break;\n case 0x2A:\n // TR: Text Restart\n break;\n case 0x2B:\n // RTD: Resume Text Display\n break;\n case 0x2C:\n // EDM: Erase Displayed Memory\n this._clearActiveCues(timestamp);\n break;\n case 0x2D:\n // CR: Carriage Return\n // only affects roll-up\n //this._rollup(1);\n break;\n case 0x2E:\n // ENM: Erase non-displayed memory\n this._text = '';\n break;\n case 0x2F:\n this._flipMemory(timestamp);\n // EOC: End of caption\n // hide any displayed captions and show any hidden one\n break;\n }\n }\n if ((ccbyte1 === 0x17 || ccbyte1 === 0x1F) && ccbyte2 >= 0x21 && ccbyte2 <= 0x23)\n {\n // Mid-row codes: color/underline\n switch (ccbyte2)\n {\n case 0x21:\n // TO1: tab offset 1 column\n break;\n case 0x22:\n // TO1: tab offset 2 column\n break;\n case 0x23:\n // TO1: tab offset 3 column\n break;\n }\n }\n else {\n // Probably a pre-amble address code\n }\n }\n }\n }\n }\n\n _fromCharCode(tmpByte)\n {\n switch (tmpByte)\n {\n case 42:\n return 'á';\n\n case 2:\n return 'á';\n\n case 2:\n return 'é';\n\n case 4:\n return 'í';\n\n case 5:\n return 'ó';\n\n case 6:\n return 'ú';\n\n case 3:\n return 'ç';\n\n case 4:\n return '÷';\n\n case 5:\n return 'Ñ';\n\n case 6:\n return 'ñ';\n\n case 7:\n return '█';\n\n default:\n return String.fromCharCode(tmpByte);\n }\n }\n\n _flipMemory(timestamp)\n {\n this._clearActiveCues(timestamp);\n this._flushCaptions(timestamp);\n }\n\n _flushCaptions(timestamp)\n {\n if (!this._has708)\n {\n this._textTrack = this.media.addTextTrack('captions', 'English', 'en');\n this._has708 = true;\n }\n\n for(let memoryItem of this.memory)\n {\n memoryItem.startTime = timestamp;\n this._textTrack.addCue(memoryItem);\n this.display.push(memoryItem);\n }\n\n this.memory = [];\n this.cue = null;\n }\n\n _clearActiveCues(timestamp)\n {\n for (let displayItem of this.display)\n {\n displayItem.endTime = timestamp;\n }\n\n this.display = [];\n }\n\n/* _rollUp(n)\n {\n // TODO: implement roll-up captions\n }\n*/\n _clearBufferedCues()\n {\n //remove them all...\n }\n\n}\n\nexport default CEA708Interpreter;\n\n", - "/*\n * compute an Exponential Weighted moving average\n * - https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average\n * - heavily inspired from shaka-player\n */\n\nclass EWMA {\n\n // About half of the estimated value will be from the last |halfLife| samples by weight.\n constructor(halfLife) {\n // Larger values of alpha expire historical data more slowly.\n this.alpha_ = halfLife ? Math.exp(Math.log(0.5) / halfLife) : 0;\n this.estimate_ = 0;\n this.totalWeight_ = 0;\n }\n\n sample(weight,value) {\n var adjAlpha = Math.pow(this.alpha_, weight);\n this.estimate_ = value * (1 - adjAlpha) + adjAlpha * this.estimate_;\n this.totalWeight_ += weight;\n }\n\n getTotalWeight() {\n return this.totalWeight_;\n }\n\n getEstimate() {\n if (this.alpha_) {\n var zeroFactor = 1 - Math.pow(this.alpha_, this.totalWeight_);\n return this.estimate_ / zeroFactor;\n } else {\n return this.estimate_;\n }\n }\n}\n\nexport default EWMA;\n", - "'use strict';\n\nfunction noop() {}\n\nconst fakeLogger = {\n trace: noop,\n debug: noop,\n log: noop,\n warn: noop,\n info: noop,\n error: noop\n};\n\nlet exportedLogger = fakeLogger;\n\n//let lastCallTime;\n// function formatMsgWithTimeInfo(type, msg) {\n// const now = Date.now();\n// const diff = lastCallTime ? '+' + (now - lastCallTime) : '0';\n// lastCallTime = now;\n// msg = (new Date(now)).toISOString() + ' | [' + type + '] > ' + msg + ' ( ' + diff + ' ms )';\n// return msg;\n// }\n\nfunction formatMsg(type, msg) {\n msg = '[' + type + '] > ' + msg;\n return msg;\n}\n\nfunction consolePrintFn(type) {\n const func = window.console[type];\n if (func) {\n return function(...args) {\n if(args[0]) {\n args[0] = formatMsg(type, args[0]);\n }\n func.apply(window.console, args);\n };\n }\n return noop;\n}\n\nfunction exportLoggerFunctions(debugConfig, ...functions) {\n functions.forEach(function(type) {\n exportedLogger[type] = debugConfig[type] ? debugConfig[type].bind(debugConfig) : consolePrintFn(type);\n });\n}\n\nexport var enableLogs = function(debugConfig) {\n if (debugConfig === true || typeof debugConfig === 'object') {\n exportLoggerFunctions(debugConfig,\n // Remove out from list here to hard-disable a log-level\n //'trace',\n 'debug',\n 'log',\n 'info',\n 'warn',\n 'error'\n );\n // Some browsers don't allow to use bind on console object anyway\n // fallback to default if needed\n try {\n exportedLogger.log();\n } catch (e) {\n exportedLogger = fakeLogger;\n }\n }\n else {\n exportedLogger = fakeLogger;\n }\n};\n\nexport var logger = exportedLogger;\n", - "var URLHelper = {\n // build an absolute URL from a relative one using the provided baseURL\n // if relativeURL is an absolute URL it will be returned as is.\n buildAbsoluteURL: function(baseURL, relativeURL) {\n // remove any remaining space and CRLF\n relativeURL = relativeURL.trim();\n if (/^[a-z]+:/i.test(relativeURL)) {\n // complete url, not relative\n return relativeURL;\n }\n\n var relativeURLQuery = null;\n var relativeURLHash = null;\n\n var relativeURLHashSplit = /^([^#]*)(.*)$/.exec(relativeURL);\n if (relativeURLHashSplit) {\n relativeURLHash = relativeURLHashSplit[2];\n relativeURL = relativeURLHashSplit[1];\n }\n var relativeURLQuerySplit = /^([^\\?]*)(.*)$/.exec(relativeURL);\n if (relativeURLQuerySplit) {\n relativeURLQuery = relativeURLQuerySplit[2];\n relativeURL = relativeURLQuerySplit[1];\n }\n\n var baseURLHashSplit = /^([^#]*)(.*)$/.exec(baseURL);\n if (baseURLHashSplit) {\n baseURL = baseURLHashSplit[1];\n }\n var baseURLQuerySplit = /^([^\\?]*)(.*)$/.exec(baseURL);\n if (baseURLQuerySplit) {\n baseURL = baseURLQuerySplit[1];\n }\n\n var baseURLDomainSplit = /^(([a-z]+:)?\\/\\/[a-z0-9\\.\\-_~]+(:[0-9]+)?)?(\\/.*)$/i.exec(baseURL);\n if (!baseURLDomainSplit) {\n throw new Error('Error trying to parse base URL.');\n }\n \n // e.g. 'http:', 'https:', ''\n var baseURLProtocol = baseURLDomainSplit[2] || '';\n // e.g. 'http://example.com', '//example.com', ''\n var baseURLProtocolDomain = baseURLDomainSplit[1] || '';\n // e.g. '/a/b/c/playlist.m3u8'\n var baseURLPath = baseURLDomainSplit[4];\n\n var builtURL = null;\n if (/^\\/\\//.test(relativeURL)) {\n // relative url starts wth '//' so copy protocol (which may be '' if baseUrl didn't provide one)\n builtURL = baseURLProtocol+'//'+URLHelper.buildAbsolutePath('', relativeURL.substring(2));\n }\n else if (/^\\//.test(relativeURL)) {\n // relative url starts with '/' so start from root of domain\n builtURL = baseURLProtocolDomain+'/'+URLHelper.buildAbsolutePath('', relativeURL.substring(1));\n }\n else {\n builtURL = URLHelper.buildAbsolutePath(baseURLProtocolDomain+baseURLPath, relativeURL);\n }\n\n // put the query and hash parts back\n if (relativeURLQuery) {\n builtURL += relativeURLQuery;\n }\n if (relativeURLHash) {\n builtURL += relativeURLHash;\n }\n return builtURL;\n },\n\n // build an absolute path using the provided basePath\n // adapted from https://developer.mozilla.org/en-US/docs/Web/API/document/cookie#Using_relative_URLs_in_the_path_parameter\n // this does not handle the case where relativePath is \"/\" or \"//\". These cases should be handled outside this.\n buildAbsolutePath: function(basePath, relativePath) {\n var sRelPath = relativePath;\n var nUpLn, sDir = '', sPath = basePath.replace(/[^\\/]*$/, sRelPath.replace(/(\\/|^)(?:\\.?\\/+)+/g, '$1'));\n for (var nEnd, nStart = 0; nEnd = sPath.indexOf('/../', nStart), nEnd > -1; nStart = nEnd + nUpLn) {\n nUpLn = /^\\/(?:\\.\\.\\/)*/.exec(sPath.slice(nEnd))[0].length;\n sDir = (sDir + sPath.substring(nStart, nEnd)).replace(new RegExp('(?:\\\\\\/+[^\\\\\\/]*){0,' + ((nUpLn - 1) / 3) + '}$'), '/');\n }\n return sDir + sPath.substr(nStart);\n }\n};\n\nmodule.exports = URLHelper;\n", - "/**\n * XHR based logger\n*/\n\nimport {logger} from '../utils/logger';\n\nclass XhrLoader {\n\n constructor(config) {\n if (config && config.xhrSetup) {\n this.xhrSetup = config.xhrSetup;\n }\n }\n\n destroy() {\n this.abort();\n this.loader = null;\n }\n\n abort() {\n var loader = this.loader,\n timeoutHandle = this.timeoutHandle;\n if (loader && loader.readyState !== 4) {\n this.stats.aborted = true;\n loader.abort();\n }\n if (timeoutHandle) {\n window.clearTimeout(timeoutHandle);\n }\n }\n\n load(url, responseType, onSuccess, onError, onTimeout, timeout, maxRetry, retryDelay, onProgress = null, frag = null) {\n this.url = url;\n if (frag && !isNaN(frag.byteRangeStartOffset) && !isNaN(frag.byteRangeEndOffset)) {\n this.byteRange = frag.byteRangeStartOffset + '-' + (frag.byteRangeEndOffset-1);\n }\n this.responseType = responseType;\n this.onSuccess = onSuccess;\n this.onProgress = onProgress;\n this.onTimeout = onTimeout;\n this.onError = onError;\n this.stats = {trequest: performance.now(), retry: 0};\n this.timeout = timeout;\n this.maxRetry = maxRetry;\n this.retryDelay = retryDelay;\n this.loadInternal();\n }\n\n loadInternal() {\n var xhr;\n\n if (typeof XDomainRequest !== 'undefined') {\n xhr = this.loader = new XDomainRequest();\n } else {\n xhr = this.loader = new XMLHttpRequest();\n }\n\n xhr.onloadend = this.loadend.bind(this);\n xhr.onprogress = this.loadprogress.bind(this);\n\n xhr.open('GET', this.url, true);\n if (this.byteRange) {\n xhr.setRequestHeader('Range', 'bytes=' + this.byteRange);\n }\n xhr.responseType = this.responseType;\n let stats = this.stats;\n stats.tfirst = 0;\n stats.loaded = 0;\n if (this.xhrSetup) {\n this.xhrSetup(xhr, this.url);\n }\n this.timeoutHandle = window.setTimeout(this.loadtimeout.bind(this), this.timeout);\n xhr.send();\n }\n\n loadend(event) {\n var xhr = event.currentTarget,\n status = xhr.status,\n stats = this.stats;\n // don't proceed if xhr has been aborted\n if (!stats.aborted) {\n // http status between 200 to 299 are all successful\n if (status >= 200 && status < 300) {\n window.clearTimeout(this.timeoutHandle);\n stats.tload = Math.max(stats.tfirst,performance.now());\n this.onSuccess(event, stats);\n } else {\n // error ...\n if (stats.retry < this.maxRetry) {\n logger.warn(`${status} while loading ${this.url}, retrying in ${this.retryDelay}...`);\n this.destroy();\n window.setTimeout(this.loadInternal.bind(this), this.retryDelay);\n // exponential backoff\n this.retryDelay = Math.min(2 * this.retryDelay, 64000);\n stats.retry++;\n } else {\n window.clearTimeout(this.timeoutHandle);\n logger.error(`${status} while loading ${this.url}` );\n this.onError(event);\n }\n }\n }\n }\n\n loadtimeout(event) {\n logger.warn(`timeout while loading ${this.url}` );\n this.onTimeout(event, this.stats);\n }\n\n loadprogress(event) {\n var stats = this.stats;\n if (stats.tfirst === 0) {\n stats.tfirst = Math.max(performance.now(), stats.trequest);\n }\n stats.loaded = event.loaded;\n if (this.onProgress) {\n this.onProgress(event, stats);\n }\n }\n}\n\nexport default XhrLoader;\n" - ] -} \ No newline at end of file diff --git a/dashboard-ui/bower_components/hls.js/misc/mp4-inspector.js b/dashboard-ui/bower_components/hls.js/misc/mp4-inspector.js deleted file mode 100644 index 47b2cf531..000000000 --- a/dashboard-ui/bower_components/hls.js/misc/mp4-inspector.js +++ /dev/null @@ -1,688 +0,0 @@ -(function() { -'use strict'; - -var - DataView = window.DataView, - /** - * Returns the string representation of an ASCII encoded four byte buffer. - * @param buffer {Uint8Array} a four-byte buffer to translate - * @return {string} the corresponding string - */ - parseType = function(buffer) { - var result = ''; - result += String.fromCharCode(buffer[0]); - result += String.fromCharCode(buffer[1]); - result += String.fromCharCode(buffer[2]); - result += String.fromCharCode(buffer[3]); - return result; - }, - parseMp4Date = function(seconds) { - return new Date(seconds * 1000 - 2082844800000); - }, - parseSampleFlags = function(flags) { - return { - isLeading: (flags[0] & 0x0c) >>> 2, - dependsOn: flags[0] & 0x03, - isDependedOn: (flags[1] & 0xc0) >>> 6, - hasRedundancy: (flags[1] & 0x30) >>> 4, - paddingValue: (flags[1] & 0x0e) >>> 1, - isNonSyncSample: flags[1] & 0x01, - degradationPriority: (flags[2] << 8) | flags[3] - }; - }, - nalParse = function(avcStream) { - var - avcView = new DataView(avcStream.buffer, avcStream.byteOffset, avcStream.byteLength), - result = [], - i, - length; - for (i = 0; i < avcStream.length; i += length) { - length = avcView.getUint32(i); - i += 4; - switch(avcStream[i] & 0x1F) { - case 0x01: - result.push('NDR'); - break; - case 0x05: - result.push('IDR'); - break; - case 0x06: - result.push('SEI'); - break; - case 0x07: - result.push('SPS'); - break; - case 0x08: - result.push('PPS'); - break; - case 0x09: - result.push('AUD'); - break; - default: - result.push(avcStream[i] & 0x1F); - break; - } - } - return result; - }, - - // registry of handlers for individual mp4 box types - parse = { - // codingname, not a first-class box type. stsd entries share the - // same format as real boxes so the parsing infrastructure can be - // shared - avc1: function(data) { - var view = new DataView(data.buffer, data.byteOffset, data.byteLength); - return { - dataReferenceIndex: view.getUint16(6), - width: view.getUint16(24), - height: view.getUint16(26), - horizresolution: view.getUint16(28) + (view.getUint16(30) / 16), - vertresolution: view.getUint16(32) + (view.getUint16(34) / 16), - frameCount: view.getUint16(40), - depth: view.getUint16(74), - config: mp4toJSON(data.subarray(78, data.byteLength)) - }; - }, - avcC: function(data) { - var - view = new DataView(data.buffer, data.byteOffset, data.byteLength), - result = { - configurationVersion: data[0], - avcProfileIndication: data[1], - profileCompatibility: data[2], - avcLevelIndication: data[3], - lengthSizeMinusOne: data[4] & 0x03, - sps: [], - pps: [] - }, - numOfSequenceParameterSets = data[5] & 0x1f, - numOfPictureParameterSets, - nalSize, - offset, - i; - - // iterate past any SPSs - offset = 6; - for (i = 0; i < numOfSequenceParameterSets; i++) { - nalSize = view.getUint16(offset); - offset += 2; - result.sps.push(new Uint8Array(data.subarray(offset, offset + nalSize))); - offset += nalSize; - } - // iterate past any PPSs - numOfPictureParameterSets = data[offset]; - offset++; - for (i = 0; i < numOfPictureParameterSets; i++) { - nalSize = view.getUint16(offset); - offset += 2; - result.pps.push(new Uint8Array(data.subarray(offset, offset + nalSize))); - offset += nalSize; - } - return result; - }, - btrt: function(data) { - var view = new DataView(data.buffer, data.byteOffset, data.byteLength); - return { - bufferSizeDB: view.getUint32(0), - maxBitrate: view.getUint32(4), - avgBitrate: view.getUint32(8) - }; - }, - ftyp: function(data) { - var - view = new DataView(data.buffer, data.byteOffset, data.byteLength), - result = { - majorBrand: parseType(data.subarray(0, 4)), - minorVersion: view.getUint32(4), - compatibleBrands: [] - }, - i = 8; - while (i < data.byteLength) { - result.compatibleBrands.push(parseType(data.subarray(i, i + 4))); - i += 4; - } - return result; - }, - dinf: function(data) { - return { - boxes: mp4toJSON(data) - }; - }, - dref: function(data) { - return { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)), - dataReferences: mp4toJSON(data.subarray(8)) - }; - }, - hdlr: function(data) { - var - view = new DataView(data.buffer, data.byteOffset, data.byteLength), - result = { - version: view.getUint8(0), - flags: new Uint8Array(data.subarray(1, 4)), - handlerType: parseType(data.subarray(8, 12)), - name: '' - }, - i = 8; - - // parse out the name field - for (i = 24; i < data.byteLength; i++) { - if (data[i] === 0x00) { - // the name field is null-terminated - i++; - break; - } - result.name += String.fromCharCode(data[i]); - } - // decode UTF-8 to javascript's internal representation - // see http://ecmanaut.blogspot.com/2006/07/encoding-decoding-utf8-in-javascript.html - result.name = window.decodeURIComponent(window.escape(result.name)); - - return result; - }, - mdat: function(data) { - return { - byteLength: data.byteLength, - nals: nalParse(data) - }; - }, - mdhd: function(data) { - var - view = new DataView(data.buffer, data.byteOffset, data.byteLength), - i = 4, - language, - result = { - version: view.getUint8(0), - flags: new Uint8Array(data.subarray(1, 4)), - language: '' - }; - if (result.version === 1) { - i += 4; - result.creationTime = parseMp4Date(view.getUint32(i)); // truncating top 4 bytes - i += 8; - result.modificationTime = parseMp4Date(view.getUint32(i)); // truncating top 4 bytes - i += 4; - result.timescale = view.getUint32(i); - i += 8; - result.duration = view.getUint32(i); // truncating top 4 bytes - } else { - result.creationTime = parseMp4Date(view.getUint32(i)); - i += 4; - result.modificationTime = parseMp4Date(view.getUint32(i)); - i += 4; - result.timescale = view.getUint32(i); - i += 4; - result.duration = view.getUint32(i); - } - i += 4; - // language is stored as an ISO-639-2/T code in an array of three 5-bit fields - // each field is the packed difference between its ASCII value and 0x60 - language = view.getUint16(i); - result.language += String.fromCharCode((language >> 10) + 0x60); - result.language += String.fromCharCode(((language & 0x03c0) >> 5) + 0x60); - result.language += String.fromCharCode((language & 0x1f) + 0x60); - - return result; - }, - mdia: function(data) { - return { - boxes: mp4toJSON(data) - }; - }, - mfhd: function(data) { - return { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)), - sequenceNumber: (data[4] << 24) | - (data[5] << 16) | - (data[6] << 8) | - (data[7]) - }; - }, - minf: function(data) { - return { - boxes: mp4toJSON(data) - }; - }, - moof: function(data) { - return { - boxes: mp4toJSON(data) - }; - }, - moov: function(data) { - return { - boxes: mp4toJSON(data) - }; - }, - mvex: function(data) { - return { - boxes: mp4toJSON(data) - }; - }, - mvhd: function(data) { - var - view = new DataView(data.buffer, data.byteOffset, data.byteLength), - i = 4, - result = { - version: view.getUint8(0), - flags: new Uint8Array(data.subarray(1, 4)) - }; - - if (result.version === 1) { - i += 4; - result.creationTime = parseMp4Date(view.getUint32(i)); // truncating top 4 bytes - i += 8; - result.modificationTime = parseMp4Date(view.getUint32(i)); // truncating top 4 bytes - i += 4; - result.timescale = view.getUint32(i); - i += 8; - result.duration = view.getUint32(i); // truncating top 4 bytes - } else { - result.creationTime = parseMp4Date(view.getUint32(i)); - i += 4; - result.modificationTime = parseMp4Date(view.getUint32(i)); - i += 4; - result.timescale = view.getUint32(i); - i += 4; - result.duration = view.getUint32(i); - } - i += 4; - - // convert fixed-point, base 16 back to a number - result.rate = view.getUint16(i) + (view.getUint16(i + 2) / 16); - i += 4; - result.volume = view.getUint8(i) + (view.getUint8(i + 1) / 8); - i += 2; - i += 2; - i += 2 * 4; - result.matrix = new Uint32Array(data.subarray(i, i + (9 * 4))); - i += 9 * 4; - i += 6 * 4; - result.nextTrackId = view.getUint32(i); - return result; - }, - pdin: function(data) { - var view = new DataView(data.buffer, data.byteOffset, data.byteLength); - return { - version: view.getUint8(0), - flags: new Uint8Array(data.subarray(1, 4)), - rate: view.getUint32(4), - initialDelay: view.getUint32(8) - }; - }, - sdtp: function(data) { - var - result = { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)), - samples: [] - }, i; - - for (i = 4; i < data.byteLength; i++) { - result.samples.push({ - dependsOn: (data[i] & 0x30) >> 4, - isDependedOn: (data[i] & 0x0c) >> 2, - hasRedundancy: data[i] & 0x03 - }); - } - return result; - }, - sidx: function(data) { - var view = new DataView(data.buffer, data.byteOffset, data.byteLength), - result = { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)), - references: [], - referenceId: view.getUint32(4), - timescale: view.getUint32(8), - earliestPresentationTime: view.getUint32(12), - firstOffset: view.getUint32(16) - }, - referenceCount = view.getUint16(22), - i; - - for (i = 24; referenceCount; i += 12, referenceCount-- ) { - result.references.push({ - referenceType: (data[i] & 0x80) >>> 7, - referencedSize: view.getUint32(i) & 0x7FFFFFFF, - subsegmentDuration: view.getUint32(i + 4), - startsWithSap: !!(data[i + 8] & 0x80), - sapType: (data[i + 8] & 0x70) >>> 4, - sapDeltaTime: view.getUint32(i + 8) & 0x0FFFFFFF - }); - } - - return result; - }, - stbl: function(data) { - return { - boxes: mp4toJSON(data) - }; - }, - stco: function(data) { - var - view = new DataView(data.buffer, data.byteOffset, data.byteLength), - result = { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)), - chunkOffsets: [] - }, - entryCount = view.getUint32(4), - i; - for (i = 8; entryCount; i += 4, entryCount--) { - result.chunkOffsets.push(view.getUint32(i)); - } - return result; - }, - stsc: function(data) { - var - view = new DataView(data.buffer, data.byteOffset, data.byteLength), - entryCount = view.getUint32(4), - result = { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)), - sampleToChunks: [] - }, - i; - for (i = 8; entryCount; i += 12, entryCount--) { - result.sampleToChunks.push({ - firstChunk: view.getUint32(i), - samplesPerChunk: view.getUint32(i + 4), - sampleDescriptionIndex: view.getUint32(i + 8) - }); - } - return result; - }, - stsd: function(data) { - return { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)), - sampleDescriptions: mp4toJSON(data.subarray(8)) - }; - }, - stsz: function(data) { - var - view = new DataView(data.buffer, data.byteOffset, data.byteLength), - result = { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)), - sampleSize: view.getUint32(4), - entries: [] - }, - i; - for (i = 12; i < data.byteLength; i += 4) { - result.entries.push(view.getUint32(i)); - } - return result; - }, - stts: function(data) { - var - view = new DataView(data.buffer, data.byteOffset, data.byteLength), - result = { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)), - timeToSamples: [] - }, - entryCount = view.getUint32(4), - i; - - for (i = 8; entryCount; i += 8, entryCount--) { - result.timeToSamples.push({ - sampleCount: view.getUint32(i), - sampleDelta: view.getUint32(i + 4) - }); - } - return result; - }, - styp: function(data) { - return parse.ftyp(data); - }, - tfdt: function(data) { - return { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)), - baseMediaDecodeTime: data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7] - }; - }, - tfhd: function(data) { - var - view = new DataView(data.buffer, data.byteOffset, data.byteLength), - result = { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)), - trackId: view.getUint32(4) - }, - baseDataOffsetPresent = result.flags[2] & 0x01, - sampleDescriptionIndexPresent = result.flags[2] & 0x02, - defaultSampleDurationPresent = result.flags[2] & 0x08, - defaultSampleSizePresent = result.flags[2] & 0x10, - defaultSampleFlagsPresent = result.flags[2] & 0x20, - i; - - i = 8; - if (baseDataOffsetPresent) { - i += 4; // truncate top 4 bytes - result.baseDataOffset = view.getUint32(12); - i += 4; - } - if (sampleDescriptionIndexPresent) { - result.sampleDescriptionIndex = view.getUint32(i); - i += 4; - } - if (defaultSampleDurationPresent) { - result.defaultSampleDuration = view.getUint32(i); - i += 4; - } - if (defaultSampleSizePresent) { - result.defaultSampleSize = view.getUint32(i); - i += 4; - } - if (defaultSampleFlagsPresent) { - result.defaultSampleFlags = view.getUint32(i); - } - return result; - }, - tkhd: function(data) { - var - view = new DataView(data.buffer, data.byteOffset, data.byteLength), - i = 4, - result = { - version: view.getUint8(0), - flags: new Uint8Array(data.subarray(1, 4)), - }; - if (result.version === 1) { - i += 4; - result.creationTime = parseMp4Date(view.getUint32(i)); // truncating top 4 bytes - i += 8; - result.modificationTime = parseMp4Date(view.getUint32(i)); // truncating top 4 bytes - i += 4; - result.trackId = view.getUint32(i); - i += 4; - i += 8; - result.duration = view.getUint32(i); // truncating top 4 bytes - } else { - result.creationTime = parseMp4Date(view.getUint32(i)); - i += 4; - result.modificationTime = parseMp4Date(view.getUint32(i)); - i += 4; - result.trackId = view.getUint32(i); - i += 4; - i += 4; - result.duration = view.getUint32(i); - } - i += 4; - i += 2 * 4; - result.layer = view.getUint16(i); - i += 2; - result.alternateGroup = view.getUint16(i); - i += 2; - // convert fixed-point, base 16 back to a number - result.volume = view.getUint8(i) + (view.getUint8(i + 1) / 8); - i += 2; - i += 2; - result.matrix = new Uint32Array(data.subarray(i, i + (9 * 4))); - i += 9 * 4; - result.width = view.getUint16(i) + (view.getUint16(i + 2) / 16); - i += 4; - result.height = view.getUint16(i) + (view.getUint16(i + 2) / 16); - return result; - }, - traf: function(data) { - return { - boxes: mp4toJSON(data) - }; - }, - trak: function(data) { - return { - boxes: mp4toJSON(data) - }; - }, - trex: function(data) { - var view = new DataView(data.buffer, data.byteOffset, data.byteLength); - return { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)), - trackId: view.getUint32(4), - defaultSampleDescriptionIndex: view.getUint32(8), - defaultSampleDuration: view.getUint32(12), - defaultSampleSize: view.getUint32(16), - sampleDependsOn: data[20] & 0x03, - sampleIsDependedOn: (data[21] & 0xc0) >> 6, - sampleHasRedundancy: (data[21] & 0x30) >> 4, - samplePaddingValue: (data[21] & 0x0e) >> 1, - sampleIsDifferenceSample: !!(data[21] & 0x01), - sampleDegradationPriority: view.getUint16(22) - }; - }, - trun: function(data) { - var - result = { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)), - samples: [] - }, - view = new DataView(data.buffer, data.byteOffset, data.byteLength), - dataOffsetPresent = result.flags[2] & 0x01, - firstSampleFlagsPresent = result.flags[2] & 0x04, - sampleDurationPresent = result.flags[1] & 0x01, - sampleSizePresent = result.flags[1] & 0x02, - sampleFlagsPresent = result.flags[1] & 0x04, - sampleCompositionTimeOffsetPresent = result.flags[1] & 0x08, - sampleCount = view.getUint32(4), - offset = 8, - sample; - - if (dataOffsetPresent) { - result.dataOffset = view.getUint32(offset); - offset += 4; - } - if (firstSampleFlagsPresent && sampleCount) { - sample = { - flags: parseSampleFlags(data.subarray(offset, offset + 4)) - }; - offset += 4; - if (sampleDurationPresent) { - sample.duration = view.getUint32(offset); - offset += 4; - } - if (sampleSizePresent) { - sample.size = view.getUint32(offset); - offset += 4; - } - if (sampleCompositionTimeOffsetPresent) { - sample.compositionTimeOffset = view.getUint32(offset); - offset += 4; - } - result.samples.push(sample); - sampleCount--; - } - while (sampleCount--) { - sample = {}; - if (sampleDurationPresent) { - sample.duration = view.getUint32(offset); - offset += 4; - } - if (sampleSizePresent) { - sample.size = view.getUint32(offset); - offset += 4; - } - if (sampleFlagsPresent) { - sample.flags = parseSampleFlags(data.subarray(offset, offset + 4)); - offset += 4; - } - if (sampleCompositionTimeOffsetPresent) { - sample.compositionTimeOffset = view.getUint32(offset); - offset += 4; - } - result.samples.push(sample); - } - return result; - }, - 'url ': function(data) { - return { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)) - }; - }, - vmhd: function(data) { - //var view = new DataView(data.buffer, data.byteOffset, data.byteLength); - return { - version: data[0], - flags: new Uint8Array(data.subarray(1, 4)), - //graphicsmode: view.getUint16(4), - //opcolor: new Uint16Array([view.getUint16(6), - // view.getUint16(8), - // view.getUint16(10)]) - }; - } - }; - -/** - * Return a javascript array of box objects parsed from an ISO base - * media file. - * @param data {Uint8Array} the binary data of the media to be inspected - * @return {array} a javascript array of potentially nested box objects - */ -var mp4toJSON = function(data) { - var - i = 0, - result = [], - view = new DataView(data.buffer, data.byteOffset, data.byteLength), - size, - type, - end, - box; - - while (i < data.byteLength) { - // parse box data - size = view.getUint32(i), - type = parseType(data.subarray(i + 4, i + 8)); - end = size > 1 ? i + size : data.byteLength; - - // parse type-specific data - box = (parse[type] || function(data) { - return { - data: data - }; - })(data.subarray(i + 8, end)); - box.size = size; - box.type = type; - - // store this box and move to the next - result.push(box); - i = end; - } - return result; -}; - - -let MP4Inspect = { - mp4toJSON: mp4toJSON -}; - -export default MP4Inspect; - - -})(); diff --git a/dashboard-ui/bower_components/hls.js/misc/sync_gh.sh b/dashboard-ui/bower_components/hls.js/misc/sync_gh.sh deleted file mode 100644 index 59f7ff958..000000000 --- a/dashboard-ui/bower_components/hls.js/misc/sync_gh.sh +++ /dev/null @@ -1,5 +0,0 @@ -#/bin/sh -git checkout gh-pages -git rebase v0.5.x -git push origin gh-pages --force -git checkout v0.5.x diff --git a/dashboard-ui/bower_components/hls.js/src/controller/abr-controller.js b/dashboard-ui/bower_components/hls.js/src/controller/abr-controller.js deleted file mode 100644 index d4e7f1dea..000000000 --- a/dashboard-ui/bower_components/hls.js/src/controller/abr-controller.js +++ /dev/null @@ -1,214 +0,0 @@ -/* - * simple ABR Controller - * - compute next level based on last fragment bw heuristics - * - implement an abandon rules triggered if we have less than 2 frag buffered and if computed bw shows that we risk buffer stalling - */ - -import Event from '../events'; -import EventHandler from '../event-handler'; -import BufferHelper from '../helper/buffer-helper'; -import {ErrorDetails} from '../errors'; -import {logger} from '../utils/logger'; -import EwmaBandWidthEstimator from './ewma-bandwidth-estimator'; - -class AbrController extends EventHandler { - - constructor(hls) { - super(hls, Event.FRAG_LOADING, - Event.FRAG_LOADED, - Event.ERROR); - this.lastLoadedFragLevel = 0; - this._autoLevelCapping = -1; - this._nextAutoLevel = -1; - this.hls = hls; - this.onCheck = this.abandonRulesCheck.bind(this); - } - - destroy() { - this.clearTimer(); - EventHandler.prototype.destroy.call(this); - } - - onFragLoading(data) { - if (!this.timer) { - this.timer = setInterval(this.onCheck, 100); - } - - // lazy init of bw Estimator, rationale is that we use different params for Live/VoD - // so we need to wait for stream manifest / playlist type to instantiate it. - if (!this.bwEstimator) { - let hls = this.hls, - level = data.frag.level, - isLive = hls.levels[level].details.live, - config = hls.config, - ewmaFast, ewmaSlow; - - if (isLive) { - ewmaFast = config.abrEwmaFastLive; - ewmaSlow = config.abrEwmaSlowLive; - } else { - ewmaFast = config.abrEwmaFastVoD; - ewmaSlow = config.abrEwmaSlowVoD; - } - this.bwEstimator = new EwmaBandWidthEstimator(hls,ewmaSlow,ewmaFast,config.abrEwmaDefaultEstimate); - } - - let frag = data.frag; - frag.trequest = performance.now(); - this.fragCurrent = frag; - } - - abandonRulesCheck() { - /* - monitor fragment retrieval time... - we compute expected time of arrival of the complete fragment. - we compare it to expected time of buffer starvation - */ - let hls = this.hls, v = hls.media,frag = this.fragCurrent; - - // if loader has been destroyed or loading has been aborted, stop timer and return - if(!frag.loader || ( frag.loader.stats && frag.loader.stats.aborted)) { - logger.warn(`frag loader destroy or aborted, disarm abandonRulesCheck`); - this.clearTimer(); - return; - } - /* only monitor frag retrieval time if - (video not paused OR first fragment being loaded(ready state === HAVE_NOTHING = 0)) AND autoswitching enabled AND not lowest level (=> means that we have several levels) */ - if (v && (!v.paused || !v.readyState) && frag.autoLevel && frag.level) { - let requestDelay = performance.now() - frag.trequest; - // monitor fragment load progress after half of expected fragment duration,to stabilize bitrate - if (requestDelay > (500 * frag.duration)) { - let levels = hls.levels, - loadRate = Math.max(1,frag.loaded * 1000 / requestDelay), // byte/s; at least 1 byte/s to avoid division by zero - // compute expected fragment length using frag duration and level bitrate. also ensure that expected len is gte than already loaded size - expectedLen = Math.max(frag.loaded, Math.round(frag.duration * levels[frag.level].bitrate / 8)); - - let pos = v.currentTime; - let fragLoadedDelay = (expectedLen - frag.loaded) / loadRate; - let bufferStarvationDelay = BufferHelper.bufferInfo(v,pos,hls.config.maxBufferHole).end - pos; - // consider emergency switch down only if we have less than 2 frag buffered AND - // time to finish loading current fragment is bigger than buffer starvation delay - // ie if we risk buffer starvation if bw does not increase quickly - if (bufferStarvationDelay < 2*frag.duration && fragLoadedDelay > bufferStarvationDelay) { - let fragLevelNextLoadedDelay, nextLoadLevel; - // lets iterate through lower level and try to find the biggest one that could avoid rebuffering - // we start from current level - 1 and we step down , until we find a matching level - for (nextLoadLevel = frag.level - 1 ; nextLoadLevel >=0 ; nextLoadLevel--) { - // compute time to load next fragment at lower level - // 0.8 : consider only 80% of current bw to be conservative - // 8 = bits per byte (bps/Bps) - fragLevelNextLoadedDelay = frag.duration * levels[nextLoadLevel].bitrate / (8 * 0.8 * loadRate); - logger.log(`fragLoadedDelay/bufferStarvationDelay/fragLevelNextLoadedDelay[${nextLoadLevel}] :${fragLoadedDelay.toFixed(1)}/${bufferStarvationDelay.toFixed(1)}/${fragLevelNextLoadedDelay.toFixed(1)}`); - if (fragLevelNextLoadedDelay < bufferStarvationDelay) { - // we found a lower level that be rebuffering free with current estimated bw ! - break; - } - } - // only emergency switch down if it takes less time to load new fragment at lowest level instead - // of finishing loading current one ... - if (fragLevelNextLoadedDelay < fragLoadedDelay) { - // ensure nextLoadLevel is not negative - nextLoadLevel = Math.max(0,nextLoadLevel); - // force next load level in auto mode - hls.nextLoadLevel = nextLoadLevel; - // update bw estimate for this fragment before cancelling load (this will help reducing the bw) - this.bwEstimator.sample(requestDelay,frag.loaded); - // abort fragment loading ... - logger.warn(`loading too slow, abort fragment loading and switch to level ${nextLoadLevel}`); - //abort fragment loading - frag.loader.abort(); - this.clearTimer(); - hls.trigger(Event.FRAG_LOAD_EMERGENCY_ABORTED, {frag: frag}); - } - } - } - } - } - - onFragLoaded(data) { - var stats = data.stats; - // only update stats on first frag loading - // if same frag is loaded multiple times, it might be in browser cache, and loaded quickly - // and leading to wrong bw estimation - if (stats.aborted === undefined && data.frag.loadCounter === 1) { - this.bwEstimator.sample(performance.now() - stats.trequest,stats.loaded); - } - - // stop monitoring bw once frag loaded - this.clearTimer(); - // store level id after successful fragment load - this.lastLoadedFragLevel = data.frag.level; - // reset forced auto level value so that next level will be selected - this._nextAutoLevel = -1; - } - - onError(data) { - // stop timer in case of frag loading error - switch(data.details) { - case ErrorDetails.FRAG_LOAD_ERROR: - case ErrorDetails.FRAG_LOAD_TIMEOUT: - this.clearTimer(); - break; - default: - break; - } - } - - clearTimer() { - if (this.timer) { - clearInterval(this.timer); - this.timer = null; - } - } - - /** Return the capping/max level value that could be used by automatic level selection algorithm **/ - get autoLevelCapping() { - return this._autoLevelCapping; - } - - /** set the capping/max level value that could be used by automatic level selection algorithm **/ - set autoLevelCapping(newLevel) { - this._autoLevelCapping = newLevel; - } - - get nextAutoLevel() { - var hls = this.hls, i, maxAutoLevel, levels = hls.levels, config = hls.config; - if (this._autoLevelCapping === -1 && levels && levels.length) { - maxAutoLevel = levels.length - 1; - } else { - maxAutoLevel = this._autoLevelCapping; - } - - // in case next auto level has been forced, return it straight-away (but capped) - if (this._nextAutoLevel !== -1) { - return Math.min(this._nextAutoLevel,maxAutoLevel); - } - - let avgbw = this.bwEstimator ? this.bwEstimator.getEstimate() : config.abrEwmaDefaultEstimate, - adjustedbw; - // follow algorithm captured from stagefright : - // https://android.googlesource.com/platform/frameworks/av/+/master/media/libstagefright/httplive/LiveSession.cpp - // Pick the highest bandwidth stream below or equal to estimated bandwidth. - for (i = 0; i <= maxAutoLevel; i++) { - // consider only 80% of the available bandwidth, but if we are switching up, - // be even more conservative (70%) to avoid overestimating and immediately - // switching back. - if (i <= this.lastLoadedFragLevel) { - adjustedbw = config.abrBandWidthFactor * avgbw; - } else { - adjustedbw = config.abrBandWidthUpFactor * avgbw; - } - if (adjustedbw < levels[i].bitrate) { - return Math.max(0, i - 1); - } - } - return i - 1; - } - - set nextAutoLevel(nextLevel) { - this._nextAutoLevel = nextLevel; - } -} - -export default AbrController; - diff --git a/dashboard-ui/bower_components/hls.js/src/controller/buffer-controller.js b/dashboard-ui/bower_components/hls.js/src/controller/buffer-controller.js deleted file mode 100644 index 9a7cd18d9..000000000 --- a/dashboard-ui/bower_components/hls.js/src/controller/buffer-controller.js +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Buffer Controller -*/ - -import Event from '../events'; -import EventHandler from '../event-handler'; -import {logger} from '../utils/logger'; -import {ErrorTypes, ErrorDetails} from '../errors'; - - -class BufferController extends EventHandler { - - constructor(hls) { - super(hls, - Event.MEDIA_ATTACHING, - Event.MEDIA_DETACHING, - Event.BUFFER_RESET, - Event.BUFFER_APPENDING, - Event.BUFFER_CODECS, - Event.BUFFER_EOS, - Event.BUFFER_FLUSHING, - Event.LEVEL_UPDATED); - - // the value that we have set mediasource.duration to - // (the actual duration may be tweaked slighly by the browser) - this._msDuration = null; - // the value that we want to set mediaSource.duration to - this._levelDuration = null; - - // Source Buffer listeners - this.onsbue = this.onSBUpdateEnd.bind(this); - this.onsbe = this.onSBUpdateError.bind(this); - } - - destroy() { - EventHandler.prototype.destroy.call(this); - } - - onMediaAttaching(data) { - let media = this.media = data.media; - if (media) { - // setup the media source - var ms = this.mediaSource = new MediaSource(); - //Media Source listeners - this.onmso = this.onMediaSourceOpen.bind(this); - this.onmse = this.onMediaSourceEnded.bind(this); - this.onmsc = this.onMediaSourceClose.bind(this); - ms.addEventListener('sourceopen', this.onmso); - ms.addEventListener('sourceended', this.onmse); - ms.addEventListener('sourceclose', this.onmsc); - // link video and media Source - media.src = URL.createObjectURL(ms); - } - } - - onMediaDetaching() { - var ms = this.mediaSource; - if (ms) { - if (ms.readyState === 'open') { - try { - // endOfStream could trigger exception if any sourcebuffer is in updating state - // we don't really care about checking sourcebuffer state here, - // as we are anyway detaching the MediaSource - // let's just avoid this exception to propagate - ms.endOfStream(); - } catch(err) { - logger.warn(`onMediaDetaching:${err.message} while calling endOfStream`); - } - } - ms.removeEventListener('sourceopen', this.onmso); - ms.removeEventListener('sourceended', this.onmse); - ms.removeEventListener('sourceclose', this.onmsc); - - try { - // unlink MediaSource from video tag - this.media.src = ''; - this.media.removeAttribute('src'); - } catch(err) { - logger.warn(`onMediaDetaching:${err.message} while unlinking video.src`); - } - this.mediaSource = null; - this.media = null; - this.pendingTracks = null; - this.sourceBuffer = null; - } - this.onmso = this.onmse = this.onmsc = null; - this.hls.trigger(Event.MEDIA_DETACHED); - } - - onMediaSourceOpen() { - logger.log('media source opened'); - this.hls.trigger(Event.MEDIA_ATTACHED, { media : this.media }); - // once received, don't listen anymore to sourceopen event - this.mediaSource.removeEventListener('sourceopen', this.onmso); - // if any buffer codecs pending, treat it here. - var pendingTracks = this.pendingTracks; - if (pendingTracks) { - this.onBufferCodecs(pendingTracks); - this.pendingTracks = null; - this.doAppending(); - } - } - - onMediaSourceClose() { - logger.log('media source closed'); - } - - onMediaSourceEnded() { - logger.log('media source ended'); - } - - - onSBUpdateEnd() { - - if (this._needsFlush) { - this.doFlush(); - } - - if (this._needsEos) { - this.onBufferEos(); - } - - this.hls.trigger(Event.BUFFER_APPENDED); - - this.doAppending(); - } - - onSBUpdateError(event) { - logger.error(`sourceBuffer error:${event}`); - // according to http://www.w3.org/TR/media-source/#sourcebuffer-append-error - // this error might not always be fatal (it is fatal if decode error is set, in that case - // it will be followed by a mediaElement error ...) - this.hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.BUFFER_APPENDING_ERROR, fatal: false}); - // we don't need to do more than that, as accordin to the spec, updateend will be fired just after - } - - onBufferReset() { - var sourceBuffer = this.sourceBuffer; - if (sourceBuffer) { - for(var type in sourceBuffer) { - var sb = sourceBuffer[type]; - try { - this.mediaSource.removeSourceBuffer(sb); - sb.removeEventListener('updateend', this.onsbue); - sb.removeEventListener('error', this.onsbe); - } catch(err) { - } - } - this.sourceBuffer = null; - } - this.flushRange = []; - this.appended = 0; - } - - onBufferCodecs(tracks) { - let mediaSource = this.mediaSource; - - // delay sourcebuffer creation if media source not opened yet - if(!mediaSource || mediaSource.readyState !== 'open') { - this.pendingTracks = tracks; - return; - } - - if (!this.sourceBuffer) { - let sourceBuffer = {}; - for (let trackName in tracks) { - let track = tracks[trackName]; - // use levelCodec as first priority - let codec = track.levelCodec || track.codec; - let mimeType = `${track.container};codecs=${codec}`; - logger.log(`creating sourceBuffer with mimeType:${mimeType}`); - let sb = sourceBuffer[trackName] = mediaSource.addSourceBuffer(mimeType); - sb.addEventListener('updateend', this.onsbue); - sb.addEventListener('error', this.onsbe); - } - this.sourceBuffer = sourceBuffer; - } - } - - onBufferAppending(data) { - if (!this.segments) { - this.segments = [ data ]; - } else { - this.segments.push(data); - } - this.doAppending(); - } - - onBufferAppendFail(data) { - logger.error(`sourceBuffer error:${data.event}`); - // according to http://www.w3.org/TR/media-source/#sourcebuffer-append-error - // this error might not always be fatal (it is fatal if decode error is set, in that case - // it will be followed by a mediaElement error ...) - this.hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.BUFFER_APPENDING_ERROR, fatal: false, frag: this.fragCurrent}); - } - - onBufferEos() { - var sb = this.sourceBuffer, mediaSource = this.mediaSource; - if (!mediaSource || mediaSource.readyState !== 'open') { - return; - } - if (!((sb.audio && sb.audio.updating) || (sb.video && sb.video.updating))) { - logger.log('all media data available, signal endOfStream() to MediaSource and stop loading fragment'); - //Notify the media element that it now has all of the media data - mediaSource.endOfStream(); - this._needsEos = false; - } else { - this._needsEos = true; - } - } - - onBufferFlushing(data) { - this.flushRange.push({start: data.startOffset, end: data.endOffset}); - // attempt flush immediatly - this.flushBufferCounter = 0; - this.doFlush(); - } - - onLevelUpdated(event) { - let details = event.details; - if (details.fragments.length === 0) { - return; - } - this._levelDuration = details.totalduration + details.fragments[0].start; - this.updateMediaElementDuration(); - } - - // https://github.com/dailymotion/hls.js/issues/355 - updateMediaElementDuration() { - if (this._levelDuration === null) { - return; - } - let media = this.media; - let mediaSource = this.mediaSource; - if (!media || !mediaSource || media.readyState === 0 || mediaSource.readyState !== 'open') { - return; - } - for (let type in mediaSource.sourceBuffers) { - if (mediaSource.sourceBuffers[type].updating) { - // can't set duration whilst a buffer is updating - return; - } - } - if (this._msDuration === null) { - // initialise to the value that the media source is reporting - this._msDuration = mediaSource.duration; - } - // this._levelDuration was the last value we set. - // not using mediaSource.duration as the browser may tweak this value - // only update mediasource duration if its value increase, this is to avoid - // flushing already buffered portion when switching between quality level, as they - if (this._levelDuration > this._msDuration) { - logger.log(`Updating mediasource duration to ${this._levelDuration}`); - mediaSource.duration = this._levelDuration; - this._msDuration = this._levelDuration; - } - } - - doFlush() { - // loop through all buffer ranges to flush - while(this.flushRange.length) { - var range = this.flushRange[0]; - // flushBuffer will abort any buffer append in progress and flush Audio/Video Buffer - if (this.flushBuffer(range.start, range.end)) { - // range flushed, remove from flush array - this.flushRange.shift(); - this.flushBufferCounter = 0; - } else { - this._needsFlush = true; - // avoid looping, wait for SB update end to retrigger a flush - return; - } - } - if (this.flushRange.length === 0) { - // everything flushed - this._needsFlush = false; - - // let's recompute this.appended, which is used to avoid flush looping - var appended = 0; - var sourceBuffer = this.sourceBuffer; - if (sourceBuffer) { - for (var type in sourceBuffer) { - appended += sourceBuffer[type].buffered.length; - } - } - this.appended = appended; - this.hls.trigger(Event.BUFFER_FLUSHED); - } - } - - doAppending() { - var hls = this.hls, sourceBuffer = this.sourceBuffer, segments = this.segments; - if (sourceBuffer) { - if (this.media.error) { - segments = []; - logger.error('trying to append although a media error occured, flush segment and abort'); - return; - } - for (var type in sourceBuffer) { - if (sourceBuffer[type].updating) { - //logger.log('sb update in progress'); - return; - } - } - if (segments.length) { - var segment = segments.shift(); - try { - //logger.log(`appending ${segment.type} SB, size:${segment.data.length}); - sourceBuffer[segment.type].appendBuffer(segment.data); - this.appendError = 0; - this.appended++; - } catch(err) { - // in case any error occured while appending, put back segment in segments table - logger.error(`error while trying to append buffer:${err.message}`); - segments.unshift(segment); - var event = {type: ErrorTypes.MEDIA_ERROR}; - if(err.code !== 22) { - if (this.appendError) { - this.appendError++; - } else { - this.appendError = 1; - } - event.details = ErrorDetails.BUFFER_APPEND_ERROR; - event.frag = this.fragCurrent; - /* with UHD content, we could get loop of quota exceeded error until - browser is able to evict some data from sourcebuffer. retrying help recovering this - */ - if (this.appendError > hls.config.appendErrorMaxRetry) { - logger.log(`fail ${hls.config.appendErrorMaxRetry} times to append segment in sourceBuffer`); - segments = []; - event.fatal = true; - hls.trigger(Event.ERROR, event); - return; - } else { - event.fatal = false; - hls.trigger(Event.ERROR, event); - } - } else { - // QuotaExceededError: http://www.w3.org/TR/html5/infrastructure.html#quotaexceedederror - // let's stop appending any segments, and report BUFFER_FULL_ERROR error - this.segments = []; - event.details = ErrorDetails.BUFFER_FULL_ERROR; - hls.trigger(Event.ERROR,event); - return; - } - } - } - } - } - - /* - flush specified buffered range, - return true once range has been flushed. - as sourceBuffer.remove() is asynchronous, flushBuffer will be retriggered on sourceBuffer update end - */ - flushBuffer(startOffset, endOffset) { - var sb, i, bufStart, bufEnd, flushStart, flushEnd; - //logger.log('flushBuffer,pos/start/end: ' + this.media.currentTime + '/' + startOffset + '/' + endOffset); - // safeguard to avoid infinite looping : don't try to flush more than the nb of appended segments - if (this.flushBufferCounter < this.appended && this.sourceBuffer) { - for (var type in this.sourceBuffer) { - sb = this.sourceBuffer[type]; - if (!sb.updating) { - for (i = 0; i < sb.buffered.length; i++) { - bufStart = sb.buffered.start(i); - bufEnd = sb.buffered.end(i); - // workaround firefox not able to properly flush multiple buffered range. - if (navigator.userAgent.toLowerCase().indexOf('firefox') !== -1 && endOffset === Number.POSITIVE_INFINITY) { - flushStart = startOffset; - flushEnd = endOffset; - } else { - flushStart = Math.max(bufStart, startOffset); - flushEnd = Math.min(bufEnd, endOffset); - } - /* sometimes sourcebuffer.remove() does not flush - the exact expected time range. - to avoid rounding issues/infinite loop, - only flush buffer range of length greater than 500ms. - */ - if (Math.min(flushEnd,bufEnd) - flushStart > 0.5 ) { - this.flushBufferCounter++; - logger.log(`flush ${type} [${flushStart},${flushEnd}], of [${bufStart},${bufEnd}], pos:${this.media.currentTime}`); - sb.remove(flushStart, flushEnd); - return false; - } - } - } else { - //logger.log('abort ' + type + ' append in progress'); - // this will abort any appending in progress - //sb.abort(); - logger.warn('cannot flush, sb updating in progress'); - return false; - } - } - } else { - logger.warn('abort flushing too many retries'); - } - logger.log('buffer flushed'); - // everything flushed ! - return true; - } -} - -export default BufferController; diff --git a/dashboard-ui/bower_components/hls.js/src/controller/cap-level-controller.js b/dashboard-ui/bower_components/hls.js/src/controller/cap-level-controller.js deleted file mode 100644 index 5018bc598..000000000 --- a/dashboard-ui/bower_components/hls.js/src/controller/cap-level-controller.js +++ /dev/null @@ -1,106 +0,0 @@ -/* - * cap stream level to media size dimension controller -*/ - -import Event from '../events'; -import EventHandler from '../event-handler'; - -class CapLevelController extends EventHandler { - constructor(hls) { - super(hls, - Event.MEDIA_ATTACHING, - Event.MANIFEST_PARSED); - } - - destroy() { - if (this.hls.config.capLevelToPlayerSize) { - this.media = null; - this.autoLevelCapping = Number.POSITIVE_INFINITY; - if (this.timer) { - this.timer = clearInterval(this.timer); - } - } - } - - onMediaAttaching(data) { - this.media = data.media instanceof HTMLVideoElement ? data.media : null; - } - - onManifestParsed(data) { - if (this.hls.config.capLevelToPlayerSize) { - this.autoLevelCapping = Number.POSITIVE_INFINITY; - this.levels = data.levels; - this.hls.firstLevel = this.getMaxLevel(data.firstLevel); - clearInterval(this.timer); - this.timer = setInterval(this.detectPlayerSize.bind(this), 1000); - this.detectPlayerSize(); - } - } - - detectPlayerSize() { - if (this.media) { - let levelsLength = this.levels ? this.levels.length : 0; - if (levelsLength) { - this.hls.autoLevelCapping = this.getMaxLevel(levelsLength - 1); - if (this.hls.autoLevelCapping > this.autoLevelCapping) { - // if auto level capping has a higher value for the previous one, flush the buffer using nextLevelSwitch - // usually happen when the user go to the fullscreen mode. - this.hls.streamController.nextLevelSwitch(); - } - this.autoLevelCapping = this.hls.autoLevelCapping; - } - } - } - - /* - * returns level should be the one with the dimensions equal or greater than the media (player) dimensions (so the video will be downscaled) - */ - getMaxLevel(capLevelIndex) { - let result, - i, - level, - mWidth = this.mediaWidth, - mHeight = this.mediaHeight, - lWidth = 0, - lHeight = 0; - - for (i = 0; i <= capLevelIndex; i++) { - level = this.levels[i]; - result = i; - lWidth = level.width; - lHeight = level.height; - if (mWidth <= lWidth || mHeight <= lHeight) { - break; - } - } - return result; - } - - get contentScaleFactor() { - let pixelRatio = 1; - try { - pixelRatio = window.devicePixelRatio; - } catch(e) {} - return pixelRatio; - } - - get mediaWidth() { - let width; - if (this.media) { - width = this.media.width || this.media.clientWidth || this.media.offsetWidth; - width *= this.contentScaleFactor; - } - return width; - } - - get mediaHeight() { - let height; - if (this.media) { - height = this.media.height || this.media.clientHeight || this.media.offsetHeight; - height *= this.contentScaleFactor; - } - return height; - } -} - -export default CapLevelController; \ No newline at end of file diff --git a/dashboard-ui/bower_components/hls.js/src/controller/ewma-bandwidth-estimator.js b/dashboard-ui/bower_components/hls.js/src/controller/ewma-bandwidth-estimator.js deleted file mode 100644 index 546bce5b7..000000000 --- a/dashboard-ui/bower_components/hls.js/src/controller/ewma-bandwidth-estimator.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - * EWMA Bandwidth Estimator - * - heavily inspired from shaka-player - * Tracks bandwidth samples and estimates available bandwidth. - * Based on the minimum of two exponentially-weighted moving averages with - * different half-lives. - */ - -import EWMA from '../utils/ewma'; - - -class EwmaBandWidthEstimator { - - constructor(hls,slow,fast,defaultEstimate) { - this.hls = hls; - this.defaultEstimate_ = defaultEstimate; - this.minWeight_ = 0.001; - this.minDelayMs_ = 50; - this.slow_ = new EWMA(slow); - this.fast_ = new EWMA(fast); - } - - sample(durationMs,numBytes) { - durationMs = Math.max(durationMs, this.minDelayMs_); - var bandwidth = 8000* numBytes / durationMs, - //console.log('instant bw:'+ Math.round(bandwidth)); - // we weight sample using loading duration.... - weight = durationMs / 1000; - this.fast_.sample(weight,bandwidth); - this.slow_.sample(weight,bandwidth); - } - - - getEstimate() { - if (!this.fast_ || !this.slow_ || this.fast_.getTotalWeight() < this.minWeight_) { - return this.defaultEstimate_; - } - //console.log('slow estimate:'+ Math.round(this.slow_.getEstimate())); - //console.log('fast estimate:'+ Math.round(this.fast_.getEstimate())); - // Take the minimum of these two estimates. This should have the effect of - // adapting down quickly, but up more slowly. - return Math.min(this.fast_.getEstimate(),this.slow_.getEstimate()); - } - - destroy() { - } -} -export default EwmaBandWidthEstimator; - diff --git a/dashboard-ui/bower_components/hls.js/src/controller/fps-controller.js b/dashboard-ui/bower_components/hls.js/src/controller/fps-controller.js deleted file mode 100644 index bf9b3fe62..000000000 --- a/dashboard-ui/bower_components/hls.js/src/controller/fps-controller.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - * FPS Controller -*/ - -import Event from '../events'; -import {logger} from '../utils/logger'; - -class FPSController { - - constructor(hls) { - this.hls = hls; - this.timer = setInterval(this.checkFPS, hls.config.fpsDroppedMonitoringPeriod); - } - - destroy() { - if (this.timer) { - clearInterval(this.timer); - } - } - - checkFPS() { - var v = this.hls.video; - if (v) { - var decodedFrames = v.webkitDecodedFrameCount, droppedFrames = v.webkitDroppedFrameCount, currentTime = new Date(); - if (decodedFrames) { - if (this.lastTime) { - var currentPeriod = currentTime - this.lastTime; - var currentDropped = droppedFrames - this.lastDroppedFrames; - var currentDecoded = decodedFrames - this.lastDecodedFrames; - var decodedFPS = 1000 * currentDecoded / currentPeriod; - var droppedFPS = 1000 * currentDropped / currentPeriod; - if (droppedFPS > 0) { - logger.log(`checkFPS : droppedFPS/decodedFPS:${droppedFPS.toFixed(1)}/${decodedFPS.toFixed(1)}`); - if (currentDropped > this.hls.config.fpsDroppedMonitoringThreshold * currentDecoded) { - logger.warn('drop FPS ratio greater than max allowed value'); - this.hls.trigger(Event.FPS_DROP, {currentDropped: currentDropped, currentDecoded: currentDecoded, totalDroppedFrames: droppedFrames}); - } - } - } - this.lastTime = currentTime; - this.lastDroppedFrames = droppedFrames; - this.lastDecodedFrames = decodedFrames; - } - } - } -} - -export default FPSController; - diff --git a/dashboard-ui/bower_components/hls.js/src/controller/level-controller.js b/dashboard-ui/bower_components/hls.js/src/controller/level-controller.js deleted file mode 100644 index c0a3fff73..000000000 --- a/dashboard-ui/bower_components/hls.js/src/controller/level-controller.js +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Level Controller -*/ - -import Event from '../events'; -import EventHandler from '../event-handler'; -import {logger} from '../utils/logger'; -import {ErrorTypes, ErrorDetails} from '../errors'; - -class LevelController extends EventHandler { - - constructor(hls) { - super(hls, - Event.MANIFEST_LOADED, - Event.LEVEL_LOADED, - Event.ERROR); - this.ontick = this.tick.bind(this); - this._manualLevel = this._autoLevelCapping = -1; - } - - destroy() { - if (this.timer) { - clearTimeout(this.timer); - this.timer = null; - } - this._manualLevel = -1; - } - - startLoad() { - this.canload = true; - // speed up live playlist refresh if timer exists - if (this.timer) { - this.tick(); - } - } - - stopLoad() { - this.canload = false; - } - - onManifestLoaded(data) { - var levels0 = [], levels = [], bitrateStart, i, bitrateSet = {}, videoCodecFound = false, audioCodecFound = false, hls = this.hls; - - // regroup redundant level together - data.levels.forEach(level => { - if(level.videoCodec) { - videoCodecFound = true; - } - if(level.audioCodec) { - audioCodecFound = true; - } - var redundantLevelId = bitrateSet[level.bitrate]; - if (redundantLevelId === undefined) { - bitrateSet[level.bitrate] = levels0.length; - level.url = [level.url]; - level.urlId = 0; - levels0.push(level); - } else { - levels0[redundantLevelId].url.push(level.url); - } - }); - - // remove audio-only level if we also have levels with audio+video codecs signalled - if(videoCodecFound && audioCodecFound) { - levels0.forEach(level => { - if(level.videoCodec) { - levels.push(level); - } - }); - } else { - levels = levels0; - } - - // only keep level with supported audio/video codecs - levels = levels.filter(function(level) { - var checkSupportedAudio = function(codec) { return MediaSource.isTypeSupported(`audio/mp4;codecs=${codec}`);}; - var checkSupportedVideo = function(codec) { return MediaSource.isTypeSupported(`video/mp4;codecs=${codec}`);}; - var audioCodec = level.audioCodec, videoCodec = level.videoCodec; - - return (!audioCodec || checkSupportedAudio(audioCodec)) && - (!videoCodec || checkSupportedVideo(videoCodec)); - }); - - if(levels.length) { - // start bitrate is the first bitrate of the manifest - bitrateStart = levels[0].bitrate; - // sort level on bitrate - levels.sort(function (a, b) { - return a.bitrate - b.bitrate; - }); - this._levels = levels; - // find index of first level in sorted levels - for (i = 0; i < levels.length; i++) { - if (levels[i].bitrate === bitrateStart) { - this._firstLevel = i; - logger.log(`manifest loaded,${levels.length} level(s) found, first bitrate:${bitrateStart}`); - break; - } - } - hls.trigger(Event.MANIFEST_PARSED, {levels: this._levels, firstLevel: this._firstLevel, stats: data.stats}); - } else { - hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.MANIFEST_INCOMPATIBLE_CODECS_ERROR, fatal: true, url: hls.url, reason: 'no level with compatible codecs found in manifest'}); - } - return; - } - - get levels() { - return this._levels; - } - - get level() { - return this._level; - } - - set level(newLevel) { - let levels = this._levels; - if (levels && levels.length > newLevel) { - if (this._level !== newLevel || levels[newLevel].details === undefined) { - this.setLevelInternal(newLevel); - } - } - } - - setLevelInternal(newLevel) { - let levels = this._levels; - // check if level idx is valid - if (newLevel >= 0 && newLevel < levels.length) { - // stopping live reloading timer if any - if (this.timer) { - clearTimeout(this.timer); - this.timer = null; - } - this._level = newLevel; - logger.log(`switching to level ${newLevel}`); - this.hls.trigger(Event.LEVEL_SWITCH, {level: newLevel}); - var level = levels[newLevel]; - // check if we need to load playlist for this level - if (level.details === undefined || level.details.live === true) { - // level not retrieved yet, or live playlist we need to (re)load it - logger.log(`(re)loading playlist for level ${newLevel}`); - var urlId = level.urlId; - this.hls.trigger(Event.LEVEL_LOADING, {url: level.url[urlId], level: newLevel, id: urlId}); - } - } else { - // invalid level id given, trigger error - this.hls.trigger(Event.ERROR, {type : ErrorTypes.OTHER_ERROR, details: ErrorDetails.LEVEL_SWITCH_ERROR, level: newLevel, fatal: false, reason: 'invalid level idx'}); - } - } - - get manualLevel() { - return this._manualLevel; - } - - set manualLevel(newLevel) { - this._manualLevel = newLevel; - if (this._startLevel === undefined) { - this._startLevel = newLevel; - } - if (newLevel !== -1) { - this.level = newLevel; - } - } - - get firstLevel() { - return this._firstLevel; - } - - set firstLevel(newLevel) { - this._firstLevel = newLevel; - } - - get startLevel() { - if (this._startLevel === undefined) { - return this._firstLevel; - } else { - return this._startLevel; - } - } - - set startLevel(newLevel) { - this._startLevel = newLevel; - } - - onError(data) { - if(data.fatal) { - return; - } - - let details = data.details, hls = this.hls, levelId, level, levelError = false; - // try to recover not fatal errors - switch(details) { - case ErrorDetails.FRAG_LOAD_ERROR: - case ErrorDetails.FRAG_LOAD_TIMEOUT: - case ErrorDetails.FRAG_LOOP_LOADING_ERROR: - case ErrorDetails.KEY_LOAD_ERROR: - case ErrorDetails.KEY_LOAD_TIMEOUT: - levelId = data.frag.level; - break; - case ErrorDetails.LEVEL_LOAD_ERROR: - case ErrorDetails.LEVEL_LOAD_TIMEOUT: - levelId = data.level; - levelError = true; - break; - default: - break; - } - /* try to switch to a redundant stream if any available. - * if no redundant stream available, emergency switch down (if in auto mode and current level not 0) - * otherwise, we cannot recover this network error ... - * don't raise FRAG_LOAD_ERROR and FRAG_LOAD_TIMEOUT as fatal, as it is handled by mediaController - */ - if (levelId !== undefined) { - level = this._levels[levelId]; - if (level.urlId < (level.url.length - 1)) { - level.urlId++; - level.details = undefined; - logger.warn(`level controller,${details} for level ${levelId}: switching to redundant stream id ${level.urlId}`); - } else { - // we could try to recover if in auto mode and current level not lowest level (0) - let recoverable = ((this._manualLevel === -1) && levelId); - if (recoverable) { - logger.warn(`level controller,${details}: emergency switch-down for next fragment`); - hls.abrController.nextAutoLevel = 0; - } else if(level && level.details && level.details.live) { - logger.warn(`level controller,${details} on live stream, discard`); - if (levelError) { - // reset this._level so that another call to set level() will retrigger a frag load - this._level = undefined; - } - // FRAG_LOAD_ERROR and FRAG_LOAD_TIMEOUT are handled by mediaController - } else if (details !== ErrorDetails.FRAG_LOAD_ERROR && details !== ErrorDetails.FRAG_LOAD_TIMEOUT) { - logger.error(`cannot recover ${details} error`); - this._level = undefined; - // stopping live reloading timer if any - if (this.timer) { - clearTimeout(this.timer); - this.timer = null; - } - // redispatch same error but with fatal set to true - data.fatal = true; - hls.trigger(Event.ERROR, data); - } - } - } - } - - onLevelLoaded(data) { - // only process level loaded events matching with expected level - if (data.level === this._level) { - let newDetails = data.details; - // if current playlist is a live playlist, arm a timer to reload it - if (newDetails.live) { - let reloadInterval = 1000*newDetails.targetduration, - curLevel = this._levels[data.level], - curDetails = curLevel.details; - if (curDetails && newDetails.endSN === curDetails.endSN) { - // follow HLS Spec, If the client reloads a Playlist file and finds that it has not - // changed then it MUST wait for a period of one-half the target - // duration before retrying. - reloadInterval /=2; - logger.log(`same live playlist, reload twice faster`); - } - // decrement reloadInterval with level loading delay - reloadInterval -= performance.now() - data.stats.trequest; - // in any case, don't reload more than every second - reloadInterval = Math.max(1000,Math.round(reloadInterval)); - logger.log(`live playlist, reload in ${reloadInterval} ms`); - this.timer = setTimeout(this.ontick,reloadInterval); - } else { - this.timer = null; - } - } - } - - tick() { - var levelId = this._level; - if (levelId !== undefined && this.canload) { - var level = this._levels[levelId], urlId = level.urlId; - this.hls.trigger(Event.LEVEL_LOADING, {url: level.url[urlId], level: levelId, id: urlId}); - } - } - - get nextLoadLevel() { - if (this._manualLevel !== -1) { - return this._manualLevel; - } else { - return this.hls.abrController.nextAutoLevel; - } - } - - set nextLoadLevel(nextLevel) { - this.level = nextLevel; - if (this._manualLevel === -1) { - this.hls.abrController.nextAutoLevel = nextLevel; - } - } -} - -export default LevelController; - diff --git a/dashboard-ui/bower_components/hls.js/src/controller/stream-controller.js b/dashboard-ui/bower_components/hls.js/src/controller/stream-controller.js deleted file mode 100644 index f53642663..000000000 --- a/dashboard-ui/bower_components/hls.js/src/controller/stream-controller.js +++ /dev/null @@ -1,1153 +0,0 @@ -/* - * Stream Controller -*/ - -import Demuxer from '../demux/demuxer'; -import Event from '../events'; -import EventHandler from '../event-handler'; -import {logger} from '../utils/logger'; -import BinarySearch from '../utils/binary-search'; -import BufferHelper from '../helper/buffer-helper'; -import LevelHelper from '../helper/level-helper'; -import {ErrorTypes, ErrorDetails} from '../errors'; - -const State = { - STOPPED : 'STOPPED', - STARTING : 'STARTING', - IDLE : 'IDLE', - PAUSED : 'PAUSED', - KEY_LOADING : 'KEY_LOADING', - FRAG_LOADING : 'FRAG_LOADING', - FRAG_LOADING_WAITING_RETRY : 'FRAG_LOADING_WAITING_RETRY', - WAITING_LEVEL : 'WAITING_LEVEL', - PARSING : 'PARSING', - PARSED : 'PARSED', - ENDED : 'ENDED', - ERROR : 'ERROR' -}; - -class StreamController extends EventHandler { - - constructor(hls) { - super(hls, - Event.MEDIA_ATTACHED, - Event.MEDIA_DETACHING, - Event.MANIFEST_LOADING, - Event.MANIFEST_PARSED, - Event.LEVEL_LOADED, - Event.KEY_LOADED, - Event.FRAG_LOADED, - Event.FRAG_LOAD_EMERGENCY_ABORTED, - Event.FRAG_PARSING_INIT_SEGMENT, - Event.FRAG_PARSING_DATA, - Event.FRAG_PARSED, - Event.ERROR, - Event.BUFFER_APPENDED, - Event.BUFFER_FLUSHED); - - this.config = hls.config; - this.audioCodecSwap = false; - this.ticks = 0; - this.ontick = this.tick.bind(this); - } - - destroy() { - this.stopLoad(); - if (this.timer) { - clearInterval(this.timer); - this.timer = null; - } - EventHandler.prototype.destroy.call(this); - this.state = State.STOPPED; - } - - startLoad(startPosition) { - if (this.levels) { - var media = this.media, lastCurrentTime = this.lastCurrentTime; - this.stopLoad(); - this.demuxer = new Demuxer(this.hls); - if (!this.timer) { - this.timer = setInterval(this.ontick, 100); - } - this.level = -1; - this.fragLoadError = 0; - if (media && lastCurrentTime > 0) { - logger.log(`configure startPosition @${lastCurrentTime}`); - if (!this.lastPaused) { - logger.log('resuming video'); - media.play(); - } - this.state = State.IDLE; - } else { - this.lastCurrentTime = this.startPosition ? this.startPosition : startPosition; - this.state = State.STARTING; - } - this.nextLoadPosition = this.startPosition = this.lastCurrentTime; - this.tick(); - } else { - logger.warn('cannot start loading as manifest not parsed yet'); - this.state = State.STOPPED; - } - } - - stopLoad() { - var frag = this.fragCurrent; - if (frag) { - if (frag.loader) { - frag.loader.abort(); - } - this.fragCurrent = null; - } - this.fragPrevious = null; - if (this.demuxer) { - this.demuxer.destroy(); - this.demuxer = null; - } - this.state = State.STOPPED; - } - - tick() { - this.ticks++; - if (this.ticks === 1) { - this.doTick(); - if (this.ticks > 1) { - setTimeout(this.tick, 1); - } - this.ticks = 0; - } - } - - doTick() { - var pos, level, levelDetails, hls = this.hls, config = hls.config, media = this.media, isSeeking = media && media.seeking; - //logger.log(this.state); - switch(this.state) { - case State.ERROR: - //don't do anything in error state to avoid breaking further ... - case State.PAUSED: - //don't do anything in paused state either ... - break; - case State.STARTING: - // determine load level - let startLevel = hls.startLevel; - if (startLevel === -1) { - // -1 : guess start Level by doing a bitrate test by loading first fragment of lowest quality level - startLevel = 0; - this.fragBitrateTest = true; - } - // set new level to playlist loader : this will trigger start level load - // hls.nextLoadLevel remains until it is set to a new value or until a new frag is successfully loaded - this.level = hls.nextLoadLevel = startLevel; - this.state = State.WAITING_LEVEL; - this.loadedmetadata = false; - break; - case State.IDLE: - // if video not attached AND - // start fragment already requested OR start frag prefetch disable - // exit loop - // => if media not attached but start frag prefetch is enabled and start frag not requested yet, we will not exit loop - if (!media && - (this.startFragRequested || !config.startFragPrefetch)) { - break; - } - // determine next candidate fragment to be loaded, based on current position and - // end of buffer position - // ensure 60s of buffer upfront - // if we have not yet loaded any fragment, start loading from start position - if (this.loadedmetadata) { - pos = media.currentTime; - } else { - pos = this.nextLoadPosition; - } - level = hls.nextLoadLevel; - var bufferInfo = BufferHelper.bufferInfo(media,pos,config.maxBufferHole), - bufferLen = bufferInfo.len, - bufferEnd = bufferInfo.end, - fragPrevious = this.fragPrevious, - maxBufLen; - // compute max Buffer Length that we could get from this load level, based on level bitrate. don't buffer more than 60 MB and more than 30s - if ((this.levels[level]).hasOwnProperty('bitrate')) { - maxBufLen = Math.max(8 * config.maxBufferSize / this.levels[level].bitrate, config.maxBufferLength); - maxBufLen = Math.min(maxBufLen, config.maxMaxBufferLength); - } else { - maxBufLen = config.maxBufferLength; - } - // if buffer length is less than maxBufLen try to load a new fragment - if (bufferLen < maxBufLen) { - // set next load level : this will trigger a playlist load if needed - hls.nextLoadLevel = level; - this.level = level; - levelDetails = this.levels[level].details; - // if level info not retrieved yet, switch state and wait for level retrieval - // if live playlist, ensure that new playlist has been refreshed to avoid loading/try to load - // a useless and outdated fragment (that might even introduce load error if it is already out of the live playlist) - if (typeof levelDetails === 'undefined' || levelDetails.live && this.levelLastLoaded !== level) { - this.state = State.WAITING_LEVEL; - break; - } - // find fragment index, contiguous with end of buffer position - let fragments = levelDetails.fragments, - fragLen = fragments.length, - start = fragments[0].start, - end = fragments[fragLen-1].start + fragments[fragLen-1].duration, - frag; - - // in case of live playlist we need to ensure that requested position is not located before playlist start - if (levelDetails.live) { - // check if requested position is within seekable boundaries : - //logger.log(`start/pos/bufEnd/seeking:${start.toFixed(3)}/${pos.toFixed(3)}/${bufferEnd.toFixed(3)}/${media.seeking}`); - let maxLatency = config.liveMaxLatencyDuration !== undefined ? config.liveMaxLatencyDuration : config.liveMaxLatencyDurationCount*levelDetails.targetduration; - - if (bufferEnd < Math.max(start, end - maxLatency)) { - let targetLatency = config.liveSyncDuration !== undefined ? config.liveSyncDuration : config.liveSyncDurationCount * levelDetails.targetduration; - let liveSyncPosition = start + Math.max(0, levelDetails.totalduration - targetLatency); - logger.log(`buffer end: ${bufferEnd} is located too far from the end of live sliding playlist, reset currentTime to : ${liveSyncPosition.toFixed(3)}`); - bufferEnd = liveSyncPosition; - if (media && media.readyState && media.duration > liveSyncPosition) { - media.currentTime = liveSyncPosition; - } - } - - // if end of buffer greater than live edge, don't load any fragment - // this could happen if live playlist intermittently slides in the past. - // level 1 loaded [182580161,182580167] - // level 1 loaded [182580162,182580169] - // Loading 182580168 of [182580162 ,182580169],level 1 .. - // Loading 182580169 of [182580162 ,182580169],level 1 .. - // level 1 loaded [182580162,182580168] <============= here we should have bufferEnd > end. in that case break to avoid reloading 182580168 - // level 1 loaded [182580164,182580171] - // - if (levelDetails.PTSKnown && bufferEnd > end) { - break; - } - - if (this.startFragRequested && !levelDetails.PTSKnown) { - /* we are switching level on live playlist, but we don't have any PTS info for that quality level ... - try to load frag matching with next SN. - even if SN are not synchronized between playlists, loading this frag will help us - compute playlist sliding and find the right one after in case it was not the right consecutive one */ - if (fragPrevious) { - var targetSN = fragPrevious.sn + 1; - if (targetSN >= levelDetails.startSN && targetSN <= levelDetails.endSN) { - frag = fragments[targetSN - levelDetails.startSN]; - logger.log(`live playlist, switching playlist, load frag with next SN: ${frag.sn}`); - } - } - if (!frag) { - /* we have no idea about which fragment should be loaded. - so let's load mid fragment. it will help computing playlist sliding and find the right one - */ - frag = fragments[Math.min(fragLen - 1, Math.round(fragLen / 2))]; - logger.log(`live playlist, switching playlist, unknown, load middle frag : ${frag.sn}`); - } - } - } else { - // VoD playlist: if bufferEnd before start of playlist, load first fragment - if (bufferEnd < start) { - frag = fragments[0]; - } - } - if (!frag) { - let maxFragLookUpTolerance = config.maxFragLookUpTolerance; - if (bufferEnd < end) { - // no frag look up tolerance in case bufferEnd close to end, or media seeking - if (bufferEnd > end - maxFragLookUpTolerance || isSeeking) { - maxFragLookUpTolerance = 0; - } - frag = BinarySearch.search(fragments, (candidate) => { - // offset should be within fragment boundary - config.maxFragLookUpTolerance - // this is to cope with situations like - // bufferEnd = 9.991 - // frag[Ø] : [0,10] - // frag[1] : [10,20] - // bufferEnd is within frag[0] range ... although what we are expecting is to return frag[1] here - // frag start frag start+duration - // |-----------------------------| - // <---> <---> - // ...--------><-----------------------------><---------.... - // previous frag matching fragment next frag - // return -1 return 0 return 1 - //logger.log(`level/sn/start/end/bufEnd:${level}/${candidate.sn}/${candidate.start}/${(candidate.start+candidate.duration)}/${bufferEnd}`); - if ((candidate.start + candidate.duration - maxFragLookUpTolerance) <= bufferEnd) { - return 1; - } - else if (candidate.start - maxFragLookUpTolerance > bufferEnd) { - return -1; - } - return 0; - }); - } else { - // reach end of playlist - frag = fragments[fragLen-1]; - } - } - if(frag) { - start = frag.start; - //logger.log('find SN matching with pos:' + bufferEnd + ':' + frag.sn); - if (fragPrevious && frag.level === fragPrevious.level && frag.sn === fragPrevious.sn) { - if (frag.sn < levelDetails.endSN) { - let deltaPTS = fragPrevious.deltaPTS, - curSNIdx = frag.sn - levelDetails.startSN; - // if there is a significant delta between audio and video, larger than max allowed hole, - // and if previous remuxed fragment did not start with a keyframe. (fragPrevious.dropped) - // let's try to load previous fragment again to get last keyframe - // then we will reload again current fragment (that way we should be able to fill the buffer hole ...) - if (deltaPTS && deltaPTS > config.maxBufferHole && fragPrevious.dropped) { - frag = fragments[curSNIdx-1]; - logger.warn(`SN just loaded, with large PTS gap between audio and video, maybe frag is not starting with a keyframe ? load previous one to try to overcome this`); - // decrement previous frag load counter to avoid frag loop loading error when next fragment will get reloaded - fragPrevious.loadCounter--; - } else { - frag = fragments[curSNIdx+1]; - logger.log(`SN just loaded, load next one: ${frag.sn}`); - } - // ensure frag is not undefined - if(!frag) { - break; - } - } else { - // have we reached end of VOD playlist ? - if (!levelDetails.live) { - // Finalize the media stream - this.hls.trigger(Event.BUFFER_EOS); - // We might be loading the last fragment but actually the media - // is currently processing a seek command and waiting for new data to resume at another point. - // Going to ended state while media is seeking can spawn an infinite buffering broken state. - if (!isSeeking) { - this.state = State.ENDED; - } - } - break; - } - } - //logger.log(' loading frag ' + i +',pos/bufEnd:' + pos.toFixed(3) + '/' + bufferEnd.toFixed(3)); - if ((frag.decryptdata.uri != null) && (frag.decryptdata.key == null)) { - logger.log(`Loading key for ${frag.sn} of [${levelDetails.startSN} ,${levelDetails.endSN}],level ${level}`); - this.state = State.KEY_LOADING; - hls.trigger(Event.KEY_LOADING, {frag: frag}); - } else { - logger.log(`Loading ${frag.sn} of [${levelDetails.startSN} ,${levelDetails.endSN}],level ${level}, currentTime:${pos},bufferEnd:${bufferEnd.toFixed(3)}`); - // ensure that we are not reloading the same fragments in loop ... - if (this.fragLoadIdx !== undefined) { - this.fragLoadIdx++; - } else { - this.fragLoadIdx = 0; - } - if (frag.loadCounter) { - frag.loadCounter++; - let maxThreshold = config.fragLoadingLoopThreshold; - // if this frag has already been loaded 3 times, and if it has been reloaded recently - if (frag.loadCounter > maxThreshold && (Math.abs(this.fragLoadIdx - frag.loadIdx) < maxThreshold)) { - hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_LOOP_LOADING_ERROR, fatal: false, frag: frag}); - return; - } - } else { - frag.loadCounter = 1; - } - frag.loadIdx = this.fragLoadIdx; - this.fragCurrent = frag; - this.startFragRequested = true; - frag.autoLevel = hls.autoLevelEnabled; - hls.trigger(Event.FRAG_LOADING, {frag: frag}); - this.state = State.FRAG_LOADING; - } - } - } - break; - case State.WAITING_LEVEL: - level = this.levels[this.level]; - // check if playlist is already loaded - if (level && level.details) { - this.state = State.IDLE; - } - break; - case State.FRAG_LOADING_WAITING_RETRY: - var now = performance.now(); - var retryDate = this.retryDate; - // if current time is gt than retryDate, or if media seeking let's switch to IDLE state to retry loading - if(!retryDate || (now >= retryDate) || isSeeking) { - logger.log(`mediaController: retryDate reached, switch back to IDLE state`); - this.state = State.IDLE; - } - break; - case State.STOPPED: - case State.FRAG_LOADING: - case State.PARSING: - case State.PARSED: - case State.ENDED: - break; - default: - break; - } - // check buffer - this._checkBuffer(); - // check/update current fragment - this._checkFragmentChanged(); - } - - - - - getBufferRange(position) { - var i, range, - bufferRange = this.bufferRange; - if (bufferRange) { - for (i = bufferRange.length - 1; i >=0; i--) { - range = bufferRange[i]; - if (position >= range.start && position <= range.end) { - return range; - } - } - } - return null; - } - - get currentLevel() { - if (this.media) { - var range = this.getBufferRange(this.media.currentTime); - if (range) { - return range.frag.level; - } - } - return -1; - } - - get nextBufferRange() { - if (this.media) { - // first get end range of current fragment - return this.followingBufferRange(this.getBufferRange(this.media.currentTime)); - } else { - return null; - } - } - - followingBufferRange(range) { - if (range) { - // try to get range of next fragment (500ms after this range) - return this.getBufferRange(range.end + 0.5); - } - return null; - } - - get nextLevel() { - var range = this.nextBufferRange; - if (range) { - return range.frag.level; - } else { - return -1; - } - } - - isBuffered(position) { - let media = this.media; - if (media) { - let buffered = media.buffered; - for (let i = 0; i < buffered.length; i++) { - if (position >= buffered.start(i) && position <= buffered.end(i)) { - return true; - } - } - } - return false; - } - - _checkFragmentChanged() { - var rangeCurrent, currentTime, video = this.media; - if (video && video.seeking === false) { - currentTime = video.currentTime; - /* if video element is in seeked state, currentTime can only increase. - (assuming that playback rate is positive ...) - As sometimes currentTime jumps back to zero after a - media decode error, check this, to avoid seeking back to - wrong position after a media decode error - */ - if(currentTime > video.playbackRate*this.lastCurrentTime) { - this.lastCurrentTime = currentTime; - } - if (this.isBuffered(currentTime)) { - rangeCurrent = this.getBufferRange(currentTime); - } else if (this.isBuffered(currentTime + 0.1)) { - /* ensure that FRAG_CHANGED event is triggered at startup, - when first video frame is displayed and playback is paused. - add a tolerance of 100ms, in case current position is not buffered, - check if current pos+100ms is buffered and use that buffer range - for FRAG_CHANGED event reporting */ - rangeCurrent = this.getBufferRange(currentTime + 0.1); - } - if (rangeCurrent) { - var fragPlaying = rangeCurrent.frag; - if (fragPlaying !== this.fragPlaying) { - this.fragPlaying = fragPlaying; - this.hls.trigger(Event.FRAG_CHANGED, {frag: fragPlaying}); - } - } - } - } - - /* - on immediate level switch : - - pause playback if playing - - cancel any pending load request - - and trigger a buffer flush - */ - immediateLevelSwitch() { - logger.log('immediateLevelSwitch'); - if (!this.immediateSwitch) { - this.immediateSwitch = true; - let media = this.media, previouslyPaused; - if (media) { - previouslyPaused = media.paused; - media.pause(); - } else { - // don't restart playback after instant level switch in case media not attached - previouslyPaused = true; - } - this.previouslyPaused = previouslyPaused; - } - var fragCurrent = this.fragCurrent; - if (fragCurrent && fragCurrent.loader) { - fragCurrent.loader.abort(); - } - this.fragCurrent = null; - // increase fragment load Index to avoid frag loop loading error after buffer flush - this.fragLoadIdx += 2 * this.config.fragLoadingLoopThreshold; - this.state = State.PAUSED; - // flush everything - this.hls.trigger(Event.BUFFER_FLUSHING, {startOffset: 0, endOffset: Number.POSITIVE_INFINITY}); - } - - /* - on immediate level switch end, after new fragment has been buffered : - - nudge video decoder by slightly adjusting video currentTime - - resume the playback if needed - */ - immediateLevelSwitchEnd() { - this.immediateSwitch = false; - let media = this.media; - if (media && media.readyState) { - media.currentTime -= 0.0001; - if (!this.previouslyPaused) { - media.play(); - } - } - } - - nextLevelSwitch() { - /* try to switch ASAP without breaking video playback : - in order to ensure smooth but quick level switching, - we need to find the next flushable buffer range - we should take into account new segment fetch time - */ - let media = this.media; - // ensure that media is defined and that metadata are available (to retrieve currentTime) - if (media && media.readyState) { - let fetchdelay, currentRange, nextRange; - // increase fragment load Index to avoid frag loop loading error after buffer flush - this.fragLoadIdx += 2 * this.config.fragLoadingLoopThreshold; - currentRange = this.getBufferRange(media.currentTime); - if (currentRange && currentRange.start > 1) { - // flush buffer preceding current fragment (flush until current fragment start offset) - // minus 1s to avoid video freezing, that could happen if we flush keyframe of current video ... - this.state = State.PAUSED; - this.hls.trigger(Event.BUFFER_FLUSHING, {startOffset: 0, endOffset: currentRange.start - 1}); - } - if (!media.paused) { - // add a safety delay of 1s - var nextLevelId = this.hls.nextLoadLevel,nextLevel = this.levels[nextLevelId], fragLastKbps = this.fragLastKbps; - if (fragLastKbps && this.fragCurrent) { - fetchdelay = this.fragCurrent.duration * nextLevel.bitrate / (1000 * fragLastKbps) + 1; - } else { - fetchdelay = 0; - } - } else { - fetchdelay = 0; - } - //logger.log('fetchdelay:'+fetchdelay); - // find buffer range that will be reached once new fragment will be fetched - nextRange = this.getBufferRange(media.currentTime + fetchdelay); - if (nextRange) { - // we can flush buffer range following this one without stalling playback - nextRange = this.followingBufferRange(nextRange); - if (nextRange) { - // if we are here, we can also cancel any loading/demuxing in progress, as they are useless - var fragCurrent = this.fragCurrent; - if (fragCurrent && fragCurrent.loader) { - fragCurrent.loader.abort(); - } - this.fragCurrent = null; - // flush position is the start position of this new buffer - this.state = State.PAUSED; - this.hls.trigger(Event.BUFFER_FLUSHING, {startOffset: nextRange.start, endOffset: Number.POSITIVE_INFINITY}); - } - } - } - } - - onMediaAttached(data) { - var media = this.media = data.media; - this.onvseeking = this.onMediaSeeking.bind(this); - this.onvseeked = this.onMediaSeeked.bind(this); - this.onvended = this.onMediaEnded.bind(this); - media.addEventListener('seeking', this.onvseeking); - media.addEventListener('seeked', this.onvseeked); - media.addEventListener('ended', this.onvended); - let config = this.config; - if(this.levels && config.autoStartLoad) { - this.hls.startLoad(config.startPosition); - } - } - - onMediaDetaching() { - var media = this.media; - if (media && media.ended) { - logger.log('MSE detaching and video ended, reset startPosition'); - this.startPosition = this.lastCurrentTime = 0; - } - - // reset fragment loading counter on MSE detaching to avoid reporting FRAG_LOOP_LOADING_ERROR after error recovery - var levels = this.levels; - if (levels) { - // reset fragment load counter - levels.forEach(level => { - if(level.details) { - level.details.fragments.forEach(fragment => { - fragment.loadCounter = undefined; - }); - } - }); - } - // remove video listeners - if (media) { - media.removeEventListener('seeking', this.onvseeking); - media.removeEventListener('seeked', this.onvseeked); - media.removeEventListener('ended', this.onvended); - this.onvseeking = this.onvseeked = this.onvended = null; - } - this.media = null; - this.loadedmetadata = false; - this.stopLoad(); - } - - onMediaSeeking() { - if (this.state === State.FRAG_LOADING) { - // check if currently loaded fragment is inside buffer. - //if outside, cancel fragment loading, otherwise do nothing - if (BufferHelper.bufferInfo(this.media,this.media.currentTime,this.config.maxBufferHole).len === 0) { - logger.log('seeking outside of buffer while fragment load in progress, cancel fragment load'); - var fragCurrent = this.fragCurrent; - if (fragCurrent) { - if (fragCurrent.loader) { - fragCurrent.loader.abort(); - } - this.fragCurrent = null; - } - this.fragPrevious = null; - // switch to IDLE state to load new fragment - this.state = State.IDLE; - } - } else if (this.state === State.ENDED) { - // switch to IDLE state to check for potential new fragment - this.state = State.IDLE; - } - if (this.media) { - this.lastCurrentTime = this.media.currentTime; - } - // avoid reporting fragment loop loading error in case user is seeking several times on same position - if (this.fragLoadIdx !== undefined) { - this.fragLoadIdx += 2 * this.config.fragLoadingLoopThreshold; - } - // tick to speed up processing - this.tick(); - } - - onMediaSeeked() { - // tick to speed up FRAGMENT_PLAYING triggering - this.tick(); - } - - onMediaEnded() { - logger.log('media ended'); - // reset startPosition and lastCurrentTime to restart playback @ stream beginning - this.startPosition = this.lastCurrentTime = 0; - } - - - onManifestLoading() { - // reset buffer on manifest loading - logger.log('trigger BUFFER_RESET'); - this.hls.trigger(Event.BUFFER_RESET); - this.bufferRange = []; - this.stalled = false; - } - - onManifestParsed(data) { - var aac = false, heaac = false, codec; - data.levels.forEach(level => { - // detect if we have different kind of audio codecs used amongst playlists - codec = level.audioCodec; - if (codec) { - if (codec.indexOf('mp4a.40.2') !== -1) { - aac = true; - } - if (codec.indexOf('mp4a.40.5') !== -1) { - heaac = true; - } - } - }); - this.audioCodecSwitch = (aac && heaac); - if (this.audioCodecSwitch) { - logger.log('both AAC/HE-AAC audio found in levels; declaring level codec as HE-AAC'); - } - this.levels = data.levels; - this.startLevelLoaded = false; - this.startFragRequested = false; - let config = this.config; - if (config.autoStartLoad) { - this.hls.startLoad(config.startPosition); - } - } - - onLevelLoaded(data) { - var newDetails = data.details, - newLevelId = data.level, - curLevel = this.levels[newLevelId], - duration = newDetails.totalduration, - sliding = 0; - - logger.log(`level ${newLevelId} loaded [${newDetails.startSN},${newDetails.endSN}],duration:${duration}`); - this.levelLastLoaded = newLevelId; - - if (newDetails.live) { - var curDetails = curLevel.details; - if (curDetails) { - // we already have details for that level, merge them - LevelHelper.mergeDetails(curDetails,newDetails); - sliding = newDetails.fragments[0].start; - if (newDetails.PTSKnown) { - logger.log(`live playlist sliding:${sliding.toFixed(3)}`); - } else { - logger.log('live playlist - outdated PTS, unknown sliding'); - } - } else { - newDetails.PTSKnown = false; - logger.log('live playlist - first load, unknown sliding'); - } - } else { - newDetails.PTSKnown = false; - } - // override level info - curLevel.details = newDetails; - this.hls.trigger(Event.LEVEL_UPDATED, { details: newDetails, level: newLevelId }); - - if (this.startFragRequested === false) { - // compute start position if set to -1. use it straight away if value is defined - if (this.startPosition === -1) { - // first, check if start time offset has been set in playlist, if yes, use this value - let startTimeOffset = newDetails.startTimeOffset; - if(!isNaN(startTimeOffset)) { - logger.log(`start time offset found in playlist, adjust startPosition to ${startTimeOffset}`); - this.startPosition = startTimeOffset; - } else { - // if live playlist, set start position to be fragment N-this.config.liveSyncDurationCount (usually 3) - if (newDetails.live) { - let targetLatency = this.config.liveSyncDuration !== undefined ? this.config.liveSyncDuration : this.config.liveSyncDurationCount * newDetails.targetduration; - this.startPosition = Math.max(0, sliding + duration - targetLatency); - } else { - this.startPosition = 0; - } - } - } - this.nextLoadPosition = this.startPosition; - } - // only switch batck to IDLE state if we were waiting for level to start downloading a new fragment - if (this.state === State.WAITING_LEVEL) { - this.state = State.IDLE; - } - //trigger handler right now - this.tick(); - } - - onKeyLoaded() { - if (this.state === State.KEY_LOADING) { - this.state = State.IDLE; - this.tick(); - } - } - - onFragLoaded(data) { - var fragCurrent = this.fragCurrent; - if (this.state === State.FRAG_LOADING && - fragCurrent && - data.frag.level === fragCurrent.level && - data.frag.sn === fragCurrent.sn) { - - logger.log(`Loaded ${fragCurrent.sn} of level ${fragCurrent.level}`); - if (this.fragBitrateTest === true) { - // switch back to IDLE state ... we just loaded a fragment to determine adequate start bitrate and initialize autoswitch algo - this.state = State.IDLE; - this.fragBitrateTest = false; - this.startFragRequested = false; - data.stats.tparsed = data.stats.tbuffered = performance.now(); - this.hls.trigger(Event.FRAG_BUFFERED, {stats: data.stats, frag: fragCurrent}); - } else { - this.state = State.PARSING; - // transmux the MPEG-TS data to ISO-BMFF segments - this.stats = data.stats; - var currentLevel = this.levels[this.level], - details = currentLevel.details, - duration = details.totalduration, - start = fragCurrent.startDTS !== undefined ? fragCurrent.startDTS : fragCurrent.start, - level = fragCurrent.level, - sn = fragCurrent.sn, - audioCodec = currentLevel.audioCodec || this.config.defaultAudioCodec; - if(this.audioCodecSwap) { - logger.log('swapping playlist audio codec'); - if(audioCodec === undefined) { - audioCodec = this.lastAudioCodec; - } - if(audioCodec) { - if(audioCodec.indexOf('mp4a.40.5') !==-1) { - audioCodec = 'mp4a.40.2'; - } else { - audioCodec = 'mp4a.40.5'; - } - } - } - this.pendingAppending = 0; - logger.log(`Demuxing ${sn} of [${details.startSN} ,${details.endSN}],level ${level}, cc ${fragCurrent.cc}`); - let demuxer = this.demuxer; - if (demuxer) { - demuxer.push(data.payload, audioCodec, currentLevel.videoCodec, start, fragCurrent.cc, level, sn, duration, fragCurrent.decryptdata); - } - } - } - this.fragLoadError = 0; - } - - onFragParsingInitSegment(data) { - if (this.state === State.PARSING) { - var tracks = data.tracks, trackName, track; - - // include levelCodec in audio and video tracks - track = tracks.audio; - if(track) { - var audioCodec = this.levels[this.level].audioCodec, - ua = navigator.userAgent.toLowerCase(); - if(audioCodec && this.audioCodecSwap) { - logger.log('swapping playlist audio codec'); - if(audioCodec.indexOf('mp4a.40.5') !==-1) { - audioCodec = 'mp4a.40.2'; - } else { - audioCodec = 'mp4a.40.5'; - } - } - // in case AAC and HE-AAC audio codecs are signalled in manifest - // force HE-AAC , as it seems that most browsers prefers that way, - // except for mono streams OR on FF - // these conditions might need to be reviewed ... - if (this.audioCodecSwitch) { - // don't force HE-AAC if mono stream - if(track.metadata.channelCount !== 1 && - // don't force HE-AAC if firefox - ua.indexOf('firefox') === -1) { - audioCodec = 'mp4a.40.5'; - } - } - // HE-AAC is broken on Android, always signal audio codec as AAC even if variant manifest states otherwise - if(ua.indexOf('android') !== -1) { - audioCodec = 'mp4a.40.2'; - logger.log(`Android: force audio codec to` + audioCodec); - } - track.levelCodec = audioCodec; - } - track = tracks.video; - if(track) { - track.levelCodec = this.levels[this.level].videoCodec; - } - - // if remuxer specify that a unique track needs to generated, - // let's merge all tracks together - if (data.unique) { - var mergedTrack = { - codec : '', - levelCodec : '' - }; - for (trackName in data.tracks) { - track = tracks[trackName]; - mergedTrack.container = track.container; - if (mergedTrack.codec) { - mergedTrack.codec += ','; - mergedTrack.levelCodec += ','; - } - if(track.codec) { - mergedTrack.codec += track.codec; - } - if (track.levelCodec) { - mergedTrack.levelCodec += track.levelCodec; - } - } - tracks = { audiovideo : mergedTrack }; - } - this.hls.trigger(Event.BUFFER_CODECS,tracks); - // loop through tracks that are going to be provided to bufferController - for (trackName in tracks) { - track = tracks[trackName]; - logger.log(`track:${trackName},container:${track.container},codecs[level/parsed]=[${track.levelCodec}/${track.codec}]`); - var initSegment = track.initSegment; - if (initSegment) { - this.pendingAppending++; - this.hls.trigger(Event.BUFFER_APPENDING, {type: trackName, data: initSegment}); - } - } - //trigger handler right now - this.tick(); - } - } - - onFragParsingData(data) { - if (this.state === State.PARSING) { - this.tparse2 = Date.now(); - var level = this.levels[this.level], - frag = this.fragCurrent; - - logger.log(`parsed ${data.type},PTS:[${data.startPTS.toFixed(3)},${data.endPTS.toFixed(3)}],DTS:[${data.startDTS.toFixed(3)}/${data.endDTS.toFixed(3)}],nb:${data.nb},dropped:${data.dropped || 0}`); - - var drift = LevelHelper.updateFragPTSDTS(level.details,frag.sn,data.startPTS,data.endPTS,data.startDTS,data.endDTS), - hls = this.hls; - hls.trigger(Event.LEVEL_PTS_UPDATED, {details: level.details, level: this.level, drift: drift}); - - // has remuxer dropped video frames located before first keyframe ? - if(data.type === 'video') { - frag.dropped = data.dropped; - } - - [data.data1, data.data2].forEach(buffer => { - if (buffer) { - this.pendingAppending++; - hls.trigger(Event.BUFFER_APPENDING, {type: data.type, data: buffer}); - } - }); - - this.nextLoadPosition = data.endPTS; - this.bufferRange.push({type: data.type, start: data.startPTS, end: data.endPTS, frag: frag}); - - //trigger handler right now - this.tick(); - } else { - logger.warn(`not in PARSING state but ${this.state}, ignoring FRAG_PARSING_DATA event`); - } - } - - onFragParsed() { - if (this.state === State.PARSING) { - this.stats.tparsed = performance.now(); - this.state = State.PARSED; - this._checkAppendedParsed(); - } - } - - onBufferAppended() { - switch (this.state) { - case State.PARSING: - case State.PARSED: - this.pendingAppending--; - this._checkAppendedParsed(); - break; - default: - break; - } - } - - _checkAppendedParsed() { - //trigger handler right now - if (this.state === State.PARSED && this.pendingAppending === 0) { - var frag = this.fragCurrent, stats = this.stats; - if (frag) { - this.fragPrevious = frag; - stats.tbuffered = performance.now(); - this.fragLastKbps = Math.round(8 * stats.length / (stats.tbuffered - stats.tfirst)); - this.hls.trigger(Event.FRAG_BUFFERED, {stats: stats, frag: frag}); - logger.log(`media buffered : ${this.timeRangesToString(this.media.buffered)}`); - this.state = State.IDLE; - } - this.tick(); - } - } - - onError(data) { - switch(data.details) { - case ErrorDetails.FRAG_LOAD_ERROR: - case ErrorDetails.FRAG_LOAD_TIMEOUT: - if(!data.fatal) { - var loadError = this.fragLoadError; - if(loadError) { - loadError++; - } else { - loadError=1; - } - if (loadError <= this.config.fragLoadingMaxRetry) { - this.fragLoadError = loadError; - // reset load counter to avoid frag loop loading error - data.frag.loadCounter = 0; - // exponential backoff capped to 64s - var delay = Math.min(Math.pow(2,loadError-1)*this.config.fragLoadingRetryDelay,64000); - logger.warn(`mediaController: frag loading failed, retry in ${delay} ms`); - this.retryDate = performance.now() + delay; - // retry loading state - this.state = State.FRAG_LOADING_WAITING_RETRY; - } else { - logger.error(`mediaController: ${data.details} reaches max retry, redispatch as fatal ...`); - // redispatch same error but with fatal set to true - data.fatal = true; - this.hls.trigger(Event.ERROR, data); - this.state = State.ERROR; - } - } - break; - case ErrorDetails.FRAG_LOOP_LOADING_ERROR: - case ErrorDetails.LEVEL_LOAD_ERROR: - case ErrorDetails.LEVEL_LOAD_TIMEOUT: - case ErrorDetails.KEY_LOAD_ERROR: - case ErrorDetails.KEY_LOAD_TIMEOUT: - // when in ERROR state, don't switch back to IDLE state in case a non-fatal error is received - if(this.state !== State.ERROR) { - // if fatal error, stop processing, otherwise move to IDLE to retry loading - this.state = data.fatal ? State.ERROR : State.IDLE; - logger.warn(`mediaController: ${data.details} while loading frag,switch to ${this.state} state ...`); - } - break; - case ErrorDetails.BUFFER_FULL_ERROR: - // only reduce max buf len if in appending state - if (this.state === State.PARSING || this.state === State.PARSED) { - // reduce max buffer length as it might be too high. we do this to avoid loop flushing ... - this.config.maxMaxBufferLength/=2; - logger.warn(`reduce max buffer length to ${this.config.maxMaxBufferLength}s and switch to IDLE state`); - // increase fragment load Index to avoid frag loop loading error after buffer flush - this.fragLoadIdx += 2 * this.config.fragLoadingLoopThreshold; - this.state = State.IDLE; - } - break; - default: - break; - } - } - -_checkBuffer() { - var media = this.media; - // if ready state different from HAVE_NOTHING (numeric value 0), we are allowed to seek - if(media && media.readyState) { - let currentTime = media.currentTime, - buffered = media.buffered; - // adjust currentTime to start position on loaded metadata - if(!this.loadedmetadata && buffered.length) { - this.loadedmetadata = true; - // only adjust currentTime if startPosition not equal to 0 - let startPosition = this.startPosition; - // if currentTime === 0 AND not matching with expected startPosition - if (!currentTime && currentTime !== startPosition) { - if (startPosition) { - logger.log(`target start position:${startPosition}`); - // at that stage, there should be only one buffered range, as we reach that code after first fragment has been - let bufferStart = buffered.start(0), - bufferEnd = buffered.end(0); - // if startPosition not buffered, let's seek to buffered.start(0) - if(startPosition < bufferStart || startPosition > bufferEnd) { - startPosition = bufferStart; - logger.log(`target start position not buffered, seek to buffered.start(0) ${bufferStart}`); - } - logger.log(`adjust currentTime from ${currentTime} to ${startPosition}`); - media.currentTime = startPosition; - } - } - } else { - let bufferInfo = BufferHelper.bufferInfo(media,currentTime,0), - expectedPlaying = !(media.paused || // not playing when media is paused - media.ended || // not playing when media is ended - media.buffered.length === 0), // not playing if nothing buffered - jumpThreshold = 0.4, // tolerance needed as some browsers stalls playback before reaching buffered range end - playheadMoving = currentTime > media.playbackRate*this.lastCurrentTime; - - if (this.stalled && playheadMoving) { - this.stalled = false; - logger.log(`playback not stuck anymore @${currentTime}`); - } - // check buffer upfront - // if less than jumpThreshold second is buffered, let's check in more details - if(expectedPlaying && bufferInfo.len <= jumpThreshold) { - if(playheadMoving) { - // playhead moving - jumpThreshold = 0; - this.seekHoleNudgeDuration = 0; - } else { - // playhead not moving AND media expected to play - if(!this.stalled) { - this.seekHoleNudgeDuration = 0; - logger.log(`playback seems stuck @${currentTime}`); - this.hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.BUFFER_STALLED_ERROR, fatal: false}); - this.stalled = true; - } else { - this.seekHoleNudgeDuration += this.config.seekHoleNudgeDuration; - } - } - // if we are below threshold, try to jump to start of next buffer range if close - if(bufferInfo.len <= jumpThreshold) { - // no buffer available @ currentTime, check if next buffer is close (within a config.maxSeekHole second range) - var nextBufferStart = bufferInfo.nextStart, delta = nextBufferStart-currentTime; - if(nextBufferStart && - (delta < this.config.maxSeekHole) && - (delta > 0)) { - // next buffer is close ! adjust currentTime to nextBufferStart - // this will ensure effective video decoding - logger.log(`adjust currentTime from ${media.currentTime} to next buffered @ ${nextBufferStart} + nudge ${this.seekHoleNudgeDuration}`); - let hole = nextBufferStart + this.seekHoleNudgeDuration - media.currentTime; - media.currentTime = nextBufferStart + this.seekHoleNudgeDuration; - this.hls.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.BUFFER_SEEK_OVER_HOLE, fatal: false, hole : hole}); - } - } - } - } - } - } - - onFragLoadEmergencyAborted() { - this.state = State.IDLE; - this.tick(); - } - - onBufferFlushed() { - /* after successful buffer flushing, rebuild buffer Range array - loop through existing buffer range and check if - corresponding range is still buffered. only push to new array already buffered range - */ - var newRange = [],range,i; - for (i = 0; i < this.bufferRange.length; i++) { - range = this.bufferRange[i]; - if (this.isBuffered((range.start + range.end) / 2)) { - newRange.push(range); - } - } - this.bufferRange = newRange; - - // handle end of immediate switching if needed - if (this.immediateSwitch) { - this.immediateLevelSwitchEnd(); - } - // move to IDLE once flush complete. this should trigger new fragment loading - this.state = State.IDLE; - // reset reference to frag - this.fragPrevious = null; - } - - swapAudioCodec() { - this.audioCodecSwap = !this.audioCodecSwap; - } - - timeRangesToString(r) { - var log = '', len = r.length; - for (var i=0; i OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation - * are those of the authors and should not be interpreted as representing - * official policies, either expressed or implied, of the authors. - */ -class AES { - - /** - * Schedule out an AES key for both encryption and decryption. This - * is a low-level class. Use a cipher mode to do bulk encryption. - * - * @constructor - * @param key {Array} The key as an array of 4, 6 or 8 words. - */ - constructor(key) { - /** - * The expanded S-box and inverse S-box tables. These will be computed - * on the client so that we don't have to send them down the wire. - * - * There are two tables, _tables[0] is for encryption and - * _tables[1] is for decryption. - * - * The first 4 sub-tables are the expanded S-box with MixColumns. The - * last (_tables[01][4]) is the S-box itself. - * - * @private - */ - this._tables = [[[],[],[],[],[]],[[],[],[],[],[]]]; - - this._precompute(); - - var i, j, tmp, - encKey, decKey, - sbox = this._tables[0][4], decTable = this._tables[1], - keyLen = key.length, rcon = 1; - - if (keyLen !== 4 && keyLen !== 6 && keyLen !== 8) { - throw new Error('Invalid aes key size=' + keyLen); - } - - encKey = key.slice(0); - decKey = []; - this._key = [encKey, decKey]; - - // schedule encryption keys - for (i = keyLen; i < 4 * keyLen + 28; i++) { - tmp = encKey[i-1]; - - // apply sbox - if (i%keyLen === 0 || (keyLen === 8 && i%keyLen === 4)) { - tmp = sbox[tmp>>>24]<<24 ^ sbox[tmp>>16&255]<<16 ^ sbox[tmp>>8&255]<<8 ^ sbox[tmp&255]; - - // shift rows and add rcon - if (i%keyLen === 0) { - tmp = tmp<<8 ^ tmp>>>24 ^ rcon<<24; - rcon = rcon<<1 ^ (rcon>>7)*283; - } - } - - encKey[i] = encKey[i-keyLen] ^ tmp; - } - - // schedule decryption keys - for (j = 0; i; j++, i--) { - tmp = encKey[j&3 ? i : i - 4]; - if (i<=4 || j<4) { - decKey[j] = tmp; - } else { - decKey[j] = decTable[0][sbox[tmp>>>24 ]] ^ - decTable[1][sbox[tmp>>16 & 255]] ^ - decTable[2][sbox[tmp>>8 & 255]] ^ - decTable[3][sbox[tmp & 255]]; - } - } - } - - /** - * Expand the S-box tables. - * - * @private - */ - _precompute() { - var encTable = this._tables[0], decTable = this._tables[1], - sbox = encTable[4], sboxInv = decTable[4], - i, x, xInv, d=[], th=[], x2, x4, x8, s, tEnc, tDec; - - // Compute double and third tables - for (i = 0; i < 256; i++) { - th[( d[i] = i<<1 ^ (i>>7)*283 )^i]=i; - } - - for (x = xInv = 0; !sbox[x]; x ^= x2 || 1, xInv = th[xInv] || 1) { - // Compute sbox - s = xInv ^ xInv<<1 ^ xInv<<2 ^ xInv<<3 ^ xInv<<4; - s = s>>8 ^ s&255 ^ 99; - sbox[x] = s; - sboxInv[s] = x; - - // Compute MixColumns - x8 = d[x4 = d[x2 = d[x]]]; - tDec = x8*0x1010101 ^ x4*0x10001 ^ x2*0x101 ^ x*0x1010100; - tEnc = d[s]*0x101 ^ s*0x1010100; - - for (i = 0; i < 4; i++) { - encTable[i][x] = tEnc = tEnc<<24 ^ tEnc>>>8; - decTable[i][s] = tDec = tDec<<24 ^ tDec>>>8; - } - } - - // Compactify. Considerable speedup on Firefox. - for (i = 0; i < 5; i++) { - encTable[i] = encTable[i].slice(0); - decTable[i] = decTable[i].slice(0); - } - } - - /** - * Decrypt 16 bytes, specified as four 32-bit words. - * @param encrypted0 {number} the first word to decrypt - * @param encrypted1 {number} the second word to decrypt - * @param encrypted2 {number} the third word to decrypt - * @param encrypted3 {number} the fourth word to decrypt - * @param out {Int32Array} the array to write the decrypted words - * into - * @param offset {number} the offset into the output array to start - * writing results - * @return {Array} The plaintext. - */ - decrypt(encrypted0, encrypted1, encrypted2, encrypted3, out, offset) { - var key = this._key[1], - // state variables a,b,c,d are loaded with pre-whitened data - a = encrypted0 ^ key[0], - b = encrypted3 ^ key[1], - c = encrypted2 ^ key[2], - d = encrypted1 ^ key[3], - a2, b2, c2, - - nInnerRounds = key.length / 4 - 2, // key.length === 2 ? - i, - kIndex = 4, - table = this._tables[1], - - // load up the tables - table0 = table[0], - table1 = table[1], - table2 = table[2], - table3 = table[3], - sbox = table[4]; - - // Inner rounds. Cribbed from OpenSSL. - for (i = 0; i < nInnerRounds; i++) { - a2 = table0[a>>>24] ^ table1[b>>16 & 255] ^ table2[c>>8 & 255] ^ table3[d & 255] ^ key[kIndex]; - b2 = table0[b>>>24] ^ table1[c>>16 & 255] ^ table2[d>>8 & 255] ^ table3[a & 255] ^ key[kIndex + 1]; - c2 = table0[c>>>24] ^ table1[d>>16 & 255] ^ table2[a>>8 & 255] ^ table3[b & 255] ^ key[kIndex + 2]; - d = table0[d>>>24] ^ table1[a>>16 & 255] ^ table2[b>>8 & 255] ^ table3[c & 255] ^ key[kIndex + 3]; - kIndex += 4; - a=a2; b=b2; c=c2; - } - - // Last round. - for (i = 0; i < 4; i++) { - out[(3 & -i) + offset] = - sbox[a>>>24 ]<<24 ^ - sbox[b>>16 & 255]<<16 ^ - sbox[c>>8 & 255]<<8 ^ - sbox[d & 255] ^ - key[kIndex++]; - a2=a; a=b; b=c; c=d; d=a2; - } - } -} - -export default AES; diff --git a/dashboard-ui/bower_components/hls.js/src/crypt/aes128-decrypter.js b/dashboard-ui/bower_components/hls.js/src/crypt/aes128-decrypter.js deleted file mode 100644 index 78fc6b936..000000000 --- a/dashboard-ui/bower_components/hls.js/src/crypt/aes128-decrypter.js +++ /dev/null @@ -1,167 +0,0 @@ -/* - * - * This file contains an adaptation of the AES decryption algorithm - * from the Standford Javascript Cryptography Library. That work is - * covered by the following copyright and permissions notice: - * - * Copyright 2009-2010 Emily Stark, Mike Hamburg, Dan Boneh. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation - * are those of the authors and should not be interpreted as representing - * official policies, either expressed or implied, of the authors. - */ - -import AES from './aes'; - -class AES128Decrypter { - - constructor(key, initVector) { - this.key = key; - this.iv = initVector; - } - - /** - * Convert network-order (big-endian) bytes into their little-endian - * representation. - */ - ntoh(word) { - return (word << 24) | - ((word & 0xff00) << 8) | - ((word & 0xff0000) >> 8) | - (word >>> 24); - } - - - /** - * Decrypt bytes using AES-128 with CBC and PKCS#7 padding. - * @param encrypted {Uint8Array} the encrypted bytes - * @param key {Uint32Array} the bytes of the decryption key - * @param initVector {Uint32Array} the initialization vector (IV) to - * use for the first round of CBC. - * @return {Uint8Array} the decrypted bytes - * - * @see http://en.wikipedia.org/wiki/Advanced_Encryption_Standard - * @see http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29 - * @see https://tools.ietf.org/html/rfc2315 - */ - doDecrypt(encrypted, key, initVector) { - var - // word-level access to the encrypted bytes - encrypted32 = new Int32Array(encrypted.buffer, encrypted.byteOffset, encrypted.byteLength >> 2), - - decipher = new AES(Array.prototype.slice.call(key)), - - // byte and word-level access for the decrypted output - decrypted = new Uint8Array(encrypted.byteLength), - decrypted32 = new Int32Array(decrypted.buffer), - - // temporary variables for working with the IV, encrypted, and - // decrypted data - init0, init1, init2, init3, - encrypted0, encrypted1, encrypted2, encrypted3, - - // iteration variable - wordIx; - - // pull out the words of the IV to ensure we don't modify the - // passed-in reference and easier access - init0 = ~~initVector[0]; - init1 = ~~initVector[1]; - init2 = ~~initVector[2]; - init3 = ~~initVector[3]; - - // decrypt four word sequences, applying cipher-block chaining (CBC) - // to each decrypted block - for (wordIx = 0; wordIx < encrypted32.length; wordIx += 4) { - // convert big-endian (network order) words into little-endian - // (javascript order) - encrypted0 = ~~this.ntoh(encrypted32[wordIx]); - encrypted1 = ~~this.ntoh(encrypted32[wordIx + 1]); - encrypted2 = ~~this.ntoh(encrypted32[wordIx + 2]); - encrypted3 = ~~this.ntoh(encrypted32[wordIx + 3]); - - // decrypt the block - decipher.decrypt(encrypted0, - encrypted1, - encrypted2, - encrypted3, - decrypted32, - wordIx); - - // XOR with the IV, and restore network byte-order to obtain the - // plaintext - decrypted32[wordIx] = this.ntoh(decrypted32[wordIx] ^ init0); - decrypted32[wordIx + 1] = this.ntoh(decrypted32[wordIx + 1] ^ init1); - decrypted32[wordIx + 2] = this.ntoh(decrypted32[wordIx + 2] ^ init2); - decrypted32[wordIx + 3] = this.ntoh(decrypted32[wordIx + 3] ^ init3); - - // setup the IV for the next round - init0 = encrypted0; - init1 = encrypted1; - init2 = encrypted2; - init3 = encrypted3; - } - - return decrypted; - } - - localDecrypt(encrypted, key, initVector, decrypted) { - var bytes = this.doDecrypt(encrypted, - key, - initVector); - decrypted.set(bytes, encrypted.byteOffset); - } - - decrypt(encrypted) { - var - step = 4 * 8000, - //encrypted32 = new Int32Array(encrypted.buffer), - encrypted32 = new Int32Array(encrypted), - decrypted = new Uint8Array(encrypted.byteLength), - i = 0; - - // split up the encryption job and do the individual chunks asynchronously - var key = this.key; - var initVector = this.iv; - this.localDecrypt(encrypted32.subarray(i, i + step), key, initVector, decrypted); - - for (i = step; i < encrypted32.length; i += step) { - initVector = new Uint32Array([ - this.ntoh(encrypted32[i - 4]), - this.ntoh(encrypted32[i - 3]), - this.ntoh(encrypted32[i - 2]), - this.ntoh(encrypted32[i - 1]) - ]); - this.localDecrypt(encrypted32.subarray(i, i + step), key, initVector, decrypted); - } - - return decrypted; - } -} - -export default AES128Decrypter; diff --git a/dashboard-ui/bower_components/hls.js/src/crypt/decrypter.js b/dashboard-ui/bower_components/hls.js/src/crypt/decrypter.js deleted file mode 100644 index f0345f7f1..000000000 --- a/dashboard-ui/bower_components/hls.js/src/crypt/decrypter.js +++ /dev/null @@ -1,86 +0,0 @@ -/* - * AES128 decryption. - */ - -import AES128Decrypter from './aes128-decrypter'; -import {ErrorTypes, ErrorDetails} from '../errors'; -import {logger} from '../utils/logger'; - -class Decrypter { - - constructor(hls) { - this.hls = hls; - try { - const browserCrypto = window ? window.crypto : crypto; - this.subtle = browserCrypto.subtle || browserCrypto.webkitSubtle; - this.disableWebCrypto = !this.subtle; - } catch (e) { - this.disableWebCrypto = true; - } - } - - destroy() { - } - - decrypt(data, key, iv, callback) { - if (this.disableWebCrypto && this.hls.config.enableSoftwareAES) { - this.decryptBySoftware(data, key, iv, callback); - } else { - this.decryptByWebCrypto(data, key, iv, callback); - } - } - - decryptByWebCrypto(data, key, iv, callback) { - logger.log('decrypting by WebCrypto API'); - - this.subtle.importKey('raw', key, { name : 'AES-CBC', length : 128 }, false, ['decrypt']). - then((importedKey) => { - this.subtle.decrypt({ name : 'AES-CBC', iv : iv.buffer }, importedKey, data). - then(callback). - catch ((err) => { - this.onWebCryptoError(err, data, key, iv, callback); - }); - }). - catch ((err) => { - this.onWebCryptoError(err, data, key, iv, callback); - }); - } - - decryptBySoftware(data, key8, iv8, callback) { - logger.log('decrypting by JavaScript Implementation'); - - var view = new DataView(key8.buffer); - var key = new Uint32Array([ - view.getUint32(0), - view.getUint32(4), - view.getUint32(8), - view.getUint32(12) - ]); - - view = new DataView(iv8.buffer); - var iv = new Uint32Array([ - view.getUint32(0), - view.getUint32(4), - view.getUint32(8), - view.getUint32(12) - ]); - - var decrypter = new AES128Decrypter(key, iv); - callback(decrypter.decrypt(data).buffer); - } - - onWebCryptoError(err, data, key, iv, callback) { - if (this.hls.config.enableSoftwareAES) { - logger.log('disabling to use WebCrypto API'); - this.disableWebCrypto = true; - this.decryptBySoftware(data, key, iv, callback); - } - else { - logger.error(`decrypting error : ${err.message}`); - this.hls.trigger(Event.ERROR, {type : ErrorTypes.MEDIA_ERROR, details : ErrorDetails.FRAG_DECRYPT_ERROR, fatal : true, reason : err.message}); - } - } - -} - -export default Decrypter; diff --git a/dashboard-ui/bower_components/hls.js/src/demux/aacdemuxer.js b/dashboard-ui/bower_components/hls.js/src/demux/aacdemuxer.js deleted file mode 100644 index ddc52add8..000000000 --- a/dashboard-ui/bower_components/hls.js/src/demux/aacdemuxer.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - * AAC demuxer - */ -import ADTS from './adts'; -import {logger} from '../utils/logger'; -import ID3 from '../demux/id3'; - - class AACDemuxer { - - constructor(observer,remuxerClass) { - this.observer = observer; - this.remuxerClass = remuxerClass; - this.remuxer = new this.remuxerClass(observer); - this._aacTrack = {container : 'audio/adts', type: 'audio', id :-1, sequenceNumber: 0, samples : [], len : 0}; - } - - static probe(data) { - // check if data contains ID3 timestamp and ADTS sync worc - var id3 = new ID3(data), offset,len; - if(id3.hasTimeStamp) { - // look for ADTS header (0xFFFx) - for (offset = id3.length, len = data.length; offset < len - 1; offset++) { - if ((data[offset] === 0xff) && (data[offset+1] & 0xf0) === 0xf0) { - //logger.log('ADTS sync word found !'); - return true; - } - } - } - return false; - } - - - // feed incoming data to the front of the parsing pipeline - push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) { - var track = this._aacTrack, - id3 = new ID3(data), - pts = 90*id3.timeStamp, - config, frameLength, frameDuration, frameIndex, offset, headerLength, stamp, len, aacSample; - // look for ADTS header (0xFFFx) - for (offset = id3.length, len = data.length; offset < len - 1; offset++) { - if ((data[offset] === 0xff) && (data[offset+1] & 0xf0) === 0xf0) { - break; - } - } - - if (!track.audiosamplerate) { - config = ADTS.getAudioConfig(this.observer,data, offset, audioCodec); - track.config = config.config; - track.audiosamplerate = config.samplerate; - track.channelCount = config.channelCount; - track.codec = config.codec; - track.duration = duration; - logger.log(`parsed codec:${track.codec},rate:${config.samplerate},nb channel:${config.channelCount}`); - } - frameIndex = 0; - frameDuration = 1024 * 90000 / track.audiosamplerate; - while ((offset + 5) < len) { - // The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header - headerLength = (!!(data[offset + 1] & 0x01) ? 7 : 9); - // retrieve frame size - frameLength = ((data[offset + 3] & 0x03) << 11) | - (data[offset + 4] << 3) | - ((data[offset + 5] & 0xE0) >>> 5); - frameLength -= headerLength; - //stamp = pes.pts; - - if ((frameLength > 0) && ((offset + headerLength + frameLength) <= len)) { - stamp = pts + frameIndex * frameDuration; - //logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}/${(stamp/90).toFixed(0)}`); - aacSample = {unit: data.subarray(offset + headerLength, offset + headerLength + frameLength), pts: stamp, dts: stamp}; - track.samples.push(aacSample); - track.len += frameLength; - offset += frameLength + headerLength; - frameIndex++; - // look for ADTS header (0xFFFx) - for ( ; offset < (len - 1); offset++) { - if ((data[offset] === 0xff) && ((data[offset + 1] & 0xf0) === 0xf0)) { - break; - } - } - } else { - break; - } - } - this.remuxer.remux(this._aacTrack,{samples : []}, {samples : [ { pts: pts, dts : pts, unit : id3.payload} ]}, { samples: [] }, timeOffset); - } - - destroy() { - } - -} - -export default AACDemuxer; diff --git a/dashboard-ui/bower_components/hls.js/src/demux/adts.js b/dashboard-ui/bower_components/hls.js/src/demux/adts.js deleted file mode 100644 index 9ba4b6478..000000000 --- a/dashboard-ui/bower_components/hls.js/src/demux/adts.js +++ /dev/null @@ -1,132 +0,0 @@ -/** - * ADTS parser helper - */ -import {logger} from '../utils/logger'; -import {ErrorTypes, ErrorDetails} from '../errors'; - - class ADTS { - - static getAudioConfig(observer, data, offset, audioCodec) { - var adtsObjectType, // :int - adtsSampleingIndex, // :int - adtsExtensionSampleingIndex, // :int - adtsChanelConfig, // :int - config, - userAgent = navigator.userAgent.toLowerCase(), - adtsSampleingRates = [ - 96000, 88200, - 64000, 48000, - 44100, 32000, - 24000, 22050, - 16000, 12000, - 11025, 8000, - 7350]; - // byte 2 - adtsObjectType = ((data[offset + 2] & 0xC0) >>> 6) + 1; - adtsSampleingIndex = ((data[offset + 2] & 0x3C) >>> 2); - if(adtsSampleingIndex > adtsSampleingRates.length-1) { - observer.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_PARSING_ERROR, fatal: true, reason: `invalid ADTS sampling index:${adtsSampleingIndex}`}); - return; - } - adtsChanelConfig = ((data[offset + 2] & 0x01) << 2); - // byte 3 - adtsChanelConfig |= ((data[offset + 3] & 0xC0) >>> 6); - logger.log(`manifest codec:${audioCodec},ADTS data:type:${adtsObjectType},sampleingIndex:${adtsSampleingIndex}[${adtsSampleingRates[adtsSampleingIndex]}Hz],channelConfig:${adtsChanelConfig}`); - // firefox: freq less than 24kHz = AAC SBR (HE-AAC) - if (userAgent.indexOf('firefox') !== -1) { - if (adtsSampleingIndex >= 6) { - adtsObjectType = 5; - config = new Array(4); - // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies - // there is a factor 2 between frame sample rate and output sample rate - // multiply frequency by 2 (see table below, equivalent to substract 3) - adtsExtensionSampleingIndex = adtsSampleingIndex - 3; - } else { - adtsObjectType = 2; - config = new Array(2); - adtsExtensionSampleingIndex = adtsSampleingIndex; - } - // Android : always use AAC - } else if (userAgent.indexOf('android') !== -1) { - adtsObjectType = 2; - config = new Array(2); - adtsExtensionSampleingIndex = adtsSampleingIndex; - } else { - /* for other browsers (chrome ...) - always force audio type to be HE-AAC SBR, as some browsers do not support audio codec switch properly (like Chrome ...) - */ - adtsObjectType = 5; - config = new Array(4); - // if (manifest codec is HE-AAC or HE-AACv2) OR (manifest codec not specified AND frequency less than 24kHz) - if ((audioCodec && ((audioCodec.indexOf('mp4a.40.29') !== -1) || - (audioCodec.indexOf('mp4a.40.5') !== -1))) || - (!audioCodec && adtsSampleingIndex >= 6)) { - // HE-AAC uses SBR (Spectral Band Replication) , high frequencies are constructed from low frequencies - // there is a factor 2 between frame sample rate and output sample rate - // multiply frequency by 2 (see table below, equivalent to substract 3) - adtsExtensionSampleingIndex = adtsSampleingIndex - 3; - } else { - // if (manifest codec is AAC) AND (frequency less than 24kHz AND nb channel is 1) OR (manifest codec not specified and mono audio) - // Chrome fails to play back with low frequency AAC LC mono when initialized with HE-AAC. This is not a problem with stereo. - if (audioCodec && audioCodec.indexOf('mp4a.40.2') !== -1 && (adtsSampleingIndex >= 6 && adtsChanelConfig === 1) || - (!audioCodec && adtsChanelConfig === 1)) { - adtsObjectType = 2; - config = new Array(2); - } - adtsExtensionSampleingIndex = adtsSampleingIndex; - } - } - /* refer to http://wiki.multimedia.cx/index.php?title=MPEG-4_Audio#Audio_Specific_Config - ISO 14496-3 (AAC).pdf - Table 1.13 — Syntax of AudioSpecificConfig() - Audio Profile / Audio Object Type - 0: Null - 1: AAC Main - 2: AAC LC (Low Complexity) - 3: AAC SSR (Scalable Sample Rate) - 4: AAC LTP (Long Term Prediction) - 5: SBR (Spectral Band Replication) - 6: AAC Scalable - sampling freq - 0: 96000 Hz - 1: 88200 Hz - 2: 64000 Hz - 3: 48000 Hz - 4: 44100 Hz - 5: 32000 Hz - 6: 24000 Hz - 7: 22050 Hz - 8: 16000 Hz - 9: 12000 Hz - 10: 11025 Hz - 11: 8000 Hz - 12: 7350 Hz - 13: Reserved - 14: Reserved - 15: frequency is written explictly - Channel Configurations - These are the channel configurations: - 0: Defined in AOT Specifc Config - 1: 1 channel: front-center - 2: 2 channels: front-left, front-right - */ - // audioObjectType = profile => profile, the MPEG-4 Audio Object Type minus 1 - config[0] = adtsObjectType << 3; - // samplingFrequencyIndex - config[0] |= (adtsSampleingIndex & 0x0E) >> 1; - config[1] |= (adtsSampleingIndex & 0x01) << 7; - // channelConfiguration - config[1] |= adtsChanelConfig << 3; - if (adtsObjectType === 5) { - // adtsExtensionSampleingIndex - config[1] |= (adtsExtensionSampleingIndex & 0x0E) >> 1; - config[2] = (adtsExtensionSampleingIndex & 0x01) << 7; - // adtsObjectType (force to 2, chrome is checking that object type is less than 5 ??? - // https://chromium.googlesource.com/chromium/src.git/+/master/media/formats/mp4/aac.cc - config[2] |= 2 << 2; - config[3] = 0; - } - return {config: config, samplerate: adtsSampleingRates[adtsSampleingIndex], channelCount: adtsChanelConfig, codec: ('mp4a.40.' + adtsObjectType)}; - } -} - -export default ADTS; diff --git a/dashboard-ui/bower_components/hls.js/src/demux/demuxer-inline.js b/dashboard-ui/bower_components/hls.js/src/demux/demuxer-inline.js deleted file mode 100644 index 2f21b1ef2..000000000 --- a/dashboard-ui/bower_components/hls.js/src/demux/demuxer-inline.js +++ /dev/null @@ -1,49 +0,0 @@ -/* inline demuxer. - * probe fragments and instantiate appropriate demuxer depending on content type (TSDemuxer, AACDemuxer, ...) - */ - -import Event from '../events'; -import {ErrorTypes, ErrorDetails} from '../errors'; -import AACDemuxer from '../demux/aacdemuxer'; -import TSDemuxer from '../demux/tsdemuxer'; -import MP4Remuxer from '../remux/mp4-remuxer'; -import PassThroughRemuxer from '../remux/passthrough-remuxer'; - -class DemuxerInline { - - constructor(hls,typeSupported) { - this.hls = hls; - this.typeSupported = typeSupported; - } - - destroy() { - var demuxer = this.demuxer; - if (demuxer) { - demuxer.destroy(); - } - } - - push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) { - var demuxer = this.demuxer; - if (!demuxer) { - var hls = this.hls; - // probe for content type - if (TSDemuxer.probe(data)) { - if (this.typeSupported.mp2t === true) { - demuxer = new TSDemuxer(hls,PassThroughRemuxer); - } else { - demuxer = new TSDemuxer(hls,MP4Remuxer); - } - } else if(AACDemuxer.probe(data)) { - demuxer = new AACDemuxer(hls,MP4Remuxer); - } else { - hls.trigger(Event.ERROR, {type : ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_PARSING_ERROR, fatal: true, reason: 'no demux matching with content found'}); - return; - } - this.demuxer = demuxer; - } - demuxer.push(data,audioCodec,videoCodec,timeOffset,cc,level,sn,duration); - } -} - -export default DemuxerInline; diff --git a/dashboard-ui/bower_components/hls.js/src/demux/demuxer-worker.js b/dashboard-ui/bower_components/hls.js/src/demux/demuxer-worker.js deleted file mode 100644 index 14825614d..000000000 --- a/dashboard-ui/bower_components/hls.js/src/demux/demuxer-worker.js +++ /dev/null @@ -1,67 +0,0 @@ -/* demuxer web worker. - * - listen to worker message, and trigger DemuxerInline upon reception of Fragments. - * - provides MP4 Boxes back to main thread using [transferable objects](https://developers.google.com/web/updates/2011/12/Transferable-Objects-Lightning-Fast) in order to minimize message passing overhead. - */ - - import DemuxerInline from '../demux/demuxer-inline'; - import Event from '../events'; - import EventEmitter from 'events'; - -var DemuxerWorker = function (self) { - // observer setup - var observer = new EventEmitter(); - observer.trigger = function trigger (event, ...data) { - observer.emit(event, event, ...data); - }; - - observer.off = function off (event, ...data) { - observer.removeListener(event, ...data); - }; - self.addEventListener('message', function (ev) { - var data = ev.data; - //console.log('demuxer cmd:' + data.cmd); - switch (data.cmd) { - case 'init': - self.demuxer = new DemuxerInline(observer, data.typeSupported); - break; - case 'demux': - self.demuxer.push(new Uint8Array(data.data), data.audioCodec, data.videoCodec, data.timeOffset, data.cc, data.level, data.sn, data.duration); - break; - default: - break; - } - }); - - // listen to events triggered by Demuxer - observer.on(Event.FRAG_PARSING_INIT_SEGMENT, function(ev, data) { - self.postMessage({event: ev, tracks : data.tracks, unique : data.unique }); - }); - - observer.on(Event.FRAG_PARSING_DATA, function(ev, data) { - var objData = {event: ev, type: data.type, startPTS: data.startPTS, endPTS: data.endPTS, startDTS: data.startDTS, endDTS: data.endDTS, data1: data.data1.buffer, data2: data.data2.buffer, nb: data.nb, dropped : data.dropped}; - // pass data1/data2 as transferable object (no copy) - self.postMessage(objData, [objData.data1, objData.data2]); - }); - - observer.on(Event.FRAG_PARSED, function(event) { - self.postMessage({event: event}); - }); - - observer.on(Event.ERROR, function(event, data) { - self.postMessage({event: event, data: data}); - }); - - observer.on(Event.FRAG_PARSING_METADATA, function(event, data) { - var objData = {event: event, samples: data.samples}; - self.postMessage(objData); - }); - - observer.on(Event.FRAG_PARSING_USERDATA, function(event, data) { - var objData = {event: event, samples: data.samples}; - self.postMessage(objData); - }); - -}; - -export default DemuxerWorker; - diff --git a/dashboard-ui/bower_components/hls.js/src/demux/demuxer.js b/dashboard-ui/bower_components/hls.js/src/demux/demuxer.js deleted file mode 100644 index 6b075ccb4..000000000 --- a/dashboard-ui/bower_components/hls.js/src/demux/demuxer.js +++ /dev/null @@ -1,113 +0,0 @@ -import Event from '../events'; -import DemuxerInline from '../demux/demuxer-inline'; -import DemuxerWorker from '../demux/demuxer-worker'; -import {logger} from '../utils/logger'; -import Decrypter from '../crypt/decrypter'; - -class Demuxer { - - constructor(hls) { - this.hls = hls; - var typeSupported = { - mp4 : MediaSource.isTypeSupported('video/mp4'), - mp2t : hls.config.enableMP2TPassThrough && MediaSource.isTypeSupported('video/mp2t') - }; - if (hls.config.enableWorker && (typeof(Worker) !== 'undefined')) { - logger.log('demuxing in webworker'); - try { - var work = require('webworkify'); - this.w = work(DemuxerWorker); - this.onwmsg = this.onWorkerMessage.bind(this); - this.w.addEventListener('message', this.onwmsg); - this.w.postMessage({cmd: 'init', typeSupported : typeSupported}); - } catch(err) { - logger.error('error while initializing DemuxerWorker, fallback on DemuxerInline'); - this.demuxer = new DemuxerInline(hls,typeSupported); - } - } else { - this.demuxer = new DemuxerInline(hls,typeSupported); - } - this.demuxInitialized = true; - } - - destroy() { - if (this.w) { - this.w.removeEventListener('message', this.onwmsg); - this.w.terminate(); - this.w = null; - } else { - this.demuxer.destroy(); - this.demuxer = null; - } - if (this.decrypter) { - this.decrypter.destroy(); - this.decrypter = null; - } - } - - pushDecrypted(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) { - if (this.w) { - // post fragment payload as transferable objects (no copy) - this.w.postMessage({cmd: 'demux', data: data, audioCodec: audioCodec, videoCodec: videoCodec, timeOffset: timeOffset, cc: cc, level: level, sn : sn, duration: duration}, [data]); - } else { - this.demuxer.push(new Uint8Array(data), audioCodec, videoCodec, timeOffset, cc, level, sn, duration); - } - } - - push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration, decryptdata) { - if ((data.byteLength > 0) && (decryptdata != null) && (decryptdata.key != null) && (decryptdata.method === 'AES-128')) { - if (this.decrypter == null) { - this.decrypter = new Decrypter(this.hls); - } - - var localthis = this; - this.decrypter.decrypt(data, decryptdata.key, decryptdata.iv, function(decryptedData){ - localthis.pushDecrypted(decryptedData, audioCodec, videoCodec, timeOffset, cc, level, sn, duration); - }); - } else { - this.pushDecrypted(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration); - } - } - - onWorkerMessage(ev) { - var data = ev.data; - //console.log('onWorkerMessage:' + data.event); - switch(data.event) { - case Event.FRAG_PARSING_INIT_SEGMENT: - var obj = {}; - obj.tracks = data.tracks; - obj.unique = data.unique; - this.hls.trigger(Event.FRAG_PARSING_INIT_SEGMENT, obj); - break; - case Event.FRAG_PARSING_DATA: - this.hls.trigger(Event.FRAG_PARSING_DATA,{ - data1: new Uint8Array(data.data1), - data2: new Uint8Array(data.data2), - startPTS: data.startPTS, - endPTS: data.endPTS, - startDTS: data.startDTS, - endDTS: data.endDTS, - type: data.type, - nb: data.nb, - dropped: data.dropped, - }); - break; - case Event.FRAG_PARSING_METADATA: - this.hls.trigger(Event.FRAG_PARSING_METADATA, { - samples: data.samples - }); - break; - case Event.FRAG_PARSING_USERDATA: - this.hls.trigger(Event.FRAG_PARSING_USERDATA, { - samples: data.samples - }); - break; - default: - this.hls.trigger(data.event, data.data); - break; - } - } -} - -export default Demuxer; - diff --git a/dashboard-ui/bower_components/hls.js/src/demux/exp-golomb.js b/dashboard-ui/bower_components/hls.js/src/demux/exp-golomb.js deleted file mode 100644 index 23e206383..000000000 --- a/dashboard-ui/bower_components/hls.js/src/demux/exp-golomb.js +++ /dev/null @@ -1,294 +0,0 @@ -/** - * Parser for exponential Golomb codes, a variable-bitwidth number encoding scheme used by h264. -*/ - -import {logger} from '../utils/logger'; - -class ExpGolomb { - - constructor(data) { - this.data = data; - // the number of bytes left to examine in this.data - this.bytesAvailable = this.data.byteLength; - // the current word being examined - this.word = 0; // :uint - // the number of bits left to examine in the current word - this.bitsAvailable = 0; // :uint - } - - // ():void - loadWord() { - var - position = this.data.byteLength - this.bytesAvailable, - workingBytes = new Uint8Array(4), - availableBytes = Math.min(4, this.bytesAvailable); - if (availableBytes === 0) { - throw new Error('no bytes available'); - } - workingBytes.set(this.data.subarray(position, position + availableBytes)); - this.word = new DataView(workingBytes.buffer).getUint32(0); - // track the amount of this.data that has been processed - this.bitsAvailable = availableBytes * 8; - this.bytesAvailable -= availableBytes; - } - - // (count:int):void - skipBits(count) { - var skipBytes; // :int - if (this.bitsAvailable > count) { - this.word <<= count; - this.bitsAvailable -= count; - } else { - count -= this.bitsAvailable; - skipBytes = count >> 3; - count -= (skipBytes >> 3); - this.bytesAvailable -= skipBytes; - this.loadWord(); - this.word <<= count; - this.bitsAvailable -= count; - } - } - - // (size:int):uint - readBits(size) { - var - bits = Math.min(this.bitsAvailable, size), // :uint - valu = this.word >>> (32 - bits); // :uint - if (size > 32) { - logger.error('Cannot read more than 32 bits at a time'); - } - this.bitsAvailable -= bits; - if (this.bitsAvailable > 0) { - this.word <<= bits; - } else if (this.bytesAvailable > 0) { - this.loadWord(); - } - bits = size - bits; - if (bits > 0) { - return valu << bits | this.readBits(bits); - } else { - return valu; - } - } - - // ():uint - skipLZ() { - var leadingZeroCount; // :uint - for (leadingZeroCount = 0; leadingZeroCount < this.bitsAvailable; ++leadingZeroCount) { - if (0 !== (this.word & (0x80000000 >>> leadingZeroCount))) { - // the first bit of working word is 1 - this.word <<= leadingZeroCount; - this.bitsAvailable -= leadingZeroCount; - return leadingZeroCount; - } - } - // we exhausted word and still have not found a 1 - this.loadWord(); - return leadingZeroCount + this.skipLZ(); - } - - // ():void - skipUEG() { - this.skipBits(1 + this.skipLZ()); - } - - // ():void - skipEG() { - this.skipBits(1 + this.skipLZ()); - } - - // ():uint - readUEG() { - var clz = this.skipLZ(); // :uint - return this.readBits(clz + 1) - 1; - } - - // ():int - readEG() { - var valu = this.readUEG(); // :int - if (0x01 & valu) { - // the number is odd if the low order bit is set - return (1 + valu) >>> 1; // add 1 to make it even, and divide by 2 - } else { - return -1 * (valu >>> 1); // divide by two then make it negative - } - } - - // Some convenience functions - // :Boolean - readBoolean() { - return 1 === this.readBits(1); - } - - // ():int - readUByte() { - return this.readBits(8); - } - - // ():int - readUShort() { - return this.readBits(16); - } - // ():int - readUInt() { - return this.readBits(32); - } - - /** - * Advance the ExpGolomb decoder past a scaling list. The scaling - * list is optionally transmitted as part of a sequence parameter - * set and is not relevant to transmuxing. - * @param count {number} the number of entries in this scaling list - * @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1 - */ - skipScalingList(count) { - var - lastScale = 8, - nextScale = 8, - j, - deltaScale; - for (j = 0; j < count; j++) { - if (nextScale !== 0) { - deltaScale = this.readEG(); - nextScale = (lastScale + deltaScale + 256) % 256; - } - lastScale = (nextScale === 0) ? lastScale : nextScale; - } - } - - /** - * Read a sequence parameter set and return some interesting video - * properties. A sequence parameter set is the H264 metadata that - * describes the properties of upcoming video frames. - * @param data {Uint8Array} the bytes of a sequence parameter set - * @return {object} an object with configuration parsed from the - * sequence parameter set, including the dimensions of the - * associated video frames. - */ - readSPS() { - var - frameCropLeftOffset = 0, - frameCropRightOffset = 0, - frameCropTopOffset = 0, - frameCropBottomOffset = 0, - sarScale = 1, - profileIdc,profileCompat,levelIdc, - numRefFramesInPicOrderCntCycle, picWidthInMbsMinus1, - picHeightInMapUnitsMinus1, - frameMbsOnlyFlag, - scalingListCount, - i; - this.readUByte(); - profileIdc = this.readUByte(); // profile_idc - profileCompat = this.readBits(5); // constraint_set[0-4]_flag, u(5) - this.skipBits(3); // reserved_zero_3bits u(3), - levelIdc = this.readUByte(); //level_idc u(8) - this.skipUEG(); // seq_parameter_set_id - // some profiles have more optional data we don't need - if (profileIdc === 100 || - profileIdc === 110 || - profileIdc === 122 || - profileIdc === 244 || - profileIdc === 44 || - profileIdc === 83 || - profileIdc === 86 || - profileIdc === 118 || - profileIdc === 128) { - var chromaFormatIdc = this.readUEG(); - if (chromaFormatIdc === 3) { - this.skipBits(1); // separate_colour_plane_flag - } - this.skipUEG(); // bit_depth_luma_minus8 - this.skipUEG(); // bit_depth_chroma_minus8 - this.skipBits(1); // qpprime_y_zero_transform_bypass_flag - if (this.readBoolean()) { // seq_scaling_matrix_present_flag - scalingListCount = (chromaFormatIdc !== 3) ? 8 : 12; - for (i = 0; i < scalingListCount; i++) { - if (this.readBoolean()) { // seq_scaling_list_present_flag[ i ] - if (i < 6) { - this.skipScalingList(16); - } else { - this.skipScalingList(64); - } - } - } - } - } - this.skipUEG(); // log2_max_frame_num_minus4 - var picOrderCntType = this.readUEG(); - if (picOrderCntType === 0) { - this.readUEG(); //log2_max_pic_order_cnt_lsb_minus4 - } else if (picOrderCntType === 1) { - this.skipBits(1); // delta_pic_order_always_zero_flag - this.skipEG(); // offset_for_non_ref_pic - this.skipEG(); // offset_for_top_to_bottom_field - numRefFramesInPicOrderCntCycle = this.readUEG(); - for(i = 0; i < numRefFramesInPicOrderCntCycle; i++) { - this.skipEG(); // offset_for_ref_frame[ i ] - } - } - this.skipUEG(); // max_num_ref_frames - this.skipBits(1); // gaps_in_frame_num_value_allowed_flag - picWidthInMbsMinus1 = this.readUEG(); - picHeightInMapUnitsMinus1 = this.readUEG(); - frameMbsOnlyFlag = this.readBits(1); - if (frameMbsOnlyFlag === 0) { - this.skipBits(1); // mb_adaptive_frame_field_flag - } - this.skipBits(1); // direct_8x8_inference_flag - if (this.readBoolean()) { // frame_cropping_flag - frameCropLeftOffset = this.readUEG(); - frameCropRightOffset = this.readUEG(); - frameCropTopOffset = this.readUEG(); - frameCropBottomOffset = this.readUEG(); - } - if (this.readBoolean()) { - // vui_parameters_present_flag - if (this.readBoolean()) { - // aspect_ratio_info_present_flag - let sarRatio; - const aspectRatioIdc = this.readUByte(); - switch (aspectRatioIdc) { - case 1: sarRatio = [1,1]; break; - case 2: sarRatio = [12,11]; break; - case 3: sarRatio = [10,11]; break; - case 4: sarRatio = [16,11]; break; - case 5: sarRatio = [40,33]; break; - case 6: sarRatio = [24,11]; break; - case 7: sarRatio = [20,11]; break; - case 8: sarRatio = [32,11]; break; - case 9: sarRatio = [80,33]; break; - case 10: sarRatio = [18,11]; break; - case 11: sarRatio = [15,11]; break; - case 12: sarRatio = [64,33]; break; - case 13: sarRatio = [160,99]; break; - case 14: sarRatio = [4,3]; break; - case 15: sarRatio = [3,2]; break; - case 16: sarRatio = [2,1]; break; - case 255: { - sarRatio = [this.readUByte() << 8 | this.readUByte(), this.readUByte() << 8 | this.readUByte()]; - break; - } - } - if (sarRatio) { - sarScale = sarRatio[0] / sarRatio[1]; - } - } - } - return { - width: Math.ceil((((picWidthInMbsMinus1 + 1) * 16) - frameCropLeftOffset * 2 - frameCropRightOffset * 2) * sarScale), - height: ((2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16) - ((frameMbsOnlyFlag? 2 : 4) * (frameCropTopOffset + frameCropBottomOffset)) - }; - } - - readSliceType() { - // skip NALu type - this.readUByte(); - // discard first_mb_in_slice - this.readUEG(); - // return slice_type - return this.readUEG(); - } -} - -export default ExpGolomb; diff --git a/dashboard-ui/bower_components/hls.js/src/demux/id3.js b/dashboard-ui/bower_components/hls.js/src/demux/id3.js deleted file mode 100644 index d296bf455..000000000 --- a/dashboard-ui/bower_components/hls.js/src/demux/id3.js +++ /dev/null @@ -1,128 +0,0 @@ -/** - * ID3 parser - */ -import {logger} from '../utils/logger'; -//import Hex from '../utils/hex'; - - class ID3 { - - constructor(data) { - this._hasTimeStamp = false; - var offset = 0, byte1,byte2,byte3,byte4,tagSize,endPos,header,len; - do { - header = this.readUTF(data,offset,3); - offset+=3; - // first check for ID3 header - if (header === 'ID3') { - // skip 24 bits - offset += 3; - // retrieve tag(s) length - byte1 = data[offset++] & 0x7f; - byte2 = data[offset++] & 0x7f; - byte3 = data[offset++] & 0x7f; - byte4 = data[offset++] & 0x7f; - tagSize = (byte1 << 21) + (byte2 << 14) + (byte3 << 7) + byte4; - endPos = offset + tagSize; - //logger.log(`ID3 tag found, size/end: ${tagSize}/${endPos}`); - - // read ID3 tags - this._parseID3Frames(data, offset,endPos); - offset = endPos; - } else if (header === '3DI') { - // http://id3.org/id3v2.4.0-structure chapter 3.4. ID3v2 footer - offset += 7; - logger.log(`3DI footer found, end: ${offset}`); - } else { - offset -= 3; - len = offset; - if (len) { - //logger.log(`ID3 len: ${len}`); - if (!this.hasTimeStamp) { - logger.warn('ID3 tag found, but no timestamp'); - } - this._length = len; - this._payload = data.subarray(0,len); - } - return; - } - } while (true); - } - - readUTF(data,start,len) { - - var result = '',offset = start, end = start + len; - do { - result += String.fromCharCode(data[offset++]); - } while(offset < end); - return result; - } - - _parseID3Frames(data,offset,endPos) { - var tagId,tagLen,tagStart,tagFlags,timestamp; - while(offset + 8 <= endPos) { - tagId = this.readUTF(data,offset,4); - offset +=4; - - tagLen = data[offset++] << 24 + - data[offset++] << 16 + - data[offset++] << 8 + - data[offset++]; - - tagFlags = data[offset++] << 8 + - data[offset++]; - - tagStart = offset; - //logger.log("ID3 tag id:" + tagId); - switch(tagId) { - case 'PRIV': - //logger.log('parse frame:' + Hex.hexDump(data.subarray(offset,endPos))); - // owner should be "com.apple.streaming.transportStreamTimestamp" - if (this.readUTF(data,offset,44) === 'com.apple.streaming.transportStreamTimestamp') { - offset+=44; - // smelling even better ! we found the right descriptor - // skip null character (string end) + 3 first bytes - offset+= 4; - - // timestamp is 33 bit expressed as a big-endian eight-octet number, with the upper 31 bits set to zero. - var pts33Bit = data[offset++] & 0x1; - this._hasTimeStamp = true; - - timestamp = ((data[offset++] << 23) + - (data[offset++] << 15) + - (data[offset++] << 7) + - data[offset++]) /45; - - if (pts33Bit) { - timestamp += 47721858.84; // 2^32 / 90 - } - timestamp = Math.round(timestamp); - logger.trace(`ID3 timestamp found: ${timestamp}`); - this._timeStamp = timestamp; - } - break; - default: - break; - } - } - } - - get hasTimeStamp() { - return this._hasTimeStamp; - } - - get timeStamp() { - return this._timeStamp; - } - - get length() { - return this._length; - } - - get payload() { - return this._payload; - } - -} - -export default ID3; - diff --git a/dashboard-ui/bower_components/hls.js/src/demux/tsdemuxer.js b/dashboard-ui/bower_components/hls.js/src/demux/tsdemuxer.js deleted file mode 100644 index 7a1e1534f..000000000 --- a/dashboard-ui/bower_components/hls.js/src/demux/tsdemuxer.js +++ /dev/null @@ -1,703 +0,0 @@ -/** - * highly optimized TS demuxer: - * parse PAT, PMT - * extract PES packet from audio and video PIDs - * extract AVC/H264 NAL units and AAC/ADTS samples from PES packet - * trigger the remuxer upon parsing completion - * it also tries to workaround as best as it can audio codec switch (HE-AAC to AAC and vice versa), without having to restart the MediaSource. - * it also controls the remuxing process : - * upon discontinuity or level switch detection, it will also notifies the remuxer so that it can reset its state. -*/ - - import ADTS from './adts'; - import Event from '../events'; - import ExpGolomb from './exp-golomb'; -// import Hex from '../utils/hex'; - import {logger} from '../utils/logger'; - import {ErrorTypes, ErrorDetails} from '../errors'; - - class TSDemuxer { - - constructor(observer,remuxerClass) { - this.observer = observer; - this.remuxerClass = remuxerClass; - this.lastCC = 0; - this.remuxer = new this.remuxerClass(observer); - } - - static probe(data) { - // a TS fragment should contain at least 3 TS packets, a PAT, a PMT, and one PID, each starting with 0x47 - if (data.length >= 3*188 && data[0] === 0x47 && data[188] === 0x47 && data[2*188] === 0x47) { - return true; - } else { - return false; - } - } - - switchLevel() { - this.pmtParsed = false; - this._pmtId = -1; - this._avcTrack = {container : 'video/mp2t', type: 'video', id :-1, sequenceNumber: 0, samples : [], len : 0, nbNalu : 0, dropped : 0}; - this._aacTrack = {container : 'video/mp2t', type: 'audio', id :-1, sequenceNumber: 0, samples : [], len : 0}; - this._id3Track = {type: 'id3', id :-1, sequenceNumber: 0, samples : [], len : 0}; - this._txtTrack = {type: 'text', id: -1, sequenceNumber: 0, samples: [], len: 0}; - // flush any partial content - this.aacOverFlow = null; - this.aacLastPTS = null; - this.avcNaluState = 0; - this.remuxer.switchLevel(); - } - - insertDiscontinuity() { - this.switchLevel(); - this.remuxer.insertDiscontinuity(); - } - - // feed incoming data to the front of the parsing pipeline - push(data, audioCodec, videoCodec, timeOffset, cc, level, sn, duration) { - var avcData, aacData, id3Data, - start, len = data.length, stt, pid, atf, offset, - codecsOnly = this.remuxer.passthrough, - unknownPIDs = false; - - this.audioCodec = audioCodec; - this.videoCodec = videoCodec; - this.timeOffset = timeOffset; - this._duration = duration; - this.contiguous = false; - if (cc !== this.lastCC) { - logger.log('discontinuity detected'); - this.insertDiscontinuity(); - this.lastCC = cc; - } - if (level !== this.lastLevel) { - logger.log('level switch detected'); - this.switchLevel(); - this.lastLevel = level; - } else if (sn === (this.lastSN+1)) { - this.contiguous = true; - } - this.lastSN = sn; - - var pmtParsed = this.pmtParsed, - avcId = this._avcTrack.id, - aacId = this._aacTrack.id, - id3Id = this._id3Track.id; - - // don't parse last TS packet if incomplete - len -= len % 188; - // loop through TS packets - for (start = 0; start < len; start += 188) { - if (data[start] === 0x47) { - stt = !!(data[start + 1] & 0x40); - // pid is a 13-bit field starting at the last bit of TS[1] - pid = ((data[start + 1] & 0x1f) << 8) + data[start + 2]; - atf = (data[start + 3] & 0x30) >> 4; - // if an adaption field is present, its length is specified by the fifth byte of the TS packet header. - if (atf > 1) { - offset = start + 5 + data[start + 4]; - // continue if there is only adaptation field - if (offset === (start + 188)) { - continue; - } - } else { - offset = start + 4; - } - if (pmtParsed) { - if (pid === avcId) { - if (stt) { - if (avcData) { - this._parseAVCPES(this._parsePES(avcData)); - if (codecsOnly) { - // if we have video codec info AND - // if audio PID is undefined OR if we have audio codec info, - // we have all codec info ! - if (this._avcTrack.codec && (aacId === -1 || this._aacTrack.codec)) { - this.remux(data); - return; - } - } - } - avcData = {data: [], size: 0}; - } - if (avcData) { - avcData.data.push(data.subarray(offset, start + 188)); - avcData.size += start + 188 - offset; - } - } else if (pid === aacId) { - if (stt) { - if (aacData) { - this._parseAACPES(this._parsePES(aacData)); - if (codecsOnly) { - // here we now that we have audio codec info - // if video PID is undefined OR if we have video codec info, - // we have all codec infos ! - if (this._aacTrack.codec && (avcId === -1 || this._avcTrack.codec)) { - this.remux(data); - return; - } - } - } - aacData = {data: [], size: 0}; - } - if (aacData) { - aacData.data.push(data.subarray(offset, start + 188)); - aacData.size += start + 188 - offset; - } - } else if (pid === id3Id) { - if (stt) { - if (id3Data) { - this._parseID3PES(this._parsePES(id3Data)); - } - id3Data = {data: [], size: 0}; - } - if (id3Data) { - id3Data.data.push(data.subarray(offset, start + 188)); - id3Data.size += start + 188 - offset; - } - } - } else { - if (stt) { - offset += data[offset] + 1; - } - if (pid === 0) { - this._parsePAT(data, offset); - } else if (pid === this._pmtId) { - this._parsePMT(data, offset); - pmtParsed = this.pmtParsed = true; - avcId = this._avcTrack.id; - aacId = this._aacTrack.id; - id3Id = this._id3Track.id; - if (unknownPIDs) { - logger.log('reparse from beginning'); - unknownPIDs = false; - // we set it to -188, the += 188 in the for loop will reset start to 0 - start = -188; - } - } else { - logger.log('unknown PID found before PAT/PMT'); - unknownPIDs = true; - } - } - } else { - this.observer.trigger(Event.ERROR, {type : ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_PARSING_ERROR, fatal: false, reason: 'TS packet did not start with 0x47'}); - } - } - // parse last PES packet - if (avcData) { - this._parseAVCPES(this._parsePES(avcData)); - } - if (aacData) { - this._parseAACPES(this._parsePES(aacData)); - } - if (id3Data) { - this._parseID3PES(this._parsePES(id3Data)); - } - this.remux(null); - } - - remux(data) { - this.remuxer.remux(this._aacTrack, this._avcTrack, this._id3Track, this._txtTrack, this.timeOffset, this.contiguous, data); - } - - destroy() { - this.switchLevel(); - this._initPTS = this._initDTS = undefined; - this._duration = 0; - } - - _parsePAT(data, offset) { - // skip the PSI header and parse the first PMT entry - this._pmtId = (data[offset + 10] & 0x1F) << 8 | data[offset + 11]; - //logger.log('PMT PID:' + this._pmtId); - } - - _parsePMT(data, offset) { - var sectionLength, tableEnd, programInfoLength, pid; - sectionLength = (data[offset + 1] & 0x0f) << 8 | data[offset + 2]; - tableEnd = offset + 3 + sectionLength - 4; - // to determine where the table is, we have to figure out how - // long the program info descriptors are - programInfoLength = (data[offset + 10] & 0x0f) << 8 | data[offset + 11]; - // advance the offset to the first entry in the mapping table - offset += 12 + programInfoLength; - while (offset < tableEnd) { - pid = (data[offset + 1] & 0x1F) << 8 | data[offset + 2]; - switch(data[offset]) { - // ISO/IEC 13818-7 ADTS AAC (MPEG-2 lower bit-rate audio) - case 0x0f: - //logger.log('AAC PID:' + pid); - this._aacTrack.id = pid; - break; - // Packetized metadata (ID3) - case 0x15: - //logger.log('ID3 PID:' + pid); - this._id3Track.id = pid; - break; - // ITU-T Rec. H.264 and ISO/IEC 14496-10 (lower bit-rate video) - case 0x1b: - //logger.log('AVC PID:' + pid); - this._avcTrack.id = pid; - break; - default: - logger.log('unkown stream type:' + data[offset]); - break; - } - // move to the next table entry - // skip past the elementary stream descriptors, if present - offset += ((data[offset + 3] & 0x0F) << 8 | data[offset + 4]) + 5; - } - } - - _parsePES(stream) { - var i = 0, frag, pesFlags, pesPrefix, pesLen, pesHdrLen, pesData, pesPts, pesDts, payloadStartOffset, data = stream.data; - //retrieve PTS/DTS from first fragment - frag = data[0]; - pesPrefix = (frag[0] << 16) + (frag[1] << 8) + frag[2]; - if (pesPrefix === 1) { - pesLen = (frag[4] << 8) + frag[5]; - pesFlags = frag[7]; - if (pesFlags & 0xC0) { - /* PES header described here : http://dvd.sourceforge.net/dvdinfo/pes-hdr.html - as PTS / DTS is 33 bit we cannot use bitwise operator in JS, - as Bitwise operators treat their operands as a sequence of 32 bits */ - pesPts = (frag[9] & 0x0E) * 536870912 +// 1 << 29 - (frag[10] & 0xFF) * 4194304 +// 1 << 22 - (frag[11] & 0xFE) * 16384 +// 1 << 14 - (frag[12] & 0xFF) * 128 +// 1 << 7 - (frag[13] & 0xFE) / 2; - // check if greater than 2^32 -1 - if (pesPts > 4294967295) { - // decrement 2^33 - pesPts -= 8589934592; - } - if (pesFlags & 0x40) { - pesDts = (frag[14] & 0x0E ) * 536870912 +// 1 << 29 - (frag[15] & 0xFF ) * 4194304 +// 1 << 22 - (frag[16] & 0xFE ) * 16384 +// 1 << 14 - (frag[17] & 0xFF ) * 128 +// 1 << 7 - (frag[18] & 0xFE ) / 2; - // check if greater than 2^32 -1 - if (pesDts > 4294967295) { - // decrement 2^33 - pesDts -= 8589934592; - } - } else { - pesDts = pesPts; - } - } - pesHdrLen = frag[8]; - payloadStartOffset = pesHdrLen + 9; - - stream.size -= payloadStartOffset; - //reassemble PES packet - pesData = new Uint8Array(stream.size); - while (data.length) { - frag = data.shift(); - var len = frag.byteLength; - if (payloadStartOffset) { - if (payloadStartOffset > len) { - // trim full frag if PES header bigger than frag - payloadStartOffset-=len; - continue; - } else { - // trim partial frag if PES header smaller than frag - frag = frag.subarray(payloadStartOffset); - len-=payloadStartOffset; - payloadStartOffset = 0; - } - } - pesData.set(frag, i); - i+=len; - } - return {data: pesData, pts: pesPts, dts: pesDts, len: pesLen}; - } else { - return null; - } - } - - _parseAVCPES(pes) { - var track = this._avcTrack, - samples = track.samples, - units = this._parseAVCNALu(pes.data), - units2 = [], - debug = false, - key = false, - length = 0, - expGolombDecoder, - avcSample, - push, - i; - // no NALu found - if (units.length === 0 && samples.length > 0) { - // append pes.data to previous NAL unit - var lastavcSample = samples[samples.length - 1]; - var lastUnit = lastavcSample.units.units[lastavcSample.units.units.length - 1]; - var tmp = new Uint8Array(lastUnit.data.byteLength + pes.data.byteLength); - tmp.set(lastUnit.data, 0); - tmp.set(pes.data, lastUnit.data.byteLength); - lastUnit.data = tmp; - lastavcSample.units.length += pes.data.byteLength; - track.len += pes.data.byteLength; - } - //free pes.data to save up some memory - pes.data = null; - var debugString = ''; - - var pushAccesUnit = function() { - if (units2.length) { - // only push AVC sample if keyframe already found in this fragment OR - // keyframe found in last fragment (track.sps) AND - // samples already appended (we already found a keyframe in this fragment) OR fragment is contiguous - if (key === true || - (track.sps && (samples.length || this.contiguous))) { - avcSample = {units: { units : units2, length : length}, pts: pes.pts, dts: pes.dts, key: key}; - samples.push(avcSample); - track.len += length; - track.nbNalu += units2.length; - } else { - // dropped samples, track it - track.dropped++; - } - units2 = []; - length = 0; - } - }.bind(this); - - units.forEach(unit => { - switch(unit.type) { - //NDR - case 1: - push = true; - if(debug) { - debugString += 'NDR '; - } - break; - //IDR - case 5: - push = true; - if(debug) { - debugString += 'IDR '; - } - key = true; - break; - //SEI - case 6: - push = true; - if(debug) { - debugString += 'SEI '; - } - expGolombDecoder = new ExpGolomb(unit.data); - - // skip frameType - expGolombDecoder.readUByte(); - - var payloadType = expGolombDecoder.readUByte(); - - // TODO: there can be more than one payload in an SEI packet... - // TODO: need to read type and size in a while loop to get them all - if (payloadType === 4) - { - var payloadSize = 0; - - do { - payloadSize = expGolombDecoder.readUByte(); - } - while (payloadSize === 255); - - var countryCode = expGolombDecoder.readUByte(); - - if (countryCode === 181) - { - var providerCode = expGolombDecoder.readUShort(); - - if (providerCode === 49) - { - var userStructure = expGolombDecoder.readUInt(); - - if (userStructure === 0x47413934) - { - var userDataType = expGolombDecoder.readUByte(); - - // Raw CEA-608 bytes wrapped in CEA-708 packet - if (userDataType === 3) - { - var firstByte = expGolombDecoder.readUByte(); - var secondByte = expGolombDecoder.readUByte(); - - var totalCCs = 31 & firstByte; - var byteArray = [firstByte, secondByte]; - - for (i=0; i this is the first start code found in this PES packet - // first check if start code delimiter is overlapping between 2 PES packets, - // ie it started in last packet (lastState not zero) - // and ended at the beginning of this PES packet (i <= 4 - lastState) - let lastState = this.avcNaluState; - if(lastState && (i <= 4 - lastState)) { - // start delimiter overlapping between PES packets - // strip start delimiter bytes from the end of last NAL unit - let track = this._avcTrack, - samples = track.samples; - if (samples.length) { - let lastavcSample = samples[samples.length - 1], - lastUnits = lastavcSample.units.units, - lastUnit = lastUnits[lastUnits.length - 1]; - // check if lastUnit had a state different from zero - if (lastUnit.state) { - // strip last bytes - lastUnit.data = lastUnit.data.subarray(0,lastUnit.data.byteLength - lastState); - lastavcSample.units.length -= lastState; - track.len -= lastState; - } - } - } - // If NAL units are not starting right at the beginning of the PES packet, push preceding data into previous NAL unit. - overflow = i - state - 1; - if (overflow > 0) { - let track = this._avcTrack, - samples = track.samples; - //logger.log('first NALU found with overflow:' + overflow); - if (samples.length) { - let lastavcSample = samples[samples.length - 1], - lastUnits = lastavcSample.units.units, - lastUnit = lastUnits[lastUnits.length - 1], - tmp = new Uint8Array(lastUnit.data.byteLength + overflow); - tmp.set(lastUnit.data, 0); - tmp.set(array.subarray(0, overflow), lastUnit.data.byteLength); - lastUnit.data = tmp; - lastavcSample.units.length += overflow; - track.len += overflow; - } - } - } - lastUnitStart = i; - lastUnitType = unitType; - state = 0; - } else { - state = 0; - } - break; - default: - break; - } - } - if (lastUnitStart) { - unit = {data: array.subarray(lastUnitStart, len), type: lastUnitType, state : state}; - units.push(unit); - //logger.log('pushing NALU, type/size/state:' + unit.type + '/' + unit.data.byteLength + '/' + state); - this.avcNaluState = state; - } - return units; - } - - _parseAACPES(pes) { - var track = this._aacTrack, - data = pes.data, - pts = pes.pts, - startOffset = 0, - duration = this._duration, - audioCodec = this.audioCodec, - aacOverFlow = this.aacOverFlow, - aacLastPTS = this.aacLastPTS, - config, frameLength, frameDuration, frameIndex, offset, headerLength, stamp, len, aacSample; - if (aacOverFlow) { - var tmp = new Uint8Array(aacOverFlow.byteLength + data.byteLength); - tmp.set(aacOverFlow, 0); - tmp.set(data, aacOverFlow.byteLength); - //logger.log(`AAC: append overflowing ${aacOverFlow.byteLength} bytes to beginning of new PES`); - data = tmp; - } - // look for ADTS header (0xFFFx) - for (offset = startOffset, len = data.length; offset < len - 1; offset++) { - if ((data[offset] === 0xff) && (data[offset+1] & 0xf0) === 0xf0) { - break; - } - } - // if ADTS header does not start straight from the beginning of the PES payload, raise an error - if (offset) { - var reason, fatal; - if (offset < len - 1) { - reason = `AAC PES did not start with ADTS header,offset:${offset}`; - fatal = false; - } else { - reason = 'no ADTS header found in AAC PES'; - fatal = true; - } - this.observer.trigger(Event.ERROR, {type: ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_PARSING_ERROR, fatal: fatal, reason: reason}); - if (fatal) { - return; - } - } - if (!track.audiosamplerate) { - config = ADTS.getAudioConfig(this.observer,data, offset, audioCodec); - track.config = config.config; - track.audiosamplerate = config.samplerate; - track.channelCount = config.channelCount; - track.codec = config.codec; - track.duration = duration; - logger.log(`parsed codec:${track.codec},rate:${config.samplerate},nb channel:${config.channelCount}`); - } - frameIndex = 0; - frameDuration = 1024 * 90000 / track.audiosamplerate; - - // if last AAC frame is overflowing, we should ensure timestamps are contiguous: - // first sample PTS should be equal to last sample PTS + frameDuration - if(aacOverFlow && aacLastPTS) { - var newPTS = aacLastPTS+frameDuration; - if(Math.abs(newPTS-pts) > 1) { - logger.log(`AAC: align PTS for overlapping frames by ${Math.round((newPTS-pts)/90)}`); - pts=newPTS; - } - } - - while ((offset + 5) < len) { - // The protection skip bit tells us if we have 2 bytes of CRC data at the end of the ADTS header - headerLength = (!!(data[offset + 1] & 0x01) ? 7 : 9); - // retrieve frame size - frameLength = ((data[offset + 3] & 0x03) << 11) | - (data[offset + 4] << 3) | - ((data[offset + 5] & 0xE0) >>> 5); - frameLength -= headerLength; - //stamp = pes.pts; - - if ((frameLength > 0) && ((offset + headerLength + frameLength) <= len)) { - stamp = pts + frameIndex * frameDuration; - //logger.log(`AAC frame, offset/length/total/pts:${offset+headerLength}/${frameLength}/${data.byteLength}/${(stamp/90).toFixed(0)}`); - aacSample = {unit: data.subarray(offset + headerLength, offset + headerLength + frameLength), pts: stamp, dts: stamp}; - track.samples.push(aacSample); - track.len += frameLength; - offset += frameLength + headerLength; - frameIndex++; - // look for ADTS header (0xFFFx) - for ( ; offset < (len - 1); offset++) { - if ((data[offset] === 0xff) && ((data[offset + 1] & 0xf0) === 0xf0)) { - break; - } - } - } else { - break; - } - } - if (offset < len) { - aacOverFlow = data.subarray(offset, len); - //logger.log(`AAC: overflow detected:${len-offset}`); - } else { - aacOverFlow = null; - } - this.aacOverFlow = aacOverFlow; - this.aacLastPTS = stamp; - } - - _parseID3PES(pes) { - this._id3Track.samples.push(pes); - } -} - -export default TSDemuxer; - diff --git a/dashboard-ui/bower_components/hls.js/src/errors.js b/dashboard-ui/bower_components/hls.js/src/errors.js deleted file mode 100644 index 5ff545e84..000000000 --- a/dashboard-ui/bower_components/hls.js/src/errors.js +++ /dev/null @@ -1,51 +0,0 @@ -export const ErrorTypes = { - // Identifier for a network error (loading error / timeout ...) - NETWORK_ERROR: 'networkError', - // Identifier for a media Error (video/parsing/mediasource error) - MEDIA_ERROR: 'mediaError', - // Identifier for all other errors - OTHER_ERROR: 'otherError' -}; - -export const ErrorDetails = { - // Identifier for a manifest load error - data: { url : faulty URL, response : XHR response} - MANIFEST_LOAD_ERROR: 'manifestLoadError', - // Identifier for a manifest load timeout - data: { url : faulty URL, response : XHR response} - MANIFEST_LOAD_TIMEOUT: 'manifestLoadTimeOut', - // Identifier for a manifest parsing error - data: { url : faulty URL, reason : error reason} - MANIFEST_PARSING_ERROR: 'manifestParsingError', - // Identifier for a manifest with only incompatible codecs error - data: { url : faulty URL, reason : error reason} - MANIFEST_INCOMPATIBLE_CODECS_ERROR: 'manifestIncompatibleCodecsError', - // Identifier for playlist load error - data: { url : faulty URL, response : XHR response} - LEVEL_LOAD_ERROR: 'levelLoadError', - // Identifier for playlist load timeout - data: { url : faulty URL, response : XHR response} - LEVEL_LOAD_TIMEOUT: 'levelLoadTimeOut', - // Identifier for a level switch error - data: { level : faulty level Id, event : error description} - LEVEL_SWITCH_ERROR: 'levelSwitchError', - // Identifier for fragment load error - data: { frag : fragment object, response : XHR response} - FRAG_LOAD_ERROR: 'fragLoadError', - // Identifier for fragment loop loading error - data: { frag : fragment object} - FRAG_LOOP_LOADING_ERROR: 'fragLoopLoadingError', - // Identifier for fragment load timeout error - data: { frag : fragment object} - FRAG_LOAD_TIMEOUT: 'fragLoadTimeOut', - // Identifier for a fragment decryption error event - data: parsing error description - FRAG_DECRYPT_ERROR: 'fragDecryptError', - // Identifier for a fragment parsing error event - data: parsing error description - FRAG_PARSING_ERROR: 'fragParsingError', - // Identifier for decrypt key load error - data: { frag : fragment object, response : XHR response} - KEY_LOAD_ERROR: 'keyLoadError', - // Identifier for decrypt key load timeout error - data: { frag : fragment object} - KEY_LOAD_TIMEOUT: 'keyLoadTimeOut', - // Identifier for a buffer append error - data: append error description - BUFFER_APPEND_ERROR: 'bufferAppendError', - // Identifier for a buffer appending error event - data: appending error description - BUFFER_APPENDING_ERROR: 'bufferAppendingError', - // Identifier for a buffer stalled error event - BUFFER_STALLED_ERROR: 'bufferStalledError', - // Identifier for a buffer full event - BUFFER_FULL_ERROR: 'bufferFullError', - // Identifier for a buffer seek over hole event - BUFFER_SEEK_OVER_HOLE: 'bufferSeekOverHole', - // Identifier for an internal exception happening inside hls.js while handling an event - INTERNAL_EXCEPTION: 'internalException' -}; diff --git a/dashboard-ui/bower_components/hls.js/src/event-handler.js b/dashboard-ui/bower_components/hls.js/src/event-handler.js deleted file mode 100644 index c949ac882..000000000 --- a/dashboard-ui/bower_components/hls.js/src/event-handler.js +++ /dev/null @@ -1,73 +0,0 @@ -/* -* -* All objects in the event handling chain should inherit from this class -* -*/ - -import {logger} from './utils/logger'; -import {ErrorTypes, ErrorDetails} from './errors'; -import Event from './events'; - -class EventHandler { - - constructor(hls, ...events) { - this.hls = hls; - this.onEvent = this.onEvent.bind(this); - this.handledEvents = events; - this.useGenericHandler = true; - - this.registerListeners(); - } - - destroy() { - this.unregisterListeners(); - } - - isEventHandler() { - return typeof this.handledEvents === 'object' && this.handledEvents.length && typeof this.onEvent === 'function'; - } - - registerListeners() { - if (this.isEventHandler()) { - this.handledEvents.forEach(function(event) { - if (event === 'hlsEventGeneric') { - throw new Error('Forbidden event name: ' + event); - } - this.hls.on(event, this.onEvent); - }.bind(this)); - } - } - - unregisterListeners() { - if (this.isEventHandler()) { - this.handledEvents.forEach(function(event) { - this.hls.off(event, this.onEvent); - }.bind(this)); - } - } - - /* - * arguments: event (string), data (any) - */ - onEvent(event, data) { - this.onEventGeneric(event, data); - } - - onEventGeneric(event, data) { - var eventToFunction = function(event, data) { - var funcName = 'on' + event.replace('hls', ''); - if (typeof this[funcName] !== 'function') { - throw new Error(`Event ${event} has no generic handler in this ${this.constructor.name} class (tried ${funcName})`); - } - return this[funcName].bind(this, data); - }; - try { - eventToFunction.call(this, event, data).call(); - } catch (err) { - logger.error(`internal error happened while processing ${event}:${err.message}`); - this.hls.trigger(Event.ERROR, {type: ErrorTypes.OTHER_ERROR, details: ErrorDetails.INTERNAL_EXCEPTION, fatal: false, event : event, err : err}); - } - } -} - -export default EventHandler; diff --git a/dashboard-ui/bower_components/hls.js/src/events.js b/dashboard-ui/bower_components/hls.js/src/events.js deleted file mode 100644 index 4f518fd22..000000000 --- a/dashboard-ui/bower_components/hls.js/src/events.js +++ /dev/null @@ -1,72 +0,0 @@ -module.exports = { - // fired before MediaSource is attaching to media element - data: { media } - MEDIA_ATTACHING: 'hlsMediaAttaching', - // fired when MediaSource has been succesfully attached to media element - data: { } - MEDIA_ATTACHED: 'hlsMediaAttached', - // fired before detaching MediaSource from media element - data: { } - MEDIA_DETACHING: 'hlsMediaDetaching', - // fired when MediaSource has been detached from media element - data: { } - MEDIA_DETACHED: 'hlsMediaDetached', - // fired when we buffer is going to be resetted - BUFFER_RESET: 'hlsBufferReset', - // fired when we know about the codecs that we need buffers for to push into - data: {tracks : { container, codec, levelCodec, initSegment, metadata }} - BUFFER_CODECS: 'hlsBufferCodecs', - // fired when we append a segment to the buffer - data: { segment: segment object } - BUFFER_APPENDING: 'hlsBufferAppending', - // fired when we are done with appending a media segment to the buffer - BUFFER_APPENDED: 'hlsBufferAppended', - // fired when the stream is finished and we want to notify the media buffer that there will be no more data - BUFFER_EOS: 'hlsBufferEos', - // fired when the media buffer should be flushed - data {startOffset, endOffset} - BUFFER_FLUSHING: 'hlsBufferFlushing', - // fired when the media has been flushed - BUFFER_FLUSHED: 'hlsBufferFlushed', - // fired to signal that a manifest loading starts - data: { url : manifestURL} - MANIFEST_LOADING: 'hlsManifestLoading', - // fired after manifest has been loaded - data: { levels : [available quality levels] , url : manifestURL, stats : { trequest, tfirst, tload, mtime}} - MANIFEST_LOADED: 'hlsManifestLoaded', - // fired after manifest has been parsed - data: { levels : [available quality levels] , firstLevel : index of first quality level appearing in Manifest} - MANIFEST_PARSED: 'hlsManifestParsed', - // fired when a level playlist loading starts - data: { url : level URL level : id of level being loaded} - LEVEL_LOADING: 'hlsLevelLoading', - // fired when a level playlist loading finishes - data: { details : levelDetails object, level : id of loaded level, stats : { trequest, tfirst, tload, mtime} } - LEVEL_LOADED: 'hlsLevelLoaded', - // fired when a level's details have been updated based on previous details, after it has been loaded. - data: { details : levelDetails object, level : id of updated level } - LEVEL_UPDATED: 'hlsLevelUpdated', - // fired when a level's PTS information has been updated after parsing a fragment - data: { details : levelDetails object, level : id of updated level, drift: PTS drift observed when parsing last fragment } - LEVEL_PTS_UPDATED: 'hlsLevelPtsUpdated', - // fired when a level switch is requested - data: { level : id of new level } - LEVEL_SWITCH: 'hlsLevelSwitch', - // fired when a fragment loading starts - data: { frag : fragment object} - FRAG_LOADING: 'hlsFragLoading', - // fired when a fragment loading is progressing - data: { frag : fragment object, { trequest, tfirst, loaded}} - FRAG_LOAD_PROGRESS: 'hlsFragLoadProgress', - // Identifier for fragment load aborting for emergency switch down - data: {frag : fragment object} - FRAG_LOAD_EMERGENCY_ABORTED: 'hlsFragLoadEmergencyAborted', - // fired when a fragment loading is completed - data: { frag : fragment object, payload : fragment payload, stats : { trequest, tfirst, tload, length}} - FRAG_LOADED: 'hlsFragLoaded', - // fired when Init Segment has been extracted from fragment - data: { moov : moov MP4 box, codecs : codecs found while parsing fragment} - FRAG_PARSING_INIT_SEGMENT: 'hlsFragParsingInitSegment', - // fired when parsing sei text is completed - data: { samples : [ sei samples pes ] } - FRAG_PARSING_USERDATA: 'hlsFragParsingUserdata', - // fired when parsing id3 is completed - data: { samples : [ id3 samples pes ] } - FRAG_PARSING_METADATA: 'hlsFragParsingMetadata', - // fired when data have been extracted from fragment - data: { data1 : moof MP4 box or TS fragments, data2 : mdat MP4 box or null} - FRAG_PARSING_DATA: 'hlsFragParsingData', - // fired when fragment parsing is completed - data: undefined - FRAG_PARSED: 'hlsFragParsed', - // fired when fragment remuxed MP4 boxes have all been appended into SourceBuffer - data: { frag : fragment object, stats : { trequest, tfirst, tload, tparsed, tbuffered, length} } - FRAG_BUFFERED: 'hlsFragBuffered', - // fired when fragment matching with current media position is changing - data : { frag : fragment object } - FRAG_CHANGED: 'hlsFragChanged', - // Identifier for a FPS drop event - data: {curentDropped, currentDecoded, totalDroppedFrames} - FPS_DROP: 'hlsFpsDrop', - // Identifier for an error event - data: { type : error type, details : error details, fatal : if true, hls.js cannot/will not try to recover, if false, hls.js will try to recover,other error specific data} - ERROR: 'hlsError', - // fired when hls.js instance starts destroying. Different from MEDIA_DETACHED as one could want to detach and reattach a media to the instance of hls.js to handle mid-rolls for example - DESTROYING: 'hlsDestroying', - // fired when a decrypt key loading starts - data: { frag : fragment object} - KEY_LOADING: 'hlsKeyLoading', - // fired when a decrypt key loading is completed - data: { frag : fragment object, payload : key payload, stats : { trequest, tfirst, tload, length}} - KEY_LOADED: 'hlsKeyLoaded', -}; diff --git a/dashboard-ui/bower_components/hls.js/src/helper/buffer-helper.js b/dashboard-ui/bower_components/hls.js/src/helper/buffer-helper.js deleted file mode 100644 index 3257978e1..000000000 --- a/dashboard-ui/bower_components/hls.js/src/helper/buffer-helper.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Buffer Helper class, providing methods dealing buffer length retrieval -*/ - - -class BufferHelper { - - static bufferInfo(media, pos,maxHoleDuration) { - if (media) { - var vbuffered = media.buffered, buffered = [],i; - for (i = 0; i < vbuffered.length; i++) { - buffered.push({start: vbuffered.start(i), end: vbuffered.end(i)}); - } - return this.bufferedInfo(buffered,pos,maxHoleDuration); - } else { - return {len: 0, start: 0, end: 0, nextStart : undefined} ; - } - } - - static bufferedInfo(buffered,pos,maxHoleDuration) { - var buffered2 = [], - // bufferStart and bufferEnd are buffer boundaries around current video position - bufferLen,bufferStart, bufferEnd,bufferStartNext,i; - // sort on buffer.start/smaller end (IE does not always return sorted buffered range) - buffered.sort(function (a, b) { - var diff = a.start - b.start; - if (diff) { - return diff; - } else { - return b.end - a.end; - } - }); - // there might be some small holes between buffer time range - // consider that holes smaller than maxHoleDuration are irrelevant and build another - // buffer time range representations that discards those holes - for (i = 0; i < buffered.length; i++) { - var buf2len = buffered2.length; - if(buf2len) { - var buf2end = buffered2[buf2len - 1].end; - // if small hole (value between 0 or maxHoleDuration ) or overlapping (negative) - if((buffered[i].start - buf2end) < maxHoleDuration) { - // merge overlapping time ranges - // update lastRange.end only if smaller than item.end - // e.g. [ 1, 15] with [ 2,8] => [ 1,15] (no need to modify lastRange.end) - // whereas [ 1, 8] with [ 2,15] => [ 1,15] ( lastRange should switch from [1,8] to [1,15]) - if(buffered[i].end > buf2end) { - buffered2[buf2len - 1].end = buffered[i].end; - } - } else { - // big hole - buffered2.push(buffered[i]); - } - } else { - // first value - buffered2.push(buffered[i]); - } - } - for (i = 0, bufferLen = 0, bufferStart = bufferEnd = pos; i < buffered2.length; i++) { - var start = buffered2[i].start, - end = buffered2[i].end; - //logger.log('buf start/end:' + buffered.start(i) + '/' + buffered.end(i)); - if ((pos + maxHoleDuration) >= start && pos < end) { - // play position is inside this buffer TimeRange, retrieve end of buffer position and buffer length - bufferStart = start; - bufferEnd = end; - bufferLen = bufferEnd - pos; - } else if ((pos + maxHoleDuration) < start) { - bufferStartNext = start; - break; - } - } - return {len: bufferLen, start: bufferStart, end: bufferEnd, nextStart : bufferStartNext}; - } - -} - -export default BufferHelper; diff --git a/dashboard-ui/bower_components/hls.js/src/helper/level-helper.js b/dashboard-ui/bower_components/hls.js/src/helper/level-helper.js deleted file mode 100644 index f611b1927..000000000 --- a/dashboard-ui/bower_components/hls.js/src/helper/level-helper.js +++ /dev/null @@ -1,137 +0,0 @@ -/** - * Level Helper class, providing methods dealing with playlist sliding and drift -*/ - -import {logger} from '../utils/logger'; - -class LevelHelper { - - static mergeDetails(oldDetails,newDetails) { - var start = Math.max(oldDetails.startSN,newDetails.startSN)-newDetails.startSN, - end = Math.min(oldDetails.endSN,newDetails.endSN)-newDetails.startSN, - delta = newDetails.startSN - oldDetails.startSN, - oldfragments = oldDetails.fragments, - newfragments = newDetails.fragments, - ccOffset =0, - PTSFrag; - - // check if old/new playlists have fragments in common - if ( end < start) { - newDetails.PTSKnown = false; - return; - } - // loop through overlapping SN and update startPTS , cc, and duration if any found - for(var i = start ; i <= end ; i++) { - var oldFrag = oldfragments[delta+i], - newFrag = newfragments[i]; - ccOffset = oldFrag.cc - newFrag.cc; - if (!isNaN(oldFrag.startPTS)) { - newFrag.start = newFrag.startPTS = oldFrag.startPTS; - newFrag.endPTS = oldFrag.endPTS; - newFrag.duration = oldFrag.duration; - PTSFrag = newFrag; - } - } - - if(ccOffset) { - logger.log(`discontinuity sliding from playlist, take drift into account`); - for(i = 0 ; i < newfragments.length ; i++) { - newfragments[i].cc += ccOffset; - } - } - - // if at least one fragment contains PTS info, recompute PTS information for all fragments - if(PTSFrag) { - LevelHelper.updateFragPTSDTS(newDetails,PTSFrag.sn,PTSFrag.startPTS,PTSFrag.endPTS,PTSFrag.startDTS,PTSFrag.endDTS); - } else { - // ensure that delta is within oldfragments range - // also adjust sliding in case delta is 0 (we could have old=[50-60] and new=old=[50-61]) - // in that case we also need to adjust start offset of all fragments - if (delta >= 0 && delta < oldfragments.length) { - // adjust start by sliding offset - var sliding = oldfragments[delta].start; - for(i = 0 ; i < newfragments.length ; i++) { - newfragments[i].start += sliding; - } - } - } - // if we are here, it means we have fragments overlapping between - // old and new level. reliable PTS info is thus relying on old level - newDetails.PTSKnown = oldDetails.PTSKnown; - return; - } - - static updateFragPTSDTS(details,sn,startPTS,endPTS,startDTS,endDTS) { - var fragIdx, fragments, frag, i; - // exit if sn out of range - if (sn < details.startSN || sn > details.endSN) { - return 0; - } - fragIdx = sn - details.startSN; - fragments = details.fragments; - frag = fragments[fragIdx]; - if(!isNaN(frag.startPTS)) { - // delta PTS between audio and video - let deltaPTS = Math.abs(frag.startPTS-startPTS); - if (isNaN(frag.deltaPTS)) { - frag.deltaPTS = deltaPTS; - } else { - frag.deltaPTS = Math.max(deltaPTS,frag.deltaPTS); - } - startPTS = Math.min(startPTS,frag.startPTS); - endPTS = Math.max(endPTS, frag.endPTS); - startDTS = Math.min(startDTS,frag.startDTS); - endDTS = Math.max(endDTS, frag.endDTS); - } - - var drift = startPTS - frag.start; - - frag.start = frag.startPTS = startPTS; - frag.endPTS = endPTS; - frag.startDTS = startDTS; - frag.endDTS = endDTS; - frag.duration = endPTS - startPTS; - // adjust fragment PTS/duration from seqnum-1 to frag 0 - for(i = fragIdx ; i > 0 ; i--) { - LevelHelper.updatePTS(fragments,i,i-1); - } - - // adjust fragment PTS/duration from seqnum to last frag - for(i = fragIdx ; i < fragments.length - 1 ; i++) { - LevelHelper.updatePTS(fragments,i,i+1); - } - details.PTSKnown = true; - //logger.log(` frag start/end:${startPTS.toFixed(3)}/${endPTS.toFixed(3)}`); - - return drift; - } - - static updatePTS(fragments,fromIdx, toIdx) { - var fragFrom = fragments[fromIdx],fragTo = fragments[toIdx], fragToPTS = fragTo.startPTS; - // if we know startPTS[toIdx] - if(!isNaN(fragToPTS)) { - // update fragment duration. - // it helps to fix drifts between playlist reported duration and fragment real duration - if (toIdx > fromIdx) { - fragFrom.duration = fragToPTS-fragFrom.start; - if(fragFrom.duration < 0) { - logger.error(`negative duration computed for frag ${fragFrom.sn},level ${fragFrom.level}, there should be some duration drift between playlist and fragment!`); - } - } else { - fragTo.duration = fragFrom.start - fragToPTS; - if(fragTo.duration < 0) { - logger.error(`negative duration computed for frag ${fragTo.sn},level ${fragTo.level}, there should be some duration drift between playlist and fragment!`); - } - } - } else { - // we dont know startPTS[toIdx] - if (toIdx > fromIdx) { - fragTo.start = fragFrom.start + fragFrom.duration; - } else { - fragTo.start = fragFrom.start - fragTo.duration; - } - } - } -} - -export default LevelHelper; diff --git a/dashboard-ui/bower_components/hls.js/src/hls.js b/dashboard-ui/bower_components/hls.js/src/hls.js deleted file mode 100644 index 6866f9e64..000000000 --- a/dashboard-ui/bower_components/hls.js/src/hls.js +++ /dev/null @@ -1,312 +0,0 @@ -/** - * HLS interface - */ -'use strict'; - -import Event from './events'; -import {ErrorTypes, ErrorDetails} from './errors'; -import PlaylistLoader from './loader/playlist-loader'; -import FragmentLoader from './loader/fragment-loader'; -import AbrController from './controller/abr-controller'; -import BufferController from './controller/buffer-controller'; -import CapLevelController from './controller/cap-level-controller'; -import StreamController from './controller/stream-controller'; -import LevelController from './controller/level-controller'; -import TimelineController from './controller/timeline-controller'; -//import FPSController from './controller/fps-controller'; -import {logger, enableLogs} from './utils/logger'; -import XhrLoader from './utils/xhr-loader'; -import EventEmitter from 'events'; -import KeyLoader from './loader/key-loader'; - -class Hls { - - static isSupported() { - return (window.MediaSource && - typeof window.MediaSource.isTypeSupported === 'function' && - window.MediaSource.isTypeSupported('video/mp4; codecs="avc1.42E01E,mp4a.40.2"')); - } - - static get Events() { - return Event; - } - - static get ErrorTypes() { - return ErrorTypes; - } - - static get ErrorDetails() { - return ErrorDetails; - } - - static get DefaultConfig() { - if(!Hls.defaultConfig) { - Hls.defaultConfig = { - autoStartLoad: true, - startPosition: -1, - debug: false, - capLevelToPlayerSize: false, - maxBufferLength: 30, - maxBufferSize: 60 * 1000 * 1000, - maxBufferHole: 0.5, - maxSeekHole: 2, - seekHoleNudgeDuration : 0.01, - stalledInBufferedNudgeThreshold: 10, - maxFragLookUpTolerance : 0.2, - liveSyncDurationCount:3, - liveMaxLatencyDurationCount: Infinity, - liveSyncDuration: undefined, - liveMaxLatencyDuration: undefined, - maxMaxBufferLength: 600, - enableWorker: true, - enableSoftwareAES: true, - manifestLoadingTimeOut: 10000, - manifestLoadingMaxRetry: 1, - manifestLoadingRetryDelay: 1000, - levelLoadingTimeOut: 10000, - levelLoadingMaxRetry: 4, - levelLoadingRetryDelay: 1000, - fragLoadingTimeOut: 20000, - fragLoadingMaxRetry: 6, - fragLoadingRetryDelay: 1000, - fragLoadingLoopThreshold: 3, - startFragPrefetch : false, - // fpsDroppedMonitoringPeriod: 5000, - // fpsDroppedMonitoringThreshold: 0.2, - appendErrorMaxRetry: 3, - loader: XhrLoader, - fLoader: undefined, - pLoader: undefined, - abrController : AbrController, - bufferController : BufferController, - capLevelController : CapLevelController, - streamController: StreamController, - timelineController: TimelineController, - enableCEA708Captions: true, - enableMP2TPassThrough : false, - abrEwmaFastLive: 5, - abrEwmaSlowLive: 9, - abrEwmaFastVoD: 4, - abrEwmaSlowVoD: 15, - abrEwmaDefaultEstimate: 5e5, // 500 kbps - abrBandWidthFactor : 0.8, - abrBandWidthUpFactor : 0.7 - }; - } - return Hls.defaultConfig; - } - - static set DefaultConfig(defaultConfig) { - Hls.defaultConfig = defaultConfig; - } - - constructor(config = {}) { - var defaultConfig = Hls.DefaultConfig; - - if ((config.liveSyncDurationCount || config.liveMaxLatencyDurationCount) && (config.liveSyncDuration || config.liveMaxLatencyDuration)) { - throw new Error('Illegal hls.js config: don\'t mix up liveSyncDurationCount/liveMaxLatencyDurationCount and liveSyncDuration/liveMaxLatencyDuration'); - } - - for (var prop in defaultConfig) { - if (prop in config) { continue; } - config[prop] = defaultConfig[prop]; - } - - if (config.liveMaxLatencyDurationCount !== undefined && config.liveMaxLatencyDurationCount <= config.liveSyncDurationCount) { - throw new Error('Illegal hls.js config: "liveMaxLatencyDurationCount" must be gt "liveSyncDurationCount"'); - } - - if (config.liveMaxLatencyDuration !== undefined && (config.liveMaxLatencyDuration <= config.liveSyncDuration || config.liveSyncDuration === undefined)) { - throw new Error('Illegal hls.js config: "liveMaxLatencyDuration" must be gt "liveSyncDuration"'); - } - - enableLogs(config.debug); - this.config = config; - // observer setup - var observer = this.observer = new EventEmitter(); - observer.trigger = function trigger (event, ...data) { - observer.emit(event, event, ...data); - }; - - observer.off = function off (event, ...data) { - observer.removeListener(event, ...data); - }; - this.on = observer.on.bind(observer); - this.off = observer.off.bind(observer); - this.trigger = observer.trigger.bind(observer); - this.playlistLoader = new PlaylistLoader(this); - this.fragmentLoader = new FragmentLoader(this); - this.levelController = new LevelController(this); - this.abrController = new config.abrController(this); - this.bufferController = new config.bufferController(this); - this.capLevelController = new config.capLevelController(this); - this.streamController = new config.streamController(this); - this.timelineController = new config.timelineController(this); - this.keyLoader = new KeyLoader(this); - //this.fpsController = new FPSController(this); - } - - destroy() { - logger.log('destroy'); - this.trigger(Event.DESTROYING); - this.detachMedia(); - this.playlistLoader.destroy(); - this.fragmentLoader.destroy(); - this.levelController.destroy(); - this.abrController.destroy(); - this.bufferController.destroy(); - this.capLevelController.destroy(); - this.streamController.destroy(); - this.timelineController.destroy(); - this.keyLoader.destroy(); - //this.fpsController.destroy(); - this.url = null; - this.observer.removeAllListeners(); - } - - attachMedia(media) { - logger.log('attachMedia'); - this.media = media; - this.trigger(Event.MEDIA_ATTACHING, {media: media}); - } - - detachMedia() { - logger.log('detachMedia'); - this.trigger(Event.MEDIA_DETACHING); - this.media = null; - } - - loadSource(url) { - logger.log(`loadSource:${url}`); - this.url = url; - // when attaching to a source URL, trigger a playlist load - this.trigger(Event.MANIFEST_LOADING, {url: url}); - } - - startLoad(startPosition=-1) { - logger.log('startLoad'); - this.levelController.startLoad(); - this.streamController.startLoad(startPosition); - } - - stopLoad() { - logger.log('stopLoad'); - this.levelController.stopLoad(); - this.streamController.stopLoad(); - } - - swapAudioCodec() { - logger.log('swapAudioCodec'); - this.streamController.swapAudioCodec(); - } - - recoverMediaError() { - logger.log('recoverMediaError'); - var media = this.media; - this.detachMedia(); - this.attachMedia(media); - } - - /** Return all quality levels **/ - get levels() { - return this.levelController.levels; - } - - /** Return current playback quality level **/ - get currentLevel() { - return this.streamController.currentLevel; - } - - /* set quality level immediately (-1 for automatic level selection) */ - set currentLevel(newLevel) { - logger.log(`set currentLevel:${newLevel}`); - this.loadLevel = newLevel; - this.streamController.immediateLevelSwitch(); - } - - /** Return next playback quality level (quality level of next fragment) **/ - get nextLevel() { - return this.streamController.nextLevel; - } - - /* set quality level for next fragment (-1 for automatic level selection) */ - set nextLevel(newLevel) { - logger.log(`set nextLevel:${newLevel}`); - this.levelController.manualLevel = newLevel; - this.streamController.nextLevelSwitch(); - } - - /** Return the quality level of current/last loaded fragment **/ - get loadLevel() { - return this.levelController.level; - } - - /* set quality level for current/next loaded fragment (-1 for automatic level selection) */ - set loadLevel(newLevel) { - logger.log(`set loadLevel:${newLevel}`); - this.levelController.manualLevel = newLevel; - } - - /** Return the quality level of next loaded fragment **/ - get nextLoadLevel() { - return this.levelController.nextLoadLevel; - } - - /** set quality level of next loaded fragment **/ - set nextLoadLevel(level) { - this.levelController.nextLoadLevel = level; - } - - /** Return first level (index of first level referenced in manifest) - **/ - get firstLevel() { - return this.levelController.firstLevel; - } - - /** set first level (index of first level referenced in manifest) - **/ - set firstLevel(newLevel) { - logger.log(`set firstLevel:${newLevel}`); - this.levelController.firstLevel = newLevel; - } - - /** Return start level (level of first fragment that will be played back) - if not overrided by user, first level appearing in manifest will be used as start level - if -1 : automatic start level selection, playback will start from level matching download bandwidth (determined from download of first segment) - **/ - get startLevel() { - return this.levelController.startLevel; - } - - /** set start level (level of first fragment that will be played back) - if not overrided by user, first level appearing in manifest will be used as start level - if -1 : automatic start level selection, playback will start from level matching download bandwidth (determined from download of first segment) - **/ - set startLevel(newLevel) { - logger.log(`set startLevel:${newLevel}`); - this.levelController.startLevel = newLevel; - } - - /** Return the capping/max level value that could be used by automatic level selection algorithm **/ - get autoLevelCapping() { - return this.abrController.autoLevelCapping; - } - - /** set the capping/max level value that could be used by automatic level selection algorithm **/ - set autoLevelCapping(newLevel) { - logger.log(`set autoLevelCapping:${newLevel}`); - this.abrController.autoLevelCapping = newLevel; - } - - /* check if we are in automatic level selection mode */ - get autoLevelEnabled() { - return (this.levelController.manualLevel === -1); - } - - /* return manual level */ - get manualLevel() { - return this.levelController.manualLevel; - } -} - -export default Hls; diff --git a/dashboard-ui/bower_components/hls.js/src/index.js b/dashboard-ui/bower_components/hls.js/src/index.js deleted file mode 100644 index d87cf3a8c..000000000 --- a/dashboard-ui/bower_components/hls.js/src/index.js +++ /dev/null @@ -1,4 +0,0 @@ -// This is mostly for support of the es6 module export -// syntax with the babel compiler, it looks like it doesnt support -// function exports like we are used to in node/commonjs -module.exports = require('./hls.js').default; diff --git a/dashboard-ui/bower_components/hls.js/src/loader/fragment-loader.js b/dashboard-ui/bower_components/hls.js/src/loader/fragment-loader.js deleted file mode 100644 index 36dae020c..000000000 --- a/dashboard-ui/bower_components/hls.js/src/loader/fragment-loader.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Fragment Loader -*/ - -import Event from '../events'; -import EventHandler from '../event-handler'; -import {ErrorTypes, ErrorDetails} from '../errors'; - -class FragmentLoader extends EventHandler { - - constructor(hls) { - super(hls, Event.FRAG_LOADING); - } - - destroy() { - if (this.loader) { - this.loader.destroy(); - this.loader = null; - } - EventHandler.prototype.destroy.call(this); - } - - onFragLoading(data) { - var frag = data.frag; - this.frag = frag; - this.frag.loaded = 0; - var config = this.hls.config; - frag.loader = this.loader = typeof(config.fLoader) !== 'undefined' ? new config.fLoader(config) : new config.loader(config); - this.loader.load(frag.url, 'arraybuffer', this.loadsuccess.bind(this), this.loaderror.bind(this), this.loadtimeout.bind(this), config.fragLoadingTimeOut, 1, 0, this.loadprogress.bind(this), frag); - } - - loadsuccess(event, stats) { - var payload = event.currentTarget.response; - stats.length = payload.byteLength; - // detach fragment loader on load success - this.frag.loader = undefined; - this.hls.trigger(Event.FRAG_LOADED, {payload: payload, frag: this.frag, stats: stats}); - } - - loaderror(event) { - if (this.loader) { - this.loader.abort(); - } - this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.FRAG_LOAD_ERROR, fatal: false, frag: this.frag, response: event}); - } - - loadtimeout() { - if (this.loader) { - this.loader.abort(); - } - this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.FRAG_LOAD_TIMEOUT, fatal: false, frag: this.frag}); - } - - loadprogress(event, stats) { - this.frag.loaded = stats.loaded; - this.hls.trigger(Event.FRAG_LOAD_PROGRESS, {frag: this.frag, stats: stats}); - } -} - -export default FragmentLoader; diff --git a/dashboard-ui/bower_components/hls.js/src/loader/key-loader.js b/dashboard-ui/bower_components/hls.js/src/loader/key-loader.js deleted file mode 100644 index b9b3f9396..000000000 --- a/dashboard-ui/bower_components/hls.js/src/loader/key-loader.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Decrypt key Loader -*/ - -import Event from '../events'; -import EventHandler from '../event-handler'; -import {ErrorTypes, ErrorDetails} from '../errors'; - -class KeyLoader extends EventHandler { - - constructor(hls) { - super(hls, Event.KEY_LOADING); - this.decryptkey = null; - this.decrypturl = null; - } - - destroy() { - if (this.loader) { - this.loader.destroy(); - this.loader = null; - } - EventHandler.prototype.destroy.call(this); - } - - onKeyLoading(data) { - var frag = this.frag = data.frag, - decryptdata = frag.decryptdata, - uri = decryptdata.uri; - // if uri is different from previous one or if decrypt key not retrieved yet - if (uri !== this.decrypturl || this.decryptkey === null) { - var config = this.hls.config; - frag.loader = this.loader = new config.loader(config); - this.decrypturl = uri; - this.decryptkey = null; - frag.loader.load(uri, 'arraybuffer', this.loadsuccess.bind(this), this.loaderror.bind(this), this.loadtimeout.bind(this), config.fragLoadingTimeOut, config.fragLoadingMaxRetry, config.fragLoadingRetryDelay, this.loadprogress.bind(this), frag); - } else if (this.decryptkey) { - // we already loaded this key, return it - decryptdata.key = this.decryptkey; - this.hls.trigger(Event.KEY_LOADED, {frag: frag}); - } - } - - loadsuccess(event) { - var frag = this.frag; - this.decryptkey = frag.decryptdata.key = new Uint8Array(event.currentTarget.response); - // detach fragment loader on load success - frag.loader = undefined; - this.hls.trigger(Event.KEY_LOADED, {frag: frag}); - } - - loaderror(event) { - if (this.loader) { - this.loader.abort(); - } - this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.KEY_LOAD_ERROR, fatal: false, frag: this.frag, response: event}); - } - - loadtimeout() { - if (this.loader) { - this.loader.abort(); - } - this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.KEY_LOAD_TIMEOUT, fatal: false, frag: this.frag}); - } - - loadprogress() { - - } -} - -export default KeyLoader; diff --git a/dashboard-ui/bower_components/hls.js/src/loader/playlist-loader.js b/dashboard-ui/bower_components/hls.js/src/loader/playlist-loader.js deleted file mode 100644 index 1c7f16c19..000000000 --- a/dashboard-ui/bower_components/hls.js/src/loader/playlist-loader.js +++ /dev/null @@ -1,318 +0,0 @@ -/** - * Playlist Loader -*/ - -import Event from '../events'; -import EventHandler from '../event-handler'; -import {ErrorTypes, ErrorDetails} from '../errors'; -import URLHelper from '../utils/url'; -import AttrList from '../utils/attr-list'; -//import {logger} from '../utils/logger'; - -class PlaylistLoader extends EventHandler { - - constructor(hls) { - super(hls, - Event.MANIFEST_LOADING, - Event.LEVEL_LOADING); - } - - destroy() { - if (this.loader) { - this.loader.destroy(); - this.loader = null; - } - this.url = this.id = null; - EventHandler.prototype.destroy.call(this); - } - - onManifestLoading(data) { - this.load(data.url, null); - } - - onLevelLoading(data) { - this.load(data.url, data.level, data.id); - } - - load(url, id1, id2) { - var config = this.hls.config, - retry, - timeout, - retryDelay; - - if (this.loading && this.loader) { - if (this.url === url && this.id === id1 && this.id2 === id2) { - // same request than last pending one, don't do anything - return; - } else { - // one playlist load request is pending, but with different params, abort it before loading new playlist - this.loader.abort(); - } - } - - this.url = url; - this.id = id1; - this.id2 = id2; - if(this.id === null) { - retry = config.manifestLoadingMaxRetry; - timeout = config.manifestLoadingTimeOut; - retryDelay = config.manifestLoadingRetryDelay; - } else { - retry = config.levelLoadingMaxRetry; - timeout = config.levelLoadingTimeOut; - retryDelay = config.levelLoadingRetryDelay; - } - this.loader = typeof(config.pLoader) !== 'undefined' ? new config.pLoader(config) : new config.loader(config); - this.loading = true; - this.loader.load(url, '', this.loadsuccess.bind(this), this.loaderror.bind(this), this.loadtimeout.bind(this), timeout, retry, retryDelay); - } - - resolve(url, baseUrl) { - return URLHelper.buildAbsoluteURL(baseUrl, url); - } - - parseMasterPlaylist(string, baseurl) { - let levels = [], result; - - // https://regex101.com is your friend - const re = /#EXT-X-STREAM-INF:([^\n\r]*)[\r\n]+([^\r\n]+)/g; - while ((result = re.exec(string)) != null){ - const level = {}; - - var attrs = level.attrs = new AttrList(result[1]); - level.url = this.resolve(result[2], baseurl); - - var resolution = attrs.decimalResolution('RESOLUTION'); - if(resolution) { - level.width = resolution.width; - level.height = resolution.height; - } - level.bitrate = attrs.decimalInteger('AVERAGE-BANDWIDTH') || attrs.decimalInteger('BANDWIDTH'); - level.name = attrs.NAME; - - var codecs = attrs.CODECS; - if(codecs) { - codecs = codecs.split(','); - for (let i = 0; i < codecs.length; i++) { - const codec = codecs[i]; - if (codec.indexOf('avc1') !== -1) { - level.videoCodec = this.avc1toavcoti(codec); - } else { - level.audioCodec = codec; - } - } - } - - levels.push(level); - } - return levels; - } - - avc1toavcoti(codec) { - var result, avcdata = codec.split('.'); - if (avcdata.length > 2) { - result = avcdata.shift() + '.'; - result += parseInt(avcdata.shift()).toString(16); - result += ('000' + parseInt(avcdata.shift()).toString(16)).substr(-4); - } else { - result = codec; - } - return result; - } - - cloneObj(obj) { - return JSON.parse(JSON.stringify(obj)); - } - - parseLevelPlaylist(string, baseurl, id) { - var currentSN = 0, - totalduration = 0, - level = {url: baseurl, fragments: [], live: true, startSN: 0}, - levelkey = {method : null, key : null, iv : null, uri : null}, - cc = 0, - programDateTime = null, - frag = null, - result, - regexp, - byteRangeEndOffset, - byteRangeStartOffset; - - regexp = /(?:#EXT-X-(MEDIA-SEQUENCE):(\d+))|(?:#EXT-X-(TARGETDURATION):(\d+))|(?:#EXT-X-(KEY):(.*))|(?:#EXT-X-(START):(.*))|(?:#EXT(INF):([\d\.]+)[^\r\n]*([\r\n]+[^#|\r\n]+)?)|(?:#EXT-X-(BYTERANGE):([\d]+[@[\d]*)]*[\r\n]+([^#|\r\n]+)?|(?:#EXT-X-(ENDLIST))|(?:#EXT-X-(DIS)CONTINUITY))|(?:#EXT-X-(PROGRAM-DATE-TIME):(.*)[\r\n]+([^#|\r\n]+)?)/g; - while ((result = regexp.exec(string)) !== null) { - result.shift(); - result = result.filter(function(n) { return (n !== undefined); }); - switch (result[0]) { - case 'MEDIA-SEQUENCE': - currentSN = level.startSN = parseInt(result[1]); - break; - case 'TARGETDURATION': - level.targetduration = parseFloat(result[1]); - break; - case 'ENDLIST': - level.live = false; - break; - case 'DIS': - cc++; - break; - case 'BYTERANGE': - var params = result[1].split('@'); - if (params.length === 1) { - byteRangeStartOffset = byteRangeEndOffset; - } else { - byteRangeStartOffset = parseInt(params[1]); - } - byteRangeEndOffset = parseInt(params[0]) + byteRangeStartOffset; - if (frag && !frag.url) { - frag.byteRangeStartOffset = byteRangeStartOffset; - frag.byteRangeEndOffset = byteRangeEndOffset; - frag.url = this.resolve(result[2], baseurl); - } - break; - case 'INF': - var duration = parseFloat(result[1]); - if (!isNaN(duration)) { - var fragdecryptdata, - sn = currentSN++; - if (levelkey.method && levelkey.uri && !levelkey.iv) { - fragdecryptdata = this.cloneObj(levelkey); - var uint8View = new Uint8Array(16); - for (var i = 12; i < 16; i++) { - uint8View[i] = (sn >> 8*(15-i)) & 0xff; - } - fragdecryptdata.iv = uint8View; - } else { - fragdecryptdata = levelkey; - } - var url = result[2] ? this.resolve(result[2], baseurl) : null; - frag = {url: url, duration: duration, start: totalduration, sn: sn, level: id, cc: cc, byteRangeStartOffset: byteRangeStartOffset, byteRangeEndOffset: byteRangeEndOffset, decryptdata : fragdecryptdata, programDateTime: programDateTime}; - level.fragments.push(frag); - totalduration += duration; - byteRangeStartOffset = null; - programDateTime = null; - } - break; - case 'KEY': - // https://tools.ietf.org/html/draft-pantos-http-live-streaming-08#section-3.4.4 - var decryptparams = result[1]; - var keyAttrs = new AttrList(decryptparams); - var decryptmethod = keyAttrs.enumeratedString('METHOD'), - decrypturi = keyAttrs.URI, - decryptiv = keyAttrs.hexadecimalInteger('IV'); - if (decryptmethod) { - levelkey = { method: null, key: null, iv: null, uri: null }; - if ((decrypturi) && (decryptmethod === 'AES-128')) { - levelkey.method = decryptmethod; - // URI to get the key - levelkey.uri = this.resolve(decrypturi, baseurl); - levelkey.key = null; - // Initialization Vector (IV) - levelkey.iv = decryptiv; - } - } - break; - case 'START': - let startParams = result[1]; - let startAttrs = new AttrList(startParams); - let startTimeOffset = startAttrs.decimalFloatingPoint('TIME-OFFSET'); - if (startTimeOffset) { - level.startTimeOffset = startTimeOffset; - } - break; - case 'PROGRAM-DATE-TIME': - programDateTime = new Date(Date.parse(result[1])); - if (frag && !frag.url && result.length >= 3) { - frag.url = this.resolve(result[2], baseurl); - frag.programDateTime = programDateTime; - } - break; - default: - break; - } - } - //logger.log('found ' + level.fragments.length + ' fragments'); - if(frag && !frag.url) { - level.fragments.pop(); - totalduration-=frag.duration; - } - level.totalduration = totalduration; - level.endSN = currentSN - 1; - return level; - } - - loadsuccess(event, stats) { - var target = event.currentTarget, - string = target.responseText, - url = target.responseURL, - id = this.id, - id2 = this.id2, - hls = this.hls, - levels; - - this.loading = false; - // responseURL not supported on some browsers (it is used to detect URL redirection) - if (url === undefined) { - // fallback to initial URL - url = this.url; - } - stats.tload = performance.now(); - stats.mtime = new Date(target.getResponseHeader('Last-Modified')); - if (string.indexOf('#EXTM3U') === 0) { - if (string.indexOf('#EXTINF:') > 0) { - // 1 level playlist - // if first request, fire manifest loaded event, level will be reloaded afterwards - // (this is to have a uniform logic for 1 level/multilevel playlists) - if (this.id === null) { - hls.trigger(Event.MANIFEST_LOADED, {levels: [{url: url}], url: url, stats: stats}); - } else { - var levelDetails = this.parseLevelPlaylist(string, url, id); - stats.tparsed = performance.now(); - hls.trigger(Event.LEVEL_LOADED, {details: levelDetails, level: id, id: id2, stats: stats}); - } - } else { - levels = this.parseMasterPlaylist(string, url); - // multi level playlist, parse level info - if (levels.length) { - hls.trigger(Event.MANIFEST_LOADED, {levels: levels, url: url, stats: stats}); - } else { - hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.MANIFEST_PARSING_ERROR, fatal: true, url: url, reason: 'no level found in manifest'}); - } - } - } else { - hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: ErrorDetails.MANIFEST_PARSING_ERROR, fatal: true, url: url, reason: 'no EXTM3U delimiter'}); - } - } - - loaderror(event) { - var details, fatal; - if (this.id === null) { - details = ErrorDetails.MANIFEST_LOAD_ERROR; - fatal = true; - } else { - details = ErrorDetails.LEVEL_LOAD_ERROR; - fatal = false; - } - if (this.loader) { - this.loader.abort(); - } - this.loading = false; - this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: details, fatal: fatal, url: this.url, loader: this.loader, response: event.currentTarget, level: this.id, id: this.id2}); - } - - loadtimeout() { - var details, fatal; - if (this.id === null) { - details = ErrorDetails.MANIFEST_LOAD_TIMEOUT; - fatal = true; - } else { - details = ErrorDetails.LEVEL_LOAD_TIMEOUT; - fatal = false; - } - if (this.loader) { - this.loader.abort(); - } - this.loading = false; - this.hls.trigger(Event.ERROR, {type: ErrorTypes.NETWORK_ERROR, details: details, fatal: fatal, url: this.url, loader: this.loader, level: this.id, id: this.id2}); - } -} - -export default PlaylistLoader; diff --git a/dashboard-ui/bower_components/hls.js/src/remux/dummy-remuxer.js b/dashboard-ui/bower_components/hls.js/src/remux/dummy-remuxer.js deleted file mode 100644 index 871b5df0c..000000000 --- a/dashboard-ui/bower_components/hls.js/src/remux/dummy-remuxer.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * dummy remuxer -*/ - -class DummyRemuxer { - constructor(observer) { - this.PES_TIMESCALE = 90000; - this.observer = observer; - } - - get passthrough() { - return false; - } - - destroy() { - } - - insertDiscontinuity() { - } - - remux(audioTrack,videoTrack,id3Track,textTrack,timeOffset) { - this._remuxAACSamples(audioTrack,timeOffset); - this._remuxAVCSamples(videoTrack,timeOffset); - this._remuxID3Samples(id3Track,timeOffset); - this._remuxTextSamples(textTrack,timeOffset); - } - - _remuxAVCSamples(track, timeOffset) { - var avcSample, unit; - // loop through track.samples - while (track.samples.length) { - avcSample = track.samples.shift(); - // loop through AVC sample NALUs - while (avcSample.units.units.length) { - unit = avcSample.units.units.shift(); - } - } - //please lint - timeOffset = timeOffset; - } - - _remuxAACSamples(track,timeOffset) { - var aacSample,unit; - // loop through track.samples - while (track.samples.length) { - aacSample = track.samples.shift(); - unit = aacSample.unit; - } - //please lint - timeOffset = timeOffset; - } - - _remuxID3Samples(track,timeOffset) { - var id3Sample,unit; - // loop through track.samples - while (track.samples.length) { - id3Sample = track.samples.shift(); - unit = id3Sample.unit; - } - //please lint - timeOffset = timeOffset; - } - - _remuxTextSamples(track,timeOffset) { - var textSample,bytes; - // loop through track.samples - while (track.samples.length) { - textSample = track.samples.shift(); - bytes = textSample.bytes; - } - //please lint - timeOffset = timeOffset; - } -} - -export default DummyRemuxer; - diff --git a/dashboard-ui/bower_components/hls.js/src/remux/mp4-generator.js b/dashboard-ui/bower_components/hls.js/src/remux/mp4-generator.js deleted file mode 100644 index 5c77f23eb..000000000 --- a/dashboard-ui/bower_components/hls.js/src/remux/mp4-generator.js +++ /dev/null @@ -1,589 +0,0 @@ -/** - * Generate MP4 Box -*/ - -//import Hex from '../utils/hex'; -class MP4 { - static init() { - MP4.types = { - avc1: [], // codingname - avcC: [], - btrt: [], - dinf: [], - dref: [], - esds: [], - ftyp: [], - hdlr: [], - mdat: [], - mdhd: [], - mdia: [], - mfhd: [], - minf: [], - moof: [], - moov: [], - mp4a: [], - mvex: [], - mvhd: [], - sdtp: [], - stbl: [], - stco: [], - stsc: [], - stsd: [], - stsz: [], - stts: [], - tfdt: [], - tfhd: [], - traf: [], - trak: [], - trun: [], - trex: [], - tkhd: [], - vmhd: [], - smhd: [] - }; - - var i; - for (i in MP4.types) { - if (MP4.types.hasOwnProperty(i)) { - MP4.types[i] = [ - i.charCodeAt(0), - i.charCodeAt(1), - i.charCodeAt(2), - i.charCodeAt(3) - ]; - } - } - - var videoHdlr = new Uint8Array([ - 0x00, // version 0 - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x00, // pre_defined - 0x76, 0x69, 0x64, 0x65, // handler_type: 'vide' - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, 0x00, // reserved - 0x56, 0x69, 0x64, 0x65, - 0x6f, 0x48, 0x61, 0x6e, - 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'VideoHandler' - ]); - - var audioHdlr = new Uint8Array([ - 0x00, // version 0 - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x00, // pre_defined - 0x73, 0x6f, 0x75, 0x6e, // handler_type: 'soun' - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, 0x00, // reserved - 0x53, 0x6f, 0x75, 0x6e, - 0x64, 0x48, 0x61, 0x6e, - 0x64, 0x6c, 0x65, 0x72, 0x00 // name: 'SoundHandler' - ]); - - MP4.HDLR_TYPES = { - 'video': videoHdlr, - 'audio': audioHdlr - }; - - var dref = new Uint8Array([ - 0x00, // version 0 - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x01, // entry_count - 0x00, 0x00, 0x00, 0x0c, // entry_size - 0x75, 0x72, 0x6c, 0x20, // 'url' type - 0x00, // version 0 - 0x00, 0x00, 0x01 // entry_flags - ]); - - var stco = new Uint8Array([ - 0x00, // version - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x00 // entry_count - ]); - - MP4.STTS = MP4.STSC = MP4.STCO = stco; - - MP4.STSZ = new Uint8Array([ - 0x00, // version - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x00, // sample_size - 0x00, 0x00, 0x00, 0x00, // sample_count - ]); - MP4.VMHD = new Uint8Array([ - 0x00, // version - 0x00, 0x00, 0x01, // flags - 0x00, 0x00, // graphicsmode - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00 // opcolor - ]); - MP4.SMHD = new Uint8Array([ - 0x00, // version - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, // balance - 0x00, 0x00 // reserved - ]); - - MP4.STSD = new Uint8Array([ - 0x00, // version 0 - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x01]);// entry_count - - var majorBrand = new Uint8Array([105,115,111,109]); // isom - var avc1Brand = new Uint8Array([97,118,99,49]); // avc1 - var minorVersion = new Uint8Array([0, 0, 0, 1]); - - MP4.FTYP = MP4.box(MP4.types.ftyp, majorBrand, minorVersion, majorBrand, avc1Brand); - MP4.DINF = MP4.box(MP4.types.dinf, MP4.box(MP4.types.dref, dref)); - } - - static box(type) { - var - payload = Array.prototype.slice.call(arguments, 1), - size = 8, - i = payload.length, - len = i, - result; - // calculate the total size we need to allocate - while (i--) { - size += payload[i].byteLength; - } - result = new Uint8Array(size); - result[0] = (size >> 24) & 0xff; - result[1] = (size >> 16) & 0xff; - result[2] = (size >> 8) & 0xff; - result[3] = size & 0xff; - result.set(type, 4); - // copy the payload into the result - for (i = 0, size = 8; i < len; i++) { - // copy payload[i] array @ offset size - result.set(payload[i], size); - size += payload[i].byteLength; - } - return result; - } - - static hdlr(type) { - return MP4.box(MP4.types.hdlr, MP4.HDLR_TYPES[type]); - } - - static mdat(data) { - return MP4.box(MP4.types.mdat, data); - } - - static mdhd(timescale, duration) { - duration *= timescale; - return MP4.box(MP4.types.mdhd, new Uint8Array([ - 0x00, // version 0 - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x02, // creation_time - 0x00, 0x00, 0x00, 0x03, // modification_time - (timescale >> 24) & 0xFF, - (timescale >> 16) & 0xFF, - (timescale >> 8) & 0xFF, - timescale & 0xFF, // timescale - (duration >> 24), - (duration >> 16) & 0xFF, - (duration >> 8) & 0xFF, - duration & 0xFF, // duration - 0x55, 0xc4, // 'und' language (undetermined) - 0x00, 0x00 - ])); - } - - static mdia(track) { - return MP4.box(MP4.types.mdia, MP4.mdhd(track.timescale, track.duration), MP4.hdlr(track.type), MP4.minf(track)); - } - - static mfhd(sequenceNumber) { - return MP4.box(MP4.types.mfhd, new Uint8Array([ - 0x00, - 0x00, 0x00, 0x00, // flags - (sequenceNumber >> 24), - (sequenceNumber >> 16) & 0xFF, - (sequenceNumber >> 8) & 0xFF, - sequenceNumber & 0xFF, // sequence_number - ])); - } - - static minf(track) { - if (track.type === 'audio') { - return MP4.box(MP4.types.minf, MP4.box(MP4.types.smhd, MP4.SMHD), MP4.DINF, MP4.stbl(track)); - } else { - return MP4.box(MP4.types.minf, MP4.box(MP4.types.vmhd, MP4.VMHD), MP4.DINF, MP4.stbl(track)); - } - } - - static moof(sn, baseMediaDecodeTime, track) { - return MP4.box(MP4.types.moof, MP4.mfhd(sn), MP4.traf(track,baseMediaDecodeTime)); - } -/** - * @param tracks... (optional) {array} the tracks associated with this movie - */ - static moov(tracks) { - var - i = tracks.length, - boxes = []; - - while (i--) { - boxes[i] = MP4.trak(tracks[i]); - } - - return MP4.box.apply(null, [MP4.types.moov, MP4.mvhd(tracks[0].timescale, tracks[0].duration)].concat(boxes).concat(MP4.mvex(tracks))); - } - - static mvex(tracks) { - var - i = tracks.length, - boxes = []; - - while (i--) { - boxes[i] = MP4.trex(tracks[i]); - } - return MP4.box.apply(null, [MP4.types.mvex].concat(boxes)); - } - - static mvhd(timescale,duration) { - duration*=timescale; - var - bytes = new Uint8Array([ - 0x00, // version 0 - 0x00, 0x00, 0x00, // flags - 0x00, 0x00, 0x00, 0x01, // creation_time - 0x00, 0x00, 0x00, 0x02, // modification_time - (timescale >> 24) & 0xFF, - (timescale >> 16) & 0xFF, - (timescale >> 8) & 0xFF, - timescale & 0xFF, // timescale - (duration >> 24) & 0xFF, - (duration >> 16) & 0xFF, - (duration >> 8) & 0xFF, - duration & 0xFF, // duration - 0x00, 0x01, 0x00, 0x00, // 1.0 rate - 0x01, 0x00, // 1.0 volume - 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // pre_defined - 0xff, 0xff, 0xff, 0xff // next_track_ID - ]); - return MP4.box(MP4.types.mvhd, bytes); - } - - static sdtp(track) { - var - samples = track.samples || [], - bytes = new Uint8Array(4 + samples.length), - flags, - i; - // leave the full box header (4 bytes) all zero - // write the sample table - for (i = 0; i < samples.length; i++) { - flags = samples[i].flags; - bytes[i + 4] = (flags.dependsOn << 4) | - (flags.isDependedOn << 2) | - (flags.hasRedundancy); - } - - return MP4.box(MP4.types.sdtp, bytes); - } - - static stbl(track) { - return MP4.box(MP4.types.stbl, MP4.stsd(track), MP4.box(MP4.types.stts, MP4.STTS), MP4.box(MP4.types.stsc, MP4.STSC), MP4.box(MP4.types.stsz, MP4.STSZ), MP4.box(MP4.types.stco, MP4.STCO)); - } - - static avc1(track) { - var sps = [], pps = [], i, data, len; - // assemble the SPSs - - for (i = 0; i < track.sps.length; i++) { - data = track.sps[i]; - len = data.byteLength; - sps.push((len >>> 8) & 0xFF); - sps.push((len & 0xFF)); - sps = sps.concat(Array.prototype.slice.call(data)); // SPS - } - - // assemble the PPSs - for (i = 0; i < track.pps.length; i++) { - data = track.pps[i]; - len = data.byteLength; - pps.push((len >>> 8) & 0xFF); - pps.push((len & 0xFF)); - pps = pps.concat(Array.prototype.slice.call(data)); - } - - var avcc = MP4.box(MP4.types.avcC, new Uint8Array([ - 0x01, // version - sps[3], // profile - sps[4], // profile compat - sps[5], // level - 0xfc | 3, // lengthSizeMinusOne, hard-coded to 4 bytes - 0xE0 | track.sps.length // 3bit reserved (111) + numOfSequenceParameterSets - ].concat(sps).concat([ - track.pps.length // numOfPictureParameterSets - ]).concat(pps))), // "PPS" - width = track.width, - height = track.height; - //console.log('avcc:' + Hex.hexDump(avcc)); - return MP4.box(MP4.types.avc1, new Uint8Array([ - 0x00, 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, // reserved - 0x00, 0x01, // data_reference_index - 0x00, 0x00, // pre_defined - 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // pre_defined - (width >> 8) & 0xFF, - width & 0xff, // width - (height >> 8) & 0xFF, - height & 0xff, // height - 0x00, 0x48, 0x00, 0x00, // horizresolution - 0x00, 0x48, 0x00, 0x00, // vertresolution - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x01, // frame_count - 0x12, - 0x64, 0x61, 0x69, 0x6C, //dailymotion/hls.js - 0x79, 0x6D, 0x6F, 0x74, - 0x69, 0x6F, 0x6E, 0x2F, - 0x68, 0x6C, 0x73, 0x2E, - 0x6A, 0x73, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, // compressorname - 0x00, 0x18, // depth = 24 - 0x11, 0x11]), // pre_defined = -1 - avcc, - MP4.box(MP4.types.btrt, new Uint8Array([ - 0x00, 0x1c, 0x9c, 0x80, // bufferSizeDB - 0x00, 0x2d, 0xc6, 0xc0, // maxBitrate - 0x00, 0x2d, 0xc6, 0xc0])) // avgBitrate - ); - } - - static esds(track) { - var configlen = track.config.length; - return new Uint8Array([ - 0x00, // version 0 - 0x00, 0x00, 0x00, // flags - - 0x03, // descriptor_type - 0x17+configlen, // length - 0x00, 0x01, //es_id - 0x00, // stream_priority - - 0x04, // descriptor_type - 0x0f+configlen, // length - 0x40, //codec : mpeg4_audio - 0x15, // stream_type - 0x00, 0x00, 0x00, // buffer_size - 0x00, 0x00, 0x00, 0x00, // maxBitrate - 0x00, 0x00, 0x00, 0x00, // avgBitrate - - 0x05 // descriptor_type - ].concat([configlen]).concat(track.config).concat([0x06, 0x01, 0x02])); // GASpecificConfig)); // length + audio config descriptor - } - - static mp4a(track) { - var audiosamplerate = track.audiosamplerate; - return MP4.box(MP4.types.mp4a, new Uint8Array([ - 0x00, 0x00, 0x00, // reserved - 0x00, 0x00, 0x00, // reserved - 0x00, 0x01, // data_reference_index - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, track.channelCount, // channelcount - 0x00, 0x10, // sampleSize:16bits - 0x00, 0x00, 0x00, 0x00, // reserved2 - (audiosamplerate >> 8) & 0xFF, - audiosamplerate & 0xff, // - 0x00, 0x00]), - MP4.box(MP4.types.esds, MP4.esds(track))); - } - - static stsd(track) { - if (track.type === 'audio') { - return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track)); - } else { - return MP4.box(MP4.types.stsd, MP4.STSD, MP4.avc1(track)); - } - } - - static tkhd(track) { - var id = track.id, - duration = track.duration*track.timescale, - width = track.width, - height = track.height; - return MP4.box(MP4.types.tkhd, new Uint8Array([ - 0x00, // version 0 - 0x00, 0x00, 0x07, // flags - 0x00, 0x00, 0x00, 0x00, // creation_time - 0x00, 0x00, 0x00, 0x00, // modification_time - (id >> 24) & 0xFF, - (id >> 16) & 0xFF, - (id >> 8) & 0xFF, - id & 0xFF, // track_ID - 0x00, 0x00, 0x00, 0x00, // reserved - (duration >> 24), - (duration >> 16) & 0xFF, - (duration >> 8) & 0xFF, - duration & 0xFF, // duration - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // reserved - 0x00, 0x00, // layer - 0x00, 0x00, // alternate_group - 0x00, 0x00, // non-audio track volume - 0x00, 0x00, // reserved - 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, // transformation: unity matrix - (width >> 8) & 0xFF, - width & 0xFF, - 0x00, 0x00, // width - (height >> 8) & 0xFF, - height & 0xFF, - 0x00, 0x00 // height - ])); - } - - static traf(track,baseMediaDecodeTime) { - var sampleDependencyTable = MP4.sdtp(track), - id = track.id; - return MP4.box(MP4.types.traf, - MP4.box(MP4.types.tfhd, new Uint8Array([ - 0x00, // version 0 - 0x00, 0x00, 0x00, // flags - (id >> 24), - (id >> 16) & 0XFF, - (id >> 8) & 0XFF, - (id & 0xFF) // track_ID - ])), - MP4.box(MP4.types.tfdt, new Uint8Array([ - 0x00, // version 0 - 0x00, 0x00, 0x00, // flags - (baseMediaDecodeTime >>24), - (baseMediaDecodeTime >> 16) & 0XFF, - (baseMediaDecodeTime >> 8) & 0XFF, - (baseMediaDecodeTime & 0xFF) // baseMediaDecodeTime - ])), - MP4.trun(track, - sampleDependencyTable.length + - 16 + // tfhd - 16 + // tfdt - 8 + // traf header - 16 + // mfhd - 8 + // moof header - 8), // mdat header - sampleDependencyTable); - } - - /** - * Generate a track box. - * @param track {object} a track definition - * @return {Uint8Array} the track box - */ - static trak(track) { - track.duration = track.duration || 0xffffffff; - return MP4.box(MP4.types.trak, MP4.tkhd(track), MP4.mdia(track)); - } - - static trex(track) { - var id = track.id; - return MP4.box(MP4.types.trex, new Uint8Array([ - 0x00, // version 0 - 0x00, 0x00, 0x00, // flags - (id >> 24), - (id >> 16) & 0XFF, - (id >> 8) & 0XFF, - (id & 0xFF), // track_ID - 0x00, 0x00, 0x00, 0x01, // default_sample_description_index - 0x00, 0x00, 0x00, 0x00, // default_sample_duration - 0x00, 0x00, 0x00, 0x00, // default_sample_size - 0x00, 0x01, 0x00, 0x01 // default_sample_flags - ])); - } - - static trun(track, offset) { - var samples= track.samples || [], - len = samples.length, - arraylen = 12 + (16 * len), - array = new Uint8Array(arraylen), - i,sample,duration,size,flags,cts; - offset += 8 + arraylen; - array.set([ - 0x00, // version 0 - 0x00, 0x0f, 0x01, // flags - (len >>> 24) & 0xFF, - (len >>> 16) & 0xFF, - (len >>> 8) & 0xFF, - len & 0xFF, // sample_count - (offset >>> 24) & 0xFF, - (offset >>> 16) & 0xFF, - (offset >>> 8) & 0xFF, - offset & 0xFF // data_offset - ],0); - for (i = 0; i < len; i++) { - sample = samples[i]; - duration = sample.duration; - size = sample.size; - flags = sample.flags; - cts = sample.cts; - array.set([ - (duration >>> 24) & 0xFF, - (duration >>> 16) & 0xFF, - (duration >>> 8) & 0xFF, - duration & 0xFF, // sample_duration - (size >>> 24) & 0xFF, - (size >>> 16) & 0xFF, - (size >>> 8) & 0xFF, - size & 0xFF, // sample_size - (flags.isLeading << 2) | flags.dependsOn, - (flags.isDependedOn << 6) | - (flags.hasRedundancy << 4) | - (flags.paddingValue << 1) | - flags.isNonSync, - flags.degradPrio & 0xF0 << 8, - flags.degradPrio & 0x0F, // sample_flags - (cts >>> 24) & 0xFF, - (cts >>> 16) & 0xFF, - (cts >>> 8) & 0xFF, - cts & 0xFF // sample_composition_time_offset - ],12+16*i); - } - return MP4.box(MP4.types.trun, array); - } - - static initSegment(tracks) { - if (!MP4.types) { - MP4.init(); - } - var movie = MP4.moov(tracks), result; - result = new Uint8Array(MP4.FTYP.byteLength + movie.byteLength); - result.set(MP4.FTYP); - result.set(movie, MP4.FTYP.byteLength); - return result; - } -} - -export default MP4; diff --git a/dashboard-ui/bower_components/hls.js/src/remux/mp4-remuxer.js b/dashboard-ui/bower_components/hls.js/src/remux/mp4-remuxer.js deleted file mode 100644 index 1074a5a06..000000000 --- a/dashboard-ui/bower_components/hls.js/src/remux/mp4-remuxer.js +++ /dev/null @@ -1,471 +0,0 @@ -/** - * fMP4 remuxer -*/ - - -import Event from '../events'; -import {logger} from '../utils/logger'; -import MP4 from '../remux/mp4-generator'; -import {ErrorTypes, ErrorDetails} from '../errors'; - -class MP4Remuxer { - constructor(observer) { - this.observer = observer; - this.ISGenerated = false; - this.PES2MP4SCALEFACTOR = 4; - this.PES_TIMESCALE = 90000; - this.MP4_TIMESCALE = this.PES_TIMESCALE / this.PES2MP4SCALEFACTOR; - } - - get passthrough() { - return false; - } - - destroy() { - } - - insertDiscontinuity() { - this._initPTS = this._initDTS = undefined; - } - - switchLevel() { - this.ISGenerated = false; - } - - remux(audioTrack,videoTrack,id3Track,textTrack,timeOffset, contiguous) { - // generate Init Segment if needed - if (!this.ISGenerated) { - this.generateIS(audioTrack,videoTrack,timeOffset); - } - if (this.ISGenerated) { - //logger.log('nb AVC samples:' + videoTrack.samples.length); - if (videoTrack.samples.length) { - this.remuxVideo(videoTrack,timeOffset,contiguous); - } - //logger.log('nb AAC samples:' + audioTrack.samples.length); - if (audioTrack.samples.length) { - this.remuxAudio(audioTrack,timeOffset,contiguous); - } - } - //logger.log('nb ID3 samples:' + audioTrack.samples.length); - if (id3Track.samples.length) { - this.remuxID3(id3Track,timeOffset); - } - //logger.log('nb ID3 samples:' + audioTrack.samples.length); - if (textTrack.samples.length) { - this.remuxText(textTrack,timeOffset); - } - //notify end of parsing - this.observer.trigger(Event.FRAG_PARSED); - } - - generateIS(audioTrack,videoTrack,timeOffset) { - var observer = this.observer, - audioSamples = audioTrack.samples, - videoSamples = videoTrack.samples, - pesTimeScale = this.PES_TIMESCALE, - tracks = {}, - data = { tracks : tracks, unique : false }, - computePTSDTS = (this._initPTS === undefined), - initPTS, initDTS; - - if (computePTSDTS) { - initPTS = initDTS = Infinity; - } - if (audioTrack.config && audioSamples.length) { - audioTrack.timescale = audioTrack.audiosamplerate; - // MP4 duration (track duration in seconds multiplied by timescale) is coded on 32 bits - // we know that each AAC sample contains 1024 frames.... - // in order to avoid overflowing the 32 bit counter for large duration, we use smaller timescale (timescale/gcd) - // we just need to ensure that AAC sample duration will still be an integer (will be 1024/gcd) - if (audioTrack.timescale * audioTrack.duration > Math.pow(2, 32)) { - let greatestCommonDivisor = function(a, b) { - if ( ! b) { - return a; - } - return greatestCommonDivisor(b, a % b); - }; - audioTrack.timescale = audioTrack.audiosamplerate / greatestCommonDivisor(audioTrack.audiosamplerate,1024); - } - logger.log ('audio mp4 timescale :'+ audioTrack.timescale); - tracks.audio = { - container : 'audio/mp4', - codec : audioTrack.codec, - initSegment : MP4.initSegment([audioTrack]), - metadata : { - channelCount : audioTrack.channelCount - } - }; - if (computePTSDTS) { - // remember first PTS of this demuxing context. for audio, PTS + DTS ... - initPTS = initDTS = audioSamples[0].pts - pesTimeScale * timeOffset; - } - } - - if (videoTrack.sps && videoTrack.pps && videoSamples.length) { - videoTrack.timescale = this.MP4_TIMESCALE; - tracks.video = { - container : 'video/mp4', - codec : videoTrack.codec, - initSegment : MP4.initSegment([videoTrack]), - metadata : { - width : videoTrack.width, - height : videoTrack.height - } - }; - if (computePTSDTS) { - initPTS = Math.min(initPTS,videoSamples[0].pts - pesTimeScale * timeOffset); - initDTS = Math.min(initDTS,videoSamples[0].dts - pesTimeScale * timeOffset); - } - } - - if(Object.keys(tracks).length) { - observer.trigger(Event.FRAG_PARSING_INIT_SEGMENT,data); - this.ISGenerated = true; - if (computePTSDTS) { - this._initPTS = initPTS; - this._initDTS = initDTS; - } - } else { - observer.trigger(Event.ERROR, {type : ErrorTypes.MEDIA_ERROR, details: ErrorDetails.FRAG_PARSING_ERROR, fatal: false, reason: 'no audio/video samples found'}); - } - } - - remuxVideo(track, timeOffset, contiguous) { - var view, - offset = 8, - pesTimeScale = this.PES_TIMESCALE, - pes2mp4ScaleFactor = this.PES2MP4SCALEFACTOR, - avcSample, - mp4Sample, - mp4SampleLength, - unit, - mdat, moof, - firstPTS, firstDTS, lastDTS, - pts, dts, ptsnorm, dtsnorm, - flags, - samples = []; - - // handle broken streams with PTS < DTS, tolerance up 200ms (18000 in 90kHz timescale) - let PTSDTSshift = track.samples.reduce( (prev, curr) => Math.max(Math.min(prev,curr.pts-curr.dts),-18000),0); - if (PTSDTSshift < 0) { - logger.warn(`PTS < DTS detected in video samples, shifting DTS by ${Math.round(PTSDTSshift/90)} ms to overcome this issue`); - } - /* concatenate the video data and construct the mdat in place - (need 8 more bytes to fill length and mpdat type) */ - mdat = new Uint8Array(track.len + (4 * track.nbNalu) + 8); - view = new DataView(mdat.buffer); - view.setUint32(0, mdat.byteLength); - mdat.set(MP4.types.mdat, 4); - while (track.samples.length) { - avcSample = track.samples.shift(); - mp4SampleLength = 0; - // convert NALU bitstream to MP4 format (prepend NALU with size field) - while (avcSample.units.units.length) { - unit = avcSample.units.units.shift(); - view.setUint32(offset, unit.data.byteLength); - offset += 4; - mdat.set(unit.data, offset); - offset += unit.data.byteLength; - mp4SampleLength += 4 + unit.data.byteLength; - } - pts = avcSample.pts - this._initDTS; - // shift dts by PTSDTSshift, to ensure that PTS >= DTS - dts = avcSample.dts - this._initDTS + PTSDTSshift; - // ensure DTS is not bigger than PTS // strap belt !!! - dts = Math.min(pts,dts); - //logger.log(`Video/PTS/DTS/ptsnorm/DTSnorm:${Math.round(avcSample.pts/90)}/${Math.round(avcSample.dts/90)}/${Math.round(pts/90)}/${Math.round(dts/90)}`); - // if not first AVC sample of video track, normalize PTS/DTS with previous sample value - // and ensure that sample duration is positive - if (lastDTS !== undefined) { - ptsnorm = this._PTSNormalize(pts, lastDTS); - dtsnorm = this._PTSNormalize(dts, lastDTS); - var sampleDuration = (dtsnorm - lastDTS) / pes2mp4ScaleFactor; - if (sampleDuration <= 0) { - logger.log(`invalid sample duration at PTS/DTS: ${avcSample.pts}/${avcSample.dts}:${sampleDuration}`); - sampleDuration = 1; - } - mp4Sample.duration = sampleDuration; - } else { - let nextAvcDts, delta; - if (contiguous) { - nextAvcDts = this.nextAvcDts; - } else { - nextAvcDts = timeOffset*pesTimeScale; - } - // first AVC sample of video track, normalize PTS/DTS - ptsnorm = this._PTSNormalize(pts, nextAvcDts); - dtsnorm = this._PTSNormalize(dts, nextAvcDts); - delta = Math.round((dtsnorm - nextAvcDts) / 90); - // if fragment are contiguous, detect hole/overlapping between fragments - if (contiguous) { - if (delta) { - if (delta > 1) { - logger.log(`AVC:${delta} ms hole between fragments detected,filling it`); - } else if (delta < -1) { - logger.log(`AVC:${(-delta)} ms overlapping between fragments detected`); - } - // set DTS to next DTS - dtsnorm = nextAvcDts; - // offset PTS as well, ensure that PTS is smaller or equal than new DTS - ptsnorm = Math.max(ptsnorm - delta, dtsnorm); - logger.log(`Video/PTS/DTS adjusted: ${ptsnorm}/${dtsnorm},delta:${delta}`); - } - } - // remember first PTS of our avcSamples, ensure value is positive - firstPTS = Math.max(0, ptsnorm); - firstDTS = Math.max(0, dtsnorm); - } - //console.log(`PTS/DTS/initDTS/normPTS/normDTS/relative PTS : ${avcSample.pts}/${avcSample.dts}/${this._initDTS}/${ptsnorm}/${dtsnorm}/${(avcSample.pts/4294967296).toFixed(3)}); - mp4Sample = { - size: mp4SampleLength, - duration: 0, - cts: (ptsnorm - dtsnorm) / pes2mp4ScaleFactor, - flags: { - isLeading: 0, - isDependedOn: 0, - hasRedundancy: 0, - degradPrio: 0 - } - }; - flags = mp4Sample.flags; - if (avcSample.key === true) { - // the current sample is a key frame - flags.dependsOn = 2; - flags.isNonSync = 0; - } else { - flags.dependsOn = 1; - flags.isNonSync = 1; - } - samples.push(mp4Sample); - lastDTS = dtsnorm; - } - var lastSampleDuration = 0; - if (samples.length >= 2) { - lastSampleDuration = samples[samples.length - 2].duration; - mp4Sample.duration = lastSampleDuration; - } - // next AVC sample DTS should be equal to last sample DTS + last sample duration - this.nextAvcDts = dtsnorm + lastSampleDuration * pes2mp4ScaleFactor; - let dropped = track.dropped; - track.len = 0; - track.nbNalu = 0; - track.dropped = 0; - if(samples.length && navigator.userAgent.toLowerCase().indexOf('chrome') > -1) { - flags = samples[0].flags; - // chrome workaround, mark first sample as being a Random Access Point to avoid sourcebuffer append issue - // https://code.google.com/p/chromium/issues/detail?id=229412 - flags.dependsOn = 2; - flags.isNonSync = 0; - } - track.samples = samples; - moof = MP4.moof(track.sequenceNumber++, firstDTS / pes2mp4ScaleFactor, track); - track.samples = []; - this.observer.trigger(Event.FRAG_PARSING_DATA, { - data1: moof, - data2: mdat, - startPTS: firstPTS / pesTimeScale, - endPTS: (ptsnorm + pes2mp4ScaleFactor * lastSampleDuration) / pesTimeScale, - startDTS: firstDTS / pesTimeScale, - endDTS: this.nextAvcDts / pesTimeScale, - type: 'video', - nb: samples.length, - dropped : dropped - }); - } - - remuxAudio(track,timeOffset, contiguous) { - var view, - offset = 8, - pesTimeScale = this.PES_TIMESCALE, - mp4timeScale = track.timescale, - pes2mp4ScaleFactor = pesTimeScale/mp4timeScale, - expectedSampleDuration = track.timescale * 1024 / track.audiosamplerate, - aacSample, mp4Sample, - unit, - mdat, moof, - firstPTS, firstDTS, lastDTS, - pts, dts, ptsnorm, dtsnorm, - samples = [], - samples0 = []; - - track.samples.sort(function(a, b) { - return (a.pts-b.pts); - }); - samples0 = track.samples; - - while (samples0.length) { - aacSample = samples0.shift(); - unit = aacSample.unit; - pts = aacSample.pts - this._initDTS; - dts = aacSample.dts - this._initDTS; - //logger.log(`Audio/PTS:${Math.round(pts/90)}`); - // if not first sample - if (lastDTS !== undefined) { - ptsnorm = this._PTSNormalize(pts, lastDTS); - dtsnorm = this._PTSNormalize(dts, lastDTS); - // let's compute sample duration. - // sample Duration should be close to expectedSampleDuration - mp4Sample.duration = (dtsnorm - lastDTS) / pes2mp4ScaleFactor; - if(Math.abs(mp4Sample.duration - expectedSampleDuration) > expectedSampleDuration/10) { - // more than 10% diff between sample duration and expectedSampleDuration .... lets log that - logger.log(`invalid AAC sample duration at PTS ${Math.round(pts/90)},should be 1024,found :${Math.round(mp4Sample.duration*track.audiosamplerate/track.timescale)}`); - } - // always adjust sample duration to avoid av sync issue - mp4Sample.duration = expectedSampleDuration; - ptsnorm = dtsnorm = expectedSampleDuration * pes2mp4ScaleFactor + lastDTS; - } else { - let nextAacPts, delta; - if (contiguous) { - nextAacPts = this.nextAacPts; - } else { - nextAacPts = timeOffset*pesTimeScale; - } - ptsnorm = this._PTSNormalize(pts, nextAacPts); - dtsnorm = this._PTSNormalize(dts, nextAacPts); - delta = Math.round(1000 * (ptsnorm - nextAacPts) / pesTimeScale); - // if fragment are contiguous, detect hole/overlapping between fragments - if (contiguous) { - // log delta - if (delta) { - if (delta > 0) { - logger.log(`${delta} ms hole between AAC samples detected,filling it`); - // if we have frame overlap, overlapping for more than half a frame duration - } else if (delta < -12) { - // drop overlapping audio frames... browser will deal with it - logger.log(`${(-delta)} ms overlapping between AAC samples detected, drop frame`); - track.len -= unit.byteLength; - continue; - } - // set PTS/DTS to next PTS/DTS - ptsnorm = dtsnorm = nextAacPts; - } - } - // remember first PTS of our aacSamples, ensure value is positive - firstPTS = Math.max(0, ptsnorm); - firstDTS = Math.max(0, dtsnorm); - if(track.len > 0) { - /* concatenate the audio data and construct the mdat in place - (need 8 more bytes to fill length and mdat type) */ - mdat = new Uint8Array(track.len + 8); - view = new DataView(mdat.buffer); - view.setUint32(0, mdat.byteLength); - mdat.set(MP4.types.mdat, 4); - } else { - // no audio samples - return; - } - } - mdat.set(unit, offset); - offset += unit.byteLength; - //console.log('PTS/DTS/initDTS/normPTS/normDTS/relative PTS : ${aacSample.pts}/${aacSample.dts}/${this._initDTS}/${ptsnorm}/${dtsnorm}/${(aacSample.pts/4294967296).toFixed(3)}'); - mp4Sample = { - size: unit.byteLength, - cts: 0, - duration:0, - flags: { - isLeading: 0, - isDependedOn: 0, - hasRedundancy: 0, - degradPrio: 0, - dependsOn: 1, - } - }; - samples.push(mp4Sample); - lastDTS = dtsnorm; - } - var lastSampleDuration = 0; - var nbSamples = samples.length; - //set last sample duration as being identical to previous sample - if (nbSamples >= 2) { - lastSampleDuration = samples[nbSamples - 2].duration; - mp4Sample.duration = lastSampleDuration; - } - if (nbSamples) { - // next aac sample PTS should be equal to last sample PTS + duration - this.nextAacPts = ptsnorm + pes2mp4ScaleFactor * lastSampleDuration; - //logger.log('Audio/PTS/PTSend:' + aacSample.pts.toFixed(0) + '/' + this.nextAacDts.toFixed(0)); - track.len = 0; - track.samples = samples; - moof = MP4.moof(track.sequenceNumber++, firstDTS / pes2mp4ScaleFactor, track); - track.samples = []; - this.observer.trigger(Event.FRAG_PARSING_DATA, { - data1: moof, - data2: mdat, - startPTS: firstPTS / pesTimeScale, - endPTS: this.nextAacPts / pesTimeScale, - startDTS: firstDTS / pesTimeScale, - endDTS: (dtsnorm + pes2mp4ScaleFactor * lastSampleDuration) / pesTimeScale, - type: 'audio', - nb: nbSamples - }); - } - } - - remuxID3(track,timeOffset) { - var length = track.samples.length, sample; - // consume samples - if(length) { - for(var index = 0; index < length; index++) { - sample = track.samples[index]; - // setting id3 pts, dts to relative time - // using this._initPTS and this._initDTS to calculate relative time - sample.pts = ((sample.pts - this._initPTS) / this.PES_TIMESCALE); - sample.dts = ((sample.dts - this._initDTS) / this.PES_TIMESCALE); - } - this.observer.trigger(Event.FRAG_PARSING_METADATA, { - samples:track.samples - }); - } - - track.samples = []; - timeOffset = timeOffset; - } - - remuxText(track,timeOffset) { - track.samples.sort(function(a, b) { - return (a.pts-b.pts); - }); - - var length = track.samples.length, sample; - // consume samples - if(length) { - for(var index = 0; index < length; index++) { - sample = track.samples[index]; - // setting text pts, dts to relative time - // using this._initPTS and this._initDTS to calculate relative time - sample.pts = ((sample.pts - this._initPTS) / this.PES_TIMESCALE); - } - this.observer.trigger(Event.FRAG_PARSING_USERDATA, { - samples:track.samples - }); - } - - track.samples = []; - timeOffset = timeOffset; - } - - _PTSNormalize(value, reference) { - var offset; - if (reference === undefined) { - return value; - } - if (reference < value) { - // - 2^33 - offset = -8589934592; - } else { - // + 2^33 - offset = 8589934592; - } - /* PTS is 33bit (from 0 to 2^33 -1) - if diff between value and reference is bigger than half of the amplitude (2^32) then it means that - PTS looping occured. fill the gap */ - while (Math.abs(value - reference) > 4294967296) { - value += offset; - } - return value; - } - -} - -export default MP4Remuxer; diff --git a/dashboard-ui/bower_components/hls.js/src/remux/passthrough-remuxer.js b/dashboard-ui/bower_components/hls.js/src/remux/passthrough-remuxer.js deleted file mode 100644 index 97cb2cb38..000000000 --- a/dashboard-ui/bower_components/hls.js/src/remux/passthrough-remuxer.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * passthrough remuxer -*/ -import Event from '../events'; - -class PassThroughRemuxer { - constructor(observer) { - this.observer = observer; - this.ISGenerated = false; - } - - get passthrough() { - return true; - } - - destroy() { - } - - insertDiscontinuity() { - } - - switchLevel() { - this.ISGenerated = false; - } - - remux(audioTrack,videoTrack,id3Track,textTrack,timeOffset,rawData) { - var observer = this.observer; - // generate Init Segment if needed - if (!this.ISGenerated) { - var tracks = {}, - data = { tracks : tracks, unique : true }, - track = videoTrack, - codec = track.codec; - - if (codec) { - data.tracks.video = { - container : track.container, - codec : codec, - metadata : { - width : track.width, - height : track.height - } - }; - } - - track = audioTrack; - codec = track.codec; - if (codec) { - data.tracks.audio = { - container : track.container, - codec : codec, - metadata : { - channelCount : track.channelCount - } - }; - } - this.ISGenerated = true; - observer.trigger(Event.FRAG_PARSING_INIT_SEGMENT,data); - } - observer.trigger(Event.FRAG_PARSING_DATA, { - data1: rawData, - startPTS: timeOffset, - startDTS: timeOffset, - type: 'audiovideo', - nb: 1, - dropped : 0 - }); - } -} - -export default PassThroughRemuxer; diff --git a/dashboard-ui/bower_components/hls.js/src/utils/attr-list.js b/dashboard-ui/bower_components/hls.js/src/utils/attr-list.js deleted file mode 100644 index 24d509a41..000000000 --- a/dashboard-ui/bower_components/hls.js/src/utils/attr-list.js +++ /dev/null @@ -1,83 +0,0 @@ - -// adapted from https://github.com/kanongil/node-m3u8parse/blob/master/attrlist.js -class AttrList { - - constructor(attrs) { - if (typeof attrs === 'string') { - attrs = AttrList.parseAttrList(attrs); - } - for(var attr in attrs){ - if(attrs.hasOwnProperty(attr)) { - this[attr] = attrs[attr]; - } - } - } - - decimalInteger(attrName) { - const intValue = parseInt(this[attrName], 10); - if (intValue > Number.MAX_SAFE_INTEGER) { - return Infinity; - } - return intValue; - } - - hexadecimalInteger(attrName) { - if(this[attrName]) { - let stringValue = (this[attrName] || '0x').slice(2); - stringValue = ((stringValue.length & 1) ? '0' : '') + stringValue; - - const value = new Uint8Array(stringValue.length / 2); - for (let i = 0; i < stringValue.length / 2; i++) { - value[i] = parseInt(stringValue.slice(i * 2, i * 2 + 2), 16); - } - return value; - } else { - return null; - } - } - - hexadecimalIntegerAsNumber(attrName) { - const intValue = parseInt(this[attrName], 16); - if (intValue > Number.MAX_SAFE_INTEGER) { - return Infinity; - } - return intValue; - } - - decimalFloatingPoint(attrName) { - return parseFloat(this[attrName]); - } - - enumeratedString(attrName) { - return this[attrName]; - } - - decimalResolution(attrName) { - const res = /^(\d+)x(\d+)$/.exec(this[attrName]); - if (res === null) { - return undefined; - } - return { - width: parseInt(res[1], 10), - height: parseInt(res[2], 10) - }; - } - - static parseAttrList(input) { - const re = /\s*(.+?)\s*=((?:\".*?\")|.*?)(?:,|$)/g; - var match, attrs = {}; - while ((match = re.exec(input)) !== null) { - var value = match[2], quote = '"'; - - if (value.indexOf(quote) === 0 && - value.lastIndexOf(quote) === (value.length-1)) { - value = value.slice(1, -1); - } - attrs[match[1]] = value; - } - return attrs; - } - -} - -export default AttrList; diff --git a/dashboard-ui/bower_components/hls.js/src/utils/binary-search.js b/dashboard-ui/bower_components/hls.js/src/utils/binary-search.js deleted file mode 100644 index a27ce1983..000000000 --- a/dashboard-ui/bower_components/hls.js/src/utils/binary-search.js +++ /dev/null @@ -1,43 +0,0 @@ -var BinarySearch = { - /** - * Searches for an item in an array which matches a certain condition. - * This requires the condition to only match one item in the array, - * and for the array to be ordered. - * - * @param {Array} list The array to search. - * @param {Function} comparisonFunction - * Called and provided a candidate item as the first argument. - * Should return: - * > -1 if the item should be located at a lower index than the provided item. - * > 1 if the item should be located at a higher index than the provided item. - * > 0 if the item is the item you're looking for. - * - * @return {*} The object if it is found or null otherwise. - */ - search: function(list, comparisonFunction) { - var minIndex = 0; - var maxIndex = list.length - 1; - var currentIndex = null; - var currentElement = null; - - while (minIndex <= maxIndex) { - currentIndex = (minIndex + maxIndex) / 2 | 0; - currentElement = list[currentIndex]; - - var comparisonResult = comparisonFunction(currentElement); - if (comparisonResult > 0) { - minIndex = currentIndex + 1; - } - else if (comparisonResult < 0) { - maxIndex = currentIndex - 1; - } - else { - return currentElement; - } - } - - return null; - } -}; - -module.exports = BinarySearch; diff --git a/dashboard-ui/bower_components/hls.js/src/utils/cea-708-interpreter.js b/dashboard-ui/bower_components/hls.js/src/utils/cea-708-interpreter.js deleted file mode 100644 index 8ed66bc55..000000000 --- a/dashboard-ui/bower_components/hls.js/src/utils/cea-708-interpreter.js +++ /dev/null @@ -1,381 +0,0 @@ -/* - * CEA-708 interpreter -*/ - -class CEA708Interpreter { - - constructor() { - } - - attach(media) { - this.media = media; - this.display = []; - this.memory = []; - } - - detach() - { - this.clear(); - } - - destroy() { - } - - _createCue() - { - var VTTCue = window.VTTCue || window.TextTrackCue; - - var cue = this.cue = new VTTCue(-1, -1, ''); - cue.text = ''; - cue.pauseOnExit = false; - - // make sure it doesn't show up before it's ready - cue.startTime = Number.MAX_VALUE; - - // show it 'forever' once we do show it - // (we'll set the end time once we know it later) - cue.endTime = Number.MAX_VALUE; - - this.memory.push(cue); - } - - clear() - { - var textTrack = this._textTrack; - if (textTrack && textTrack.cues) - { - while (textTrack.cues.length > 0) - { - textTrack.removeCue(textTrack.cues[0]); - } - } - } - - push(timestamp, bytes) - { - if (!this.cue) - { - this._createCue(); - } - - var count = bytes[0] & 31; - var position = 2; - var tmpByte, ccbyte1, ccbyte2, ccValid, ccType; - - for (var j=0; j= 0x30 && ccbyte2 <= 0x3F) - { - // extended chars, e.g. musical note, accents - switch (ccbyte2) - { - case 48: - this.cue.text += '®'; - break; - case 49: - this.cue.text += '°'; - break; - case 50: - this.cue.text += '½'; - break; - case 51: - this.cue.text += '¿'; - break; - case 52: - this.cue.text += '™'; - break; - case 53: - this.cue.text += '¢'; - break; - case 54: - this.cue.text += ''; - break; - case 55: - this.cue.text += '£'; - break; - case 56: - this.cue.text += '♪'; - break; - case 57: - this.cue.text += ' '; - break; - case 58: - this.cue.text += 'è'; - break; - case 59: - this.cue.text += 'â'; - break; - case 60: - this.cue.text += 'ê'; - break; - case 61: - this.cue.text += 'î'; - break; - case 62: - this.cue.text += 'ô'; - break; - case 63: - this.cue.text += 'û'; - break; - } - } - if ((ccbyte1 === 0x11 || ccbyte1 === 0x19) && ccbyte2 >= 0x20 && ccbyte2 <= 0x2F) - { - // Mid-row codes: color/underline - switch (ccbyte2) - { - case 0x20: - // White - break; - case 0x21: - // White Underline - break; - case 0x22: - // Green - break; - case 0x23: - // Green Underline - break; - case 0x24: - // Blue - break; - case 0x25: - // Blue Underline - break; - case 0x26: - // Cyan - break; - case 0x27: - // Cyan Underline - break; - case 0x28: - // Red - break; - case 0x29: - // Red Underline - break; - case 0x2A: - // Yellow - break; - case 0x2B: - // Yellow Underline - break; - case 0x2C: - // Magenta - break; - case 0x2D: - // Magenta Underline - break; - case 0x2E: - // Italics - break; - case 0x2F: - // Italics Underline - break; - } - } - if ((ccbyte1 === 0x14 || ccbyte1 === 0x1C) && ccbyte2 >= 0x20 && ccbyte2 <= 0x2F) - { - // Mid-row codes: color/underline - switch (ccbyte2) - { - case 0x20: - // TODO: shouldn't affect roll-ups... - this._clearActiveCues(timestamp); - // RCL: Resume Caption Loading - // begin pop on - break; - case 0x21: - // BS: Backspace - this.cue.text = this.cue.text.substr(0, this.cue.text.length-1); - break; - case 0x22: - // AOF: reserved (formerly alarm off) - break; - case 0x23: - // AON: reserved (formerly alarm on) - break; - case 0x24: - // DER: Delete to end of row - break; - case 0x25: - // RU2: roll-up 2 rows - //this._rollup(2); - break; - case 0x26: - // RU3: roll-up 3 rows - //this._rollup(3); - break; - case 0x27: - // RU4: roll-up 4 rows - //this._rollup(4); - break; - case 0x28: - // FON: Flash on - break; - case 0x29: - // RDC: Resume direct captioning - this._clearActiveCues(timestamp); - break; - case 0x2A: - // TR: Text Restart - break; - case 0x2B: - // RTD: Resume Text Display - break; - case 0x2C: - // EDM: Erase Displayed Memory - this._clearActiveCues(timestamp); - break; - case 0x2D: - // CR: Carriage Return - // only affects roll-up - //this._rollup(1); - break; - case 0x2E: - // ENM: Erase non-displayed memory - this._text = ''; - break; - case 0x2F: - this._flipMemory(timestamp); - // EOC: End of caption - // hide any displayed captions and show any hidden one - break; - } - } - if ((ccbyte1 === 0x17 || ccbyte1 === 0x1F) && ccbyte2 >= 0x21 && ccbyte2 <= 0x23) - { - // Mid-row codes: color/underline - switch (ccbyte2) - { - case 0x21: - // TO1: tab offset 1 column - break; - case 0x22: - // TO1: tab offset 2 column - break; - case 0x23: - // TO1: tab offset 3 column - break; - } - } - else { - // Probably a pre-amble address code - } - } - } - } - } - - _fromCharCode(tmpByte) - { - switch (tmpByte) - { - case 42: - return 'á'; - - case 2: - return 'á'; - - case 2: - return 'é'; - - case 4: - return 'í'; - - case 5: - return 'ó'; - - case 6: - return 'ú'; - - case 3: - return 'ç'; - - case 4: - return '÷'; - - case 5: - return 'Ñ'; - - case 6: - return 'ñ'; - - case 7: - return '█'; - - default: - return String.fromCharCode(tmpByte); - } - } - - _flipMemory(timestamp) - { - this._clearActiveCues(timestamp); - this._flushCaptions(timestamp); - } - - _flushCaptions(timestamp) - { - if (!this._has708) - { - this._textTrack = this.media.addTextTrack('captions', 'English', 'en'); - this._has708 = true; - } - - for(let memoryItem of this.memory) - { - memoryItem.startTime = timestamp; - this._textTrack.addCue(memoryItem); - this.display.push(memoryItem); - } - - this.memory = []; - this.cue = null; - } - - _clearActiveCues(timestamp) - { - for (let displayItem of this.display) - { - displayItem.endTime = timestamp; - } - - this.display = []; - } - -/* _rollUp(n) - { - // TODO: implement roll-up captions - } -*/ - _clearBufferedCues() - { - //remove them all... - } - -} - -export default CEA708Interpreter; - diff --git a/dashboard-ui/bower_components/hls.js/src/utils/ewma.js b/dashboard-ui/bower_components/hls.js/src/utils/ewma.js deleted file mode 100644 index e54ce7ccc..000000000 --- a/dashboard-ui/bower_components/hls.js/src/utils/ewma.js +++ /dev/null @@ -1,37 +0,0 @@ -/* - * compute an Exponential Weighted moving average - * - https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average - * - heavily inspired from shaka-player - */ - -class EWMA { - - // About half of the estimated value will be from the last |halfLife| samples by weight. - constructor(halfLife) { - // Larger values of alpha expire historical data more slowly. - this.alpha_ = halfLife ? Math.exp(Math.log(0.5) / halfLife) : 0; - this.estimate_ = 0; - this.totalWeight_ = 0; - } - - sample(weight,value) { - var adjAlpha = Math.pow(this.alpha_, weight); - this.estimate_ = value * (1 - adjAlpha) + adjAlpha * this.estimate_; - this.totalWeight_ += weight; - } - - getTotalWeight() { - return this.totalWeight_; - } - - getEstimate() { - if (this.alpha_) { - var zeroFactor = 1 - Math.pow(this.alpha_, this.totalWeight_); - return this.estimate_ / zeroFactor; - } else { - return this.estimate_; - } - } -} - -export default EWMA; diff --git a/dashboard-ui/bower_components/hls.js/src/utils/hex.js b/dashboard-ui/bower_components/hls.js/src/utils/hex.js deleted file mode 100644 index 6cc0aa7cd..000000000 --- a/dashboard-ui/bower_components/hls.js/src/utils/hex.js +++ /dev/null @@ -1,16 +0,0 @@ -class Hex { - - static hexDump(array) { - var i, str = ''; - for(i = 0; i < array.length; i++) { - var h = array[i].toString(16); - if (h.length < 2) { - h = '0' + h; - } - str += h; - } - return str; - } -} - -export default Hex; diff --git a/dashboard-ui/bower_components/hls.js/src/utils/logger.js b/dashboard-ui/bower_components/hls.js/src/utils/logger.js deleted file mode 100644 index 3b8f3c43a..000000000 --- a/dashboard-ui/bower_components/hls.js/src/utils/logger.js +++ /dev/null @@ -1,73 +0,0 @@ -'use strict'; - -function noop() {} - -const fakeLogger = { - trace: noop, - debug: noop, - log: noop, - warn: noop, - info: noop, - error: noop -}; - -let exportedLogger = fakeLogger; - -//let lastCallTime; -// function formatMsgWithTimeInfo(type, msg) { -// const now = Date.now(); -// const diff = lastCallTime ? '+' + (now - lastCallTime) : '0'; -// lastCallTime = now; -// msg = (new Date(now)).toISOString() + ' | [' + type + '] > ' + msg + ' ( ' + diff + ' ms )'; -// return msg; -// } - -function formatMsg(type, msg) { - msg = '[' + type + '] > ' + msg; - return msg; -} - -function consolePrintFn(type) { - const func = window.console[type]; - if (func) { - return function(...args) { - if(args[0]) { - args[0] = formatMsg(type, args[0]); - } - func.apply(window.console, args); - }; - } - return noop; -} - -function exportLoggerFunctions(debugConfig, ...functions) { - functions.forEach(function(type) { - exportedLogger[type] = debugConfig[type] ? debugConfig[type].bind(debugConfig) : consolePrintFn(type); - }); -} - -export var enableLogs = function(debugConfig) { - if (debugConfig === true || typeof debugConfig === 'object') { - exportLoggerFunctions(debugConfig, - // Remove out from list here to hard-disable a log-level - //'trace', - 'debug', - 'log', - 'info', - 'warn', - 'error' - ); - // Some browsers don't allow to use bind on console object anyway - // fallback to default if needed - try { - exportedLogger.log(); - } catch (e) { - exportedLogger = fakeLogger; - } - } - else { - exportedLogger = fakeLogger; - } -}; - -export var logger = exportedLogger; diff --git a/dashboard-ui/bower_components/hls.js/src/utils/url.js b/dashboard-ui/bower_components/hls.js/src/utils/url.js deleted file mode 100644 index 1539adef9..000000000 --- a/dashboard-ui/bower_components/hls.js/src/utils/url.js +++ /dev/null @@ -1,84 +0,0 @@ -var URLHelper = { - // build an absolute URL from a relative one using the provided baseURL - // if relativeURL is an absolute URL it will be returned as is. - buildAbsoluteURL: function(baseURL, relativeURL) { - // remove any remaining space and CRLF - relativeURL = relativeURL.trim(); - if (/^[a-z]+:/i.test(relativeURL)) { - // complete url, not relative - return relativeURL; - } - - var relativeURLQuery = null; - var relativeURLHash = null; - - var relativeURLHashSplit = /^([^#]*)(.*)$/.exec(relativeURL); - if (relativeURLHashSplit) { - relativeURLHash = relativeURLHashSplit[2]; - relativeURL = relativeURLHashSplit[1]; - } - var relativeURLQuerySplit = /^([^\?]*)(.*)$/.exec(relativeURL); - if (relativeURLQuerySplit) { - relativeURLQuery = relativeURLQuerySplit[2]; - relativeURL = relativeURLQuerySplit[1]; - } - - var baseURLHashSplit = /^([^#]*)(.*)$/.exec(baseURL); - if (baseURLHashSplit) { - baseURL = baseURLHashSplit[1]; - } - var baseURLQuerySplit = /^([^\?]*)(.*)$/.exec(baseURL); - if (baseURLQuerySplit) { - baseURL = baseURLQuerySplit[1]; - } - - var baseURLDomainSplit = /^(([a-z]+:)?\/\/[a-z0-9\.\-_~]+(:[0-9]+)?)?(\/.*)$/i.exec(baseURL); - if (!baseURLDomainSplit) { - throw new Error('Error trying to parse base URL.'); - } - - // e.g. 'http:', 'https:', '' - var baseURLProtocol = baseURLDomainSplit[2] || ''; - // e.g. 'http://example.com', '//example.com', '' - var baseURLProtocolDomain = baseURLDomainSplit[1] || ''; - // e.g. '/a/b/c/playlist.m3u8' - var baseURLPath = baseURLDomainSplit[4]; - - var builtURL = null; - if (/^\/\//.test(relativeURL)) { - // relative url starts wth '//' so copy protocol (which may be '' if baseUrl didn't provide one) - builtURL = baseURLProtocol+'//'+URLHelper.buildAbsolutePath('', relativeURL.substring(2)); - } - else if (/^\//.test(relativeURL)) { - // relative url starts with '/' so start from root of domain - builtURL = baseURLProtocolDomain+'/'+URLHelper.buildAbsolutePath('', relativeURL.substring(1)); - } - else { - builtURL = URLHelper.buildAbsolutePath(baseURLProtocolDomain+baseURLPath, relativeURL); - } - - // put the query and hash parts back - if (relativeURLQuery) { - builtURL += relativeURLQuery; - } - if (relativeURLHash) { - builtURL += relativeURLHash; - } - return builtURL; - }, - - // build an absolute path using the provided basePath - // adapted from https://developer.mozilla.org/en-US/docs/Web/API/document/cookie#Using_relative_URLs_in_the_path_parameter - // this does not handle the case where relativePath is "/" or "//". These cases should be handled outside this. - buildAbsolutePath: function(basePath, relativePath) { - var sRelPath = relativePath; - var nUpLn, sDir = '', sPath = basePath.replace(/[^\/]*$/, sRelPath.replace(/(\/|^)(?:\.?\/+)+/g, '$1')); - for (var nEnd, nStart = 0; nEnd = sPath.indexOf('/../', nStart), nEnd > -1; nStart = nEnd + nUpLn) { - nUpLn = /^\/(?:\.\.\/)*/.exec(sPath.slice(nEnd))[0].length; - sDir = (sDir + sPath.substring(nStart, nEnd)).replace(new RegExp('(?:\\\/+[^\\\/]*){0,' + ((nUpLn - 1) / 3) + '}$'), '/'); - } - return sDir + sPath.substr(nStart); - } -}; - -module.exports = URLHelper; diff --git a/dashboard-ui/bower_components/hls.js/src/utils/xhr-loader.js b/dashboard-ui/bower_components/hls.js/src/utils/xhr-loader.js deleted file mode 100644 index cdf210dc2..000000000 --- a/dashboard-ui/bower_components/hls.js/src/utils/xhr-loader.js +++ /dev/null @@ -1,122 +0,0 @@ -/** - * XHR based logger -*/ - -import {logger} from '../utils/logger'; - -class XhrLoader { - - constructor(config) { - if (config && config.xhrSetup) { - this.xhrSetup = config.xhrSetup; - } - } - - destroy() { - this.abort(); - this.loader = null; - } - - abort() { - var loader = this.loader, - timeoutHandle = this.timeoutHandle; - if (loader && loader.readyState !== 4) { - this.stats.aborted = true; - loader.abort(); - } - if (timeoutHandle) { - window.clearTimeout(timeoutHandle); - } - } - - load(url, responseType, onSuccess, onError, onTimeout, timeout, maxRetry, retryDelay, onProgress = null, frag = null) { - this.url = url; - if (frag && !isNaN(frag.byteRangeStartOffset) && !isNaN(frag.byteRangeEndOffset)) { - this.byteRange = frag.byteRangeStartOffset + '-' + (frag.byteRangeEndOffset-1); - } - this.responseType = responseType; - this.onSuccess = onSuccess; - this.onProgress = onProgress; - this.onTimeout = onTimeout; - this.onError = onError; - this.stats = {trequest: performance.now(), retry: 0}; - this.timeout = timeout; - this.maxRetry = maxRetry; - this.retryDelay = retryDelay; - this.loadInternal(); - } - - loadInternal() { - var xhr; - - if (typeof XDomainRequest !== 'undefined') { - xhr = this.loader = new XDomainRequest(); - } else { - xhr = this.loader = new XMLHttpRequest(); - } - - xhr.onloadend = this.loadend.bind(this); - xhr.onprogress = this.loadprogress.bind(this); - - xhr.open('GET', this.url, true); - if (this.byteRange) { - xhr.setRequestHeader('Range', 'bytes=' + this.byteRange); - } - xhr.responseType = this.responseType; - let stats = this.stats; - stats.tfirst = 0; - stats.loaded = 0; - if (this.xhrSetup) { - this.xhrSetup(xhr, this.url); - } - this.timeoutHandle = window.setTimeout(this.loadtimeout.bind(this), this.timeout); - xhr.send(); - } - - loadend(event) { - var xhr = event.currentTarget, - status = xhr.status, - stats = this.stats; - // don't proceed if xhr has been aborted - if (!stats.aborted) { - // http status between 200 to 299 are all successful - if (status >= 200 && status < 300) { - window.clearTimeout(this.timeoutHandle); - stats.tload = Math.max(stats.tfirst,performance.now()); - this.onSuccess(event, stats); - } else { - // error ... - if (stats.retry < this.maxRetry) { - logger.warn(`${status} while loading ${this.url}, retrying in ${this.retryDelay}...`); - this.destroy(); - window.setTimeout(this.loadInternal.bind(this), this.retryDelay); - // exponential backoff - this.retryDelay = Math.min(2 * this.retryDelay, 64000); - stats.retry++; - } else { - window.clearTimeout(this.timeoutHandle); - logger.error(`${status} while loading ${this.url}` ); - this.onError(event); - } - } - } - } - - loadtimeout(event) { - logger.warn(`timeout while loading ${this.url}` ); - this.onTimeout(event, this.stats); - } - - loadprogress(event) { - var stats = this.stats; - if (stats.tfirst === 0) { - stats.tfirst = Math.max(performance.now(), stats.trequest); - } - stats.loaded = event.loaded; - if (this.onProgress) { - this.onProgress(event, stats); - } - } -} - -export default XhrLoader; diff --git a/dashboard-ui/bower_components/howler.js/.bower.json b/dashboard-ui/bower_components/howler.js/.bower.json index b5d0a5d29..dc34ee4c2 100644 --- a/dashboard-ui/bower_components/howler.js/.bower.json +++ b/dashboard-ui/bower_components/howler.js/.bower.json @@ -10,7 +10,7 @@ "tag": "v1.1.29", "commit": "169feb2702632459cb0eb37bf24a20e1d840f78c" }, - "_source": "git://github.com/goldfire/howler.js.git", + "_source": "https://github.com/goldfire/howler.js.git", "_target": "~1.1.27", "_originalSource": "howler" } \ No newline at end of file diff --git a/dashboard-ui/bower_components/howler.js/howler.js b/dashboard-ui/bower_components/howler.js/howler.js deleted file mode 100644 index d3943aa8b..000000000 --- a/dashboard-ui/bower_components/howler.js/howler.js +++ /dev/null @@ -1,1352 +0,0 @@ -/*! - * howler.js v1.1.29 - * howlerjs.com - * - * (c) 2013-2016, James Simpson of GoldFire Studios - * goldfirestudios.com - * - * MIT License - */ - -(function() { - // setup - var cache = {}; - - // setup the audio context - var ctx = null, - usingWebAudio = true, - noAudio = false; - try { - if (typeof AudioContext !== 'undefined') { - ctx = new AudioContext(); - } else if (typeof webkitAudioContext !== 'undefined') { - ctx = new webkitAudioContext(); - } else { - usingWebAudio = false; - } - } catch(e) { - usingWebAudio = false; - } - - if (!usingWebAudio) { - if (typeof Audio !== 'undefined') { - try { - new Audio(); - } catch(e) { - noAudio = true; - } - } else { - noAudio = true; - } - } - - // create a master gain node - if (usingWebAudio) { - var masterGain = (typeof ctx.createGain === 'undefined') ? ctx.createGainNode() : ctx.createGain(); - masterGain.gain.value = 1; - masterGain.connect(ctx.destination); - } - - // create global controller - var HowlerGlobal = function(codecs) { - this._volume = 1; - this._muted = false; - this.usingWebAudio = usingWebAudio; - this.ctx = ctx; - this.noAudio = noAudio; - this._howls = []; - this._codecs = codecs; - this.iOSAutoEnable = true; - }; - HowlerGlobal.prototype = { - /** - * Get/set the global volume for all sounds. - * @param {Float} vol Volume from 0.0 to 1.0. - * @return {Howler/Float} Returns self or current volume. - */ - volume: function(vol) { - var self = this; - - // make sure volume is a number - vol = parseFloat(vol); - - if (vol >= 0 && vol <= 1) { - self._volume = vol; - - if (usingWebAudio) { - masterGain.gain.value = vol; - } - - // loop through cache and change volume of all nodes that are using HTML5 Audio - for (var key in self._howls) { - if (self._howls.hasOwnProperty(key) && self._howls[key]._webAudio === false) { - // loop through the audio nodes - for (var i=0; i 0) ? node._pos : self._sprite[sprite][0] / 1000; - - // determine how long to play for - var duration = 0; - if (self._webAudio) { - duration = self._sprite[sprite][1] / 1000 - node._pos; - if (node._pos > 0) { - pos = self._sprite[sprite][0] / 1000 + pos; - } - } else { - duration = self._sprite[sprite][1] / 1000 - (pos - self._sprite[sprite][0] / 1000); - } - - // determine if this sound should be looped - var loop = !!(self._loop || self._sprite[sprite][2]); - - // set timer to fire the 'onend' event - var soundId = (typeof callback === 'string') ? callback : Math.round(Date.now() * Math.random()) + '', - timerId; - (function() { - var data = { - id: soundId, - sprite: sprite, - loop: loop - }; - timerId = setTimeout(function() { - // if looping, restart the track - if (!self._webAudio && loop) { - self.stop(data.id).play(sprite, data.id); - } - - // set web audio node to paused at end - if (self._webAudio && !loop) { - self._nodeById(data.id).paused = true; - self._nodeById(data.id)._pos = 0; - - // clear the end timer - self._clearEndTimer(data.id); - } - - // end the track if it is HTML audio and a sprite - if (!self._webAudio && !loop) { - self.stop(data.id); - } - - // fire ended event - self.on('end', soundId); - }, (duration / self._rate) * 1000); - - // store the reference to the timer - self._onendTimer.push({timer: timerId, id: data.id}); - })(); - - if (self._webAudio) { - var loopStart = self._sprite[sprite][0] / 1000, - loopEnd = self._sprite[sprite][1] / 1000; - - // set the play id to this node and load into context - node.id = soundId; - node.paused = false; - refreshBuffer(self, [loop, loopStart, loopEnd], soundId); - self._playStart = ctx.currentTime; - node.gain.value = self._volume; - - if (typeof node.bufferSource.start === 'undefined') { - loop ? node.bufferSource.noteGrainOn(0, pos, 86400) : node.bufferSource.noteGrainOn(0, pos, duration); - } else { - loop ? node.bufferSource.start(0, pos, 86400) : node.bufferSource.start(0, pos, duration); - } - } else { - if (node.readyState === 4 || !node.readyState && navigator.isCocoonJS) { - node.readyState = 4; - node.id = soundId; - node.currentTime = pos; - node.muted = Howler._muted || node.muted; - node.volume = self._volume * Howler.volume(); - setTimeout(function() { node.play(); }, 0); - } else { - self._clearEndTimer(soundId); - - (function(){ - var sound = self, - playSprite = sprite, - fn = callback, - newNode = node; - var listener = function() { - sound.play(playSprite, fn); - - // clear the event listener - newNode.removeEventListener('canplaythrough', listener, false); - }; - newNode.addEventListener('canplaythrough', listener, false); - })(); - - return self; - } - } - - // fire the play event and send the soundId back in the callback - self.on('play'); - if (typeof callback === 'function') callback(soundId); - - return self; - }); - - return self; - }, - - /** - * Pause playback and save the current position. - * @param {String} id (optional) The play instance ID. - * @return {Howl} - */ - pause: function(id) { - var self = this; - - // if the sound hasn't been loaded, add it to the event queue - if (!self._loaded) { - self.on('play', function() { - self.pause(id); - }); - - return self; - } - - // clear 'onend' timer - self._clearEndTimer(id); - - var activeNode = (id) ? self._nodeById(id) : self._activeNode(); - if (activeNode) { - activeNode._pos = self.pos(null, id); - - if (self._webAudio) { - // make sure the sound has been created - if (!activeNode.bufferSource || activeNode.paused) { - return self; - } - - activeNode.paused = true; - if (typeof activeNode.bufferSource.stop === 'undefined') { - activeNode.bufferSource.noteOff(0); - } else { - activeNode.bufferSource.stop(0); - } - } else { - activeNode.pause(); - } - } - - self.on('pause'); - - return self; - }, - - /** - * Stop playback and reset to start. - * @param {String} id (optional) The play instance ID. - * @return {Howl} - */ - stop: function(id) { - var self = this; - - // if the sound hasn't been loaded, add it to the event queue - if (!self._loaded) { - self.on('play', function() { - self.stop(id); - }); - - return self; - } - - // clear 'onend' timer - self._clearEndTimer(id); - - var activeNode = (id) ? self._nodeById(id) : self._activeNode(); - if (activeNode) { - activeNode._pos = 0; - - if (self._webAudio) { - // make sure the sound has been created - if (!activeNode.bufferSource || activeNode.paused) { - return self; - } - - activeNode.paused = true; - - if (typeof activeNode.bufferSource.stop === 'undefined') { - activeNode.bufferSource.noteOff(0); - } else { - activeNode.bufferSource.stop(0); - } - } else if (!isNaN(activeNode.duration)) { - activeNode.pause(); - activeNode.currentTime = 0; - } - } - - return self; - }, - - /** - * Mute this sound. - * @param {String} id (optional) The play instance ID. - * @return {Howl} - */ - mute: function(id) { - var self = this; - - // if the sound hasn't been loaded, add it to the event queue - if (!self._loaded) { - self.on('play', function() { - self.mute(id); - }); - - return self; - } - - var activeNode = (id) ? self._nodeById(id) : self._activeNode(); - if (activeNode) { - if (self._webAudio) { - activeNode.gain.value = 0; - } else { - activeNode.muted = true; - } - } - - return self; - }, - - /** - * Unmute this sound. - * @param {String} id (optional) The play instance ID. - * @return {Howl} - */ - unmute: function(id) { - var self = this; - - // if the sound hasn't been loaded, add it to the event queue - if (!self._loaded) { - self.on('play', function() { - self.unmute(id); - }); - - return self; - } - - var activeNode = (id) ? self._nodeById(id) : self._activeNode(); - if (activeNode) { - if (self._webAudio) { - activeNode.gain.value = self._volume; - } else { - activeNode.muted = false; - } - } - - return self; - }, - - /** - * Get/set volume of this sound. - * @param {Float} vol Volume from 0.0 to 1.0. - * @param {String} id (optional) The play instance ID. - * @return {Howl/Float} Returns self or current volume. - */ - volume: function(vol, id) { - var self = this; - - // make sure volume is a number - vol = parseFloat(vol); - - if (vol >= 0 && vol <= 1) { - self._volume = vol; - - // if the sound hasn't been loaded, add it to the event queue - if (!self._loaded) { - self.on('play', function() { - self.volume(vol, id); - }); - - return self; - } - - var activeNode = (id) ? self._nodeById(id) : self._activeNode(); - if (activeNode) { - if (self._webAudio) { - activeNode.gain.value = vol; - } else { - activeNode.volume = vol * Howler.volume(); - } - } - - return self; - } else { - return self._volume; - } - }, - - /** - * Get/set whether to loop the sound. - * @param {Boolean} loop To loop or not to loop, that is the question. - * @return {Howl/Boolean} Returns self or current looping value. - */ - loop: function(loop) { - var self = this; - - if (typeof loop === 'boolean') { - self._loop = loop; - - return self; - } else { - return self._loop; - } - }, - - /** - * Get/set sound sprite definition. - * @param {Object} sprite Example: {spriteName: [offset, duration, loop]} - * @param {Integer} offset Where to begin playback in milliseconds - * @param {Integer} duration How long to play in milliseconds - * @param {Boolean} loop (optional) Set true to loop this sprite - * @return {Howl} Returns current sprite sheet or self. - */ - sprite: function(sprite) { - var self = this; - - if (typeof sprite === 'object') { - self._sprite = sprite; - - return self; - } else { - return self._sprite; - } - }, - - /** - * Get/set the position of playback. - * @param {Float} pos The position to move current playback to. - * @param {String} id (optional) The play instance ID. - * @return {Howl/Float} Returns self or current playback position. - */ - pos: function(pos, id) { - var self = this; - - // if the sound hasn't been loaded, add it to the event queue - if (!self._loaded) { - self.on('load', function() { - self.pos(pos); - }); - - return typeof pos === 'number' ? self : self._pos || 0; - } - - // make sure we are dealing with a number for pos - pos = parseFloat(pos); - - var activeNode = (id) ? self._nodeById(id) : self._activeNode(); - if (activeNode) { - if (pos >= 0) { - self.pause(id); - activeNode._pos = pos; - self.play(activeNode._sprite, id); - - return self; - } else { - return self._webAudio ? activeNode._pos + (ctx.currentTime - self._playStart) : activeNode.currentTime; - } - } else if (pos >= 0) { - return self; - } else { - // find the first inactive node to return the pos for - for (var i=0; i= 0 || x < 0) { - if (self._webAudio) { - var activeNode = (id) ? self._nodeById(id) : self._activeNode(); - if (activeNode) { - self._pos3d = [x, y, z]; - activeNode.panner.setPosition(x, y, z); - activeNode.panner.panningModel = self._model || 'HRTF'; - } - } - } else { - return self._pos3d; - } - - return self; - }, - - /** - * Fade a currently playing sound between two volumes. - * @param {Number} from The volume to fade from (0.0 to 1.0). - * @param {Number} to The volume to fade to (0.0 to 1.0). - * @param {Number} len Time in milliseconds to fade. - * @param {Function} callback (optional) Fired when the fade is complete. - * @param {String} id (optional) The play instance ID. - * @return {Howl} - */ - fade: function(from, to, len, callback, id) { - var self = this, - diff = Math.abs(from - to), - dir = from > to ? 'down' : 'up', - steps = diff / 0.01, - stepTime = len / steps; - - // if the sound hasn't been loaded, add it to the event queue - if (!self._loaded) { - self.on('load', function() { - self.fade(from, to, len, callback, id); - }); - - return self; - } - - // set the volume to the start position - self.volume(from, id); - - for (var i=1; i<=steps; i++) { - (function() { - var change = self._volume + (dir === 'up' ? 0.01 : -0.01) * i, - vol = Math.round(1000 * change) / 1000, - toVol = to; - - setTimeout(function() { - self.volume(vol, id); - - if (vol === toVol) { - if (callback) callback(); - } - }, stepTime * i); - })(); - } - }, - - /** - * [DEPRECATED] Fade in the current sound. - * @param {Float} to Volume to fade to (0.0 to 1.0). - * @param {Number} len Time in milliseconds to fade. - * @param {Function} callback - * @return {Howl} - */ - fadeIn: function(to, len, callback) { - return this.volume(0).play().fade(0, to, len, callback); - }, - - /** - * [DEPRECATED] Fade out the current sound and pause when finished. - * @param {Float} to Volume to fade to (0.0 to 1.0). - * @param {Number} len Time in milliseconds to fade. - * @param {Function} callback - * @param {String} id (optional) The play instance ID. - * @return {Howl} - */ - fadeOut: function(to, len, callback, id) { - var self = this; - - return self.fade(self._volume, to, len, function() { - if (callback) callback(); - self.pause(id); - - // fire ended event - self.on('end'); - }, id); - }, - - /** - * Get an audio node by ID. - * @return {Howl} Audio node. - */ - _nodeById: function(id) { - var self = this, - node = self._audioNode[0]; - - // find the node with this ID - for (var i=0; i=0; i--) { - if (inactive <= 5) { - break; - } - - if (self._audioNode[i].paused) { - // disconnect the audio source if using Web Audio - if (self._webAudio) { - self._audioNode[i].disconnect(0); - } - - inactive--; - self._audioNode.splice(i, 1); - } - } - }, - - /** - * Clear 'onend' timeout before it ends. - * @param {String} soundId The play instance ID. - */ - _clearEndTimer: function(soundId) { - var self = this, - index = -1; - - // loop through the timers to find the one associated with this sound - for (var i=0; i= 0) { - Howler._howls.splice(index, 1); - } - - // delete this sound from the cache - delete cache[self._src]; - self = null; - } - - }; - - // only define these functions when using WebAudio - if (usingWebAudio) { - - /** - * Buffer a sound from URL (or from cache) and decode to audio source (Web Audio API). - * @param {Object} obj The Howl object for the sound to load. - * @param {String} url The path to the sound file. - */ - var loadBuffer = function(obj, url) { - // check if the buffer has already been cached - if (url in cache) { - // set the duration from the cache - obj._duration = cache[url].duration; - - // load the sound into this object - loadSound(obj); - return; - } - - if (/^data:[^;]+;base64,/.test(url)) { - // Decode base64 data-URIs because some browsers cannot load data-URIs with XMLHttpRequest. - var data = atob(url.split(',')[1]); - var dataView = new Uint8Array(data.length); - for (var i=0; i

>>0?1:0);T=m.low=T+J;m.high=fa+W+(T>>>0>>0?1: -0);U=N.low=U+K;N.high=ga+X+(U>>>0>>0?1:0);V=c.low=V+L;c.high=ha+Z+(V>>>0>>0?1:0)},_doFinalize:function(){var a=this._data,b=a.words,c=8*this._nDataBytes,f=8*a.sigBytes;b[f>>>5]|=128<<24-f%32;b[(f+128>>>10<<5)+30]=Math.floor(c/4294967296);b[(f+128>>>10<<5)+31]=c;a.sigBytes=4*b.length;this._process();return this._hash.toX32()},clone:function(){var a=c.clone.call(this);a._hash=this._hash.clone();return a},blockSize:32});j.SHA512=c._createHelper(b);j.HmacSHA512=c._createHmacHelper(b)})(); -(function(){var a=CryptoJS,j=a.enc.Utf8;a.algo.HMAC=a.lib.Base.extend({init:function(a,b){a=this._hasher=new a.init;"string"==typeof b&&(b=j.parse(b));var f=a.blockSize,l=4*f;b.sigBytes>l&&(b=a.finalize(b));b.clamp();for(var u=this._oKey=b.clone(),k=this._iKey=b.clone(),m=u.words,y=k.words,z=0;z>>2]|=(a[g>>>2]>>>24-8*(g%4)&255)<<24-8*((j+g)%4);else if(65535>>2]=a[g>>>2];else h.push.apply(h,a);this.sigBytes+=b;return this},clamp:function(){var b=this.words,h=this.sigBytes;b[h>>>2]&=4294967295<< -32-8*(h%4);b.length=s.ceil(h/4)},clone:function(){var b=r.clone.call(this);b.words=this.words.slice(0);return b},random:function(b){for(var h=[],a=0;a>>2]>>>24-8*(j%4)&255;g.push((k>>>4).toString(16));g.push((k&15).toString(16))}return g.join("")},parse:function(b){for(var a=b.length,g=[],j=0;j>>3]|=parseInt(b.substr(j, -2),16)<<24-4*(j%8);return new q.init(g,a/2)}},a=v.Latin1={stringify:function(b){var a=b.words;b=b.sigBytes;for(var g=[],j=0;j>>2]>>>24-8*(j%4)&255));return g.join("")},parse:function(b){for(var a=b.length,g=[],j=0;j>>2]|=(b.charCodeAt(j)&255)<<24-8*(j%4);return new q.init(g,a)}},u=v.Utf8={stringify:function(b){try{return decodeURIComponent(escape(a.stringify(b)))}catch(g){throw Error("Malformed UTF-8 data");}},parse:function(b){return a.parse(unescape(encodeURIComponent(b)))}}, -g=l.BufferedBlockAlgorithm=r.extend({reset:function(){this._data=new q.init;this._nDataBytes=0},_append:function(b){"string"==typeof b&&(b=u.parse(b));this._data.concat(b);this._nDataBytes+=b.sigBytes},_process:function(b){var a=this._data,g=a.words,j=a.sigBytes,k=this.blockSize,m=j/(4*k),m=b?s.ceil(m):s.max((m|0)-this._minBufferSize,0);b=m*k;j=s.min(4*b,j);if(b){for(var l=0;l>>32-j)+k}function m(a,k,b,h,l,j,m){a=a+(k&h|b&~h)+l+m;return(a<>>32-j)+k}function l(a,k,b,h,l,j,m){a=a+(k^b^h)+l+m;return(a<>>32-j)+k}function n(a,k,b,h,l,j,m){a=a+(b^(k|~h))+l+m;return(a<>>32-j)+k}for(var r=CryptoJS,q=r.lib,v=q.WordArray,t=q.Hasher,q=r.algo,a=[],u=0;64>u;u++)a[u]=4294967296*s.abs(s.sin(u+1))|0;q=q.MD5=t.extend({_doReset:function(){this._hash=new v.init([1732584193,4023233417,2562383102,271733878])}, -_doProcessBlock:function(g,k){for(var b=0;16>b;b++){var h=k+b,w=g[h];g[h]=(w<<8|w>>>24)&16711935|(w<<24|w>>>8)&4278255360}var b=this._hash.words,h=g[k+0],w=g[k+1],j=g[k+2],q=g[k+3],r=g[k+4],s=g[k+5],t=g[k+6],u=g[k+7],v=g[k+8],x=g[k+9],y=g[k+10],z=g[k+11],A=g[k+12],B=g[k+13],C=g[k+14],D=g[k+15],c=b[0],d=b[1],e=b[2],f=b[3],c=p(c,d,e,f,h,7,a[0]),f=p(f,c,d,e,w,12,a[1]),e=p(e,f,c,d,j,17,a[2]),d=p(d,e,f,c,q,22,a[3]),c=p(c,d,e,f,r,7,a[4]),f=p(f,c,d,e,s,12,a[5]),e=p(e,f,c,d,t,17,a[6]),d=p(d,e,f,c,u,22,a[7]), -c=p(c,d,e,f,v,7,a[8]),f=p(f,c,d,e,x,12,a[9]),e=p(e,f,c,d,y,17,a[10]),d=p(d,e,f,c,z,22,a[11]),c=p(c,d,e,f,A,7,a[12]),f=p(f,c,d,e,B,12,a[13]),e=p(e,f,c,d,C,17,a[14]),d=p(d,e,f,c,D,22,a[15]),c=m(c,d,e,f,w,5,a[16]),f=m(f,c,d,e,t,9,a[17]),e=m(e,f,c,d,z,14,a[18]),d=m(d,e,f,c,h,20,a[19]),c=m(c,d,e,f,s,5,a[20]),f=m(f,c,d,e,y,9,a[21]),e=m(e,f,c,d,D,14,a[22]),d=m(d,e,f,c,r,20,a[23]),c=m(c,d,e,f,x,5,a[24]),f=m(f,c,d,e,C,9,a[25]),e=m(e,f,c,d,q,14,a[26]),d=m(d,e,f,c,v,20,a[27]),c=m(c,d,e,f,B,5,a[28]),f=m(f,c, -d,e,j,9,a[29]),e=m(e,f,c,d,u,14,a[30]),d=m(d,e,f,c,A,20,a[31]),c=l(c,d,e,f,s,4,a[32]),f=l(f,c,d,e,v,11,a[33]),e=l(e,f,c,d,z,16,a[34]),d=l(d,e,f,c,C,23,a[35]),c=l(c,d,e,f,w,4,a[36]),f=l(f,c,d,e,r,11,a[37]),e=l(e,f,c,d,u,16,a[38]),d=l(d,e,f,c,y,23,a[39]),c=l(c,d,e,f,B,4,a[40]),f=l(f,c,d,e,h,11,a[41]),e=l(e,f,c,d,q,16,a[42]),d=l(d,e,f,c,t,23,a[43]),c=l(c,d,e,f,x,4,a[44]),f=l(f,c,d,e,A,11,a[45]),e=l(e,f,c,d,D,16,a[46]),d=l(d,e,f,c,j,23,a[47]),c=n(c,d,e,f,h,6,a[48]),f=n(f,c,d,e,u,10,a[49]),e=n(e,f,c,d, -C,15,a[50]),d=n(d,e,f,c,s,21,a[51]),c=n(c,d,e,f,A,6,a[52]),f=n(f,c,d,e,q,10,a[53]),e=n(e,f,c,d,y,15,a[54]),d=n(d,e,f,c,w,21,a[55]),c=n(c,d,e,f,v,6,a[56]),f=n(f,c,d,e,D,10,a[57]),e=n(e,f,c,d,t,15,a[58]),d=n(d,e,f,c,B,21,a[59]),c=n(c,d,e,f,r,6,a[60]),f=n(f,c,d,e,z,10,a[61]),e=n(e,f,c,d,j,15,a[62]),d=n(d,e,f,c,x,21,a[63]);b[0]=b[0]+c|0;b[1]=b[1]+d|0;b[2]=b[2]+e|0;b[3]=b[3]+f|0},_doFinalize:function(){var a=this._data,k=a.words,b=8*this._nDataBytes,h=8*a.sigBytes;k[h>>>5]|=128<<24-h%32;var l=s.floor(b/ -4294967296);k[(h+64>>>9<<4)+15]=(l<<8|l>>>24)&16711935|(l<<24|l>>>8)&4278255360;k[(h+64>>>9<<4)+14]=(b<<8|b>>>24)&16711935|(b<<24|b>>>8)&4278255360;a.sigBytes=4*(k.length+1);this._process();a=this._hash;k=a.words;for(b=0;4>b;b++)h=k[b],k[b]=(h<<8|h>>>24)&16711935|(h<<24|h>>>8)&4278255360;return a},clone:function(){var a=t.clone.call(this);a._hash=this._hash.clone();return a}});r.MD5=t._createHelper(q);r.HmacMD5=t._createHmacHelper(q)})(Math); diff --git a/dashboard-ui/bower_components/cryptojslib/rollups/pbkdf2.js b/dashboard-ui/bower_components/cryptojslib/rollups/pbkdf2.js deleted file mode 100644 index fdc7b4fe9..000000000 --- a/dashboard-ui/bower_components/cryptojslib/rollups/pbkdf2.js +++ /dev/null @@ -1,19 +0,0 @@ -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -var CryptoJS=CryptoJS||function(g,j){var e={},d=e.lib={},m=function(){},n=d.Base={extend:function(a){m.prototype=this;var c=new m;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, -q=d.WordArray=n.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=j?c:4*a.length},toString:function(a){return(a||l).stringify(this)},concat:function(a){var c=this.words,p=a.words,f=this.sigBytes;a=a.sigBytes;this.clamp();if(f%4)for(var b=0;b>>2]|=(p[b>>>2]>>>24-8*(b%4)&255)<<24-8*((f+b)%4);else if(65535>>2]=p[b>>>2];else c.push.apply(c,p);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< -32-8*(c%4);a.length=g.ceil(c/4)},clone:function(){var a=n.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],b=0;b>>2]>>>24-8*(f%4)&255;b.push((d>>>4).toString(16));b.push((d&15).toString(16))}return b.join("")},parse:function(a){for(var c=a.length,b=[],f=0;f>>3]|=parseInt(a.substr(f, -2),16)<<24-4*(f%8);return new q.init(b,c/2)}},k=b.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],f=0;f>>2]>>>24-8*(f%4)&255));return b.join("")},parse:function(a){for(var c=a.length,b=[],f=0;f>>2]|=(a.charCodeAt(f)&255)<<24-8*(f%4);return new q.init(b,c)}},h=b.Utf8={stringify:function(a){try{return decodeURIComponent(escape(k.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return k.parse(unescape(encodeURIComponent(a)))}}, -u=d.BufferedBlockAlgorithm=n.extend({reset:function(){this._data=new q.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=h.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var b=this._data,d=b.words,f=b.sigBytes,l=this.blockSize,e=f/(4*l),e=a?g.ceil(e):g.max((e|0)-this._minBufferSize,0);a=e*l;f=g.min(4*a,f);if(a){for(var h=0;ha;a++){if(16>a)m[a]=d[e+a]|0;else{var c=m[a-3]^m[a-8]^m[a-14]^m[a-16];m[a]=c<<1|c>>>31}c=(l<<5|l>>>27)+j+m[a];c=20>a?c+((k&h|~k&g)+1518500249):40>a?c+((k^h^g)+1859775393):60>a?c+((k&h|k&g|h&g)-1894007588):c+((k^h^ -g)-899497514);j=g;g=h;h=k<<30|k>>>2;k=l;l=c}b[0]=b[0]+l|0;b[1]=b[1]+k|0;b[2]=b[2]+h|0;b[3]=b[3]+g|0;b[4]=b[4]+j|0},_doFinalize:function(){var d=this._data,e=d.words,b=8*this._nDataBytes,l=8*d.sigBytes;e[l>>>5]|=128<<24-l%32;e[(l+64>>>9<<4)+14]=Math.floor(b/4294967296);e[(l+64>>>9<<4)+15]=b;d.sigBytes=4*e.length;this._process();return this._hash},clone:function(){var e=d.clone.call(this);e._hash=this._hash.clone();return e}});g.SHA1=d._createHelper(j);g.HmacSHA1=d._createHmacHelper(j)})(); -(function(){var g=CryptoJS,j=g.enc.Utf8;g.algo.HMAC=g.lib.Base.extend({init:function(e,d){e=this._hasher=new e.init;"string"==typeof d&&(d=j.parse(d));var g=e.blockSize,n=4*g;d.sigBytes>n&&(d=e.finalize(d));d.clamp();for(var q=this._oKey=d.clone(),b=this._iKey=d.clone(),l=q.words,k=b.words,h=0;h>>2]|=(m[r>>>2]>>>24-8*(r%4)&255)<<24-8*((n+r)%4);else if(65535>>2]=m[r>>>2];else b.push.apply(b,m);this.sigBytes+=a;return this},clamp:function(){var a=this.words,b=this.sigBytes;a[b>>>2]&=4294967295<< -32-8*(b%4);a.length=q.ceil(b/4)},clone:function(){var a=c.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var b=[],m=0;m>>2]>>>24-8*(n%4)&255;m.push((r>>>4).toString(16));m.push((r&15).toString(16))}return m.join("")},parse:function(a){for(var b=a.length,m=[],n=0;n>>3]|=parseInt(a.substr(n, -2),16)<<24-4*(n%8);return new s.init(m,b/2)}},a=b.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var m=[],n=0;n>>2]>>>24-8*(n%4)&255));return m.join("")},parse:function(a){for(var b=a.length,m=[],n=0;n>>2]|=(a.charCodeAt(n)&255)<<24-8*(n%4);return new s.init(m,b)}},t=b.Utf8={stringify:function(b){try{return decodeURIComponent(escape(a.stringify(b)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(b){return a.parse(unescape(encodeURIComponent(b)))}}, -u=l.BufferedBlockAlgorithm=c.extend({reset:function(){this._data=new s.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=t.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var b=this._data,m=b.words,n=b.sigBytes,r=this.blockSize,c=n/(4*r),c=a?q.ceil(c):q.max((c|0)-this._minBufferSize,0);a=c*r;n=q.min(4*a,n);if(a){for(var u=0;u>>2]>>>24-8*(k%4)&255)<<16|(l[k+1>>>2]>>>24-8*((k+1)%4)&255)<<8|l[k+2>>>2]>>>24-8*((k+2)%4)&255,d=0;4>d&&k+0.75*d>>6*(3-d)&63));if(l=c.charAt(64))for(;e.length%4;)e.push(l);return e.join("")},parse:function(e){var l=e.length,p=this._map,c=p.charAt(64);c&&(c=e.indexOf(c),-1!=c&&(l=c));for(var c=[],s=0,b=0;b< -l;b++)if(b%4){var d=p.indexOf(e.charAt(b-1))<<2*(b%4),a=p.indexOf(e.charAt(b))>>>6-2*(b%4);c[s>>>2]|=(d|a)<<24-8*(s%4);s++}return k.create(c,s)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})(); -(function(q){function k(a,b,c,d,m,n,r){a=a+(b&c|~b&d)+m+r;return(a<>>32-n)+b}function e(a,b,c,d,m,n,r){a=a+(b&d|c&~d)+m+r;return(a<>>32-n)+b}function l(a,b,c,d,m,n,r){a=a+(b^c^d)+m+r;return(a<>>32-n)+b}function p(a,b,c,d,m,n,r){a=a+(c^(b|~d))+m+r;return(a<>>32-n)+b}for(var c=CryptoJS,s=c.lib,b=s.WordArray,d=s.Hasher,s=c.algo,a=[],t=0;64>t;t++)a[t]=4294967296*q.abs(q.sin(t+1))|0;s=s.MD5=d.extend({_doReset:function(){this._hash=new b.init([1732584193,4023233417,2562383102,271733878])}, -_doProcessBlock:function(b,c){for(var d=0;16>d;d++){var t=c+d,m=b[t];b[t]=(m<<8|m>>>24)&16711935|(m<<24|m>>>8)&4278255360}var d=this._hash.words,t=b[c+0],m=b[c+1],n=b[c+2],r=b[c+3],x=b[c+4],s=b[c+5],q=b[c+6],y=b[c+7],z=b[c+8],A=b[c+9],B=b[c+10],C=b[c+11],D=b[c+12],E=b[c+13],F=b[c+14],G=b[c+15],f=d[0],g=d[1],h=d[2],j=d[3],f=k(f,g,h,j,t,7,a[0]),j=k(j,f,g,h,m,12,a[1]),h=k(h,j,f,g,n,17,a[2]),g=k(g,h,j,f,r,22,a[3]),f=k(f,g,h,j,x,7,a[4]),j=k(j,f,g,h,s,12,a[5]),h=k(h,j,f,g,q,17,a[6]),g=k(g,h,j,f,y,22,a[7]), -f=k(f,g,h,j,z,7,a[8]),j=k(j,f,g,h,A,12,a[9]),h=k(h,j,f,g,B,17,a[10]),g=k(g,h,j,f,C,22,a[11]),f=k(f,g,h,j,D,7,a[12]),j=k(j,f,g,h,E,12,a[13]),h=k(h,j,f,g,F,17,a[14]),g=k(g,h,j,f,G,22,a[15]),f=e(f,g,h,j,m,5,a[16]),j=e(j,f,g,h,q,9,a[17]),h=e(h,j,f,g,C,14,a[18]),g=e(g,h,j,f,t,20,a[19]),f=e(f,g,h,j,s,5,a[20]),j=e(j,f,g,h,B,9,a[21]),h=e(h,j,f,g,G,14,a[22]),g=e(g,h,j,f,x,20,a[23]),f=e(f,g,h,j,A,5,a[24]),j=e(j,f,g,h,F,9,a[25]),h=e(h,j,f,g,r,14,a[26]),g=e(g,h,j,f,z,20,a[27]),f=e(f,g,h,j,E,5,a[28]),j=e(j,f, -g,h,n,9,a[29]),h=e(h,j,f,g,y,14,a[30]),g=e(g,h,j,f,D,20,a[31]),f=l(f,g,h,j,s,4,a[32]),j=l(j,f,g,h,z,11,a[33]),h=l(h,j,f,g,C,16,a[34]),g=l(g,h,j,f,F,23,a[35]),f=l(f,g,h,j,m,4,a[36]),j=l(j,f,g,h,x,11,a[37]),h=l(h,j,f,g,y,16,a[38]),g=l(g,h,j,f,B,23,a[39]),f=l(f,g,h,j,E,4,a[40]),j=l(j,f,g,h,t,11,a[41]),h=l(h,j,f,g,r,16,a[42]),g=l(g,h,j,f,q,23,a[43]),f=l(f,g,h,j,A,4,a[44]),j=l(j,f,g,h,D,11,a[45]),h=l(h,j,f,g,G,16,a[46]),g=l(g,h,j,f,n,23,a[47]),f=p(f,g,h,j,t,6,a[48]),j=p(j,f,g,h,y,10,a[49]),h=p(h,j,f,g, -F,15,a[50]),g=p(g,h,j,f,s,21,a[51]),f=p(f,g,h,j,D,6,a[52]),j=p(j,f,g,h,r,10,a[53]),h=p(h,j,f,g,B,15,a[54]),g=p(g,h,j,f,m,21,a[55]),f=p(f,g,h,j,z,6,a[56]),j=p(j,f,g,h,G,10,a[57]),h=p(h,j,f,g,q,15,a[58]),g=p(g,h,j,f,E,21,a[59]),f=p(f,g,h,j,x,6,a[60]),j=p(j,f,g,h,C,10,a[61]),h=p(h,j,f,g,n,15,a[62]),g=p(g,h,j,f,A,21,a[63]);d[0]=d[0]+f|0;d[1]=d[1]+g|0;d[2]=d[2]+h|0;d[3]=d[3]+j|0},_doFinalize:function(){var a=this._data,b=a.words,c=8*this._nDataBytes,d=8*a.sigBytes;b[d>>>5]|=128<<24-d%32;var m=q.floor(c/ -4294967296);b[(d+64>>>9<<4)+15]=(m<<8|m>>>24)&16711935|(m<<24|m>>>8)&4278255360;b[(d+64>>>9<<4)+14]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;a.sigBytes=4*(b.length+1);this._process();a=this._hash;b=a.words;for(c=0;4>c;c++)d=b[c],b[c]=(d<<8|d>>>24)&16711935|(d<<24|d>>>8)&4278255360;return a},clone:function(){var a=d.clone.call(this);a._hash=this._hash.clone();return a}});c.MD5=d._createHelper(s);c.HmacMD5=d._createHmacHelper(s)})(Math); -(function(){var q=CryptoJS,k=q.lib,e=k.Base,l=k.WordArray,k=q.algo,p=k.EvpKDF=e.extend({cfg:e.extend({keySize:4,hasher:k.MD5,iterations:1}),init:function(c){this.cfg=this.cfg.extend(c)},compute:function(c,e){for(var b=this.cfg,d=b.hasher.create(),a=l.create(),k=a.words,p=b.keySize,b=b.iterations;k.length>>2]&255}};e.BlockCipher=d.extend({cfg:d.cfg.extend({mode:a,padding:u}),reset:function(){d.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a, -this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var w=e.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),a=(k.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?p.create([1398893684, -1701076831]).concat(a).concat(b):b).toString(s)},parse:function(a){a=s.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=p.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return w.create({ciphertext:a,salt:c})}},v=e.SerializableCipher=l.extend({cfg:l.extend({format:a}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var e=a.createEncryptor(c,d);b=e.finalize(b);e=e.cfg;return w.create({ciphertext:b,key:c,iv:e.iv,algorithm:a,mode:e.mode,padding:e.padding,blockSize:a.blockSize,formatter:d.format})}, -decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),k=(k.kdf={}).OpenSSL={execute:function(a,c,d,e){e||(e=p.random(8));a=b.create({keySize:c+d}).compute(a,e);d=p.create(a.words.slice(c),4*d);a.sigBytes=4*c;return w.create({key:a,iv:d,salt:e})}},H=e.PasswordBasedCipher=v.extend({cfg:v.cfg.extend({kdf:k}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);c=d.kdf.execute(c, -a.keySize,a.ivSize);d.iv=c.iv;a=v.encrypt.call(this,a,b,c.key,d);a.mixIn(c);return a},decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);c=d.kdf.execute(c,a.keySize,a.ivSize,b.salt);d.iv=c.iv;return v.decrypt.call(this,a,b,c.key,d)}})}(); -(function(){function q(){for(var b=this._X,d=this._C,a=0;8>a;a++)p[a]=d[a];d[0]=d[0]+1295307597+this._b|0;d[1]=d[1]+3545052371+(d[0]>>>0>>0?1:0)|0;d[2]=d[2]+886263092+(d[1]>>>0>>0?1:0)|0;d[3]=d[3]+1295307597+(d[2]>>>0>>0?1:0)|0;d[4]=d[4]+3545052371+(d[3]>>>0>>0?1:0)|0;d[5]=d[5]+886263092+(d[4]>>>0>>0?1:0)|0;d[6]=d[6]+1295307597+(d[5]>>>0>>0?1:0)|0;d[7]=d[7]+3545052371+(d[6]>>>0>>0?1:0)|0;this._b=d[7]>>>0>>0?1:0;for(a=0;8>a;a++){var e=b[a]+d[a],k=e&65535, -l=e>>>16;c[a]=((k*k>>>17)+k*l>>>15)+l*l^((e&4294901760)*e|0)+((e&65535)*e|0)}b[0]=c[0]+(c[7]<<16|c[7]>>>16)+(c[6]<<16|c[6]>>>16)|0;b[1]=c[1]+(c[0]<<8|c[0]>>>24)+c[7]|0;b[2]=c[2]+(c[1]<<16|c[1]>>>16)+(c[0]<<16|c[0]>>>16)|0;b[3]=c[3]+(c[2]<<8|c[2]>>>24)+c[1]|0;b[4]=c[4]+(c[3]<<16|c[3]>>>16)+(c[2]<<16|c[2]>>>16)|0;b[5]=c[5]+(c[4]<<8|c[4]>>>24)+c[3]|0;b[6]=c[6]+(c[5]<<16|c[5]>>>16)+(c[4]<<16|c[4]>>>16)|0;b[7]=c[7]+(c[6]<<8|c[6]>>>24)+c[5]|0}var k=CryptoJS,e=k.lib.StreamCipher,l=[],p=[],c=[],s=k.algo.RabbitLegacy= -e.extend({_doReset:function(){for(var b=this._key.words,c=this.cfg.iv,a=this._X=[b[0],b[3]<<16|b[2]>>>16,b[1],b[0]<<16|b[3]>>>16,b[2],b[1]<<16|b[0]>>>16,b[3],b[2]<<16|b[1]>>>16],b=this._C=[b[2]<<16|b[2]>>>16,b[0]&4294901760|b[1]&65535,b[3]<<16|b[3]>>>16,b[1]&4294901760|b[2]&65535,b[0]<<16|b[0]>>>16,b[2]&4294901760|b[3]&65535,b[1]<<16|b[1]>>>16,b[3]&4294901760|b[0]&65535],e=this._b=0;4>e;e++)q.call(this);for(e=0;8>e;e++)b[e]^=a[e+4&7];if(c){var a=c.words,c=a[0],a=a[1],c=(c<<8|c>>>24)&16711935|(c<< -24|c>>>8)&4278255360,a=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360,e=c>>>16|a&4294901760,k=a<<16|c&65535;b[0]^=c;b[1]^=e;b[2]^=a;b[3]^=k;b[4]^=c;b[5]^=e;b[6]^=a;b[7]^=k;for(e=0;4>e;e++)q.call(this)}},_doProcessBlock:function(b,c){var a=this._X;q.call(this);l[0]=a[0]^a[5]>>>16^a[3]<<16;l[1]=a[2]^a[7]>>>16^a[5]<<16;l[2]=a[4]^a[1]>>>16^a[7]<<16;l[3]=a[6]^a[3]>>>16^a[1]<<16;for(a=0;4>a;a++)l[a]=(l[a]<<8|l[a]>>>24)&16711935|(l[a]<<24|l[a]>>>8)&4278255360,b[c+a]^=l[a]},blockSize:4,ivSize:2});k.RabbitLegacy= -e._createHelper(s)})(); diff --git a/dashboard-ui/bower_components/cryptojslib/rollups/rabbit.js b/dashboard-ui/bower_components/cryptojslib/rollups/rabbit.js deleted file mode 100644 index 5ea717ed4..000000000 --- a/dashboard-ui/bower_components/cryptojslib/rollups/rabbit.js +++ /dev/null @@ -1,36 +0,0 @@ -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -var CryptoJS=CryptoJS||function(q,k){var e={},l=e.lib={},p=function(){},c=l.Base={extend:function(a){p.prototype=this;var b=new p;a&&b.mixIn(a);b.hasOwnProperty("init")||(b.init=function(){b.$super.init.apply(this,arguments)});b.init.prototype=b;b.$super=this;return b},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, -s=l.WordArray=c.extend({init:function(a,b){a=this.words=a||[];this.sigBytes=b!=k?b:4*a.length},toString:function(a){return(a||d).stringify(this)},concat:function(a){var b=this.words,m=a.words,n=this.sigBytes;a=a.sigBytes;this.clamp();if(n%4)for(var r=0;r>>2]|=(m[r>>>2]>>>24-8*(r%4)&255)<<24-8*((n+r)%4);else if(65535>>2]=m[r>>>2];else b.push.apply(b,m);this.sigBytes+=a;return this},clamp:function(){var a=this.words,b=this.sigBytes;a[b>>>2]&=4294967295<< -32-8*(b%4);a.length=q.ceil(b/4)},clone:function(){var a=c.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var b=[],m=0;m>>2]>>>24-8*(n%4)&255;m.push((r>>>4).toString(16));m.push((r&15).toString(16))}return m.join("")},parse:function(a){for(var b=a.length,m=[],n=0;n>>3]|=parseInt(a.substr(n, -2),16)<<24-4*(n%8);return new s.init(m,b/2)}},a=b.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var m=[],n=0;n>>2]>>>24-8*(n%4)&255));return m.join("")},parse:function(a){for(var b=a.length,m=[],n=0;n>>2]|=(a.charCodeAt(n)&255)<<24-8*(n%4);return new s.init(m,b)}},u=b.Utf8={stringify:function(b){try{return decodeURIComponent(escape(a.stringify(b)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(b){return a.parse(unescape(encodeURIComponent(b)))}}, -t=l.BufferedBlockAlgorithm=c.extend({reset:function(){this._data=new s.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=u.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var b=this._data,m=b.words,n=b.sigBytes,r=this.blockSize,c=n/(4*r),c=a?q.ceil(c):q.max((c|0)-this._minBufferSize,0);a=c*r;n=q.min(4*a,n);if(a){for(var t=0;t>>2]>>>24-8*(k%4)&255)<<16|(l[k+1>>>2]>>>24-8*((k+1)%4)&255)<<8|l[k+2>>>2]>>>24-8*((k+2)%4)&255,d=0;4>d&&k+0.75*d>>6*(3-d)&63));if(l=c.charAt(64))for(;e.length%4;)e.push(l);return e.join("")},parse:function(e){var l=e.length,p=this._map,c=p.charAt(64);c&&(c=e.indexOf(c),-1!=c&&(l=c));for(var c=[],s=0,b=0;b< -l;b++)if(b%4){var d=p.indexOf(e.charAt(b-1))<<2*(b%4),a=p.indexOf(e.charAt(b))>>>6-2*(b%4);c[s>>>2]|=(d|a)<<24-8*(s%4);s++}return k.create(c,s)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})(); -(function(q){function k(a,b,c,d,m,n,r){a=a+(b&c|~b&d)+m+r;return(a<>>32-n)+b}function e(a,b,c,d,m,n,r){a=a+(b&d|c&~d)+m+r;return(a<>>32-n)+b}function l(a,b,c,d,m,n,r){a=a+(b^c^d)+m+r;return(a<>>32-n)+b}function p(a,b,c,d,m,n,r){a=a+(c^(b|~d))+m+r;return(a<>>32-n)+b}for(var c=CryptoJS,s=c.lib,b=s.WordArray,d=s.Hasher,s=c.algo,a=[],u=0;64>u;u++)a[u]=4294967296*q.abs(q.sin(u+1))|0;s=s.MD5=d.extend({_doReset:function(){this._hash=new b.init([1732584193,4023233417,2562383102,271733878])}, -_doProcessBlock:function(b,c){for(var d=0;16>d;d++){var s=c+d,m=b[s];b[s]=(m<<8|m>>>24)&16711935|(m<<24|m>>>8)&4278255360}var d=this._hash.words,s=b[c+0],m=b[c+1],n=b[c+2],r=b[c+3],x=b[c+4],u=b[c+5],q=b[c+6],y=b[c+7],z=b[c+8],A=b[c+9],B=b[c+10],C=b[c+11],D=b[c+12],E=b[c+13],F=b[c+14],G=b[c+15],f=d[0],g=d[1],h=d[2],j=d[3],f=k(f,g,h,j,s,7,a[0]),j=k(j,f,g,h,m,12,a[1]),h=k(h,j,f,g,n,17,a[2]),g=k(g,h,j,f,r,22,a[3]),f=k(f,g,h,j,x,7,a[4]),j=k(j,f,g,h,u,12,a[5]),h=k(h,j,f,g,q,17,a[6]),g=k(g,h,j,f,y,22,a[7]), -f=k(f,g,h,j,z,7,a[8]),j=k(j,f,g,h,A,12,a[9]),h=k(h,j,f,g,B,17,a[10]),g=k(g,h,j,f,C,22,a[11]),f=k(f,g,h,j,D,7,a[12]),j=k(j,f,g,h,E,12,a[13]),h=k(h,j,f,g,F,17,a[14]),g=k(g,h,j,f,G,22,a[15]),f=e(f,g,h,j,m,5,a[16]),j=e(j,f,g,h,q,9,a[17]),h=e(h,j,f,g,C,14,a[18]),g=e(g,h,j,f,s,20,a[19]),f=e(f,g,h,j,u,5,a[20]),j=e(j,f,g,h,B,9,a[21]),h=e(h,j,f,g,G,14,a[22]),g=e(g,h,j,f,x,20,a[23]),f=e(f,g,h,j,A,5,a[24]),j=e(j,f,g,h,F,9,a[25]),h=e(h,j,f,g,r,14,a[26]),g=e(g,h,j,f,z,20,a[27]),f=e(f,g,h,j,E,5,a[28]),j=e(j,f, -g,h,n,9,a[29]),h=e(h,j,f,g,y,14,a[30]),g=e(g,h,j,f,D,20,a[31]),f=l(f,g,h,j,u,4,a[32]),j=l(j,f,g,h,z,11,a[33]),h=l(h,j,f,g,C,16,a[34]),g=l(g,h,j,f,F,23,a[35]),f=l(f,g,h,j,m,4,a[36]),j=l(j,f,g,h,x,11,a[37]),h=l(h,j,f,g,y,16,a[38]),g=l(g,h,j,f,B,23,a[39]),f=l(f,g,h,j,E,4,a[40]),j=l(j,f,g,h,s,11,a[41]),h=l(h,j,f,g,r,16,a[42]),g=l(g,h,j,f,q,23,a[43]),f=l(f,g,h,j,A,4,a[44]),j=l(j,f,g,h,D,11,a[45]),h=l(h,j,f,g,G,16,a[46]),g=l(g,h,j,f,n,23,a[47]),f=p(f,g,h,j,s,6,a[48]),j=p(j,f,g,h,y,10,a[49]),h=p(h,j,f,g, -F,15,a[50]),g=p(g,h,j,f,u,21,a[51]),f=p(f,g,h,j,D,6,a[52]),j=p(j,f,g,h,r,10,a[53]),h=p(h,j,f,g,B,15,a[54]),g=p(g,h,j,f,m,21,a[55]),f=p(f,g,h,j,z,6,a[56]),j=p(j,f,g,h,G,10,a[57]),h=p(h,j,f,g,q,15,a[58]),g=p(g,h,j,f,E,21,a[59]),f=p(f,g,h,j,x,6,a[60]),j=p(j,f,g,h,C,10,a[61]),h=p(h,j,f,g,n,15,a[62]),g=p(g,h,j,f,A,21,a[63]);d[0]=d[0]+f|0;d[1]=d[1]+g|0;d[2]=d[2]+h|0;d[3]=d[3]+j|0},_doFinalize:function(){var a=this._data,b=a.words,c=8*this._nDataBytes,d=8*a.sigBytes;b[d>>>5]|=128<<24-d%32;var m=q.floor(c/ -4294967296);b[(d+64>>>9<<4)+15]=(m<<8|m>>>24)&16711935|(m<<24|m>>>8)&4278255360;b[(d+64>>>9<<4)+14]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;a.sigBytes=4*(b.length+1);this._process();a=this._hash;b=a.words;for(c=0;4>c;c++)d=b[c],b[c]=(d<<8|d>>>24)&16711935|(d<<24|d>>>8)&4278255360;return a},clone:function(){var a=d.clone.call(this);a._hash=this._hash.clone();return a}});c.MD5=d._createHelper(s);c.HmacMD5=d._createHmacHelper(s)})(Math); -(function(){var q=CryptoJS,k=q.lib,e=k.Base,l=k.WordArray,k=q.algo,p=k.EvpKDF=e.extend({cfg:e.extend({keySize:4,hasher:k.MD5,iterations:1}),init:function(c){this.cfg=this.cfg.extend(c)},compute:function(c,e){for(var b=this.cfg,d=b.hasher.create(),a=l.create(),k=a.words,p=b.keySize,b=b.iterations;k.length>>2]&255}};e.BlockCipher=d.extend({cfg:d.cfg.extend({mode:a,padding:t}),reset:function(){d.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a, -this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var w=e.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),a=(k.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?p.create([1398893684, -1701076831]).concat(a).concat(b):b).toString(s)},parse:function(a){a=s.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=p.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return w.create({ciphertext:a,salt:c})}},v=e.SerializableCipher=l.extend({cfg:l.extend({format:a}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var e=a.createEncryptor(c,d);b=e.finalize(b);e=e.cfg;return w.create({ciphertext:b,key:c,iv:e.iv,algorithm:a,mode:e.mode,padding:e.padding,blockSize:a.blockSize,formatter:d.format})}, -decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),k=(k.kdf={}).OpenSSL={execute:function(a,c,d,e){e||(e=p.random(8));a=b.create({keySize:c+d}).compute(a,e);d=p.create(a.words.slice(c),4*d);a.sigBytes=4*c;return w.create({key:a,iv:d,salt:e})}},H=e.PasswordBasedCipher=v.extend({cfg:v.cfg.extend({kdf:k}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);c=d.kdf.execute(c, -a.keySize,a.ivSize);d.iv=c.iv;a=v.encrypt.call(this,a,b,c.key,d);a.mixIn(c);return a},decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);c=d.kdf.execute(c,a.keySize,a.ivSize,b.salt);d.iv=c.iv;return v.decrypt.call(this,a,b,c.key,d)}})}(); -(function(){function q(){for(var b=this._X,d=this._C,a=0;8>a;a++)p[a]=d[a];d[0]=d[0]+1295307597+this._b|0;d[1]=d[1]+3545052371+(d[0]>>>0>>0?1:0)|0;d[2]=d[2]+886263092+(d[1]>>>0>>0?1:0)|0;d[3]=d[3]+1295307597+(d[2]>>>0>>0?1:0)|0;d[4]=d[4]+3545052371+(d[3]>>>0>>0?1:0)|0;d[5]=d[5]+886263092+(d[4]>>>0>>0?1:0)|0;d[6]=d[6]+1295307597+(d[5]>>>0>>0?1:0)|0;d[7]=d[7]+3545052371+(d[6]>>>0>>0?1:0)|0;this._b=d[7]>>>0>>0?1:0;for(a=0;8>a;a++){var e=b[a]+d[a],k=e&65535, -l=e>>>16;c[a]=((k*k>>>17)+k*l>>>15)+l*l^((e&4294901760)*e|0)+((e&65535)*e|0)}b[0]=c[0]+(c[7]<<16|c[7]>>>16)+(c[6]<<16|c[6]>>>16)|0;b[1]=c[1]+(c[0]<<8|c[0]>>>24)+c[7]|0;b[2]=c[2]+(c[1]<<16|c[1]>>>16)+(c[0]<<16|c[0]>>>16)|0;b[3]=c[3]+(c[2]<<8|c[2]>>>24)+c[1]|0;b[4]=c[4]+(c[3]<<16|c[3]>>>16)+(c[2]<<16|c[2]>>>16)|0;b[5]=c[5]+(c[4]<<8|c[4]>>>24)+c[3]|0;b[6]=c[6]+(c[5]<<16|c[5]>>>16)+(c[4]<<16|c[4]>>>16)|0;b[7]=c[7]+(c[6]<<8|c[6]>>>24)+c[5]|0}var k=CryptoJS,e=k.lib.StreamCipher,l=[],p=[],c=[],s=k.algo.Rabbit= -e.extend({_doReset:function(){for(var b=this._key.words,c=this.cfg.iv,a=0;4>a;a++)b[a]=(b[a]<<8|b[a]>>>24)&16711935|(b[a]<<24|b[a]>>>8)&4278255360;for(var e=this._X=[b[0],b[3]<<16|b[2]>>>16,b[1],b[0]<<16|b[3]>>>16,b[2],b[1]<<16|b[0]>>>16,b[3],b[2]<<16|b[1]>>>16],b=this._C=[b[2]<<16|b[2]>>>16,b[0]&4294901760|b[1]&65535,b[3]<<16|b[3]>>>16,b[1]&4294901760|b[2]&65535,b[0]<<16|b[0]>>>16,b[2]&4294901760|b[3]&65535,b[1]<<16|b[1]>>>16,b[3]&4294901760|b[0]&65535],a=this._b=0;4>a;a++)q.call(this);for(a=0;8> -a;a++)b[a]^=e[a+4&7];if(c){var a=c.words,c=a[0],a=a[1],c=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360,a=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360,e=c>>>16|a&4294901760,k=a<<16|c&65535;b[0]^=c;b[1]^=e;b[2]^=a;b[3]^=k;b[4]^=c;b[5]^=e;b[6]^=a;b[7]^=k;for(a=0;4>a;a++)q.call(this)}},_doProcessBlock:function(b,c){var a=this._X;q.call(this);l[0]=a[0]^a[5]>>>16^a[3]<<16;l[1]=a[2]^a[7]>>>16^a[5]<<16;l[2]=a[4]^a[1]>>>16^a[7]<<16;l[3]=a[6]^a[3]>>>16^a[1]<<16;for(a=0;4>a;a++)l[a]=(l[a]<<8|l[a]>>>24)& -16711935|(l[a]<<24|l[a]>>>8)&4278255360,b[c+a]^=l[a]},blockSize:4,ivSize:2});k.Rabbit=e._createHelper(s)})(); diff --git a/dashboard-ui/bower_components/cryptojslib/rollups/rc4.js b/dashboard-ui/bower_components/cryptojslib/rollups/rc4.js deleted file mode 100644 index aba420f5e..000000000 --- a/dashboard-ui/bower_components/cryptojslib/rollups/rc4.js +++ /dev/null @@ -1,33 +0,0 @@ -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -var CryptoJS=CryptoJS||function(s,l){var e={},n=e.lib={},p=function(){},b=n.Base={extend:function(c){p.prototype=this;var a=new p;c&&a.mixIn(c);a.hasOwnProperty("init")||(a.init=function(){a.$super.init.apply(this,arguments)});a.init.prototype=a;a.$super=this;return a},create:function(){var c=this.extend();c.init.apply(c,arguments);return c},init:function(){},mixIn:function(c){for(var a in c)c.hasOwnProperty(a)&&(this[a]=c[a]);c.hasOwnProperty("toString")&&(this.toString=c.toString)},clone:function(){return this.init.prototype.extend(this)}}, -d=n.WordArray=b.extend({init:function(c,a){c=this.words=c||[];this.sigBytes=a!=l?a:4*c.length},toString:function(c){return(c||q).stringify(this)},concat:function(c){var a=this.words,m=c.words,f=this.sigBytes;c=c.sigBytes;this.clamp();if(f%4)for(var r=0;r>>2]|=(m[r>>>2]>>>24-8*(r%4)&255)<<24-8*((f+r)%4);else if(65535>>2]=m[r>>>2];else a.push.apply(a,m);this.sigBytes+=c;return this},clamp:function(){var c=this.words,a=this.sigBytes;c[a>>>2]&=4294967295<< -32-8*(a%4);c.length=s.ceil(a/4)},clone:function(){var c=b.clone.call(this);c.words=this.words.slice(0);return c},random:function(c){for(var a=[],m=0;m>>2]>>>24-8*(f%4)&255;m.push((r>>>4).toString(16));m.push((r&15).toString(16))}return m.join("")},parse:function(c){for(var a=c.length,m=[],f=0;f>>3]|=parseInt(c.substr(f, -2),16)<<24-4*(f%8);return new d.init(m,a/2)}},a=t.Latin1={stringify:function(c){var a=c.words;c=c.sigBytes;for(var m=[],f=0;f>>2]>>>24-8*(f%4)&255));return m.join("")},parse:function(c){for(var a=c.length,m=[],f=0;f>>2]|=(c.charCodeAt(f)&255)<<24-8*(f%4);return new d.init(m,a)}},v=t.Utf8={stringify:function(c){try{return decodeURIComponent(escape(a.stringify(c)))}catch(u){throw Error("Malformed UTF-8 data");}},parse:function(c){return a.parse(unescape(encodeURIComponent(c)))}}, -u=n.BufferedBlockAlgorithm=b.extend({reset:function(){this._data=new d.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=v.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var u=this._data,m=u.words,f=u.sigBytes,r=this.blockSize,e=f/(4*r),e=a?s.ceil(e):s.max((e|0)-this._minBufferSize,0);a=e*r;f=s.min(4*a,f);if(a){for(var b=0;b>>2]>>>24-8*(d%4)&255)<<16|(n[d+1>>>2]>>>24-8*((d+1)%4)&255)<<8|n[d+2>>>2]>>>24-8*((d+2)%4)&255,q=0;4>q&&d+0.75*q>>6*(3-q)&63));if(n=b.charAt(64))for(;e.length%4;)e.push(n);return e.join("")},parse:function(e){var n=e.length,p=this._map,b=p.charAt(64);b&&(b=e.indexOf(b),-1!=b&&(n=b));for(var b=[],d=0,t=0;t< -n;t++)if(t%4){var q=p.indexOf(e.charAt(t-1))<<2*(t%4),a=p.indexOf(e.charAt(t))>>>6-2*(t%4);b[d>>>2]|=(q|a)<<24-8*(d%4);d++}return l.create(b,d)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})(); -(function(s){function l(a,b,c,e,m,f,r){a=a+(b&c|~b&e)+m+r;return(a<>>32-f)+b}function e(a,b,c,e,m,f,r){a=a+(b&e|c&~e)+m+r;return(a<>>32-f)+b}function n(a,b,c,e,m,f,r){a=a+(b^c^e)+m+r;return(a<>>32-f)+b}function p(a,b,c,e,m,f,r){a=a+(c^(b|~e))+m+r;return(a<>>32-f)+b}for(var b=CryptoJS,d=b.lib,t=d.WordArray,q=d.Hasher,d=b.algo,a=[],v=0;64>v;v++)a[v]=4294967296*s.abs(s.sin(v+1))|0;d=d.MD5=q.extend({_doReset:function(){this._hash=new t.init([1732584193,4023233417,2562383102,271733878])}, -_doProcessBlock:function(b,d){for(var c=0;16>c;c++){var q=d+c,m=b[q];b[q]=(m<<8|m>>>24)&16711935|(m<<24|m>>>8)&4278255360}var c=this._hash.words,q=b[d+0],m=b[d+1],f=b[d+2],r=b[d+3],x=b[d+4],t=b[d+5],s=b[d+6],v=b[d+7],y=b[d+8],z=b[d+9],A=b[d+10],B=b[d+11],C=b[d+12],D=b[d+13],E=b[d+14],F=b[d+15],g=c[0],h=c[1],j=c[2],k=c[3],g=l(g,h,j,k,q,7,a[0]),k=l(k,g,h,j,m,12,a[1]),j=l(j,k,g,h,f,17,a[2]),h=l(h,j,k,g,r,22,a[3]),g=l(g,h,j,k,x,7,a[4]),k=l(k,g,h,j,t,12,a[5]),j=l(j,k,g,h,s,17,a[6]),h=l(h,j,k,g,v,22,a[7]), -g=l(g,h,j,k,y,7,a[8]),k=l(k,g,h,j,z,12,a[9]),j=l(j,k,g,h,A,17,a[10]),h=l(h,j,k,g,B,22,a[11]),g=l(g,h,j,k,C,7,a[12]),k=l(k,g,h,j,D,12,a[13]),j=l(j,k,g,h,E,17,a[14]),h=l(h,j,k,g,F,22,a[15]),g=e(g,h,j,k,m,5,a[16]),k=e(k,g,h,j,s,9,a[17]),j=e(j,k,g,h,B,14,a[18]),h=e(h,j,k,g,q,20,a[19]),g=e(g,h,j,k,t,5,a[20]),k=e(k,g,h,j,A,9,a[21]),j=e(j,k,g,h,F,14,a[22]),h=e(h,j,k,g,x,20,a[23]),g=e(g,h,j,k,z,5,a[24]),k=e(k,g,h,j,E,9,a[25]),j=e(j,k,g,h,r,14,a[26]),h=e(h,j,k,g,y,20,a[27]),g=e(g,h,j,k,D,5,a[28]),k=e(k,g, -h,j,f,9,a[29]),j=e(j,k,g,h,v,14,a[30]),h=e(h,j,k,g,C,20,a[31]),g=n(g,h,j,k,t,4,a[32]),k=n(k,g,h,j,y,11,a[33]),j=n(j,k,g,h,B,16,a[34]),h=n(h,j,k,g,E,23,a[35]),g=n(g,h,j,k,m,4,a[36]),k=n(k,g,h,j,x,11,a[37]),j=n(j,k,g,h,v,16,a[38]),h=n(h,j,k,g,A,23,a[39]),g=n(g,h,j,k,D,4,a[40]),k=n(k,g,h,j,q,11,a[41]),j=n(j,k,g,h,r,16,a[42]),h=n(h,j,k,g,s,23,a[43]),g=n(g,h,j,k,z,4,a[44]),k=n(k,g,h,j,C,11,a[45]),j=n(j,k,g,h,F,16,a[46]),h=n(h,j,k,g,f,23,a[47]),g=p(g,h,j,k,q,6,a[48]),k=p(k,g,h,j,v,10,a[49]),j=p(j,k,g,h, -E,15,a[50]),h=p(h,j,k,g,t,21,a[51]),g=p(g,h,j,k,C,6,a[52]),k=p(k,g,h,j,r,10,a[53]),j=p(j,k,g,h,A,15,a[54]),h=p(h,j,k,g,m,21,a[55]),g=p(g,h,j,k,y,6,a[56]),k=p(k,g,h,j,F,10,a[57]),j=p(j,k,g,h,s,15,a[58]),h=p(h,j,k,g,D,21,a[59]),g=p(g,h,j,k,x,6,a[60]),k=p(k,g,h,j,B,10,a[61]),j=p(j,k,g,h,f,15,a[62]),h=p(h,j,k,g,z,21,a[63]);c[0]=c[0]+g|0;c[1]=c[1]+h|0;c[2]=c[2]+j|0;c[3]=c[3]+k|0},_doFinalize:function(){var a=this._data,b=a.words,c=8*this._nDataBytes,d=8*a.sigBytes;b[d>>>5]|=128<<24-d%32;var m=s.floor(c/ -4294967296);b[(d+64>>>9<<4)+15]=(m<<8|m>>>24)&16711935|(m<<24|m>>>8)&4278255360;b[(d+64>>>9<<4)+14]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;a.sigBytes=4*(b.length+1);this._process();a=this._hash;b=a.words;for(c=0;4>c;c++)d=b[c],b[c]=(d<<8|d>>>24)&16711935|(d<<24|d>>>8)&4278255360;return a},clone:function(){var a=q.clone.call(this);a._hash=this._hash.clone();return a}});b.MD5=q._createHelper(d);b.HmacMD5=q._createHmacHelper(d)})(Math); -(function(){var s=CryptoJS,l=s.lib,e=l.Base,n=l.WordArray,l=s.algo,p=l.EvpKDF=e.extend({cfg:e.extend({keySize:4,hasher:l.MD5,iterations:1}),init:function(b){this.cfg=this.cfg.extend(b)},compute:function(b,d){for(var e=this.cfg,q=e.hasher.create(),a=n.create(),l=a.words,p=e.keySize,e=e.iterations;l.length>>2]&255}};e.BlockCipher=q.extend({cfg:q.cfg.extend({mode:a,padding:u}),reset:function(){q.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a, -this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var w=e.CipherParams=n.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),a=(l.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?p.create([1398893684, -1701076831]).concat(a).concat(b):b).toString(d)},parse:function(a){a=d.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=p.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return w.create({ciphertext:a,salt:c})}},c=e.SerializableCipher=n.extend({cfg:n.extend({format:a}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var e=a.createEncryptor(c,d);b=e.finalize(b);e=e.cfg;return w.create({ciphertext:b,key:c,iv:e.iv,algorithm:a,mode:e.mode,padding:e.padding,blockSize:a.blockSize,formatter:d.format})}, -decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),l=(l.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=p.random(8));a=t.create({keySize:b+c}).compute(a,d);c=p.create(a.words.slice(b),4*c);a.sigBytes=4*b;return w.create({key:a,iv:c,salt:d})}},G=e.PasswordBasedCipher=c.extend({cfg:c.cfg.extend({kdf:l}),encrypt:function(a,b,d,e){e=this.cfg.extend(e);d=e.kdf.execute(d, -a.keySize,a.ivSize);e.iv=d.iv;a=c.encrypt.call(this,a,b,d.key,e);a.mixIn(d);return a},decrypt:function(a,b,d,e){e=this.cfg.extend(e);b=this._parse(b,e.format);d=e.kdf.execute(d,a.keySize,a.ivSize,b.salt);e.iv=d.iv;return c.decrypt.call(this,a,b,d.key,e)}})}(); -(function(){function s(){for(var b=this._S,d=this._i,e=this._j,q=0,a=0;4>a;a++){var d=(d+1)%256,e=(e+b[d])%256,l=b[d];b[d]=b[e];b[e]=l;q|=b[(b[d]+b[e])%256]<<24-8*a}this._i=d;this._j=e;return q}var l=CryptoJS,e=l.lib.StreamCipher,n=l.algo,p=n.RC4=e.extend({_doReset:function(){for(var b=this._key,d=b.words,b=b.sigBytes,e=this._S=[],l=0;256>l;l++)e[l]=l;for(var a=l=0;256>l;l++){var n=l%b,a=(a+e[l]+(d[n>>>2]>>>24-8*(n%4)&255))%256,n=e[l];e[l]=e[a];e[a]=n}this._i=this._j=0},_doProcessBlock:function(b, -d){b[d]^=s.call(this)},keySize:8,ivSize:0});l.RC4=e._createHelper(p);n=n.RC4Drop=p.extend({cfg:p.cfg.extend({drop:192}),_doReset:function(){p._doReset.call(this);for(var b=this.cfg.drop;0>>2]|=(h[b>>>2]>>>24-8*(b%4)&255)<<24-8*((d+b)%4);else if(65535>>2]=h[b>>>2];else c.push.apply(c,h);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< -32-8*(c%4);a.length=j.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],b=0;b>>2]>>>24-8*(d%4)&255;b.push((g>>>4).toString(16));b.push((g&15).toString(16))}return b.join("")},parse:function(a){for(var c=a.length,b=[],d=0;d>>3]|=parseInt(a.substr(d, -2),16)<<24-4*(d%8);return new u.init(b,c/2)}},A=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],d=0;d>>2]>>>24-8*(d%4)&255));return b.join("")},parse:function(a){for(var b=a.length,h=[],d=0;d>>2]|=(a.charCodeAt(d)&255)<<24-8*(d%4);return new u.init(h,b)}},g=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(A.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return A.parse(unescape(encodeURIComponent(a)))}}, -v=l.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new u.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=g.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var b=this._data,h=b.words,d=b.sigBytes,g=this.blockSize,v=d/(4*g),v=a?j.ceil(v):j.max((v|0)-this._minBufferSize,0);a=v*g;d=j.min(4*a,d);if(a){for(var e=0;eb;b++){var a=e+b,c=g[a];g[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360}var a=this._hash.words,c=D.words,h=A.words,d=z.words,j=t.words,k=u.words,l=w.words,B,m,n,p,x,C,q,r,s,y;C=B=a[0];q=m=a[1];r=n=a[2];s=p=a[3];y=x=a[4];for(var f,b=0;80>b;b+=1)f=B+g[e+d[b]]|0,f=16>b?f+((m^n^p)+c[0]):32>b?f+((m&n|~m&p)+c[1]):48>b? -f+(((m|~n)^p)+c[2]):64>b?f+((m&p|n&~p)+c[3]):f+((m^(n|~p))+c[4]),f|=0,f=f<>>32-k[b],f=f+x|0,B=x,x=p,p=n<<10|n>>>22,n=m,m=f,f=C+g[e+j[b]]|0,f=16>b?f+((q^(r|~s))+h[0]):32>b?f+((q&s|r&~s)+h[1]):48>b?f+(((q|~r)^s)+h[2]):64>b?f+((q&r|~q&s)+h[3]):f+((q^r^s)+h[4]),f|=0,f=f<>>32-l[b],f=f+y|0,C=y,y=s,s=r<<10|r>>>22,r=q,q=f;f=a[1]+n+s|0;a[1]=a[2]+p+y|0;a[2]=a[3]+x+C|0;a[3]=a[4]+B+q|0;a[4]=a[0]+m+r|0;a[0]=f},_doFinalize:function(){var g=this._data,e=g.words,b=8*this._nDataBytes,a=8*g.sigBytes; -e[a>>>5]|=128<<24-a%32;e[(a+64>>>9<<4)+14]=(b<<8|b>>>24)&16711935|(b<<24|b>>>8)&4278255360;g.sigBytes=4*(e.length+1);this._process();g=this._hash;e=g.words;for(b=0;5>b;b++)a=e[b],e[b]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;return g},clone:function(){var e=l.clone.call(this);e._hash=this._hash.clone();return e}});j.RIPEMD160=l._createHelper(k);j.HmacRIPEMD160=l._createHmacHelper(k)})(Math); diff --git a/dashboard-ui/bower_components/cryptojslib/rollups/sha1.js b/dashboard-ui/bower_components/cryptojslib/rollups/sha1.js deleted file mode 100644 index d0d589f71..000000000 --- a/dashboard-ui/bower_components/cryptojslib/rollups/sha1.js +++ /dev/null @@ -1,15 +0,0 @@ -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -var CryptoJS=CryptoJS||function(e,m){var p={},j=p.lib={},l=function(){},f=j.Base={extend:function(a){l.prototype=this;var c=new l;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, -n=j.WordArray=f.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=m?c:4*a.length},toString:function(a){return(a||h).stringify(this)},concat:function(a){var c=this.words,q=a.words,d=this.sigBytes;a=a.sigBytes;this.clamp();if(d%4)for(var b=0;b>>2]|=(q[b>>>2]>>>24-8*(b%4)&255)<<24-8*((d+b)%4);else if(65535>>2]=q[b>>>2];else c.push.apply(c,q);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< -32-8*(c%4);a.length=e.ceil(c/4)},clone:function(){var a=f.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],b=0;b>>2]>>>24-8*(d%4)&255;b.push((f>>>4).toString(16));b.push((f&15).toString(16))}return b.join("")},parse:function(a){for(var c=a.length,b=[],d=0;d>>3]|=parseInt(a.substr(d, -2),16)<<24-4*(d%8);return new n.init(b,c/2)}},g=b.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],d=0;d>>2]>>>24-8*(d%4)&255));return b.join("")},parse:function(a){for(var c=a.length,b=[],d=0;d>>2]|=(a.charCodeAt(d)&255)<<24-8*(d%4);return new n.init(b,c)}},r=b.Utf8={stringify:function(a){try{return decodeURIComponent(escape(g.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return g.parse(unescape(encodeURIComponent(a)))}}, -k=j.BufferedBlockAlgorithm=f.extend({reset:function(){this._data=new n.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=r.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,b=c.words,d=c.sigBytes,f=this.blockSize,h=d/(4*f),h=a?e.ceil(h):e.max((h|0)-this._minBufferSize,0);a=h*f;d=e.min(4*a,d);if(a){for(var g=0;ga;a++){if(16>a)l[a]=f[n+a]|0;else{var c=l[a-3]^l[a-8]^l[a-14]^l[a-16];l[a]=c<<1|c>>>31}c=(h<<5|h>>>27)+j+l[a];c=20>a?c+((g&e|~g&k)+1518500249):40>a?c+((g^e^k)+1859775393):60>a?c+((g&e|g&k|e&k)-1894007588):c+((g^e^ -k)-899497514);j=k;k=e;e=g<<30|g>>>2;g=h;h=c}b[0]=b[0]+h|0;b[1]=b[1]+g|0;b[2]=b[2]+e|0;b[3]=b[3]+k|0;b[4]=b[4]+j|0},_doFinalize:function(){var f=this._data,e=f.words,b=8*this._nDataBytes,h=8*f.sigBytes;e[h>>>5]|=128<<24-h%32;e[(h+64>>>9<<4)+14]=Math.floor(b/4294967296);e[(h+64>>>9<<4)+15]=b;f.sigBytes=4*e.length;this._process();return this._hash},clone:function(){var e=j.clone.call(this);e._hash=this._hash.clone();return e}});e.SHA1=j._createHelper(m);e.HmacSHA1=j._createHmacHelper(m)})(); diff --git a/dashboard-ui/bower_components/cryptojslib/rollups/sha224.js b/dashboard-ui/bower_components/cryptojslib/rollups/sha224.js deleted file mode 100644 index e1653c988..000000000 --- a/dashboard-ui/bower_components/cryptojslib/rollups/sha224.js +++ /dev/null @@ -1,17 +0,0 @@ -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -var CryptoJS=CryptoJS||function(g,l){var f={},k=f.lib={},h=function(){},m=k.Base={extend:function(a){h.prototype=this;var c=new h;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, -q=k.WordArray=m.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=l?c:4*a.length},toString:function(a){return(a||s).stringify(this)},concat:function(a){var c=this.words,d=a.words,b=this.sigBytes;a=a.sigBytes;this.clamp();if(b%4)for(var e=0;e>>2]|=(d[e>>>2]>>>24-8*(e%4)&255)<<24-8*((b+e)%4);else if(65535>>2]=d[e>>>2];else c.push.apply(c,d);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< -32-8*(c%4);a.length=g.ceil(c/4)},clone:function(){var a=m.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],d=0;d>>2]>>>24-8*(b%4)&255;d.push((e>>>4).toString(16));d.push((e&15).toString(16))}return d.join("")},parse:function(a){for(var c=a.length,d=[],b=0;b>>3]|=parseInt(a.substr(b, -2),16)<<24-4*(b%8);return new q.init(d,c/2)}},n=t.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var d=[],b=0;b>>2]>>>24-8*(b%4)&255));return d.join("")},parse:function(a){for(var c=a.length,d=[],b=0;b>>2]|=(a.charCodeAt(b)&255)<<24-8*(b%4);return new q.init(d,c)}},j=t.Utf8={stringify:function(a){try{return decodeURIComponent(escape(n.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return n.parse(unescape(encodeURIComponent(a)))}}, -w=k.BufferedBlockAlgorithm=m.extend({reset:function(){this._data=new q.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=j.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,d=c.words,b=c.sigBytes,e=this.blockSize,f=b/(4*e),f=a?g.ceil(f):g.max((f|0)-this._minBufferSize,0);a=f*e;b=g.min(4*a,b);if(a){for(var u=0;un;){var j;a:{j=s;for(var w=g.sqrt(j),v=2;v<=w;v++)if(!(j%v)){j=!1;break a}j=!0}j&&(8>n&&(m[n]=t(g.pow(s,0.5))),q[n]=t(g.pow(s,1/3)),n++);s++}var a=[],f=f.SHA256=h.extend({_doReset:function(){this._hash=new k.init(m.slice(0))},_doProcessBlock:function(c,d){for(var b=this._hash.words,e=b[0],f=b[1],g=b[2],k=b[3],h=b[4],l=b[5],m=b[6],n=b[7],p=0;64>p;p++){if(16>p)a[p]= -c[d+p]|0;else{var j=a[p-15],r=a[p-2];a[p]=((j<<25|j>>>7)^(j<<14|j>>>18)^j>>>3)+a[p-7]+((r<<15|r>>>17)^(r<<13|r>>>19)^r>>>10)+a[p-16]}j=n+((h<<26|h>>>6)^(h<<21|h>>>11)^(h<<7|h>>>25))+(h&l^~h&m)+q[p]+a[p];r=((e<<30|e>>>2)^(e<<19|e>>>13)^(e<<10|e>>>22))+(e&f^e&g^f&g);n=m;m=l;l=h;h=k+j|0;k=g;g=f;f=e;e=j+r|0}b[0]=b[0]+e|0;b[1]=b[1]+f|0;b[2]=b[2]+g|0;b[3]=b[3]+k|0;b[4]=b[4]+h|0;b[5]=b[5]+l|0;b[6]=b[6]+m|0;b[7]=b[7]+n|0},_doFinalize:function(){var a=this._data,d=a.words,b=8*this._nDataBytes,e=8*a.sigBytes; -d[e>>>5]|=128<<24-e%32;d[(e+64>>>9<<4)+14]=g.floor(b/4294967296);d[(e+64>>>9<<4)+15]=b;a.sigBytes=4*d.length;this._process();return this._hash},clone:function(){var a=h.clone.call(this);a._hash=this._hash.clone();return a}});l.SHA256=h._createHelper(f);l.HmacSHA256=h._createHmacHelper(f)})(Math); -(function(){var g=CryptoJS,l=g.lib.WordArray,f=g.algo,k=f.SHA256,f=f.SHA224=k.extend({_doReset:function(){this._hash=new l.init([3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428])},_doFinalize:function(){var f=k._doFinalize.call(this);f.sigBytes-=4;return f}});g.SHA224=k._createHelper(f);g.HmacSHA224=k._createHmacHelper(f)})(); diff --git a/dashboard-ui/bower_components/cryptojslib/rollups/sha256.js b/dashboard-ui/bower_components/cryptojslib/rollups/sha256.js deleted file mode 100644 index 529db30cd..000000000 --- a/dashboard-ui/bower_components/cryptojslib/rollups/sha256.js +++ /dev/null @@ -1,16 +0,0 @@ -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -var CryptoJS=CryptoJS||function(h,s){var f={},t=f.lib={},g=function(){},j=t.Base={extend:function(a){g.prototype=this;var c=new g;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, -q=t.WordArray=j.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=s?c:4*a.length},toString:function(a){return(a||u).stringify(this)},concat:function(a){var c=this.words,d=a.words,b=this.sigBytes;a=a.sigBytes;this.clamp();if(b%4)for(var e=0;e>>2]|=(d[e>>>2]>>>24-8*(e%4)&255)<<24-8*((b+e)%4);else if(65535>>2]=d[e>>>2];else c.push.apply(c,d);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< -32-8*(c%4);a.length=h.ceil(c/4)},clone:function(){var a=j.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],d=0;d>>2]>>>24-8*(b%4)&255;d.push((e>>>4).toString(16));d.push((e&15).toString(16))}return d.join("")},parse:function(a){for(var c=a.length,d=[],b=0;b>>3]|=parseInt(a.substr(b, -2),16)<<24-4*(b%8);return new q.init(d,c/2)}},k=v.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var d=[],b=0;b>>2]>>>24-8*(b%4)&255));return d.join("")},parse:function(a){for(var c=a.length,d=[],b=0;b>>2]|=(a.charCodeAt(b)&255)<<24-8*(b%4);return new q.init(d,c)}},l=v.Utf8={stringify:function(a){try{return decodeURIComponent(escape(k.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return k.parse(unescape(encodeURIComponent(a)))}}, -x=t.BufferedBlockAlgorithm=j.extend({reset:function(){this._data=new q.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=l.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,d=c.words,b=c.sigBytes,e=this.blockSize,f=b/(4*e),f=a?h.ceil(f):h.max((f|0)-this._minBufferSize,0);a=f*e;b=h.min(4*a,b);if(a){for(var m=0;mk;){var l;a:{l=u;for(var x=h.sqrt(l),w=2;w<=x;w++)if(!(l%w)){l=!1;break a}l=!0}l&&(8>k&&(j[k]=v(h.pow(u,0.5))),q[k]=v(h.pow(u,1/3)),k++);u++}var a=[],f=f.SHA256=g.extend({_doReset:function(){this._hash=new t.init(j.slice(0))},_doProcessBlock:function(c,d){for(var b=this._hash.words,e=b[0],f=b[1],m=b[2],h=b[3],p=b[4],j=b[5],k=b[6],l=b[7],n=0;64>n;n++){if(16>n)a[n]= -c[d+n]|0;else{var r=a[n-15],g=a[n-2];a[n]=((r<<25|r>>>7)^(r<<14|r>>>18)^r>>>3)+a[n-7]+((g<<15|g>>>17)^(g<<13|g>>>19)^g>>>10)+a[n-16]}r=l+((p<<26|p>>>6)^(p<<21|p>>>11)^(p<<7|p>>>25))+(p&j^~p&k)+q[n]+a[n];g=((e<<30|e>>>2)^(e<<19|e>>>13)^(e<<10|e>>>22))+(e&f^e&m^f&m);l=k;k=j;j=p;p=h+r|0;h=m;m=f;f=e;e=r+g|0}b[0]=b[0]+e|0;b[1]=b[1]+f|0;b[2]=b[2]+m|0;b[3]=b[3]+h|0;b[4]=b[4]+p|0;b[5]=b[5]+j|0;b[6]=b[6]+k|0;b[7]=b[7]+l|0},_doFinalize:function(){var a=this._data,d=a.words,b=8*this._nDataBytes,e=8*a.sigBytes; -d[e>>>5]|=128<<24-e%32;d[(e+64>>>9<<4)+14]=h.floor(b/4294967296);d[(e+64>>>9<<4)+15]=b;a.sigBytes=4*d.length;this._process();return this._hash},clone:function(){var a=g.clone.call(this);a._hash=this._hash.clone();return a}});s.SHA256=g._createHelper(f);s.HmacSHA256=g._createHmacHelper(f)})(Math); diff --git a/dashboard-ui/bower_components/cryptojslib/rollups/sha3.js b/dashboard-ui/bower_components/cryptojslib/rollups/sha3.js deleted file mode 100644 index 652505c6b..000000000 --- a/dashboard-ui/bower_components/cryptojslib/rollups/sha3.js +++ /dev/null @@ -1,19 +0,0 @@ -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -var CryptoJS=CryptoJS||function(v,p){var d={},u=d.lib={},r=function(){},f=u.Base={extend:function(a){r.prototype=this;var b=new r;a&&b.mixIn(a);b.hasOwnProperty("init")||(b.init=function(){b.$super.init.apply(this,arguments)});b.init.prototype=b;b.$super=this;return b},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, -s=u.WordArray=f.extend({init:function(a,b){a=this.words=a||[];this.sigBytes=b!=p?b:4*a.length},toString:function(a){return(a||y).stringify(this)},concat:function(a){var b=this.words,c=a.words,j=this.sigBytes;a=a.sigBytes;this.clamp();if(j%4)for(var n=0;n>>2]|=(c[n>>>2]>>>24-8*(n%4)&255)<<24-8*((j+n)%4);else if(65535>>2]=c[n>>>2];else b.push.apply(b,c);this.sigBytes+=a;return this},clamp:function(){var a=this.words,b=this.sigBytes;a[b>>>2]&=4294967295<< -32-8*(b%4);a.length=v.ceil(b/4)},clone:function(){var a=f.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var b=[],c=0;c>>2]>>>24-8*(j%4)&255;c.push((n>>>4).toString(16));c.push((n&15).toString(16))}return c.join("")},parse:function(a){for(var b=a.length,c=[],j=0;j>>3]|=parseInt(a.substr(j, -2),16)<<24-4*(j%8);return new s.init(c,b/2)}},e=x.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var c=[],j=0;j>>2]>>>24-8*(j%4)&255));return c.join("")},parse:function(a){for(var b=a.length,c=[],j=0;j>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new s.init(c,b)}},q=x.Utf8={stringify:function(a){try{return decodeURIComponent(escape(e.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return e.parse(unescape(encodeURIComponent(a)))}}, -t=u.BufferedBlockAlgorithm=f.extend({reset:function(){this._data=new s.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=q.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var b=this._data,c=b.words,j=b.sigBytes,n=this.blockSize,e=j/(4*n),e=a?v.ceil(e):v.max((e|0)-this._minBufferSize,0);a=e*n;j=v.min(4*a,j);if(a){for(var f=0;ft;t++){s[e+5*q]=(t+1)*(t+2)/2%64;var w=(2*e+3*q)%5,e=q%5,q=w}for(e=0;5>e;e++)for(q=0;5>q;q++)x[e+5*q]=q+5*((2*e+3*q)%5);e=1;for(q=0;24>q;q++){for(var a=w=t=0;7>a;a++){if(e&1){var b=(1<b?w^=1<e;e++)c[e]=f.create();d=d.SHA3=r.extend({cfg:r.cfg.extend({outputLength:512}),_doReset:function(){for(var a=this._state= -[],b=0;25>b;b++)a[b]=new f.init;this.blockSize=(1600-2*this.cfg.outputLength)/32},_doProcessBlock:function(a,b){for(var e=this._state,f=this.blockSize/2,h=0;h>>24)&16711935|(l<<24|l>>>8)&4278255360,m=(m<<8|m>>>24)&16711935|(m<<24|m>>>8)&4278255360,g=e[h];g.high^=m;g.low^=l}for(f=0;24>f;f++){for(h=0;5>h;h++){for(var d=l=0,k=0;5>k;k++)g=e[h+5*k],l^=g.high,d^=g.low;g=c[h];g.high=l;g.low=d}for(h=0;5>h;h++){g=c[(h+4)%5];l=c[(h+1)%5];m=l.high;k=l.low;l=g.high^ -(m<<1|k>>>31);d=g.low^(k<<1|m>>>31);for(k=0;5>k;k++)g=e[h+5*k],g.high^=l,g.low^=d}for(m=1;25>m;m++)g=e[m],h=g.high,g=g.low,k=s[m],32>k?(l=h<>>32-k,d=g<>>32-k):(l=g<>>64-k,d=h<>>64-k),g=c[x[m]],g.high=l,g.low=d;g=c[0];h=e[0];g.high=h.high;g.low=h.low;for(h=0;5>h;h++)for(k=0;5>k;k++)m=h+5*k,g=e[m],l=c[m],m=c[(h+1)%5+5*k],d=c[(h+2)%5+5*k],g.high=l.high^~m.high&d.high,g.low=l.low^~m.low&d.low;g=e[0];h=y[f];g.high^=h.high;g.low^=h.low}},_doFinalize:function(){var a=this._data, -b=a.words,c=8*a.sigBytes,e=32*this.blockSize;b[c>>>5]|=1<<24-c%32;b[(v.ceil((c+1)/e)*e>>>5)-1]|=128;a.sigBytes=4*b.length;this._process();for(var a=this._state,b=this.cfg.outputLength/8,c=b/8,e=[],h=0;h>>24)&16711935|(f<<24|f>>>8)&4278255360,d=(d<<8|d>>>24)&16711935|(d<<24|d>>>8)&4278255360;e.push(d);e.push(f)}return new u.init(e,b)},clone:function(){for(var a=r.clone.call(this),b=a._state=this._state.slice(0),c=0;25>c;c++)b[c]=b[c].clone();return a}}); -p.SHA3=r._createHelper(d);p.HmacSHA3=r._createHmacHelper(d)})(Math); diff --git a/dashboard-ui/bower_components/cryptojslib/rollups/sha384.js b/dashboard-ui/bower_components/cryptojslib/rollups/sha384.js deleted file mode 100644 index dec5f581c..000000000 --- a/dashboard-ui/bower_components/cryptojslib/rollups/sha384.js +++ /dev/null @@ -1,25 +0,0 @@ -/* -CryptoJS v3.1.2 -code.google.com/p/crypto-js -(c) 2009-2013 by Jeff Mott. All rights reserved. -code.google.com/p/crypto-js/wiki/License -*/ -var CryptoJS=CryptoJS||function(a,c){var d={},j=d.lib={},f=function(){},m=j.Base={extend:function(a){f.prototype=this;var b=new f;a&&b.mixIn(a);b.hasOwnProperty("init")||(b.init=function(){b.$super.init.apply(this,arguments)});b.init.prototype=b;b.$super=this;return b},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, -B=j.WordArray=m.extend({init:function(a,b){a=this.words=a||[];this.sigBytes=b!=c?b:4*a.length},toString:function(a){return(a||y).stringify(this)},concat:function(a){var b=this.words,g=a.words,e=this.sigBytes;a=a.sigBytes;this.clamp();if(e%4)for(var k=0;k>>2]|=(g[k>>>2]>>>24-8*(k%4)&255)<<24-8*((e+k)%4);else if(65535>>2]=g[k>>>2];else b.push.apply(b,g);this.sigBytes+=a;return this},clamp:function(){var n=this.words,b=this.sigBytes;n[b>>>2]&=4294967295<< -32-8*(b%4);n.length=a.ceil(b/4)},clone:function(){var a=m.clone.call(this);a.words=this.words.slice(0);return a},random:function(n){for(var b=[],g=0;g>>2]>>>24-8*(e%4)&255;g.push((k>>>4).toString(16));g.push((k&15).toString(16))}return g.join("")},parse:function(a){for(var b=a.length,g=[],e=0;e>>3]|=parseInt(a.substr(e, -2),16)<<24-4*(e%8);return new B.init(g,b/2)}},F=v.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var g=[],e=0;e>>2]>>>24-8*(e%4)&255));return g.join("")},parse:function(a){for(var b=a.length,g=[],e=0;e>>2]|=(a.charCodeAt(e)&255)<<24-8*(e%4);return new B.init(g,b)}},ha=v.Utf8={stringify:function(a){try{return decodeURIComponent(escape(F.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data");}},parse:function(a){return F.parse(unescape(encodeURIComponent(a)))}}, -Z=j.BufferedBlockAlgorithm=m.extend({reset:function(){this._data=new B.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=ha.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(n){var b=this._data,g=b.words,e=b.sigBytes,k=this.blockSize,m=e/(4*k),m=n?a.ceil(m):a.max((m|0)-this._minBufferSize,0);n=m*k;e=a.min(4*n,e);if(n){for(var c=0;cy;y++)v[y]=a();j=j.SHA512=d.extend({_doReset:function(){this._hash=new m.init([new f.init(1779033703,4089235720),new f.init(3144134277,2227873595),new f.init(1013904242,4271175723),new f.init(2773480762,1595750129),new f.init(1359893119,2917565137),new f.init(2600822924,725511199),new f.init(528734635,4215389547),new f.init(1541459225,327033209)])},_doProcessBlock:function(a,c){for(var d=this._hash.words, -f=d[0],j=d[1],b=d[2],g=d[3],e=d[4],k=d[5],m=d[6],d=d[7],y=f.high,M=f.low,$=j.high,N=j.low,aa=b.high,O=b.low,ba=g.high,P=g.low,ca=e.high,Q=e.low,da=k.high,R=k.low,ea=m.high,S=m.low,fa=d.high,T=d.low,s=y,p=M,G=$,D=N,H=aa,E=O,W=ba,I=P,t=ca,q=Q,U=da,J=R,V=ea,K=S,X=fa,L=T,u=0;80>u;u++){var z=v[u];if(16>u)var r=z.high=a[c+2*u]|0,h=z.low=a[c+2*u+1]|0;else{var r=v[u-15],h=r.high,w=r.low,r=(h>>>1|w<<31)^(h>>>8|w<<24)^h>>>7,w=(w>>>1|h<<31)^(w>>>8|h<<24)^(w>>>7|h<<25),C=v[u-2],h=C.high,l=C.low,C=(h>>>19|l<< -13)^(h<<3|l>>>29)^h>>>6,l=(l>>>19|h<<13)^(l<<3|h>>>29)^(l>>>6|h<<26),h=v[u-7],Y=h.high,A=v[u-16],x=A.high,A=A.low,h=w+h.low,r=r+Y+(h>>>0>>0?1:0),h=h+l,r=r+C+(h>>>0>>0?1:0),h=h+A,r=r+x+(h>>>0>>0?1:0);z.high=r;z.low=h}var Y=t&U^~t&V,A=q&J^~q&K,z=s&G^s&H^G&H,ja=p&D^p&E^D&E,w=(s>>>28|p<<4)^(s<<30|p>>>2)^(s<<25|p>>>7),C=(p>>>28|s<<4)^(p<<30|s>>>2)^(p<<25|s>>>7),l=B[u],ka=l.high,ga=l.low,l=L+((q>>>14|t<<18)^(q>>>18|t<<14)^(q<<23|t>>>9)),x=X+((t>>>14|q<<18)^(t>>>18|q<<14)^(t<<23|q>>>9))+(l>>>0< -L>>>0?1:0),l=l+A,x=x+Y+(l>>>0>>0?1:0),l=l+ga,x=x+ka+(l>>>0>>0?1:0),l=l+h,x=x+r+(l>>>0>>0?1:0),h=C+ja,z=w+z+(h>>>0>>0?1:0),X=V,L=K,V=U,K=J,U=t,J=q,q=I+l|0,t=W+x+(q>>>0>>0?1:0)|0,W=H,I=E,H=G,E=D,G=s,D=p,p=l+h|0,s=x+z+(p>>>0>>0?1:0)|0}M=f.low=M+p;f.high=y+s+(M>>>0