Changeset 104951 in spip-zone


Ignore:
Timestamp:
Jun 23, 2017, 3:45:18 PM (2 years ago)
Author:
booz@…
Message:

maj en version v297a-20170601

Location:
_plugins_/soundmanager
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/soundmanager/360-player/script/360player.js

    r92863 r104951  
    1616*/
    1717
    18 /*jslint white: false, onevar: true, undef: true, nomen: false, eqeqeq: true, plusplus: false, bitwise: true, regexp: false, newcap: true, immed: true */
    1918/*global document, window, soundManager, navigator */
    2019
    21 var threeSixtyPlayer, // instance
    22     ThreeSixtyPlayer; // constructor
     20var threeSixtyPlayer; // instance
    2321
    2422(function(window) {
     
    3432      isSafari = (uA.match(/safari/i)),
    3533      isChrome = (uA.match(/chrome/i)),
    36       isFirefox = (uA.match(/firefox/i)),
    3734      isTouchDevice = (uA.match(/ipad|iphone/i)),
    3835      hasRealCanvas = (typeof window.G_vmlCanvasManager === 'undefined' && typeof document.createElement('canvas').getContext('2d') !== 'undefined'),
    3936      // I dunno what Opera doesn't like about this. I'm probably doing it wrong.
    40       fullCircle = (isOpera||isChrome?359.9:360),
     37      fullCircle = (isOpera || isChrome ? 359.9 : 360),
    4138      // exclude old IE from hi-DPI / "retina"-scale display size
    42       hiDPIScale = (navigator.userAgent.match(/msie [678]/i)? 1 : 2);
     39      hiDPIScale = (navigator.userAgent.match(/msie [678]/i) ? 1 : 2);
    4340
    4441  // CSS class for ignoring MP3 links
     
    122119
    123120  this.addEventHandler = (typeof window.addEventListener !== 'undefined' ? function(o, evtName, evtHandler) {
    124     return o.addEventListener(evtName,evtHandler,false);
     121    return o.addEventListener(evtName, evtHandler, false);
    125122  } : function(o, evtName, evtHandler) {
    126     o.attachEvent('on'+evtName,evtHandler);
     123    o.attachEvent('on' + evtName, evtHandler);
    127124  });
    128125
    129126  this.removeEventHandler = (typeof window.removeEventListener !== 'undefined' ? function(o, evtName, evtHandler) {
    130     return o.removeEventListener(evtName,evtHandler,false);
     127    return o.removeEventListener(evtName, evtHandler, false);
    131128  } : function(o, evtName, evtHandler) {
    132     return o.detachEvent('on'+evtName,evtHandler);
     129    return o.detachEvent('on' + evtName, evtHandler);
    133130  });
    134131
    135   this.hasClass = function(o,cStr) {
    136     return typeof(o.className)!=='undefined'?o.className.match(new RegExp('(\\s|^)'+cStr+'(\\s|$)')):false;
    137   };
    138 
    139   this.addClass = function(o,cStr) {
    140 
    141     if (!o || !cStr || self.hasClass(o,cStr)) {
    142       return false;
    143     }
    144     o.className = (o.className?o.className+' ':'')+cStr;
    145 
    146   };
    147 
    148   this.removeClass = function(o,cStr) {
    149 
    150     if (!o || !cStr || !self.hasClass(o,cStr)) {
    151       return false;
    152     }
    153     o.className = o.className.replace(new RegExp('( '+cStr+')|('+cStr+')','g'),'');
    154 
    155   };
    156 
    157   this.getElementsByClassName = function(className,tagNames,oParent) {
    158 
    159     var doc = (oParent||document),
    160         matches = [], i,j, nodes = [];
     132  this.hasClass = function(o, cStr) {
     133    return typeof (o.className) !== 'undefined' ? o.className.match(new RegExp('(\\s|^)' + cStr + '(\\s|$)')) : false;
     134  };
     135
     136  this.addClass = function(o, cStr) {
     137
     138    if (!o || !cStr || self.hasClass(o, cStr)) {
     139      return;
     140    }
     141    o.className = (o.className ? o.className + ' ' : '') + cStr;
     142
     143  };
     144
     145  this.removeClass = function(o, cStr) {
     146
     147    if (!o || !cStr || !self.hasClass(o, cStr)) {
     148      return;
     149    }
     150    o.className = o.className.replace(new RegExp('( ' + cStr + ')|(' + cStr + ')', 'g'), '');
     151
     152  };
     153
     154  this.getElementsByClassName = function(className, tagNames, oParent) {
     155
     156    var doc = (oParent || document),
     157        matches = [], i, j, nodes = [];
    161158    if (typeof tagNames !== 'undefined' && typeof tagNames !== 'string') {
    162       for (i=tagNames.length; i--;) {
     159      for (i = tagNames.length; i--;) {
    163160        if (!nodes || !nodes[tagNames[i]]) {
    164161          nodes[tagNames[i]] = doc.getElementsByTagName(tagNames[i]);
     
    168165      nodes = doc.getElementsByTagName(tagNames);
    169166    } else {
    170       nodes = doc.all||doc.getElementsByTagName('*');
    171     }
    172     if (typeof(tagNames)!=='string') {
    173       for (i=tagNames.length; i--;) {
    174         for (j=nodes[tagNames[i]].length; j--;) {
    175           if (self.hasClass(nodes[tagNames[i]][j],className)) {
     167      nodes = doc.all || doc.getElementsByTagName('*');
     168    }
     169    if (typeof (tagNames) !== 'string') {
     170      for (i = tagNames.length; i--;) {
     171        for (j = nodes[tagNames[i]].length; j--;) {
     172          if (self.hasClass(nodes[tagNames[i]][j], className)) {
    176173            matches.push(nodes[tagNames[i]][j]);
    177174          }
     
    179176      }
    180177    } else {
    181       for (i=0; i<nodes.length; i++) {
    182         if (self.hasClass(nodes[i],className)) {
     178      for (i = 0; i < nodes.length; i++) {
     179        if (self.hasClass(nodes[i], className)) {
    183180          matches.push(nodes[i]);
    184181        }
     
    189186  };
    190187
    191   this.getParentByNodeName = function(oChild,sParentNodeName) {
     188  this.getParentByNodeName = function(oChild, sParentNodeName) {
    192189
    193190    if (!oChild || !sParentNodeName) {
     
    198195      oChild = oChild.parentNode;
    199196    }
    200     return (oChild.parentNode && sParentNodeName === oChild.parentNode.nodeName.toLowerCase()?oChild.parentNode:null);
    201 
    202   };
    203 
    204   this.getParentByClassName = function(oChild,sParentClassName) {
     197    return (oChild.parentNode && sParentNodeName === oChild.parentNode.nodeName.toLowerCase() ? oChild.parentNode : null);
     198
     199  };
     200
     201  this.getParentByClassName = function(oChild, sParentClassName) {
    205202
    206203    if (!oChild || !sParentClassName) {
    207       return false;
    208     }
    209     while (oChild.parentNode && !self.hasClass(oChild.parentNode,sParentClassName)) {
     204      return null;
     205    }
     206    while (oChild.parentNode && !self.hasClass(oChild.parentNode, sParentClassName)) {
    210207      oChild = oChild.parentNode;
    211208    }
    212     return (oChild.parentNode && self.hasClass(oChild.parentNode,sParentClassName)?oChild.parentNode:null);
     209    return (oChild.parentNode && self.hasClass(oChild.parentNode, sParentClassName) ? oChild.parentNode : null);
    213210
    214211  };
    215212
    216213  this.getSoundByURL = function(sURL) {
    217     return (typeof self.soundsByURL[sURL] !== 'undefined'?self.soundsByURL[sURL]:null);
    218   };
    219 
    220   this.isChildOfNode = function(o,sNodeName) {
     214    return (typeof self.soundsByURL[sURL] !== 'undefined' ? self.soundsByURL[sURL] : null);
     215  };
     216
     217  this.isChildOfNode = function(o, sNodeName) {
    221218
    222219    if (!o || !o.parentNode) {
     
    227224      o = o.parentNode;
    228225    } while (o && o.parentNode && o.nodeName.toLowerCase() !== sNodeName);
    229     return (o && o.nodeName.toLowerCase() === sNodeName?o:null);
    230 
    231   };
    232 
    233   this.isChildOfClass = function(oChild,oClass) {
     226    return (o && o.nodeName.toLowerCase() === sNodeName ? o : null);
     227
     228  };
     229
     230  this.isChildOfClass = function(oChild, oClass) {
    234231
    235232    if (!oChild || !oClass) {
    236233      return false;
    237234    }
    238     while (oChild.parentNode && !self.hasClass(oChild,oClass)) {
     235    while (oChild.parentNode && !self.hasClass(oChild, oClass)) {
    239236      oChild = self.findParent(oChild);
    240237    }
    241     return (self.hasClass(oChild,oClass));
     238    return (self.hasClass(oChild, oClass));
    242239
    243240  };
     
    258255  };
    259256
    260   this.getStyle = function(o,sProp) {
     257  this.getStyle = function(o, sProp) {
    261258
    262259    // http://www.quirksmode.org/dom/getstyles.html
     
    265262        return o.currentStyle[sProp];
    266263      } else if (window.getComputedStyle) {
    267         return document.defaultView.getComputedStyle(o,null).getPropertyValue(sProp);
     264        return document.defaultView.getComputedStyle(o, null).getPropertyValue(sProp);
    268265      }
    269266    } catch(e) {
     
    280277      curleft += obj.offsetLeft;
    281278      curtop += obj.offsetTop;
    282     } while (!!(obj = obj.offsetParent));
    283     return [curleft,curtop];
     279    } while (obj = obj.offsetParent);
     280    return [curleft, curtop];
    284281
    285282  };
     
    288285
    289286    // http://www.quirksmode.org/js/events_properties.html
    290     e = e?e:window.event;
     287    e = e || window.event;
    291288    if (isTouchDevice && e.touches) {
    292289      e = e.touches[0];
    293290    }
    294291    if (e.pageX || e.pageY) {
    295       return [e.pageX,e.pageY];
     292      return [e.pageX, e.pageY];
    296293    } else if (e.clientX || e.clientY) {
    297       return [e.clientX+self.getScrollLeft(),e.clientY+self.getScrollTop()];
    298     }
     294      return [e.clientX + self.getScrollLeft(), e.clientY + self.getScrollTop()];
     295    }
     296    return [undefined, undefined];
    299297
    300298  };
    301299
    302300  this.getScrollLeft = function() {
    303     return (document.body.scrollLeft+document.documentElement.scrollLeft);
     301    return (document.body.scrollLeft + document.documentElement.scrollLeft);
    304302  };
    305303
    306304  this.getScrollTop = function() {
    307     return (document.body.scrollTop+document.documentElement.scrollTop);
     305    return (document.body.scrollTop + document.documentElement.scrollTop);
    308306  };
    309307
     
    313311
    314312    play: function() {
    315       pl.removeClass(this._360data.oUIBox,this._360data.className);
     313      pl.removeClass(this._360data.oUIBox, this._360data.className);
    316314      this._360data.className = pl.css.sPlaying;
    317       pl.addClass(this._360data.oUIBox,this._360data.className);
     315      pl.addClass(this._360data.oUIBox, this._360data.className);
    318316      self.fanOut(this);
    319317    },
    320318
    321319    stop: function() {
    322       pl.removeClass(this._360data.oUIBox,this._360data.className);
     320      pl.removeClass(this._360data.oUIBox, this._360data.className);
    323321      this._360data.className = '';
    324322      self.fanIn(this);
     
    326324
    327325    pause: function() {
    328       pl.removeClass(this._360data.oUIBox,this._360data.className);
     326      pl.removeClass(this._360data.oUIBox, this._360data.className);
    329327      this._360data.className = pl.css.sPaused;
    330       pl.addClass(this._360data.oUIBox,this._360data.className);
     328      pl.addClass(this._360data.oUIBox, this._360data.className);
    331329    },
    332330
    333331    resume: function() {
    334       pl.removeClass(this._360data.oUIBox,this._360data.className);
     332      pl.removeClass(this._360data.oUIBox, this._360data.className);
    335333      this._360data.className = pl.css.sPlaying;
    336       pl.addClass(this._360data.oUIBox,this._360data.className);     
     334      pl.addClass(this._360data.oUIBox, this._360data.className);
    337335    },
    338336
    339337    finish: function() {
    340338      var nextLink;
    341       pl.removeClass(this._360data.oUIBox,this._360data.className);
     339      pl.removeClass(this._360data.oUIBox, this._360data.className);
    342340      this._360data.className = '';
    343341      // self.clearCanvas(this._360data.oCanvas);
     
    345343      self.fanIn(this);
    346344      if (pl.config.playNext) {
    347         nextLink = (pl.indexByURL[this._360data.oLink.href]+1);
    348         if (nextLink<pl.links.length) {
    349           pl.handleClick({'target':pl.links[nextLink]});
     345        nextLink = (pl.indexByURL[this._360data.oLink.href] + 1);
     346        if (nextLink < pl.links.length) {
     347          pl.handleClick({ target: pl.links[nextLink] });
    350348        }
    351349      }
     
    365363    bufferchange: function() {
    366364      if (this.isBuffering) {
    367         pl.addClass(this._360data.oUIBox,pl.css.sBuffering);
     365        pl.addClass(this._360data.oUIBox, pl.css.sBuffering);
    368366      } else {
    369         pl.removeClass(this._360data.oUIBox,pl.css.sBuffering);
     367        pl.removeClass(this._360data.oUIBox, pl.css.sBuffering);
    370368      }
    371369    }
     
    384382  };
    385383
    386   this.getTheDamnLink = (isIE)?function(e) {
     384  this.getTheDamnLink = (isIE) ? function(e) {
    387385    // I really didn't want to have to do this.
    388     return (e && e.target?e.target:window.event.srcElement);
    389   }:function(e) {
     386    return (e && e.target ? e.target : window.event.srcElement);
     387  } : function(e) {
    390388    return e.target;
    391389  };
     
    400398
    401399    var o = self.getTheDamnLink(e),
    402         canvasElements, sURL, soundURL, thisSound, oContainer, has_vis, diameter;
     400        canvasElements, soundURL, thisSound, oContainer, has_vis, diameter;
    403401
    404402    if (o.nodeName.toLowerCase() !== 'a') {
    405       o = self.isChildOfNode(o,'a');
     403      o = self.isChildOfNode(o, 'a');
    406404      if (!o) {
    407405        return true;
     
    409407    }
    410408
    411     if (!self.isChildOfClass(o,'ui360')) {
     409    if (!self.isChildOfClass(o, 'ui360')) {
    412410      // not a link we're interested in
    413411      return true;
    414412    }
    415413
    416     sURL = o.getAttribute('href');
    417 
    418     if (!o.href || !sm.canPlayLink(o) || self.hasClass(o,self.excludeClass)) {
     414    if (!o.href || !sm.canPlayLink(o) || self.hasClass(o, self.excludeClass)) {
    419415      return true; // pass-thru for non-MP3/non-links
    420416    }
     
    433429        // different sound
    434430        thisSound.togglePause(); // start playing current
    435         sm._writeDebug('sound different than last sound: '+self.lastSound.id);
     431        sm._writeDebug('sound different than last sound: ' + self.lastSound.id);
    436432        if (!self.config.allowMultiple && self.lastSound) {
    437433          self.stopSound(self.lastSound);
     
    444440
    445441      oContainer = o.parentNode;
    446       has_vis = (self.getElementsByClassName('ui360-vis','div',oContainer.parentNode).length);
     442      has_vis = (self.getElementsByClassName('ui360-vis', 'div', oContainer.parentNode).length);
    447443
    448444      // create sound
    449445      thisSound = sm.createSound({
    450        id:'ui360Sound'+(self.soundCount++),
    451        url:soundURL,
    452        onplay:self.events.play,
    453        onstop:self.events.stop,
    454        onpause:self.events.pause,
    455        onresume:self.events.resume,
    456        onfinish:self.events.finish,
    457        onbufferchange:self.events.bufferchange,
    458        type:(o.type||null),
    459        whileloading:self.events.whileloading,
    460        whileplaying:self.events.whileplaying,
    461        useWaveformData:(has_vis && self.config.useWaveformData),
    462        useEQData:(has_vis && self.config.useEQData),
    463        usePeakData:(has_vis && self.config.usePeakData)
     446       id: 'ui360Sound' + (self.soundCount++),
     447       url: soundURL,
     448       onplay: self.events.play,
     449       onstop: self.events.stop,
     450       onpause: self.events.pause,
     451       onresume: self.events.resume,
     452       onfinish: self.events.finish,
     453       onbufferchange: self.events.bufferchange,
     454       type: (o.type || null),
     455       whileloading: self.events.whileloading,
     456       whileplaying: self.events.whileplaying,
     457       useWaveformData: (has_vis && self.config.useWaveformData),
     458       useEQData: (has_vis && self.config.useEQData),
     459       usePeakData: (has_vis && self.config.usePeakData)
    464460      });
    465461
    466462      // tack on some custom data
    467463
    468       diameter = parseInt(self.getElementsByClassName('sm2-360ui','div',oContainer)[0].offsetWidth * hiDPIScale, 10);
     464      diameter = parseInt(self.getElementsByClassName('sm2-360ui', 'div', oContainer)[0].offsetWidth * hiDPIScale, 10);
    469465
    470466      // see note re: IE <9 and excanvas when Modernizr is included, making weird things happen with <canvas>.
    471       canvasElements = self.getElementsByClassName('sm2-canvas','canvas',oContainer),
     467      canvasElements = self.getElementsByClassName('sm2-canvas', 'canvas', oContainer);
    472468
    473469      thisSound._360data = {
    474         oUI360: self.getParentByClassName(o,'ui360'), // the (whole) entire container
     470        oUI360: self.getParentByClassName(o, 'ui360'), // the (whole) entire container
    475471        oLink: o, // DOM node for reference within SM2 object event handlers
    476472        className: self.css.sPlaying,
    477         oUIBox: self.getElementsByClassName('sm2-360ui','div',oContainer)[0],
    478         oCanvas: canvasElements[canvasElements.length-1],
    479         oButton: self.getElementsByClassName('sm2-360btn','span',oContainer)[0],
    480         oTiming: self.getElementsByClassName('sm2-timing','div',oContainer)[0],
    481         oCover: self.getElementsByClassName('sm2-cover','div',oContainer)[0],
     473        oUIBox: self.getElementsByClassName('sm2-360ui', 'div', oContainer)[0],
     474        oCanvas: canvasElements[canvasElements.length - 1],
     475        oButton: self.getElementsByClassName('sm2-360btn', 'span', oContainer)[0],
     476        oTiming: self.getElementsByClassName('sm2-timing', 'div', oContainer)[0],
     477        oCover: self.getElementsByClassName('sm2-cover', 'div', oContainer)[0],
    482478        circleDiameter: diameter,
    483         circleRadius: diameter/2,
     479        circleRadius: diameter / 2,
    484480        lastTime: null,
    485481        didFinish: null,
    486         pauseCount:0,
    487         radius:0,
     482        pauseCount: 0,
     483        radius: 0,
    488484        fontSize: 1,
    489485        fontSizeMax: self.config.fontSizeMax,
    490486        scaleFont: (has_vis && self.config.scaleFont),
    491487        showHMSTime: has_vis,
    492         amplifier: (has_vis && self.config.usePeakData?0.9:1), // TODO: x1 if not being used, else use dynamic "how much to amplify by" value
    493         radiusMax: diameter*0.175, // circle radius
    494         width:0,
    495         widthMax: diameter*0.4, // width of the outer ring
     488        amplifier: (has_vis && self.config.usePeakData ? 0.9 : 1), // TODO: x1 if not being used, else use dynamic "how much to amplify by" value
     489        radiusMax: diameter * 0.175, // circle radius
     490        width: 0,
     491        widthMax: diameter * 0.4, // width of the outer ring
    496492        lastValues: {
    497493          bytesLoaded: 0,
     
    503499        oAnim: new window.Animator({
    504500          duration: self.config.animDuration,
    505           transition:self.config.animTransition,
     501          transition: self.config.animTransition,
    506502          onComplete: function() {
    507503            // var thisSound = this;
     
    510506        }),
    511507        oAnimProgress: function(nProgress) {
    512           var thisSound = this;
    513           thisSound._360data.radius = parseInt(thisSound._360data.radiusMax*thisSound._360data.amplifier*nProgress, 10);
    514           thisSound._360data.width = parseInt(thisSound._360data.widthMax*thisSound._360data.amplifier*nProgress, 10);
    515           if (thisSound._360data.scaleFont && thisSound._360data.fontSizeMax !== null) {
    516             thisSound._360data.oTiming.style.fontSize = parseInt(Math.max(1,thisSound._360data.fontSizeMax*nProgress), 10)+'px';
    517             thisSound._360data.oTiming.style.opacity = nProgress;
     508          var s = this;
     509          s._360data.radius = parseInt(s._360data.radiusMax * s._360data.amplifier * nProgress, 10);
     510          s._360data.width = parseInt(s._360data.widthMax * s._360data.amplifier * nProgress, 10);
     511          if (s._360data.scaleFont && s._360data.fontSizeMax !== null) {
     512            s._360data.oTiming.style.fontSize = parseInt(Math.max(1, s._360data.fontSizeMax * nProgress), 10) + 'px';
     513            s._360data.oTiming.style.opacity = nProgress;
    518514          }
    519           if (thisSound.paused || thisSound.playState === 0 || thisSound._360data.lastValues.bytesLoaded === 0 || thisSound._360data.lastValues.position === 0) {
    520             self.updatePlaying.apply(thisSound);
     515          if (s.paused || s.playState === 0 || s._360data.lastValues.bytesLoaded === 0 || s._360data.lastValues.position === 0) {
     516            self.updatePlaying.apply(s);
    521517          }
    522518        },
     
    525521
    526522      // "Metadata" (annotations)
    527       if (typeof self.Metadata !== 'undefined' && self.getElementsByClassName('metadata','div',thisSound._360data.oUI360).length) {
    528         thisSound._360data.metadata = new self.Metadata(thisSound,self);
     523      if (typeof self.Metadata !== 'undefined' && self.getElementsByClassName('metadata', 'div', thisSound._360data.oUI360).length) {
     524        thisSound._360data.metadata = new self.Metadata(thisSound, self);
    529525      }
    530526
     
    535531
    536532      // set up ze animation
    537       thisSound._360data.oAnim.addSubject(thisSound._360data.oAnimProgress,thisSound);
     533      thisSound._360data.oAnim.addSubject(thisSound._360data.oAnimProgress, thisSound);
    538534
    539535      // animate the radius out nice
     
    566562     var thisSound = oSound;
    567563     if (thisSound._360data.animating === 1) {
    568        return false;
     564       return;
    569565     }
    570566     thisSound._360data.animating = 0;
    571      soundManager._writeDebug('fanOut: '+thisSound.id+': '+thisSound._360data.oLink.href);
     567     soundManager._writeDebug('fanOut: ' + thisSound.id + ': ' + thisSound._360data.oLink.href);
    572568     thisSound._360data.oAnim.seekTo(1); // play to end
    573569     window.setTimeout(function() {
    574570       // oncomplete hack
    575571       thisSound._360data.animating = 0;
    576      },self.config.animDuration+20);
     572     }, self.config.animDuration + 20);
    577573
    578574  };
     
    582578     var thisSound = oSound;
    583579     if (thisSound._360data.animating === -1) {
    584        return false;
     580       return;
    585581     }
    586582     thisSound._360data.animating = -1;
    587      soundManager._writeDebug('fanIn: '+thisSound.id+': '+thisSound._360data.oLink.href);
     583     soundManager._writeDebug('fanIn: ' + thisSound.id + ': ' + thisSound._360data.oLink.href);
    588584     // massive hack
    589585     thisSound._360data.oAnim.seekTo(0); // play to end
     
    593589       thisSound._360data.animating = 0;
    594590       self.resetLastValues(thisSound);
    595      }, self.config.animDuration+20);
     591     }, self.config.animDuration + 20);
    596592
    597593  };
     
    604600
    605601    thisSound._360data.canvasXY = self.findXY(thisSound._360data.oCanvas);
    606     thisSound._360data.canvasMid = [thisSound._360data.circleRadius,thisSound._360data.circleRadius];
    607     thisSound._360data.canvasMidXY = [thisSound._360data.canvasXY[0]+thisSound._360data.canvasMid[0], thisSound._360data.canvasXY[1]+thisSound._360data.canvasMid[1]];
     602    thisSound._360data.canvasMid = [thisSound._360data.circleRadius, thisSound._360data.circleRadius];
     603    thisSound._360data.canvasMidXY = [thisSound._360data.canvasXY[0] + thisSound._360data.canvasMid[0], thisSound._360data.canvasXY[1] + thisSound._360data.canvasMid[1]];
    608604
    609605  };
     
    611607  this.stopSound = function(oSound) {
    612608
    613     soundManager._writeDebug('stopSound: '+oSound.id);
     609    soundManager._writeDebug('stopSound: ' + oSound.id);
    614610    soundManager.stop(oSound.id);
    615611    if (!isTouchDevice) { // iOS 4.2+ security blocks onfinish() -> playNext() if we set a .src in-between(?)
     
    621617  this.buttonClick = function(e) {
    622618
    623     var o = e?(e.target?e.target:e.srcElement):window.event.srcElement;
    624     self.handleClick({target:self.getParentByClassName(o,'sm2-360ui').nextSibling}); // link next to the nodes we inserted
     619    var o = e ? (e.target ? e.target : e.srcElement) : window.event.srcElement;
     620    self.handleClick({ target: self.getParentByClassName(o, 'sm2-360ui').nextSibling }); // link next to the nodes we inserted
    625621    return false;
    626622
    627623  };
    628624
    629   this.buttonMouseDown = function(e) {
     625  this.buttonMouseDown = function(ee) {
    630626
    631627    // user might decide to drag from here
    632628    // watch for mouse move
    633629    if (!isTouchDevice) {
    634       document.onmousemove = function(e) {
     630      document.onmousemove = function(eee) {
    635631        // should be boundary-checked, really (eg. move 3px first?)
    636         self.mouseDown(e);
     632        self.mouseDown(eee);
    637633      };
    638634    } else {
    639       self.addEventHandler(document,'touchmove',self.mouseDown);
    640     }
    641     self.stopEvent(e);
     635      self.addEventHandler(document, 'touchmove', self.mouseDown);
     636    }
     637    self.stopEvent(ee);
    642638    return false;
    643639
    644640  };
    645641
    646   this.mouseDown = function(e) {
    647 
    648     if (!isTouchDevice && e.button > 1) {
     642  this.mouseDown = function(ee) {
     643
     644    if (!isTouchDevice && ee.button > 1) {
    649645      return true; // ignore non-left-click
    650646    }
    651647
    652648    if (!self.lastSound) {
    653       self.stopEvent(e);
     649      self.stopEvent(ee);
    654650      return false;
    655651    }
    656652
    657     var evt = e?e:window.event,
     653    var evt = ee || window.event,
    658654        target, thisSound, oData;
    659655
     
    661657      evt = evt.touches[0];
    662658    }
    663     target = (evt.target||evt.srcElement);
    664 
    665     thisSound = self.getSoundByURL(self.getElementsByClassName('sm2_link','a',self.getParentByClassName(target,'ui360'))[0].href); // self.lastSound; // TODO: In multiple sound case, figure out which sound is involved etc.
     659    target = (evt.target || evt.srcElement);
     660
     661    thisSound = self.getSoundByURL(self.getElementsByClassName('sm2_link', 'a', self.getParentByClassName(target, 'ui360'))[0].href); // self.lastSound; // TODO: In multiple sound case, figure out which sound is involved etc.
    666662    // just in case, update coordinates (maybe the element moved since last time.)
    667663    self.lastTouchedSound = thisSound;
    668664    self.refreshCoords(thisSound);
    669665    oData = thisSound._360data;
    670     self.addClass(oData.oUIBox,'sm2_dragging');
    671     oData.pauseCount = (self.lastTouchedSound.paused?1:0);
     666    self.addClass(oData.oUIBox, 'sm2_dragging');
     667    oData.pauseCount = (self.lastTouchedSound.paused ? 1 : 0);
    672668    // self.lastSound.pause();
    673     self.mmh(e?e:window.event);
     669    self.mmh(ee || window.event);
    674670
    675671    if (isTouchDevice) {
    676       self.removeEventHandler(document,'touchmove',self.mouseDown);
    677       self.addEventHandler(document,'touchmove',self.mmh);
    678       self.addEventHandler(document,'touchend',self.mouseUp);
     672      self.removeEventHandler(document, 'touchmove', self.mouseDown);
     673      self.addEventHandler(document, 'touchmove', self.mmh);
     674      self.addEventHandler(document, 'touchend', self.mouseUp);
    679675    } else {
    680676      // incredibly old-skool. TODO: Modernize.
     
    683679    }
    684680
    685     self.stopEvent(e);
     681    self.stopEvent(ee);
    686682    return false;
    687683
    688684  };
    689685
    690   this.mouseUp = function(e) {
     686  this.mouseUp = function(/*ee*/) {
    691687
    692688    var oData = self.lastTouchedSound._360data;
    693     self.removeClass(oData.oUIBox,'sm2_dragging');
     689    self.removeClass(oData.oUIBox, 'sm2_dragging');
    694690    if (oData.pauseCount === 0) {
    695691      self.lastTouchedSound.resume();
     
    699695      document.onmouseup = null;
    700696    } else {
    701       self.removeEventHandler(document,'touchmove',self.mmh);
    702       self.removeEventHandler(document,'touchend',self.mouseUP);
    703     }
    704 
    705   };
    706 
    707   this.mmh = function(e) {
    708 
    709     if (typeof e === 'undefined') {
    710       e = window.event;
     697      self.removeEventHandler(document, 'touchmove', self.mmh);
     698      self.removeEventHandler(document, 'touchend', self.mouseUP);
     699    }
     700
     701  };
     702
     703  this.mmh = function(ee) {
     704
     705    if (typeof ee === 'undefined') {
     706      ee = window.event;
    711707    }
    712708    var oSound = self.lastTouchedSound,
    713         coords = self.getMouseXY(e),
     709        coords = self.getMouseXY(ee),
    714710        x = coords[0],
    715711        y = coords[1],
    716         deltaX = x-oSound._360data.canvasMidXY[0],
    717         deltaY = y-oSound._360data.canvasMidXY[1],
    718         angle = Math.floor(fullCircle-(self.rad2deg(Math.atan2(deltaX,deltaY))+180));
    719 
    720     oSound.setPosition(oSound.durationEstimate*(angle/fullCircle));
    721     self.stopEvent(e);
     712        deltaX = x - oSound._360data.canvasMidXY[0],
     713        deltaY = y - oSound._360data.canvasMidXY[1],
     714        angle = Math.floor(fullCircle - (self.rad2deg(Math.atan2(deltaX, deltaY)) + 180));
     715
     716    oSound.setPosition(oSound.durationEstimate * (angle / fullCircle));
     717    self.stopEvent(ee);
    722718    return false;
    723719
     
    730726    // thank you, http://www.snipersystems.co.nz/community/polarclock/tutorial.html
    731727
    732     var x = radius,
    733         y = radius,
    734         canvas = oCanvas,
     728    var canvas = oCanvas,
    735729        ctx, innerRadius, doesntLikeZero, endPoint;
    736730
     
    758752    }
    759753
    760     innerRadius = radius-width;
     754    innerRadius = radius - width;
    761755    doesntLikeZero = (isOpera || isSafari); // safari 4 doesn't actually seem to mind.
    762756
     
    775769
    776770    return {
    777       x: radius * Math.cos(radians), 
     771      x: radius * Math.cos(radians),
    778772      y: radius * Math.sin(radians)
    779773    };
     
    782776
    783777  this.deg2rad = function(nDeg) {
    784     return (nDeg * Math.PI/180);
     778    return (nDeg * (Math.PI / 180));
    785779  };
    786780
    787781  this.rad2deg = function(nRad) {
    788     return (nRad * 180/Math.PI);
    789   };
    790 
    791   this.getTime = function(nMSec,bAsString) {
     782    return (nRad * (180 / Math.PI));
     783  };
     784
     785  this.getTime = function(nMSec, bAsString) {
    792786
    793787    // convert milliseconds to mm:ss, return as object literal or string
    794     var nSec = Math.floor(nMSec/1000),
    795         min = Math.floor(nSec/60),
    796         sec = nSec-(min*60);
     788    var nSec = Math.floor(nMSec / 1000),
     789        min = Math.floor(nSec / 60),
     790        sec = nSec - (min * 60);
    797791    // if (min === 0 && sec === 0) return null; // return 0:00 as null
    798     return (bAsString?(min+':'+(sec<10?'0'+sec:sec)):{'min':min,'sec':sec});
     792    return (bAsString ? (min + ':' + (sec < 10 ? '0' + sec : sec)) : { min: min, sec: sec });
    799793
    800794  };
     
    814808      width = canvas.offsetWidth;
    815809      height = canvas.offsetHeight;
    816       ctx.clearRect(-(width/2), -(height/2), width, height);
     810      ctx.clearRect(-(width / 2), -(height / 2), width, height);
    817811    }
    818812
     
    821815  this.updatePlaying = function() {
    822816
    823     var timeNow = (this._360data.showHMSTime?self.getTime(this.position,true):parseInt(this.position/1000, 10));
     817    var timeNow = (this._360data.showHMSTime ? self.getTime(this.position, true) : parseInt(this.position / 1000, 10));
    824818    var ringScaleFactor = self.config.scaleArcWidth;
    825819
     
    838832
    839833    // background ring
    840     self.drawSolidArc(this._360data.oCanvas,self.config.backgroundRingColor,this._360data.width,this._360data.radius * ringScaleFactor,self.deg2rad(fullCircle),false);
     834    self.drawSolidArc(this._360data.oCanvas, self.config.backgroundRingColor, this._360data.width, this._360data.radius * ringScaleFactor, self.deg2rad(fullCircle), false);
    841835
    842836    // loaded ring
    843     self.drawSolidArc(this._360data.oCanvas,(this._360data.metadata?self.config.loadRingColorMetadata:self.config.loadRingColor),this._360data.width,this._360data.radius * ringScaleFactor,self.deg2rad(fullCircle*(this._360data.lastValues.bytesLoaded/this._360data.lastValues.bytesTotal)),0,true);
     837    self.drawSolidArc(this._360data.oCanvas, (this._360data.metadata ? self.config.loadRingColorMetadata : self.config.loadRingColor), this._360data.width, this._360data.radius * ringScaleFactor, self.deg2rad(fullCircle * (this._360data.lastValues.bytesLoaded / this._360data.lastValues.bytesTotal)), 0, true);
    844838
    845839    // don't draw if 0 (full black circle in Opera)
    846840    if (this._360data.lastValues.position !== 0) {
    847       self.drawSolidArc(this._360data.oCanvas,(this._360data.metadata?self.config.playRingColorMetadata:self.config.playRingColor),this._360data.width,this._360data.radius * ringScaleFactor,self.deg2rad((this._360data.didFinish===1?fullCircle:fullCircle*(this._360data.lastValues.position/this._360data.lastValues.durationEstimate))),0,true);
     841      self.drawSolidArc(this._360data.oCanvas, (this._360data.metadata ? self.config.playRingColorMetadata : self.config.playRingColor), this._360data.width, this._360data.radius * ringScaleFactor, self.deg2rad((this._360data.didFinish === 1 ? fullCircle : fullCircle * (this._360data.lastValues.position / this._360data.lastValues.durationEstimate))), 0, true);
    848842    }
    849843
     
    873867    if ((!self.config.useWaveformData && !self.config.useEQData) || (!sm.features.waveformData && !sm.features.eqData)) {
    874868      // feature not enabled..
    875       return false;
     869      return;
    876870    }
    877871
    878872    if (!oSound.waveformData.left.length && !oSound.eqData.length && !oSound.peakData.left) {
    879873      // no data (or errored out/paused/unavailable?)
    880       return false;
     874      return;
    881875    }
    882876
     
    888882    */
    889883
    890     var oCanvas = oSound._360data.oCanvas.getContext('2d'),
    891         offX = 0,
    892         offY = parseInt(oSound._360data.circleDiameter/2, 10),
    893         scale = offY/2, // Y axis (+/- this distance from 0)
    894         // lineWidth = Math.floor(oSound._360data.circleDiameter-(oSound._360data.circleDiameter*0.175)/(oSound._360data.circleDiameter/255)); // width for each line
    895         lineWidth = 1,
    896         lineHeight = 1,
    897         thisY = 0,
    898         offset = offY,
    899         i, j, direction, downSample, dataLength, sampleCount, startAngle, endAngle, waveData, innerRadius, perItemAngle, yDiff, eqSamples, playedAngle, iAvg, nPeak;
     884    var offY = parseInt(oSound._360data.circleDiameter / 2, 10),
     885        scale = offY / 2, // Y axis (+/- this distance from 0)
     886        i, direction, downSample, dataLength, sampleCount, startAngle, endAngle, waveData, innerRadius, perItemAngle, eqSamples, playedAngle, nPeak;
    900887
    901888    if (self.config.useWaveformData) {
    902889      // raw waveform
    903890      downSample = self.config.waveformDataDownsample; // only sample X in 256 (greater number = less sample points)
    904       downSample = Math.max(1,downSample); // make sure it's at least 1
     891      downSample = Math.max(1, downSample); // make sure it's at least 1
    905892      dataLength = 256;
    906       sampleCount = (dataLength/downSample);
     893      sampleCount = (dataLength / downSample);
    907894      startAngle = 0;
    908895      endAngle = 0;
    909896      waveData = null;
    910       innerRadius = (self.config.waveformDataOutside?1:(self.config.waveformDataConstrain?0.5:0.565));
    911       scale = (self.config.waveformDataOutside?0.7:0.75);
    912       perItemAngle = self.deg2rad((360/sampleCount)*self.config.waveformDataLineRatio); // 0.85 = clean pixel lines at 150? // self.deg2rad(360*(Math.max(1,downSample-1))/sampleCount);
    913       for (i=0; i<dataLength; i+=downSample) {
    914         startAngle = self.deg2rad(360*(i/(sampleCount)*1/downSample)); // +0.67 - counter for spacing
    915         endAngle = startAngle+perItemAngle;
     897      innerRadius = (self.config.waveformDataOutside ? 1 : (self.config.waveformDataConstrain ? 0.5 : 0.565));
     898      scale = (self.config.waveformDataOutside ? 0.7 : 0.75);
     899      perItemAngle = self.deg2rad((360 / sampleCount) * self.config.waveformDataLineRatio); // 0.85 = clean pixel lines at 150? // self.deg2rad(360*(Math.max(1,downSample-1))/sampleCount);
     900      for (i = 0; i < dataLength; i += downSample) {
     901        startAngle = self.deg2rad(360 * ((i / sampleCount) * (1 / downSample))); // +0.67 - counter for spacing
     902        endAngle = startAngle + perItemAngle;
    916903        waveData = oSound.waveformData.left[i];
    917         if (waveData<0 && self.config.waveformDataConstrain) {
     904        if (waveData < 0 && self.config.waveformDataConstrain) {
    918905          waveData = Math.abs(waveData);
    919906        }
    920         self.drawSolidArc(oSound._360data.oCanvas,self.config.waveformDataColor,oSound._360data.width*innerRadius*(2-self.config.scaleArcWidth),oSound._360data.radius*scale*1.25*waveData,endAngle,startAngle,true);
     907        self.drawSolidArc(oSound._360data.oCanvas, self.config.waveformDataColor, oSound._360data.width * innerRadius * (2 - self.config.scaleArcWidth), oSound._360data.radius * scale * 1.25 * waveData, endAngle, startAngle, true);
    921908      }
    922909    }
     
    925912      // EQ spectrum
    926913      downSample = self.config.eqDataDownsample; // only sample N in 256
    927       yDiff = 0;
    928       downSample = Math.max(1,downSample); // make sure it's at least 1
     914      downSample = Math.max(1, downSample); // make sure it's at least 1
    929915      eqSamples = 192; // drop the last 25% of the spectrum (>16500 Hz), most stuff won't actually use it.
    930       sampleCount = (eqSamples/downSample);
    931       innerRadius = (self.config.eqDataOutside?1:0.565);
    932       direction = (self.config.eqDataOutside?-1:1);
    933       scale = (self.config.eqDataOutside?0.5:0.75);
     916      sampleCount = (eqSamples / downSample);
     917      innerRadius = (self.config.eqDataOutside ? 1 : 0.565);
     918      direction = (self.config.eqDataOutside ? -1 : 1);
     919      scale = (self.config.eqDataOutside ? 0.5 : 0.75);
    934920      startAngle = 0;
    935921      endAngle = 0;
    936       perItemAngle = self.deg2rad((360/sampleCount)*self.config.eqDataLineRatio); // self.deg2rad(360/(sampleCount+1));
    937       playedAngle = self.deg2rad((oSound._360data.didFinish===1?360:360*(oSound._360data.lastValues.position/oSound._360data.lastValues.durationEstimate)));
    938       j=0;
    939       iAvg = 0;
    940       for (i=0; i<eqSamples; i+=downSample) {
    941         startAngle = self.deg2rad(360*(i/eqSamples));
    942         endAngle = startAngle+perItemAngle;
    943         self.drawSolidArc(oSound._360data.oCanvas,(endAngle>playedAngle?self.config.eqDataColor:self.config.playRingColor),oSound._360data.width*innerRadius,oSound._360data.radius*scale*(oSound.eqData.left[i]*direction),endAngle,startAngle,true);
     922      perItemAngle = self.deg2rad((360 / sampleCount) * self.config.eqDataLineRatio); // self.deg2rad(360/(sampleCount+1));
     923      playedAngle = self.deg2rad((oSound._360data.didFinish === 1 ? 360 : 360 * (oSound._360data.lastValues.position / oSound._360data.lastValues.durationEstimate)));
     924      for (i = 0; i < eqSamples; i += downSample) {
     925        startAngle = self.deg2rad(360 * (i / eqSamples));
     926        endAngle = startAngle + perItemAngle;
     927        self.drawSolidArc(oSound._360data.oCanvas, (endAngle > playedAngle ? self.config.eqDataColor : self.config.playRingColor), oSound._360data.width * innerRadius, oSound._360data.radius * scale * (oSound.eqData.left[i] * direction), endAngle, startAngle, true);
    944928      }
    945929    }
     
    947931    if (self.config.usePeakData) {
    948932      if (!oSound._360data.animating) {
    949         nPeak = (oSound.peakData.left||oSound.peakData.right);
     933        nPeak = (oSound.peakData.left || oSound.peakData.right);
    950934        // GIANT HACK: use EQ spectrum data for bass frequencies
    951935        eqSamples = 3;
    952         for (i=0; i<eqSamples; i++) {
    953           nPeak = (nPeak||oSound.eqData[i]);
     936        for (i = 0; i < eqSamples; i++) {
     937          nPeak = (nPeak || oSound.eqData[i]);
    954938        }
    955         oSound._360data.amplifier = (self.config.useAmplifier?(0.9+(nPeak*0.1)):1);
    956         oSound._360data.radiusMax = oSound._360data.circleDiameter*0.175*oSound._360data.amplifier;
    957         oSound._360data.widthMax = oSound._360data.circleDiameter*0.4*oSound._360data.amplifier;
    958         oSound._360data.radius = parseInt(oSound._360data.radiusMax*oSound._360data.amplifier, 10);
    959         oSound._360data.width = parseInt(oSound._360data.widthMax*oSound._360data.amplifier, 10);
     939        oSound._360data.amplifier = (self.config.useAmplifier ? (0.9 + (nPeak * 0.1)) : 1);
     940        oSound._360data.radiusMax = oSound._360data.circleDiameter * 0.175 * oSound._360data.amplifier;
     941        oSound._360data.widthMax = oSound._360data.circleDiameter * 0.4 * oSound._360data.amplifier;
     942        oSound._360data.radius = parseInt(oSound._360data.radiusMax * oSound._360data.amplifier, 10);
     943        oSound._360data.width = parseInt(oSound._360data.widthMax * oSound._360data.amplifier, 10);
    960944      }
    961945    }
     
    966950
    967951    return [
    968      '<canvas class="sm2-canvas" width="'+diameter+'" height="'+diameter+'"></canvas>',
     952     '<canvas class="sm2-canvas" width="' + diameter + '" height="' + diameter + '"></canvas>',
    969953     ' <span class="sm2-360btn sm2-360btn-default"></span>', // note use of imageMap, edit or remove if you use a different-size image.
    970      ' <div class="sm2-timing'+(navigator.userAgent.match(/safari/i)?' alignTweak':'')+'"></div>', // + Ever-so-slight Safari horizontal alignment tweak
     954     ' <div class="sm2-timing' + (navigator.userAgent.match(/safari/i) ? ' alignTweak' : '') + '"></div>', // + Ever-so-slight Safari horizontal alignment tweak
    971955     ' <div class="sm2-cover"></div>'
    972956    ];
     
    984968
    985969    oFakeUI = document.createElement('div');
    986     oFakeUI.className = 'ui360'+(sClass?' '+sClass:''); // ui360 ui360-vis
     970    oFakeUI.className = 'ui360' + (sClass ? ' ' + sClass : ''); // ui360 ui360-vis
    987971
    988972    oFakeUIBox = oFakeUI.appendChild(oTemplate.cloneNode(true));
     
    997981    uiHTML = self.getUIHTML(fakeDiameter);
    998982
    999     oFakeUIBox.innerHTML = uiHTML[1]+uiHTML[2]+uiHTML[3];
     983    oFakeUIBox.innerHTML = uiHTML[1] + uiHTML[2] + uiHTML[3];
    1000984
    1001985    circleDiameter = parseInt(fakeDiameter, 10);
    1002     circleRadius = parseInt(circleDiameter/2, 10);
    1003 
    1004     oTiming = self.getElementsByClassName('sm2-timing','div',oTemp)[0];
    1005     fontSizeMax = parseInt(self.getStyle(oTiming,'font-size'), 10);
     986    circleRadius = parseInt(circleDiameter / 2, 10);
     987
     988    oTiming = self.getElementsByClassName('sm2-timing', 'div', oTemp)[0];
     989    fontSizeMax = parseInt(self.getStyle(oTiming, 'font-size'), 10);
    1006990    if (isNaN(fontSizeMax)) {
    1007991      // getStyle() etc. didn't work.
     
    10271011    sm._writeDebug('threeSixtyPlayer.init()');
    10281012
    1029     var oItems = self.getElementsByClassName('ui360','div'),
    1030         i, j, oLinks = [], is_vis = false, foundItems = 0, canvasElements, oCanvas, oCanvasCTX, oCover, diameter, radius, uiData, uiDataVis, oUI, oBtn, o, o2, oID;
    1031 
    1032     for (i=0,j=oItems.length; i<j; i++) {
     1013    var oItems = self.getElementsByClassName('ui360', 'div'),
     1014        i, j, oLinks = [], is_vis = false, foundItems = 0, canvasElements, oCanvas, oCanvasCTX, oCover, diameter, radius, uiData, uiDataVis, oUI, oBtn, o2, oID;
     1015
     1016    for (i = 0, j = oItems.length; i < j; i++) {
    10331017      oLinks.push(oItems[i].getElementsByTagName('a')[0]);
    10341018      // remove "fake" play button (unsupported case)
     
    10581042    self.oUITemplateVis.innerHTML = self.getUIHTML(uiDataVis.circleDiameter).join('');
    10591043
    1060     for (i=0,j=oLinks.length; i<j; i++) {
    1061       if (sm.canPlayLink(oLinks[i]) && !self.hasClass(oLinks[i],self.excludeClass) && !self.hasClass(oLinks[i],self.css.sDefault)) {
    1062         self.addClass(oLinks[i],self.css.sDefault); // add default CSS decoration
     1044    for (i = 0, j = oLinks.length; i < j; i++) {
     1045      if (sm.canPlayLink(oLinks[i]) && !self.hasClass(oLinks[i], self.excludeClass) && !self.hasClass(oLinks[i], self.css.sDefault)) {
     1046        self.addClass(oLinks[i], self.css.sDefault); // add default CSS decoration
    10631047        self.links[foundItems] = (oLinks[i]);
    10641048        self.indexByURL[oLinks[i].href] = foundItems; // hack for indexing
     
    10711055
    10721056        // add canvas shiz
    1073         oUI = oLinks[i].parentNode.insertBefore((is_vis?self.oUITemplateVis:self.oUITemplate).cloneNode(true),oLinks[i]);
     1057        oUI = oLinks[i].parentNode.insertBefore((is_vis ? self.oUITemplateVis : self.oUITemplate).cloneNode(true), oLinks[i]);
    10741058
    10751059        if (isIE && typeof window.G_vmlCanvasManager !== 'undefined') { // IE only
    1076           o = oLinks[i].parentNode;
    10771060          o2 = document.createElement('canvas');
    10781061          o2.className = 'sm2-canvas';
    1079           oID = 'sm2_canvas_'+i+(new Date().getTime());
     1062          oID = 'sm2_canvas_' + i + (new Date().getTime());
    10801063          o2.id = oID;
    10811064          o2.width = diameter;
     
    10901073           canvasElements = oCanvas.parentNode.getElementsByTagName('canvas');
    10911074           if (canvasElements.length > 1) {
    1092              oCanvas = canvasElements[canvasElements.length-1];
     1075             oCanvas = canvasElements[canvasElements.length - 1];
    10931076           }
    1094         } else { 
     1077        } else {
    10951078          // add a handler for the button
    10961079          oCanvas = oLinks[i].parentNode.getElementsByTagName('canvas')[0];
     
    11001083          self.addClass(oCanvas, 'hi-dpi');
    11011084        }
    1102         oCover = self.getElementsByClassName('sm2-cover','div',oLinks[i].parentNode)[0];
     1085        oCover = self.getElementsByClassName('sm2-cover', 'div', oLinks[i].parentNode)[0];
    11031086        oBtn = oLinks[i].parentNode.getElementsByTagName('span')[0];
    1104         self.addEventHandler(oBtn,'click',self.buttonClick);
     1087        self.addEventHandler(oBtn, 'click', self.buttonClick);
    11051088        if (!isTouchDevice) {
    1106           self.addEventHandler(oCover,'mousedown',self.mouseDown);
     1089          self.addEventHandler(oCover, 'mousedown', self.mouseDown);
    11071090        } else {
    1108           self.addEventHandler(oCover,'touchstart',self.mouseDown);
     1091          self.addEventHandler(oCover, 'touchstart', self.mouseDown);
    11091092        }
    11101093        oCanvasCTX = oCanvas.getContext('2d');
     
    11131096      }
    11141097    }
    1115     if (foundItems>0) {
    1116       self.addEventHandler(document,'click',self.handleClick);
     1098    if (foundItems > 0) {
     1099      self.addEventHandler(document, 'click', self.handleClick);
    11171100      if (self.config.autoPlay) {
    1118         self.handleClick({target:self.links[0],preventDefault:function(){}});
    1119       }
    1120     }
    1121     sm._writeDebug('threeSixtyPlayer.init(): Found '+foundItems+' relevant items.');
     1101        self.handleClick({ target: self.links[0], preventDefault: function() {} });
     1102      }
     1103    }
     1104    sm._writeDebug('threeSixtyPlayer.init(): Found ' + foundItems + ' relevant items.');
    11221105
    11231106    if (self.config.useFavIcon && typeof this.VUMeter !== 'undefined') {
     
    11451128
    11461129    if (!self.config.useFavIcon || !self.config.usePeakData || !sDataURL) {
    1147       return false;
     1130      return;
    11481131    }
    11491132
     
    11671150
    11681151    if (!self.config.useFavIcon) {
    1169       return false;
     1152      return;
    11701153    }
    11711154    var link = document.getElementById('favicon');
     
    11791162
    11801163    if (soundManager.flashVersion >= 9 && self.config.useFavIcon && self.config.usePeakData) {
    1181       me.setPageIcon(me.vuMeterData[parseInt(16*oSound.peakData.left, 10)][parseInt(16*oSound.peakData.right, 10)]);
     1164      me.setPageIcon(me.vuMeterData[parseInt(16 * oSound.peakData.left, 10)][parseInt(16 * oSound.peakData.right, 10)]);
    11821165    }
    11831166
     
    11861169  this.createVUData = function() {
    11871170
    1188     var i=0, j=0,
     1171    var i = 0, j = 0,
    11891172        canvas = me.vuDataCanvas.getContext('2d'),
    11901173        vuGrad = canvas.createLinearGradient(0, 16, 0, 0),
     
    11921175        outline = 'rgba(0,0,0,0.2)';
    11931176
    1194     vuGrad.addColorStop(0,'rgb(0,192,0)');
    1195     vuGrad.addColorStop(0.30,'rgb(0,255,0)');
    1196     vuGrad.addColorStop(0.625,'rgb(255,255,0)');
    1197     vuGrad.addColorStop(0.85,'rgb(255,0,0)');
    1198     bgGrad.addColorStop(0,outline);
    1199     bgGrad.addColorStop(1,'rgba(0,0,0,0.5)');
    1200     for (i=0; i<16; i++) {
     1177    vuGrad.addColorStop(0, 'rgb(0,192,0)');
     1178    vuGrad.addColorStop(0.30, 'rgb(0,255,0)');
     1179    vuGrad.addColorStop(0.625, 'rgb(255,255,0)');
     1180    vuGrad.addColorStop(0.85, 'rgb(255,0,0)');
     1181    bgGrad.addColorStop(0, outline);
     1182    bgGrad.addColorStop(1, 'rgba(0,0,0,0.5)');
     1183    for (i = 0; i < 16; i++) {
    12011184      me.vuMeterData[i] = [];
    12021185    }
    1203     for (i=0; i<16; i++) {
    1204       for (j=0; j<16; j++) {
     1186    for (i = 0; i < 16; i++) {
     1187      for (j = 0; j < 16; j++) {
    12051188        // reset/erase canvas
    1206         me.vuDataCanvas.setAttribute('width',16);
    1207         me.vuDataCanvas.setAttribute('height',16);
     1189        me.vuDataCanvas.setAttribute('width', 16);
     1190        me.vuDataCanvas.setAttribute('height', 16);
    12081191        // draw new stuffs
    12091192        canvas.fillStyle = bgGrad;
    1210         canvas.fillRect(0,0,7,15);
    1211         canvas.fillRect(8,0,7,15);
     1193        canvas.fillRect(0, 0, 7, 15);
     1194        canvas.fillRect(8, 0, 7, 15);
    12121195        /*
    12131196        // shadow
     
    12171200        */
    12181201        canvas.fillStyle = vuGrad;
    1219         canvas.fillRect(0,15-i,7,16-(16-i));
    1220         canvas.fillRect(8,15-j,7,16-(16-j));
     1202        canvas.fillRect(0, 15 - i, 7, 16 - (16 - i));
     1203        canvas.fillRect(8, 15 - j, 7, 16 - (16 - j));
    12211204        // and now, clear out some bits.
    1222         canvas.clearRect(0,3,16,1);
    1223         canvas.clearRect(0,7,16,1);
    1224         canvas.clearRect(0,11,16,1);
     1205        canvas.clearRect(0, 3, 16, 1);
     1206        canvas.clearRect(0, 7, 16, 1);
     1207        canvas.clearRect(0, 11, 16, 1);
    12251208        me.vuMeterData[i][j] = me.vuDataCanvas.toDataURL('image/png');
    12261209        // for debugging VU images
    12271210        /*
    12281211        var o = document.createElement('img');
    1229         o.style.marginRight = '5px'; 
     1212        o.style.marginRight = '5px';
    12301213        o.src = vuMeterData[i][j];
    12311214        document.documentElement.appendChild(o);
     
    12401223    // canvas + toDataURL();
    12411224    var c = document.createElement('canvas'),
    1242         ctx = null, ok;
     1225        ctx = null;
    12431226    if (!c || typeof c.getContext === 'undefined') {
    12441227      return null;
     
    12501233    // just in case..
    12511234    try {
    1252       ok = c.toDataURL('image/png');
     1235      c.toDataURL('image/png');
    12531236    } catch(e) {
    12541237      // no canvas or no toDataURL()
     
    12891272      o = oBox.getElementsByTagName('ul')[0],
    12901273      oItems = o.getElementsByTagName('li'),
    1291       isFirefox = (navigator.userAgent.match(/firefox/i)),
    1292       isAlt = false, i, oDuration;
     1274      i, oDuration;
    12931275
    12941276  this.lastWPExec = 0;
     
    13021284      var width = oSound._360data.width,
    13031285          radius = oSound._360data.radius,
    1304           fullDuration = (oSound.durationEstimate||(me.totalTime*1000)),
    1305           isAlt = null, i, j, d;
    1306 
    1307       for (i=0,j=me.data.length; i<j; i++) {
    1308         isAlt = (i%2===0);
    1309         oParent.drawSolidArc(oSound._360data.oCanvas,(isAlt?oParent.config.segmentRingColorAlt:oParent.config.segmentRingColor),isAlt?width:width, isAlt?radius/2:radius/2, oParent.deg2rad(360*(me.data[i].endTimeMS/fullDuration)), oParent.deg2rad(360*((me.data[i].startTimeMS||1)/fullDuration)), true);
     1286          fullDuration = (oSound.durationEstimate || (me.totalTime * 1000)),
     1287          isAlt = null, j, k, d;
     1288
     1289      for (j = 0, k = me.data.length; j < k; j++) {
     1290        isAlt = (j % 2 === 0);
     1291        oParent.drawSolidArc(oSound._360data.oCanvas, (isAlt ? oParent.config.segmentRingColorAlt : oParent.config.segmentRingColor), isAlt ? width : width, isAlt ? radius / 2 : radius / 2, oParent.deg2rad(360 * (me.data[i].endTimeMS / fullDuration)), oParent.deg2rad(360 * ((me.data[i].startTimeMS || 1) / fullDuration)), true);
    13101292      }
    13111293      d = new Date();
    1312       if (d-me.lastWPExec>me.refreshInterval) {
     1294      if (d - me.lastWPExec > me.refreshInterval) {
    13131295        me.refresh();
    13141296        me.lastWPExec = d;
     
    13221304
    13231305    // Display info as appropriate
    1324     var i, j, index = null,
     1306    var j, k, index = null,
    13251307        now = oSound.position,
    13261308        metadata = oSound._360data.metadata.data;
    13271309
    1328     for (i=0, j=metadata.length; i<j; i++) {
    1329       if (now >= metadata[i].startTimeMS && now <= metadata[i].endTimeMS) {
    1330         index = i;
     1310    for (j = 0, k = metadata.length; j < k; j++) {
     1311      if (now >= metadata[j].startTimeMS && now <= metadata[j].endTimeMS) {
     1312        index = j;
    13311313        break;
    13321314      }
     
    13341316    if (index !== metadata.currentItem && index < metadata.length) {
    13351317      // update
    1336       oSound._360data.oLink.innerHTML = metadata.mainTitle+' <span class="metadata"><span class="sm2_divider"> | </span><span class="sm2_metadata">'+metadata[index].title+'</span></span>';
     1318      oSound._360data.oLink.innerHTML = metadata.mainTitle + ' <span class="metadata"><span class="sm2_divider"> | </span><span class="sm2_metadata">' + metadata[index].title + '</span></span>';
    13371319      // self.setPageTitle(metadata[index].title+' | '+metadata.mainTitle);
    13381320      metadata.currentItem = index;
     
    13431325  this.strToTime = function(sTime) {
    13441326    var segments = sTime.split(':'),
    1345         seconds = 0, i;
    1346     for (i=segments.length; i--;) {
    1347       seconds += parseInt(segments[i], 10)*Math.pow(60,segments.length-1-i); // hours, minutes
     1327        seconds = 0, j;
     1328    for (j = segments.length; j--;) {
     1329      seconds += parseInt(segments[j], 10) * Math.pow(60, segments.length - 1 - j); // hours, minutes
    13481330    }
    13491331    return seconds;
     
    13551337  this.data.mainTitle = oSound._360data.oLink.innerHTML;
    13561338
    1357   for (i=0; i<oItems.length; i++) {
     1339  for (i = 0; i < oItems.length; i++) {
    13581340    this.data[i] = {
    13591341      o: null,
    13601342      title: oItems[i].getElementsByTagName('p')[0].innerHTML,
    13611343      startTime: oItems[i].getElementsByTagName('span')[0].innerHTML,
    1362       startSeconds: me.strToTime(oItems[i].getElementsByTagName('span')[0].innerHTML.replace(/[()]/g,'')),
     1344      startSeconds: me.strToTime(oItems[i].getElementsByTagName('span')[0].innerHTML.replace(/[()]/g, '')),
    13631345      duration: 0,
    13641346      durationMS: null,
     
    13681350    };
    13691351  }
    1370   oDuration = oParent.getElementsByClassName('duration','div',oBox);
    1371   this.data.givenDuration = (oDuration.length?me.strToTime(oDuration[0].innerHTML)*1000:0);
    1372   for (i=0; i<this.data.length; i++) {
    1373     this.data[i].duration = parseInt(this.data[i+1]?this.data[i+1].startSeconds:(me.data.givenDuration?me.data.givenDuration:oSound.durationEstimate)/1000, 10)-this.data[i].startSeconds;
    1374     this.data[i].startTimeMS = this.data[i].startSeconds*1000;
    1375     this.data[i].durationMS = this.data[i].duration*1000;
    1376     this.data[i].endTimeMS = this.data[i].startTimeMS+this.data[i].durationMS;
     1352  oDuration = oParent.getElementsByClassName('duration', 'div', oBox);
     1353  this.data.givenDuration = (oDuration.length ? me.strToTime(oDuration[0].innerHTML) * 1000 : 0);
     1354  for (i = 0; i < this.data.length; i++) {
     1355    this.data[i].duration = parseInt(this.data[i + 1] ? this.data[i + 1].startSeconds : (me.data.givenDuration ? me.data.givenDuration : oSound.durationEstimate) / 1000, 10) - this.data[i].startSeconds;
     1356    this.data[i].startTimeMS = this.data[i].startSeconds * 1000;
     1357    this.data[i].durationMS = this.data[i].duration * 1000;
     1358    this.data[i].endTimeMS = this.data[i].startTimeMS + this.data[i].durationMS;
    13771359    this.totalTime += this.data[i].duration;
    13781360  }
     
    14011383    var p = window.threeSixtyPlayer;
    14021384    if (p && p.lastSound && p.lastSound._360data.fps && typeof window.isHome === 'undefined') {
    1403       soundManager._writeDebug('fps: ~'+p.lastSound._360data.fps);
     1385      soundManager._writeDebug('fps: ~' + p.lastSound._360data.fps);
    14041386      p.lastSound._360data.fps = 0;
    14051387    }
    1406   },1000);
     1388  }, 1000);
    14071389}
    14081390
    14091391window.ThreeSixtyPlayer = ThreeSixtyPlayer; // constructor
    14101392
     1393window.threeSixtyPlayer = new ThreeSixtyPlayer();
     1394
    14111395}(window));
    1412 
    1413 threeSixtyPlayer = new ThreeSixtyPlayer();
    14141396
    14151397// hook into SM2 init
  • _plugins_/soundmanager/script/soundmanager2-jsmin.js

    r74395 r104951  
    1010 http://schillmania.com/projects/soundmanager2/license.txt
    1111
    12  V2.97a.20130512
     12 V2.97a.20170601
    1313*/
    14 (function(h,g){function fa(fa,wa){function ga(b){return c.preferFlash&&H&&!c.ignoreFlash&&c.flash[b]!==g&&c.flash[b]}function s(b){return function(d){var e=this._s;!e||!e._a?(e&&e.id?c._wD(e.id+": Ignoring "+d.type):c._wD(rb+"Ignoring "+d.type),d=null):d=b.call(this,d);return d}}this.setupOptions={url:fa||null,flashVersion:8,debugMode:!0,debugFlash:!1,useConsole:!0,consoleOnly:!0,waitForWindowLoad:!1,bgColor:"#ffffff",useHighPerformance:!1,flashPollingInterval:null,html5PollingInterval:null,flashLoadTimeout:1E3,
    15 wmode:null,allowScriptAccess:"always",useFlashBlock:!1,useHTML5Audio:!0,html5Test:/^(probably|maybe)$/i,preferFlash:!0,noSWFCache:!1,idPrefix:"sound"};this.defaultOptions={autoLoad:!1,autoPlay:!1,from:null,loops:1,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onposition:null,onstop:null,onfailure:null,onfinish:null,multiShot:!0,multiShotEvents:!1,position:null,pan:0,stream:!0,to:null,type:null,usePolicyFile:!1,volume:100};this.flash9Options={isMovieStar:null,
    16 usePeakData:!1,useWaveformData:!1,useEQData:!1,onbufferchange:null,ondataerror:null};this.movieStarOptions={bufferTime:3,serverURL:null,onconnect:null,duration:null};this.audioFormats={mp3:{type:['audio/mpeg; codecs\x3d"mp3"',"audio/mpeg","audio/mp3","audio/MPA","audio/mpa-robust"],required:!0},mp4:{related:["aac","m4a","m4b"],type:['audio/mp4; codecs\x3d"mp4a.40.2"',"audio/aac","audio/x-m4a","audio/MP4A-LATM","audio/mpeg4-generic"],required:!1},ogg:{type:["audio/ogg; codecs\x3dvorbis"],required:!1},
    17 opus:{type:["audio/ogg; codecs\x3dopus","audio/opus"],required:!1},wav:{type:['audio/wav; codecs\x3d"1"',"audio/wav","audio/wave","audio/x-wav"],required:!1}};this.movieID="sm2-container";this.id=wa||"sm2movie";this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.versionNumber="V2.97a.20130512";this.altURL=this.movieURL=this.version=null;this.enabled=this.swfLoaded=!1;this.oMC=null;this.sounds={};this.soundIDs=[];this.didFlashBlock=this.muted=!1;this.filePattern=null;this.filePatterns=
    18 {flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.features={buffering:!1,peakData:!1,waveformData:!1,eqData:!1,movieStar:!1};this.sandbox={type:null,types:{remote:"remote (domain-based) rules",localWithFile:"local with file access (no internet access)",localWithNetwork:"local with network (internet access only, no local access)",localTrusted:"local, trusted (local+internet access)"},description:null,noRemote:null,noLocal:null};this.html5={usingFlash:null};this.flash={};this.ignoreFlash=this.html5Only=
    19 !1;var Ua,c=this,Va=null,k=null,rb="HTML5::",A,t=navigator.userAgent,U=h.location.href.toString(),m=document,xa,Wa,ya,n,F=[],za=!0,C,V=!1,W=!1,q=!1,y=!1,ha=!1,p,sb=0,X,B,Aa,O,Ba,M,P,Q,Xa,Ca,ia,I,ja,Da,R,Ea,Y,ka,la,S,Ya,Fa,Za=["log","info","warn","error"],$a,Ga,ab,Z=null,Ha=null,r,Ia,T,bb,ma,na,J,v,$=!1,Ja=!1,cb,db,eb,oa=0,aa=null,pa,N=[],qa,u=null,fb,ra,ba,K,sa,Ka,gb,w,hb=Array.prototype.slice,E=!1,La,H,Ma,ib,G,jb,Na,ta,kb=0,ca=t.match(/(ipad|iphone|ipod)/i),lb=t.match(/android/i),L=t.match(/msie/i),
    20 tb=t.match(/webkit/i),ua=t.match(/safari/i)&&!t.match(/chrome/i),Oa=t.match(/opera/i),ub=t.match(/firefox/i),Pa=t.match(/(mobile|pre\/|xoom)/i)||ca||lb,Qa=!U.match(/usehtml5audio/i)&&!U.match(/sm2\-ignorebadua/i)&&ua&&!t.match(/silk/i)&&t.match(/OS X 10_6_([3-7])/i),da=h.console!==g&&console.log!==g,Ra=m.hasFocus!==g?m.hasFocus():null,va=ua&&(m.hasFocus===g||!m.hasFocus()),mb=!va,nb=/(mp3|mp4|mpa|m4a|m4b)/i,ea=m.location?m.location.protocol.match(/http/i):null,ob=!ea?"http://":"",pb=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,
    21 qb="mpeg4 aac flv mov mp4 m4v f4v m4a m4b mp4v 3gp 3g2".split(" "),vb=RegExp("\\.("+qb.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL=!ea;var Sa;try{Sa=Audio!==g&&(Oa&&opera!==g&&10>opera.version()?new Audio(null):new Audio).canPlayType!==g}catch(wb){Sa=!1}this.hasHTML5=Sa;this.setup=function(b){var d=!c.url;b!==g&&(q&&u&&c.ok()&&(b.flashVersion!==g||b.url!==g||b.html5Test!==g))&&J(r("setupLate"));Aa(b);b&&(d&&(Y&&b.url!==g)&&c.beginDelayedInit(),
    22 !Y&&(b.url!==g&&"complete"===m.readyState)&&setTimeout(R,1));return c};this.supported=this.ok=function(){return u?q&&!y:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(c){return A(c)||m[c]||h[c]};this.createSound=function(b,d){function e(){f=ma(f);c.sounds[f.id]=new Ua(f);c.soundIDs.push(f.id);return c.sounds[f.id]}var a,f;a=null;a="soundManager.createSound(): "+r(!q?"notReady":"notOK");if(!q||!c.ok())return J(a),!1;d!==g&&(b={id:b,url:d});f=B(b);f.url=pa(f.url);void 0===f.id&&(f.id=c.setupOptions.idPrefix+
    23 kb++);f.id.toString().charAt(0).match(/^[0-9]$/)&&c._wD("soundManager.createSound(): "+r("badID",f.id),2);c._wD("soundManager.createSound(): "+f.id+(f.url?" ("+f.url+")":""),1);if(v(f.id,!0))return c._wD("soundManager.createSound(): "+f.id+" exists",1),c.sounds[f.id];if(ra(f))a=e(),c._wD(f.id+": Using HTML5"),a._setup_html5(f);else{if(c.html5Only)return c._wD(f.id+": No HTML5 support for this sound, and no Flash. Exiting."),e();if(c.html5.usingFlash&&f.url&&f.url.match(/data\:/i))return c._wD(f.id+
    24 ": data: URIs not supported via Flash. Exiting."),e();8<n&&(null===f.isMovieStar&&(f.isMovieStar=!(!f.serverURL&&!(f.type&&f.type.match(pb)||f.url&&f.url.match(vb)))),f.isMovieStar&&(c._wD("soundManager.createSound(): using MovieStar handling"),1<f.loops&&p("noNSLoop")));f=na(f,"soundManager.createSound(): ");a=e();8===n?k._createSound(f.id,f.loops||1,f.usePolicyFile):(k._createSound(f.id,f.url,f.usePeakData,f.useWaveformData,f.useEQData,f.isMovieStar,f.isMovieStar?f.bufferTime:!1,f.loops||1,f.serverURL,
    25 f.duration||null,f.autoPlay,!0,f.autoLoad,f.usePolicyFile),f.serverURL||(a.connected=!0,f.onconnect&&f.onconnect.apply(a)));!f.serverURL&&(f.autoLoad||f.autoPlay)&&a.load(f)}!f.serverURL&&f.autoPlay&&a.play();return a};this.destroySound=function(b,d){if(!v(b))return!1;var e=c.sounds[b],a;e._iO={};e.stop();e.unload();for(a=0;a<c.soundIDs.length;a++)if(c.soundIDs[a]===b){c.soundIDs.splice(a,1);break}d||e.destruct(!0);delete c.sounds[b];return!0};this.load=function(b,d){return!v(b)?!1:c.sounds[b].load(d)};
    26 this.unload=function(b){return!v(b)?!1:c.sounds[b].unload()};this.onposition=this.onPosition=function(b,d,e,a){return!v(b)?!1:c.sounds[b].onposition(d,e,a)};this.clearOnPosition=function(b,d,e){return!v(b)?!1:c.sounds[b].clearOnPosition(d,e)};this.start=this.play=function(b,d){var e=null,a=d&&!(d instanceof Object);if(!q||!c.ok())return J("soundManager.play(): "+r(!q?"notReady":"notOK")),!1;if(v(b,a))a&&(d={url:d});else{if(!a)return!1;a&&(d={url:d});d&&d.url&&(c._wD('soundManager.play(): Attempting to create "'+
    27 b+'"',1),d.id=b,e=c.createSound(d).play())}null===e&&(e=c.sounds[b].play(d));return e};this.setPosition=function(b,d){return!v(b)?!1:c.sounds[b].setPosition(d)};this.stop=function(b){if(!v(b))return!1;c._wD("soundManager.stop("+b+")",1);return c.sounds[b].stop()};this.stopAll=function(){var b;c._wD("soundManager.stopAll()",1);for(b in c.sounds)c.sounds.hasOwnProperty(b)&&c.sounds[b].stop()};this.pause=function(b){return!v(b)?!1:c.sounds[b].pause()};this.pauseAll=function(){var b;for(b=c.soundIDs.length-
    28 1;0<=b;b--)c.sounds[c.soundIDs[b]].pause()};this.resume=function(b){return!v(b)?!1:c.sounds[b].resume()};this.resumeAll=function(){var b;for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].resume()};this.togglePause=function(b){return!v(b)?!1:c.sounds[b].togglePause()};this.setPan=function(b,d){return!v(b)?!1:c.sounds[b].setPan(d)};this.setVolume=function(b,d){return!v(b)?!1:c.sounds[b].setVolume(d)};this.mute=function(b){var d=0;b instanceof String&&(b=null);if(b){if(!v(b))return!1;c._wD('soundManager.mute(): Muting "'+
    29 b+'"');return c.sounds[b].mute()}c._wD("soundManager.mute(): Muting all sounds");for(d=c.soundIDs.length-1;0<=d;d--)c.sounds[c.soundIDs[d]].mute();return c.muted=!0};this.muteAll=function(){c.mute()};this.unmute=function(b){b instanceof String&&(b=null);if(b){if(!v(b))return!1;c._wD('soundManager.unmute(): Unmuting "'+b+'"');return c.sounds[b].unmute()}c._wD("soundManager.unmute(): Unmuting all sounds");for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].unmute();c.muted=!1;return!0};this.unmuteAll=
    30 function(){c.unmute()};this.toggleMute=function(b){return!v(b)?!1:c.sounds[b].toggleMute()};this.getMemoryUse=function(){var c=0;k&&8!==n&&(c=parseInt(k._getMemoryUse(),10));return c};this.disable=function(b){var d;b===g&&(b=!1);if(y)return!1;y=!0;p("shutdown",1);for(d=c.soundIDs.length-1;0<=d;d--)$a(c.sounds[c.soundIDs[d]]);X(b);w.remove(h,"load",P);return!0};this.canPlayMIME=function(b){var d;c.hasHTML5&&(d=ba({type:b}));!d&&u&&(d=b&&c.ok()?!!(8<n&&b.match(pb)||b.match(c.mimePattern)):null);return d};
    31 this.canPlayURL=function(b){var d;c.hasHTML5&&(d=ba({url:b}));!d&&u&&(d=b&&c.ok()?!!b.match(c.filePattern):null);return d};this.canPlayLink=function(b){return b.type!==g&&b.type&&c.canPlayMIME(b.type)?!0:c.canPlayURL(b.href)};this.getSoundById=function(b,d){if(!b)return null;var e=c.sounds[b];!e&&!d&&c._wD('soundManager.getSoundById(): Sound "'+b+'" not found.',2);return e};this.onready=function(b,d){if("function"===typeof b)q&&c._wD(r("queue","onready")),d||(d=h),Ba("onready",b,d),M();else throw r("needFunction",
    32 "onready");return!0};this.ontimeout=function(b,d){if("function"===typeof b)q&&c._wD(r("queue","ontimeout")),d||(d=h),Ba("ontimeout",b,d),M({type:"ontimeout"});else throw r("needFunction","ontimeout");return!0};this._writeDebug=function(b,d){var e,a;if(!c.debugMode)return!1;if(da&&c.useConsole){if(d&&"object"===typeof d)console.log(b,d);else if(Za[d]!==g)console[Za[d]](b);else console.log(b);if(c.consoleOnly)return!0}e=A("soundmanager-debug");if(!e)return!1;a=m.createElement("div");0===++sb%2&&(a.className=
    33 "sm2-alt");d=d===g?0:parseInt(d,10);a.appendChild(m.createTextNode(b));d&&(2<=d&&(a.style.fontWeight="bold"),3===d&&(a.style.color="#ff3333"));e.insertBefore(a,e.firstChild);return!0};-1!==U.indexOf("sm2-debug\x3dalert")&&(this._writeDebug=function(c){h.alert(c)});this._wD=this._writeDebug;this._debug=function(){var b,d;p("currentObj",1);b=0;for(d=c.soundIDs.length;b<d;b++)c.sounds[c.soundIDs[b]]._debug()};this.reboot=function(b,d){c.soundIDs.length&&c._wD("Destroying "+c.soundIDs.length+" SMSound object"+
    34 (1!==c.soundIDs.length?"s":"")+"...");var e,a,f;for(e=c.soundIDs.length-1;0<=e;e--)c.sounds[c.soundIDs[e]].destruct();if(k)try{L&&(Ha=k.innerHTML),Z=k.parentNode.removeChild(k)}catch(g){p("badRemove",2)}Ha=Z=u=k=null;c.enabled=Y=q=$=Ja=V=W=y=E=c.swfLoaded=!1;c.soundIDs=[];c.sounds={};kb=0;if(b)F=[];else for(e in F)if(F.hasOwnProperty(e)){a=0;for(f=F[e].length;a<f;a++)F[e][a].fired=!1}d||c._wD("soundManager: Rebooting...");c.html5={usingFlash:null};c.flash={};c.html5Only=!1;c.ignoreFlash=!1;h.setTimeout(function(){Da();
    35 d||c.beginDelayedInit()},20);return c};this.reset=function(){p("reset");return c.reboot(!0,!0)};this.getMoviePercent=function(){return k&&"PercentLoaded"in k?k.PercentLoaded():null};this.beginDelayedInit=function(){ha=!0;R();setTimeout(function(){if(Ja)return!1;la();ja();return Ja=!0},20);Q()};this.destruct=function(){c._wD("soundManager.destruct()");c.disable(!0)};Ua=function(b){var d,e,a=this,f,h,z,l,m,q,s=!1,D=[],t=0,Ta,y,u=null,A;e=d=null;this.sID=this.id=b.id;this.url=b.url;this._iO=this.instanceOptions=
    36 this.options=B(b);this.pan=this.options.pan;this.volume=this.options.volume;this.isHTML5=!1;this._a=null;A=this.url?!1:!0;this.id3={};this._debug=function(){c._wD(a.id+": Merged options:",a.options)};this.load=function(b){var d=null,e;b!==g?a._iO=B(b,a.options):(b=a.options,a._iO=b,u&&u!==a.url&&(p("manURL"),a._iO.url=a.url,a.url=null));a._iO.url||(a._iO.url=a.url);a._iO.url=pa(a._iO.url);e=a.instanceOptions=a._iO;c._wD(a.id+": load ("+e.url+")");if(!e.url&&!a.url)return c._wD(a.id+": load(): url is unassigned. Exiting.",
    37 2),a;!a.isHTML5&&(8===n&&!a.url&&!e.autoPlay)&&c._wD(a.id+": Flash 8 load() limitation: Wait for onload() before calling play().",1);if(e.url===a.url&&0!==a.readyState&&2!==a.readyState)return p("onURL",1),3===a.readyState&&e.onload&&ta(a,function(){e.onload.apply(a,[!!a.duration])}),a;a.loaded=!1;a.readyState=1;a.playState=0;a.id3={};if(ra(e))d=a._setup_html5(e),d._called_load?c._wD(a.id+": Ignoring request to load again"):(a._html5_canplay=!1,a.url!==e.url&&(c._wD(p("manURL")+": "+e.url),a._a.src=
    38 e.url,a.setPosition(0)),a._a.autobuffer="auto",a._a.preload="auto",a._a._called_load=!0,e.autoPlay&&a.play());else{if(c.html5Only)return c._wD(a.id+": No flash support. Exiting."),a;if(a._iO.url&&a._iO.url.match(/data\:/i))return c._wD(a.id+": data: URIs not supported via Flash. Exiting."),a;try{a.isHTML5=!1,a._iO=na(ma(e)),e=a._iO,8===n?k._load(a.id,e.url,e.stream,e.autoPlay,e.usePolicyFile):k._load(a.id,e.url,!!e.stream,!!e.autoPlay,e.loops||1,!!e.autoLoad,e.usePolicyFile)}catch(f){p("smError",
    39 2),C("onload",!1),S({type:"SMSOUND_LOAD_JS_EXCEPTION",fatal:!0})}}a.url=e.url;return a};this.unload=function(){0!==a.readyState&&(c._wD(a.id+": unload()"),a.isHTML5?(l(),a._a&&(a._a.pause(),u=sa(a._a))):8===n?k._unload(a.id,"about:blank"):k._unload(a.id),f());return a};this.destruct=function(b){c._wD(a.id+": Destruct");a.isHTML5?(l(),a._a&&(a._a.pause(),sa(a._a),E||z(),a._a._s=null,a._a=null)):(a._iO.onfailure=null,k._destroySound(a.id));b||c.destroySound(a.id,!0)};this.start=this.play=function(b,
    40 d){var e,f,l,z,h,x=!0,x=null;e=a.id+": play(): ";d=d===g?!0:d;b||(b={});a.url&&(a._iO.url=a.url);a._iO=B(a._iO,a.options);a._iO=B(b,a._iO);a._iO.url=pa(a._iO.url);a.instanceOptions=a._iO;if(!a.isHTML5&&a._iO.serverURL&&!a.connected)return a.getAutoPlay()||(c._wD(e+" Netstream not connected yet - setting autoPlay"),a.setAutoPlay(!0)),a;ra(a._iO)&&(a._setup_html5(a._iO),m());1===a.playState&&!a.paused&&((f=a._iO.multiShot)?c._wD(e+"Already playing (multi-shot)",1):(c._wD(e+"Already playing (one-shot)",
    41 1),a.isHTML5&&a.setPosition(a._iO.position),x=a));if(null!==x)return x;b.url&&b.url!==a.url&&(!a.readyState&&!a.isHTML5&&8===n&&A?A=!1:a.load(a._iO));a.loaded?c._wD(e.substr(0,e.lastIndexOf(":"))):0===a.readyState?(c._wD(e+"Attempting to load"),!a.isHTML5&&!c.html5Only?(a._iO.autoPlay=!0,a.load(a._iO)):a.isHTML5?a.load(a._iO):(c._wD(e+"Unsupported type. Exiting."),x=a),a.instanceOptions=a._iO):2===a.readyState?(c._wD(e+"Could not load - exiting",2),x=a):c._wD(e+"Loading - attempting to play...");
    42 if(null!==x)return x;!a.isHTML5&&(9===n&&0<a.position&&a.position===a.duration)&&(c._wD(e+"Sound at end, resetting to position:0"),b.position=0);if(a.paused&&0<=a.position&&(!a._iO.serverURL||0<a.position))c._wD(e+"Resuming from paused state",1),a.resume();else{a._iO=B(b,a._iO);if(null!==a._iO.from&&null!==a._iO.to&&0===a.instanceCount&&0===a.playState&&!a._iO.serverURL){f=function(){a._iO=B(b,a._iO);a.play(a._iO)};if(a.isHTML5&&!a._html5_canplay)c._wD(e+"Beginning load for from/to case"),a.load({oncanplay:f}),
    43 x=!1;else if(!a.isHTML5&&!a.loaded&&(!a.readyState||2!==a.readyState))c._wD(e+"Preloading for from/to case"),a.load({onload:f}),x=!1;if(null!==x)return x;a._iO=y()}(!a.instanceCount||a._iO.multiShotEvents||a.isHTML5&&a._iO.multiShot&&!E||!a.isHTML5&&8<n&&!a.getAutoPlay())&&a.instanceCount++;a._iO.onposition&&0===a.playState&&q(a);a.playState=1;a.paused=!1;a.position=a._iO.position!==g&&!isNaN(a._iO.position)?a._iO.position:0;a.isHTML5||(a._iO=na(ma(a._iO)));a._iO.onplay&&d&&(a._iO.onplay.apply(a),
    44 s=!0);a.setVolume(a._iO.volume,!0);a.setPan(a._iO.pan,!0);a.isHTML5?2>a.instanceCount?(m(),e=a._setup_html5(),a.setPosition(a._iO.position),e.play()):(c._wD(a.id+": Cloning Audio() for instance #"+a.instanceCount+"..."),l=new Audio(a._iO.url),z=function(){w.remove(l,"onended",z);a._onfinish(a);sa(l);l=null},h=function(){w.remove(l,"canplay",h);try{l.currentTime=a._iO.position/1E3}catch(c){J(a.id+": multiShot play() failed to apply position of "+a._iO.position/1E3)}l.play()},w.add(l,"ended",z),a._iO.position?
    45 w.add(l,"canplay",h):l.play()):(x=k._start(a.id,a._iO.loops||1,9===n?a.position:a.position/1E3,a._iO.multiShot||!1),9===n&&!x&&(c._wD(e+"No sound hardware, or 32-sound ceiling hit",2),a._iO.onplayerror&&a._iO.onplayerror.apply(a)))}return a};this.stop=function(b){var d=a._iO;1===a.playState&&(c._wD(a.id+": stop()"),a._onbufferchange(0),a._resetOnPosition(0),a.paused=!1,a.isHTML5||(a.playState=0),Ta(),d.to&&a.clearOnPosition(d.to),a.isHTML5?a._a&&(b=a.position,a.setPosition(0),a.position=b,a._a.pause(),
    46 a.playState=0,a._onTimer(),l()):(k._stop(a.id,b),d.serverURL&&a.unload()),a.instanceCount=0,a._iO={},d.onstop&&d.onstop.apply(a));return a};this.setAutoPlay=function(b){c._wD(a.id+": Autoplay turned "+(b?"on":"off"));a._iO.autoPlay=b;a.isHTML5||(k._setAutoPlay(a.id,b),b&&(!a.instanceCount&&1===a.readyState)&&(a.instanceCount++,c._wD(a.id+": Incremented instance count to "+a.instanceCount)))};this.getAutoPlay=function(){return a._iO.autoPlay};this.setPosition=function(b){b===g&&(b=0);var d=a.isHTML5?
    47 Math.max(b,0):Math.min(a.duration||a._iO.duration,Math.max(b,0));a.position=d;b=a.position/1E3;a._resetOnPosition(a.position);a._iO.position=d;if(a.isHTML5){if(a._a){if(a._html5_canplay){if(a._a.currentTime!==b){c._wD(a.id+": setPosition("+b+")");try{a._a.currentTime=b,(0===a.playState||a.paused)&&a._a.pause()}catch(e){c._wD(a.id+": setPosition("+b+") failed: "+e.message,2)}}}else if(b)return c._wD(a.id+": setPosition("+b+"): Cannot seek yet, sound not ready",2),a;a.paused&&a._onTimer(!0)}}else b=
    48 9===n?a.position:b,a.readyState&&2!==a.readyState&&k._setPosition(a.id,b,a.paused||!a.playState,a._iO.multiShot);return a};this.pause=function(b){if(a.paused||0===a.playState&&1!==a.readyState)return a;c._wD(a.id+": pause()");a.paused=!0;a.isHTML5?(a._setup_html5().pause(),l()):(b||b===g)&&k._pause(a.id,a._iO.multiShot);a._iO.onpause&&a._iO.onpause.apply(a);return a};this.resume=function(){var b=a._iO;if(!a.paused)return a;c._wD(a.id+": resume()");a.paused=!1;a.playState=1;a.isHTML5?(a._setup_html5().play(),
    49 m()):(b.isMovieStar&&!b.serverURL&&a.setPosition(a.position),k._pause(a.id,b.multiShot));!s&&b.onplay?(b.onplay.apply(a),s=!0):b.onresume&&b.onresume.apply(a);return a};this.togglePause=function(){c._wD(a.id+": togglePause()");if(0===a.playState)return a.play({position:9===n&&!a.isHTML5?a.position:a.position/1E3}),a;a.paused?a.resume():a.pause();return a};this.setPan=function(b,c){b===g&&(b=0);c===g&&(c=!1);a.isHTML5||k._setPan(a.id,b);a._iO.pan=b;c||(a.pan=b,a.options.pan=b);return a};this.setVolume=
    50 function(b,d){b===g&&(b=100);d===g&&(d=!1);a.isHTML5?a._a&&(a._a.volume=Math.max(0,Math.min(1,b/100))):k._setVolume(a.id,c.muted&&!a.muted||a.muted?0:b);a._iO.volume=b;d||(a.volume=b,a.options.volume=b);return a};this.mute=function(){a.muted=!0;a.isHTML5?a._a&&(a._a.muted=!0):k._setVolume(a.id,0);return a};this.unmute=function(){a.muted=!1;var b=a._iO.volume!==g;a.isHTML5?a._a&&(a._a.muted=!1):k._setVolume(a.id,b?a._iO.volume:a.options.volume);return a};this.toggleMute=function(){return a.muted?a.unmute():
    51 a.mute()};this.onposition=this.onPosition=function(b,c,d){D.push({position:parseInt(b,10),method:c,scope:d!==g?d:a,fired:!1});return a};this.clearOnPosition=function(a,b){var c;a=parseInt(a,10);if(isNaN(a))return!1;for(c=0;c<D.length;c++)if(a===D[c].position&&(!b||b===D[c].method))D[c].fired&&t--,D.splice(c,1)};this._processOnPosition=function(){var b,c;b=D.length;if(!b||!a.playState||t>=b)return!1;for(b-=1;0<=b;b--)c=D[b],!c.fired&&a.position>=c.position&&(c.fired=!0,t++,c.method.apply(c.scope,[c.position]));
    52 return!0};this._resetOnPosition=function(a){var b,c;b=D.length;if(!b)return!1;for(b-=1;0<=b;b--)c=D[b],c.fired&&a<=c.position&&(c.fired=!1,t--);return!0};y=function(){var b=a._iO,d=b.from,e=b.to,f,g;g=function(){c._wD(a.id+': "To" time of '+e+" reached.");a.clearOnPosition(e,g);a.stop()};f=function(){c._wD(a.id+': Playing "from" '+d);if(null!==e&&!isNaN(e))a.onPosition(e,g)};null!==d&&!isNaN(d)&&(b.position=d,b.multiShot=!1,f());return b};q=function(){var b,c=a._iO.onposition;if(c)for(b in c)if(c.hasOwnProperty(b))a.onPosition(parseInt(b,
    53 10),c[b])};Ta=function(){var b,c=a._iO.onposition;if(c)for(b in c)c.hasOwnProperty(b)&&a.clearOnPosition(parseInt(b,10))};m=function(){a.isHTML5&&cb(a)};l=function(){a.isHTML5&&db(a)};f=function(b){b||(D=[],t=0);s=!1;a._hasTimer=null;a._a=null;a._html5_canplay=!1;a.bytesLoaded=null;a.bytesTotal=null;a.duration=a._iO&&a._iO.duration?a._iO.duration:null;a.durationEstimate=null;a.buffered=[];a.eqData=[];a.eqData.left=[];a.eqData.right=[];a.failures=0;a.isBuffering=!1;a.instanceOptions={};a.instanceCount=
    54 0;a.loaded=!1;a.metadata={};a.readyState=0;a.muted=!1;a.paused=!1;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.playState=0;a.position=null;a.id3={}};f();this._onTimer=function(b){var c,f=!1,g={};if(a._hasTimer||b){if(a._a&&(b||(0<a.playState||1===a.readyState)&&!a.paused))c=a._get_html5_duration(),c!==d&&(d=c,a.duration=c,f=!0),a.durationEstimate=a.duration,c=1E3*a._a.currentTime||0,c!==e&&(e=c,f=!0),(f||b)&&a._whileplaying(c,g,g,g,g);return f}};this._get_html5_duration=function(){var b=
    55 a._iO;return(b=a._a&&a._a.duration?1E3*a._a.duration:b&&b.duration?b.duration:null)&&!isNaN(b)&&Infinity!==b?b:null};this._apply_loop=function(a,b){!a.loop&&1<b&&c._wD("Note: Native HTML5 looping is infinite.",1);a.loop=1<b?"loop":""};this._setup_html5=function(b){b=B(a._iO,b);var c=E?Va:a._a,d=decodeURI(b.url),e;E?d===decodeURI(La)&&(e=!0):d===decodeURI(u)&&(e=!0);if(c){if(c._s)if(E)c._s&&(c._s.playState&&!e)&&c._s.stop();else if(!E&&d===decodeURI(u))return a._apply_loop(c,b.loops),c;e||(f(!1),c.src=
    56 b.url,La=u=a.url=b.url,c._called_load=!1)}else a._a=b.autoLoad||b.autoPlay?new Audio(b.url):Oa&&10>opera.version()?new Audio(null):new Audio,c=a._a,c._called_load=!1,E&&(Va=c);a.isHTML5=!0;a._a=c;c._s=a;h();a._apply_loop(c,b.loops);b.autoLoad||b.autoPlay?a.load():(c.autobuffer=!1,c.preload="auto");return c};h=function(){if(a._a._added_events)return!1;var b;a._a._added_events=!0;for(b in G)G.hasOwnProperty(b)&&a._a&&a._a.addEventListener(b,G[b],!1);return!0};z=function(){var b;c._wD(a.id+": Removing event listeners");
    57 a._a._added_events=!1;for(b in G)G.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,G[b],!1)};this._onload=function(b){var d=!!b||!a.isHTML5&&8===n&&a.duration;b=a.id+": ";c._wD(b+(d?"onload()":"Failed to load / invalid sound?"+(!a.duration?" Zero-length duration reported.":" -")+" ("+a.url+")"),d?1:2);!d&&!a.isHTML5&&(!0===c.sandbox.noRemote&&c._wD(b+r("noNet"),1),!0===c.sandbox.noLocal&&c._wD(b+r("noLocal"),1));a.loaded=d;a.readyState=d?3:2;a._onbufferchange(0);a._iO.onload&&ta(a,function(){a._iO.onload.apply(a,
    58 [d])});return!0};this._onbufferchange=function(b){if(0===a.playState||b&&a.isBuffering||!b&&!a.isBuffering)return!1;a.isBuffering=1===b;a._iO.onbufferchange&&(c._wD(a.id+": Buffer state change: "+b),a._iO.onbufferchange.apply(a));return!0};this._onsuspend=function(){a._iO.onsuspend&&(c._wD(a.id+": Playback suspended"),a._iO.onsuspend.apply(a));return!0};this._onfailure=function(b,d,e){a.failures++;c._wD(a.id+": Failures \x3d "+a.failures);if(a._iO.onfailure&&1===a.failures)a._iO.onfailure(a,b,d,e);
    59 else c._wD(a.id+": Ignoring failure")};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0);a._resetOnPosition(0);if(a.instanceCount&&(a.instanceCount--,a.instanceCount||(Ta(),a.playState=0,a.paused=!1,a.instanceCount=0,a.instanceOptions={},a._iO={},l(),a.isHTML5&&(a.position=0)),(!a.instanceCount||a._iO.multiShotEvents)&&b))c._wD(a.id+": onfinish()"),ta(a,function(){b.apply(a)})};this._whileloading=function(b,c,d,e){var f=a._iO;a.bytesLoaded=b;a.bytesTotal=c;a.duration=Math.floor(d);
    60 a.bufferLength=e;a.durationEstimate=!a.isHTML5&&!f.isMovieStar?f.duration?a.duration>f.duration?a.duration:f.duration:parseInt(a.bytesTotal/a.bytesLoaded*a.duration,10):a.duration;a.isHTML5||(a.buffered=[{start:0,end:a.duration}]);(3!==a.readyState||a.isHTML5)&&f.whileloading&&f.whileloading.apply(a)};this._whileplaying=function(b,c,d,e,f){var l=a._iO;if(isNaN(b)||null===b)return!1;a.position=Math.max(0,b);a._processOnPosition();!a.isHTML5&&8<n&&(l.usePeakData&&(c!==g&&c)&&(a.peakData={left:c.leftPeak,
    61 right:c.rightPeak}),l.useWaveformData&&(d!==g&&d)&&(a.waveformData={left:d.split(","),right:e.split(",")}),l.useEQData&&(f!==g&&f&&f.leftEQ)&&(b=f.leftEQ.split(","),a.eqData=b,a.eqData.left=b,f.rightEQ!==g&&f.rightEQ&&(a.eqData.right=f.rightEQ.split(","))));1===a.playState&&(!a.isHTML5&&(8===n&&!a.position&&a.isBuffering)&&a._onbufferchange(0),l.whileplaying&&l.whileplaying.apply(a));return!0};this._oncaptiondata=function(b){c._wD(a.id+": Caption data received.");a.captiondata=b;a._iO.oncaptiondata&&
    62 a._iO.oncaptiondata.apply(a,[b])};this._onmetadata=function(b,d){c._wD(a.id+": Metadata received.");var e={},f,g;f=0;for(g=b.length;f<g;f++)e[b[f]]=d[f];a.metadata=e;a._iO.onmetadata&&a._iO.onmetadata.apply(a)};this._onid3=function(b,d){c._wD(a.id+": ID3 data received.");var e=[],f,g;f=0;for(g=b.length;f<g;f++)e[b[f]]=d[f];a.id3=B(a.id3,e);a._iO.onid3&&a._iO.onid3.apply(a)};this._onconnect=function(b){b=1===b;c._wD(a.id+": "+(b?"Connected.":"Failed to connect? - "+a.url),b?1:2);if(a.connected=b)a.failures=
    63 0,v(a.id)&&(a.getAutoPlay()?a.play(g,a.getAutoPlay()):a._iO.autoLoad&&a.load()),a._iO.onconnect&&a._iO.onconnect.apply(a,[b])};this._ondataerror=function(b){0<a.playState&&(c._wD(a.id+": Data error: "+b),a._iO.ondataerror&&a._iO.ondataerror.apply(a))};this._debug()};ka=function(){return m.body||m._docElement||m.getElementsByTagName("div")[0]};A=function(b){return m.getElementById(b)};B=function(b,d){var e=b||{},a,f;a=d===g?c.defaultOptions:d;for(f in a)a.hasOwnProperty(f)&&e[f]===g&&(e[f]="object"!==
    64 typeof a[f]||null===a[f]?a[f]:B(e[f],a[f]));return e};ta=function(b,c){!b.isHTML5&&8===n?h.setTimeout(c,0):c()};O={onready:1,ontimeout:1,defaultOptions:1,flash9Options:1,movieStarOptions:1};Aa=function(b,d){var e,a=!0,f=d!==g,x=c.setupOptions;if(b===g){a=[];for(e in x)x.hasOwnProperty(e)&&a.push(e);for(e in O)O.hasOwnProperty(e)&&("object"===typeof c[e]?a.push(e+": {...}"):c[e]instanceof Function?a.push(e+": function() {...}"):a.push(e));c._wD(r("setup",a.join(", ")));return!1}for(e in b)if(b.hasOwnProperty(e))if("object"!==
    65 typeof b[e]||null===b[e]||b[e]instanceof Array||b[e]instanceof RegExp)f&&O[d]!==g?c[d][e]=b[e]:x[e]!==g?(c.setupOptions[e]=b[e],c[e]=b[e]):O[e]===g?(J(r(c[e]===g?"setupUndef":"setupError",e),2),a=!1):c[e]instanceof Function?c[e].apply(c,b[e]instanceof Array?b[e]:[b[e]]):c[e]=b[e];else if(O[e]===g)J(r(c[e]===g?"setupUndef":"setupError",e),2),a=!1;else return Aa(b[e],e);return a};w=function(){function b(a){a=hb.call(a);var b=a.length;e?(a[1]="on"+a[1],3<b&&a.pop()):3===b&&a.push(!1);return a}function c(b,
    66 d){var g=b.shift(),l=[a[d]];if(e)g[l](b[0],b[1]);else g[l].apply(g,b)}var e=h.attachEvent,a={add:e?"attachEvent":"addEventListener",remove:e?"detachEvent":"removeEventListener"};return{add:function(){c(b(arguments),"add")},remove:function(){c(b(arguments),"remove")}}}();G={abort:s(function(){c._wD(this._s.id+": abort")}),canplay:s(function(){var b=this._s,d;if(b._html5_canplay)return!0;b._html5_canplay=!0;c._wD(b.id+": canplay");b._onbufferchange(0);d=b._iO.position!==g&&!isNaN(b._iO.position)?b._iO.position/
    67 1E3:null;if(b.position&&this.currentTime!==d){c._wD(b.id+": canplay: Setting position to "+d);try{this.currentTime=d}catch(e){c._wD(b.id+": canplay: Setting position of "+d+" failed: "+e.message,2)}}b._iO._oncanplay&&b._iO._oncanplay()}),canplaythrough:s(function(){var b=this._s;b.loaded||(b._onbufferchange(0),b._whileloading(b.bytesLoaded,b.bytesTotal,b._get_html5_duration()),b._onload(!0))}),ended:s(function(){var b=this._s;c._wD(b.id+": ended");b._onfinish()}),error:s(function(){c._wD(this._s.id+
    68 ": HTML5 error, code "+this.error.code);this._s._onload(!1)}),loadeddata:s(function(){var b=this._s;c._wD(b.id+": loadeddata");!b._loaded&&!ua&&(b.duration=b._get_html5_duration())}),loadedmetadata:s(function(){c._wD(this._s.id+": loadedmetadata")}),loadstart:s(function(){c._wD(this._s.id+": loadstart");this._s._onbufferchange(1)}),play:s(function(){this._s._onbufferchange(0)}),playing:s(function(){c._wD(this._s.id+": playing");this._s._onbufferchange(0)}),progress:s(function(b){var d=this._s,e,a,
    69 f;e=0;var g="progress"===b.type,z=b.target.buffered,l=b.loaded||0,h=b.total||1;d.buffered=[];if(z&&z.length){e=0;for(a=z.length;e<a;e++)d.buffered.push({start:1E3*z.start(e),end:1E3*z.end(e)});e=1E3*(z.end(0)-z.start(0));l=Math.min(1,e/(1E3*b.target.duration));if(g&&1<z.length){f=[];a=z.length;for(e=0;e<a;e++)f.push(1E3*b.target.buffered.start(e)+"-"+1E3*b.target.buffered.end(e));c._wD(this._s.id+": progress, timeRanges: "+f.join(", "))}g&&!isNaN(l)&&c._wD(this._s.id+": progress, "+Math.floor(100*
    70 l)+"% loaded")}isNaN(l)||(d._onbufferchange(0),d._whileloading(l,h,d._get_html5_duration()),l&&(h&&l===h)&&G.canplaythrough.call(this,b))}),ratechange:s(function(){c._wD(this._s.id+": ratechange")}),suspend:s(function(b){var d=this._s;c._wD(this._s.id+": suspend");G.progress.call(this,b);d._onsuspend()}),stalled:s(function(){c._wD(this._s.id+": stalled")}),timeupdate:s(function(){this._s._onTimer()}),waiting:s(function(){var b=this._s;c._wD(this._s.id+": waiting");b._onbufferchange(1)})};ra=function(b){return!b||
    71 !b.type&&!b.url&&!b.serverURL?!1:b.serverURL||b.type&&ga(b.type)?!1:b.type?ba({type:b.type}):ba({url:b.url})||c.html5Only||b.url.match(/data\:/i)};sa=function(b){var c;b&&(c=ua&&!ca?null:ub?"about:blank":null,b.src=c,void 0!==b._called_unload&&(b._called_load=!1));E&&(La=null);return c};ba=function(b){if(!c.useHTML5Audio||!c.hasHTML5)return!1;var d=b.url||null;b=b.type||null;var e=c.audioFormats,a;if(b&&c.html5[b]!==g)return c.html5[b]&&!ga(b);if(!K){K=[];for(a in e)e.hasOwnProperty(a)&&(K.push(a),
    72 e[a].related&&(K=K.concat(e[a].related)));K=RegExp("\\.("+K.join("|")+")(\\?.*)?$","i")}a=d?d.toLowerCase().match(K):null;!a||!a.length?b&&(d=b.indexOf(";"),a=(-1!==d?b.substr(0,d):b).substr(6)):a=a[1];a&&c.html5[a]!==g?d=c.html5[a]&&!ga(a):(b="audio/"+a,d=c.html5.canPlayType({type:b}),d=(c.html5[a]=d)&&c.html5[b]&&!ga(b));return d};gb=function(){function b(a){var b,e,f=b=!1;if(!d||"function"!==typeof d.canPlayType)return b;if(a instanceof Array){b=0;for(e=a.length;b<e;b++)if(c.html5[a[b]]||d.canPlayType(a[b]).match(c.html5Test))f=
    73 !0,c.html5[a[b]]=!0,c.flash[a[b]]=!!a[b].match(nb);b=f}else a=d&&"function"===typeof d.canPlayType?d.canPlayType(a):!1,b=!(!a||!a.match(c.html5Test));return b}if(!c.useHTML5Audio||!c.hasHTML5)return u=c.html5.usingFlash=!0,!1;var d=Audio!==g?Oa&&10>opera.version()?new Audio(null):new Audio:null,e,a,f={},h;h=c.audioFormats;for(e in h)if(h.hasOwnProperty(e)&&(a="audio/"+e,f[e]=b(h[e].type),f[a]=f[e],e.match(nb)?(c.flash[e]=!0,c.flash[a]=!0):(c.flash[e]=!1,c.flash[a]=!1),h[e]&&h[e].related))for(a=h[e].related.length-
    74 1;0<=a;a--)f["audio/"+h[e].related[a]]=f[e],c.html5[h[e].related[a]]=f[e],c.flash[h[e].related[a]]=f[e];f.canPlayType=d?b:null;c.html5=B(c.html5,f);c.html5.usingFlash=fb();u=c.html5.usingFlash;return!0};I={notReady:"Unavailable - wait until onready() has fired.",notOK:"Audio support is not available.",domError:"soundManagerexception caught while appending SWF to DOM.",spcWmode:"Removing wmode, preventing known SWF loading issue(s)",swf404:"soundManager: Verify that %s is a valid path.",tryDebug:"Try soundManager.debugFlash \x3d true for more security details (output goes to SWF.)",
    75 checkSWF:"See SWF output for more debug info.",localFail:"soundManager: Non-HTTP page ("+m.location.protocol+" URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/",waitFocus:"soundManager: Special case: Waiting for SWF to load with window focus...",waitForever:"soundManager: Waiting indefinitely for Flash (will recover if unblocked)...",
    76 waitSWF:"soundManager: Waiting for 100% SWF load...",needFunction:"soundManager: Function object expected for %s",badID:'Sound ID "%s" should be a string, starting with a non-numeric character',currentObj:"soundManager: _debug(): Current sound objects",waitOnload:"soundManager: Waiting for window.onload()",docLoaded:"soundManager: Document already loaded",onload:"soundManager: initComplete(): calling soundManager.onload()",onloadOK:"soundManager.onload() complete",didInit:"soundManager: init(): Already called?",
    77 secNote:"Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html",badRemove:"soundManager: Failed to remove Flash node.",shutdown:"soundManager.disable(): Shutting down",queue:"soundManager: Queueing %s handler",smError:"SMSound.load(): Exception: JS-Flash communication failed, or JS error.",fbTimeout:"No flash response, applying .swf_timedout CSS...",
    78 fbLoaded:"Flash loaded",fbHandler:"soundManager: flashBlockHandler()",manURL:"SMSound.load(): Using manually-assigned URL",onURL:"soundManager.load(): current URL already assigned.",badFV:'soundManager.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.',as2loop:"Note: Setting stream:false so looping can work (flash 8 limitation)",noNSLoop:"Note: Looping not implemented for MovieStar formats",needfl9:"Note: Switching to flash 9, required for MP4 formats.",mfTimeout:"Setting flashLoadTimeout \x3d 0 (infinite) for off-screen, mobile flash case",
    79 needFlash:"soundManager: Fatal error: Flash is needed to play some required formats, but is not available.",gotFocus:"soundManager: Got window focus.",policy:"Enabling usePolicyFile for data access",setup:"soundManager.setup(): allowed parameters: %s",setupError:'soundManager.setup(): "%s" cannot be assigned with this method.',setupUndef:'soundManager.setup(): Could not find option "%s"',setupLate:"soundManager.setup(): url, flashVersion and html5Test property changes will not take effect until reboot().",
    80 noURL:"soundManager: Flash URL required. Call soundManager.setup({url:...}) to get started.",sm2Loaded:"SoundManager 2: Ready.",reset:"soundManager.reset(): Removing event callbacks",mobileUA:"Mobile UA detected, preferring HTML5 by default.",globalHTML5:"Using singleton HTML5 Audio() pattern for this device."};r=function(){var b=hb.call(arguments),c=b.shift(),c=I&&I[c]?I[c]:"",e,a;if(c&&b&&b.length){e=0;for(a=b.length;e<a;e++)c=c.replace("%s",b[e])}return c};ma=function(b){8===n&&(1<b.loops&&b.stream)&&
    81 (p("as2loop"),b.stream=!1);return b};na=function(b,d){if(b&&!b.usePolicyFile&&(b.onid3||b.usePeakData||b.useWaveformData||b.useEQData))c._wD((d||"")+r("policy")),b.usePolicyFile=!0;return b};J=function(b){da&&console.warn!==g?console.warn(b):c._wD(b)};xa=function(){return!1};$a=function(b){for(var c in b)b.hasOwnProperty(c)&&"function"===typeof b[c]&&(b[c]=xa)};Ga=function(b){b===g&&(b=!1);(y||b)&&c.disable(b)};ab=function(b){var d=null;if(b)if(b.match(/\.swf(\?.*)?$/i)){if(d=b.substr(b.toLowerCase().lastIndexOf(".swf?")+
    82 4))return b}else b.lastIndexOf("/")!==b.length-1&&(b+="/");b=(b&&-1!==b.lastIndexOf("/")?b.substr(0,b.lastIndexOf("/")+1):"./")+c.movieURL;c.noSWFCache&&(b+="?ts\x3d"+(new Date).getTime());return b};Ca=function(){n=parseInt(c.flashVersion,10);8!==n&&9!==n&&(c._wD(r("badFV",n,8)),c.flashVersion=n=8);var b=c.debugMode||c.debugFlash?"_debug.swf":".swf";c.useHTML5Audio&&(!c.html5Only&&c.audioFormats.mp4.required&&9>n)&&(c._wD(r("needfl9")),c.flashVersion=n=9);c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":
    83 9===n?" (AS3/Flash 9)":" (AS2/Flash 8)");8<n?(c.defaultOptions=B(c.defaultOptions,c.flash9Options),c.features.buffering=!0,c.defaultOptions=B(c.defaultOptions,c.movieStarOptions),c.filePatterns.flash9=RegExp("\\.(mp3|"+qb.join("|")+")(\\?.*)?$","i"),c.features.movieStar=!0):c.features.movieStar=!1;c.filePattern=c.filePatterns[8!==n?"flash9":"flash8"];c.movieURL=(8===n?"soundmanager2.swf":"soundmanager2_flash9.swf").replace(".swf",b);c.features.peakData=c.features.waveformData=c.features.eqData=8<
    84 n};Ya=function(b,c){if(!k)return!1;k._setPolling(b,c)};Fa=function(){c.debugURLParam.test(U)&&(c.debugMode=!0);if(A(c.debugID))return!1;var b,d,e,a;if(c.debugMode&&!A(c.debugID)&&(!da||!c.useConsole||!c.consoleOnly)){b=m.createElement("div");b.id=c.debugID+"-toggle";d={position:"fixed",bottom:"0px",right:"0px",width:"1.2em",height:"1.2em",lineHeight:"1.2em",margin:"2px",textAlign:"center",border:"1px solid #999",cursor:"pointer",background:"#fff",color:"#333",zIndex:10001};b.appendChild(m.createTextNode("-"));
    85 b.onclick=bb;b.title="Toggle SM2 debug console";t.match(/msie 6/i)&&(b.style.position="absolute",b.style.cursor="hand");for(a in d)d.hasOwnProperty(a)&&(b.style[a]=d[a]);d=m.createElement("div");d.id=c.debugID;d.style.display=c.debugMode?"block":"none";if(c.debugMode&&!A(b.id)){try{e=ka(),e.appendChild(b)}catch(f){throw Error(r("domError")+" \n"+f.toString());}e.appendChild(d)}}};v=this.getSoundById;p=function(b,d){return!b?"":c._wD(r(b),d)};bb=function(){var b=A(c.debugID),d=A(c.debugID+"-toggle");
    86 if(!b)return!1;za?(d.innerHTML="+",b.style.display="none"):(d.innerHTML="-",b.style.display="block");za=!za};C=function(b,c,e){if(h.sm2Debugger!==g)try{sm2Debugger.handleEvent(b,c,e)}catch(a){return!1}return!0};T=function(){var b=[];c.debugMode&&b.push("sm2_debug");c.debugFlash&&b.push("flash_debug");c.useHighPerformance&&b.push("high_performance");return b.join(" ")};Ia=function(){var b=r("fbHandler"),d=c.getMoviePercent(),e={type:"FLASHBLOCK"};if(c.html5Only)return!1;c.ok()?(c.didFlashBlock&&c._wD(b+
    87 ": Unblocked"),c.oMC&&(c.oMC.className=[T(),"movieContainer","swf_loaded"+(c.didFlashBlock?" swf_unblocked":"")].join(" "))):(u&&(c.oMC.className=T()+" movieContainer "+(null===d?"swf_timedout":"swf_error"),c._wD(b+": "+r("fbTimeout")+(d?" ("+r("fbLoaded")+")":""))),c.didFlashBlock=!0,M({type:"ontimeout",ignoreInit:!0,error:e}),S(e))};Ba=function(b,c,e){F[b]===g&&(F[b]=[]);F[b].push({method:c,scope:e||null,fired:!1})};M=function(b){b||(b={type:c.ok()?"onready":"ontimeout"});if(!q&&b&&!b.ignoreInit||
    88 "ontimeout"===b.type&&(c.ok()||y&&!b.ignoreInit))return!1;var d={success:b&&b.ignoreInit?c.ok():!y},e=b&&b.type?F[b.type]||[]:[],a=[],f,d=[d],g=u&&!c.ok();b.error&&(d[0].error=b.error);b=0;for(f=e.length;b<f;b++)!0!==e[b].fired&&a.push(e[b]);if(a.length){b=0;for(f=a.length;b<f;b++)a[b].scope?a[b].method.apply(a[b].scope,d):a[b].method.apply(this,d),g||(a[b].fired=!0)}return!0};P=function(){h.setTimeout(function(){c.useFlashBlock&&Ia();M();"function"===typeof c.onload&&(p("onload",1),c.onload.apply(h),
    89 p("onloadOK",1));c.waitForWindowLoad&&w.add(h,"load",P)},1)};Ma=function(){if(H!==g)return H;var b=!1,c=navigator,e=c.plugins,a,f=h.ActiveXObject;if(e&&e.length)(c=c.mimeTypes)&&(c["application/x-shockwave-flash"]&&c["application/x-shockwave-flash"].enabledPlugin&&c["application/x-shockwave-flash"].enabledPlugin.description)&&(b=!0);else if(f!==g&&!t.match(/MSAppHost/i)){try{a=new f("ShockwaveFlash.ShockwaveFlash")}catch(m){a=null}b=!!a}return H=b};fb=function(){var b,d,e=c.audioFormats;if(ca&&t.match(/os (1|2|3_0|3_1)/i))c.hasHTML5=
    90 !1,c.html5Only=!0,c.oMC&&(c.oMC.style.display="none");else if(c.useHTML5Audio){if(!c.html5||!c.html5.canPlayType)c._wD("SoundManager: No HTML5 Audio() support detected."),c.hasHTML5=!1;Qa&&c._wD("soundManager: Note: Buggy HTML5 Audio in Safari on this OS X release, see https://bugs.webkit.org/show_bug.cgi?id\x3d32159 - "+(!H?" would use flash fallback for MP3/MP4, but none detected.":"will use flash fallback for MP3/MP4, if available"),1)}if(c.useHTML5Audio&&c.hasHTML5)for(d in qa=!0,e)if(e.hasOwnProperty(d)&&
    91 e[d].required)if(c.html5.canPlayType(e[d].type)){if(c.preferFlash&&(c.flash[d]||c.flash[e[d].type]))b=!0}else qa=!1,b=!0;c.ignoreFlash&&(b=!1,qa=!0);c.html5Only=c.hasHTML5&&c.useHTML5Audio&&!b;return!c.html5Only};pa=function(b){var d,e,a=0;if(b instanceof Array){d=0;for(e=b.length;d<e;d++)if(b[d]instanceof Object){if(c.canPlayMIME(b[d].type)){a=d;break}}else if(c.canPlayURL(b[d])){a=d;break}b[a].url&&(b[a]=b[a].url);b=b[a]}return b};cb=function(b){b._hasTimer||(b._hasTimer=!0,!Pa&&c.html5PollingInterval&&
    92 (null===aa&&0===oa&&(aa=setInterval(eb,c.html5PollingInterval)),oa++))};db=function(b){b._hasTimer&&(b._hasTimer=!1,!Pa&&c.html5PollingInterval&&oa--)};eb=function(){var b;if(null!==aa&&!oa)return clearInterval(aa),aa=null,!1;for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].isHTML5&&c.sounds[c.soundIDs[b]]._hasTimer&&c.sounds[c.soundIDs[b]]._onTimer()};S=function(b){b=b!==g?b:{};"function"===typeof c.onerror&&c.onerror.apply(h,[{type:b.type!==g?b.type:null}]);b.fatal!==g&&b.fatal&&c.disable()};
    93 ib=function(){if(!Qa||!Ma())return!1;var b=c.audioFormats,d,e;for(e in b)if(b.hasOwnProperty(e)&&("mp3"===e||"mp4"===e))if(c._wD("soundManager: Using flash fallback for "+e+" format"),c.html5[e]=!1,b[e]&&b[e].related)for(d=b[e].related.length-1;0<=d;d--)c.html5[b[e].related[d]]=!1};this._setSandboxType=function(b){var d=c.sandbox;d.type=b;d.description=d.types[d.types[b]!==g?b:"unknown"];"localWithFile"===d.type?(d.noRemote=!0,d.noLocal=!1,p("secNote",2)):"localWithNetwork"===d.type?(d.noRemote=!1,
    94 d.noLocal=!0):"localTrusted"===d.type&&(d.noRemote=!1,d.noLocal=!1)};this._externalInterfaceOK=function(b){if(c.swfLoaded)return!1;var d;C("swf",!0);C("flashtojs",!0);c.swfLoaded=!0;va=!1;Qa&&ib();if(!b||b.replace(/\+dev/i,"")!==c.versionNumber.replace(/\+dev/i,""))return d='soundManager: Fatal: JavaScript file build "'+c.versionNumber+'" does not match Flash SWF build "'+b+'" at '+c.url+". Ensure both are up-to-date.",setTimeout(function(){throw Error(d);},0),!1;setTimeout(ya,L?100:1)};la=function(b,
    95 d){function e(){var a=[],b,d=[];b="SoundManager "+c.version+(!c.html5Only&&c.useHTML5Audio?c.hasHTML5?" + HTML5 audio":", no HTML5 audio support":"");c.html5Only?c.html5PollingInterval&&a.push("html5PollingInterval ("+c.html5PollingInterval+"ms)"):(c.preferFlash&&a.push("preferFlash"),c.useHighPerformance&&a.push("useHighPerformance"),c.flashPollingInterval&&a.push("flashPollingInterval ("+c.flashPollingInterval+"ms)"),c.html5PollingInterval&&a.push("html5PollingInterval ("+c.html5PollingInterval+
    96 "ms)"),c.wmode&&a.push("wmode ("+c.wmode+")"),c.debugFlash&&a.push("debugFlash"),c.useFlashBlock&&a.push("flashBlock"));a.length&&(d=d.concat([a.join(" + ")]));c._wD(b+(d.length?" + "+d.join(", "):""),1);jb()}function a(a,b){return'\x3cparam name\x3d"'+a+'" value\x3d"'+b+'" /\x3e'}if(V&&W)return!1;if(c.html5Only)return Ca(),e(),c.oMC=A(c.movieID),ya(),W=V=!0,!1;var f=d||c.url,h=c.altURL||f,k=ka(),l=T(),n=null,n=m.getElementsByTagName("html")[0],p,s,q,n=n&&n.dir&&n.dir.match(/rtl/i);b=b===g?c.id:b;
    97 Ca();c.url=ab(ea?f:h);d=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;if(null!==c.wmode&&(t.match(/msie 8/i)||!L&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i))N.push(I.spcWmode),c.wmode=null;k={name:b,id:b,src:d,quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:ob+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};c.debugFlash&&
    98 (k.FlashVars="debug\x3d1");c.wmode||delete k.wmode;if(L)f=m.createElement("div"),s=['\x3cobject id\x3d"'+b+'" data\x3d"'+d+'" type\x3d"'+k.type+'" title\x3d"'+k.title+'" classid\x3d"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase\x3d"'+ob+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version\x3d6,0,40,0"\x3e',a("movie",d),a("AllowScriptAccess",c.allowScriptAccess),a("quality",k.quality),c.wmode?a("wmode",c.wmode):"",a("bgcolor",c.bgColor),a("hasPriority","true"),c.debugFlash?
    99 a("FlashVars",k.FlashVars):"","\x3c/object\x3e"].join("");else for(p in f=m.createElement("embed"),k)k.hasOwnProperty(p)&&f.setAttribute(p,k[p]);Fa();l=T();if(k=ka())if(c.oMC=A(c.movieID)||m.createElement("div"),c.oMC.id)q=c.oMC.className,c.oMC.className=(q?q+" ":"movieContainer")+(l?" "+l:""),c.oMC.appendChild(f),L&&(p=c.oMC.appendChild(m.createElement("div")),p.className="sm2-object-box",p.innerHTML=s),W=!0;else{c.oMC.id=c.movieID;c.oMC.className="movieContainer "+l;p=l=null;c.useFlashBlock||(c.useHighPerformance?
    100 l={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"}:(l={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},n&&(l.left=Math.abs(parseInt(l.left,10))+"px")));tb&&(c.oMC.style.zIndex=1E4);if(!c.debugFlash)for(q in l)l.hasOwnProperty(q)&&(c.oMC.style[q]=l[q]);try{L||c.oMC.appendChild(f),k.appendChild(c.oMC),L&&(p=c.oMC.appendChild(m.createElement("div")),p.className="sm2-object-box",p.innerHTML=s),W=!0}catch(u){throw Error(r("domError")+" \n"+
    101 u.toString());}}V=!0;e();return!0};ja=function(){if(c.html5Only)return la(),!1;if(k)return!1;if(!c.url)return p("noURL"),!1;k=c.getMovie(c.id);k||(Z?(L?c.oMC.innerHTML=Ha:c.oMC.appendChild(Z),Z=null,V=!0):la(c.id,c.url),k=c.getMovie(c.id));"function"===typeof c.oninitmovie&&setTimeout(c.oninitmovie,1);Na();return!0};Q=function(){setTimeout(Xa,1E3)};Xa=function(){var b,d=!1;if(!c.url||$)return!1;$=!0;w.remove(h,"load",Q);if(va&&!Ra)return p("waitFocus"),!1;q||(b=c.getMoviePercent(),0<b&&100>b&&(d=
    102 !0));setTimeout(function(){b=c.getMoviePercent();if(d)return $=!1,c._wD(r("waitSWF")),h.setTimeout(Q,1),!1;q||(c._wD("soundManager: No Flash response within expected time. Likely causes: "+(0===b?"SWF load failed, ":"")+"Flash blocked or JS-Flash security error."+(c.debugFlash?" "+r("checkSWF"):""),2),!ea&&b&&(p("localFail",2),c.debugFlash||p("tryDebug",2)),0===b&&c._wD(r("swf404",c.url),1),C("flashtojs",!1,": Timed out"+ea?" (Check flash security or flash blockers)":" (No plugin/missing SWF?)"));
    103 !q&&mb&&(null===b?c.useFlashBlock||0===c.flashLoadTimeout?(c.useFlashBlock&&Ia(),p("waitForever")):!c.useFlashBlock&&qa?h.setTimeout(function(){J("soundManager: useFlashBlock is false, 100% HTML5 mode is possible. Rebooting with preferFlash: false...");c.setup({preferFlash:!1}).reboot();c.didFlashBlock=!0;c.beginDelayedInit()},1):(p("waitForever"),M({type:"ontimeout",ignoreInit:!0})):0===c.flashLoadTimeout?p("waitForever"):Ga(!0))},c.flashLoadTimeout)};ia=function(){if(Ra||!va)return w.remove(h,"focus",
    104 ia),!0;Ra=mb=!0;p("gotFocus");$=!1;Q();w.remove(h,"focus",ia);return!0};Na=function(){N.length&&(c._wD("SoundManager 2: "+N.join(" "),1),N=[])};jb=function(){Na();var b,d=[];if(c.useHTML5Audio&&c.hasHTML5){for(b in c.audioFormats)c.audioFormats.hasOwnProperty(b)&&d.push(b+" \x3d "+c.html5[b]+(!c.html5[b]&&u&&c.flash[b]?" (using flash)":c.preferFlash&&c.flash[b]&&u?" (preferring flash)":!c.html5[b]?" ("+(c.audioFormats[b].required?"required, ":"")+"and no flash support)":""));c._wD("SoundManager 2 HTML5 support: "+
    105 d.join(", "),1)}};X=function(b){if(q)return!1;if(c.html5Only)return p("sm2Loaded"),q=!0,P(),C("onload",!0),!0;var d=!0,e;if(!c.useFlashBlock||!c.flashLoadTimeout||c.getMoviePercent())q=!0,y&&(e={type:!H&&u?"NO_FLASH":"INIT_TIMEOUT"});c._wD("SoundManager 2 "+(y?"failed to load":"loaded")+" ("+(y?"Flash security/load error":"OK")+")",y?2:1);y||b?(c.useFlashBlock&&c.oMC&&(c.oMC.className=T()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error")),M({type:"ontimeout",error:e,ignoreInit:!0}),C("onload",
    106 !1),S(e),d=!1):C("onload",!0);y||(c.waitForWindowLoad&&!ha?(p("waitOnload"),w.add(h,"load",P)):(c.waitForWindowLoad&&ha&&p("docLoaded"),P()));return d};Wa=function(){var b,d=c.setupOptions;for(b in d)d.hasOwnProperty(b)&&(c[b]===g?c[b]=d[b]:c[b]!==d[b]&&(c.setupOptions[b]=c[b]))};ya=function(){if(q)return p("didInit"),!1;if(c.html5Only)return q||(w.remove(h,"load",c.beginDelayedInit),c.enabled=!0,X()),!0;ja();try{k._externalInterfaceTest(!1),Ya(!0,c.flashPollingInterval||(c.useHighPerformance?10:
    107 50)),c.debugMode||k._disableDebug(),c.enabled=!0,C("jstoflash",!0),c.html5Only||w.add(h,"unload",xa)}catch(b){return c._wD("js/flash exception: "+b.toString()),C("jstoflash",!1),S({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),Ga(!0),X(),!1}X();w.remove(h,"load",c.beginDelayedInit);return!0};R=function(){if(Y)return!1;Y=!0;Wa();Fa();var b=null,b=null,d=U.toLowerCase();-1!==d.indexOf("sm2-usehtml5audio\x3d")&&(b="1"===d.charAt(d.indexOf("sm2-usehtml5audio\x3d")+18),da&&console.log((b?"Enabling ":"Disabling ")+
    108 "useHTML5Audio via URL parameter"),c.setup({useHTML5Audio:b}));-1!==d.indexOf("sm2-preferflash\x3d")&&(b="1"===d.charAt(d.indexOf("sm2-preferflash\x3d")+16),da&&console.log((b?"Enabling ":"Disabling ")+"preferFlash via URL parameter"),c.setup({preferFlash:b}));!H&&c.hasHTML5&&(c._wD("SoundManager: No Flash detected"+(!c.useHTML5Audio?", enabling HTML5.":". Trying HTML5-only mode."),1),c.setup({useHTML5Audio:!0,preferFlash:!1}));gb();!H&&u&&(N.push(I.needFlash),c.setup({flashLoadTimeout:1}));m.removeEventListener&&
    109 m.removeEventListener("DOMContentLoaded",R,!1);ja();return!0};Ka=function(){"complete"===m.readyState&&(R(),m.detachEvent("onreadystatechange",Ka));return!0};Ea=function(){ha=!0;w.remove(h,"load",Ea)};Da=function(){if(Pa&&((!c.setupOptions.useHTML5Audio||c.setupOptions.preferFlash)&&N.push(I.mobileUA),c.setupOptions.useHTML5Audio=!0,c.setupOptions.preferFlash=!1,ca||lb&&!t.match(/android\s2\.3/i)))N.push(I.globalHTML5),ca&&(c.ignoreFlash=!0),E=!0};Da();Ma();w.add(h,"focus",ia);w.add(h,"load",Q);w.add(h,
    110 "load",Ea);m.addEventListener?m.addEventListener("DOMContentLoaded",R,!1):m.attachEvent?m.attachEvent("onreadystatechange",Ka):(C("onload",!1),S({type:"NO_DOM2_EVENTS",fatal:!0}))}var wa=null;if(void 0===h.SM2_DEFER||!SM2_DEFER)wa=new fa;h.SoundManager=fa;h.soundManager=wa})(window);
     14(function(h,g){function J(sb,J){function ha(b){return c.preferFlash&&G&&!c.ignoreFlash&&c.flash[b]!==g&&c.flash[b]}function r(b){return function(d){var e=this._s;e&&e._a?d=b.call(this,d):(e&&e.id?c._wD(e.id+": Ignoring "+d.type):c._wD("HTML5::Ignoring "+d.type),d=null);return d}}this.setupOptions={url:sb||null,flashVersion:8,debugMode:!0,debugFlash:!1,useConsole:!0,consoleOnly:!0,waitForWindowLoad:!1,bgColor:"#ffffff",useHighPerformance:!1,flashPollingInterval:null,html5PollingInterval:null,flashLoadTimeout:1E3,
     15wmode:null,allowScriptAccess:"always",useFlashBlock:!1,useHTML5Audio:!0,forceUseGlobalHTML5Audio:!1,ignoreMobileRestrictions:!1,html5Test:/^(probably|maybe)$/i,preferFlash:!1,noSWFCache:!1,idPrefix:"sound"};this.defaultOptions={autoLoad:!1,autoPlay:!1,from:null,loops:1,onid3:null,onerror:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onposition:null,onstop:null,onfinish:null,multiShot:!0,multiShotEvents:!1,position:null,pan:0,playbackRate:1,stream:!0,to:null,
     16type:null,usePolicyFile:!1,volume:100};this.flash9Options={onfailure:null,isMovieStar:null,usePeakData:!1,useWaveformData:!1,useEQData:!1,onbufferchange:null,ondataerror:null};this.movieStarOptions={bufferTime:3,serverURL:null,onconnect:null,duration:null};this.audioFormats={mp3:{type:['audio/mpeg; codecs="mp3"',"audio/mpeg","audio/mp3","audio/MPA","audio/mpa-robust"],required:!0},mp4:{related:["aac","m4a","m4b"],type:['audio/mp4; codecs="mp4a.40.2"',"audio/aac","audio/x-m4a","audio/MP4A-LATM","audio/mpeg4-generic"],
     17required:!1},ogg:{type:["audio/ogg; codecs=vorbis"],required:!1},opus:{type:["audio/ogg; codecs=opus","audio/opus"],required:!1},wav:{type:['audio/wav; codecs="1"',"audio/wav","audio/wave","audio/x-wav"],required:!1},flac:{type:["audio/flac"],required:!1}};this.movieID="sm2-container";this.id=J||"sm2movie";this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.versionNumber="V2.97a.20170601";this.altURL=this.movieURL=this.version=null;this.enabled=this.swfLoaded=!1;this.oMC=null;
     18this.sounds={};this.soundIDs=[];this.didFlashBlock=this.muted=!1;this.filePattern=null;this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};this.features={buffering:!1,peakData:!1,waveformData:!1,eqData:!1,movieStar:!1};this.sandbox={type:null,types:{remote:"remote (domain-based) rules",localWithFile:"local with file access (no internet access)",localWithNetwork:"local with network (internet access only, no local access)",localTrusted:"local, trusted (local+internet access)"},description:null,
     19noRemote:null,noLocal:null};this.html5={usingFlash:null};this.flash={};this.ignoreFlash=this.html5Only=!1;var V,c=this,Ya=null,l=null,E,v=navigator.userAgent,ia=h.location.href.toString(),m=document,xa,Za,ya,n,H=[],za=!0,C,W=!1,X=!1,q=!1,y=!1,ja=!1,p,tb=0,Y,A,Aa,Q,Ba,O,R,S,$a,Ca,Da,ka,z,la,P,Ea,Z,ma,na,T,ab,Fa,bb=["log","info","warn","error"],Ga,Ha,cb,aa=null,Ia=null,t,Ja,U,db,oa,pa,K,w,ba=!1,Ka=!1,eb,fb,gb,qa=0,ca=null,ra,L=[],da,u=null,hb,sa,ea,ib,M,ta,La,jb,x,kb=Array.prototype.slice,B=!1,Ma,G,
     20Na,lb,I,mb,Oa,fa,nb=0,Pa,Qa=v.match(/(ipad|iphone|ipod)/i),Ra=v.match(/android/i),N=v.match(/msie|trident/i),ub=v.match(/webkit/i),ua=v.match(/safari/i)&&!v.match(/chrome/i),Sa=v.match(/opera/i),va=v.match(/(mobile|pre\/|xoom)/i)||Qa||Ra,Ta=!ia.match(/usehtml5audio/i)&&!ia.match(/sm2-ignorebadua/i)&&ua&&!v.match(/silk/i)&&v.match(/OS\sX\s10_6_([3-7])/i),Ua=h.console!==g&&console.log!==g,Va=m.hasFocus!==g?m.hasFocus():null,wa=ua&&(m.hasFocus===g||!m.hasFocus()),ob=!wa,pb=/(mp3|mp4|mpa|m4a|m4b)/i,ga=
     21m.location?m.location.protocol.match(/http/i):null,vb=ga?"":"//",qb=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4|m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,rb="mpeg4 aac flv mov mp4 m4v f4v m4a m4b mp4v 3gp 3g2".split(" "),wb=new RegExp("\\.("+rb.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL=!ga;ib=[null,"MEDIA_ERR_ABORTED","MEDIA_ERR_NETWORK","MEDIA_ERR_DECODE","MEDIA_ERR_SRC_NOT_SUPPORTED"];var Wa;try{Wa=Audio!==g&&(Sa&&opera!==g&&10>opera.version()?
     22new Audio(null):new Audio).canPlayType!==g}catch(xb){Wa=!1}this.hasHTML5=Wa;this.setup=function(b){var d=!c.url;b!==g&&q&&u&&c.ok()&&(b.flashVersion!==g||b.url!==g||b.html5Test!==g)&&K(t("setupLate"));Aa(b);if(!B)if(va){if(!c.setupOptions.ignoreMobileRestrictions||c.setupOptions.forceUseGlobalHTML5Audio)L.push(z.globalHTML5),B=!0}else c.setupOptions.forceUseGlobalHTML5Audio&&(L.push(z.globalHTML5),B=!0);if(!Pa&&va)if(c.setupOptions.ignoreMobileRestrictions)L.push(z.ignoreMobile);else if(c.setupOptions.useHTML5Audio&&
     23!c.setupOptions.preferFlash||c._wD(z.mobileUA),c.setupOptions.useHTML5Audio=!0,c.setupOptions.preferFlash=!1,Qa)c.ignoreFlash=!0;else if(Ra&&!v.match(/android\s2\.3/i)||!Ra)c._wD(z.globalHTML5),B=!0;b&&(d&&Z&&b.url!==g&&c.beginDelayedInit(),Z||b.url===g||"complete"!==m.readyState||setTimeout(P,1));Pa=!0;return c};this.supported=this.ok=function(){return u?q&&!y:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(c){return E(c)||m[c]||h[c]};this.createSound=function(b,d){function e(){f=oa(f);c.sounds[f.id]=
     24new V(f);c.soundIDs.push(f.id);return c.sounds[f.id]}var a,f;a=null;a="soundManager.createSound(): "+t(q?"notOK":"notReady");if(!q||!c.ok())return K(a),!1;d!==g&&(b={id:b,url:d});f=A(b);f.url=ra(f.url);f.id===g&&(f.id=c.setupOptions.idPrefix+nb++);f.id.toString().charAt(0).match(/^[0-9]$/)&&c._wD("soundManager.createSound(): "+t("badID",f.id),2);c._wD("soundManager.createSound(): "+f.id+(f.url?" ("+f.url+")":""),1);if(w(f.id,!0))return c._wD("soundManager.createSound(): "+f.id+" exists",1),c.sounds[f.id];
     25if(sa(f))a=e(),c.html5Only||c._wD(f.id+": Using HTML5"),a._setup_html5(f);else{if(c.html5Only)return c._wD(f.id+": No HTML5 support for this sound, and no Flash. Exiting."),e();if(c.html5.usingFlash&&f.url&&f.url.match(/data:/i))return c._wD(f.id+": data: URIs not supported via Flash. Exiting."),e();8<n&&(null===f.isMovieStar&&(f.isMovieStar=!!(f.serverURL||f.type&&f.type.match(qb)||f.url&&f.url.match(wb))),f.isMovieStar&&(c._wD("soundManager.createSound(): using MovieStar handling"),1<f.loops&&p("noNSLoop")));
     26f=pa(f,"soundManager.createSound(): ");a=e();8===n?l._createSound(f.id,f.loops||1,f.usePolicyFile):(l._createSound(f.id,f.url,f.usePeakData,f.useWaveformData,f.useEQData,f.isMovieStar,f.isMovieStar?f.bufferTime:!1,f.loops||1,f.serverURL,f.duration||null,f.autoPlay,!0,f.autoLoad,f.usePolicyFile),f.serverURL||(a.connected=!0,f.onconnect&&f.onconnect.apply(a)));f.serverURL||!f.autoLoad&&!f.autoPlay||a.load(f)}!f.serverURL&&f.autoPlay&&a.play();return a};this.destroySound=function(b,d){if(!w(b))return!1;
     27var e=c.sounds[b],a;e.stop();e._iO={};e.unload();for(a=0;a<c.soundIDs.length;a++)if(c.soundIDs[a]===b){c.soundIDs.splice(a,1);break}d||e.destruct(!0);delete c.sounds[b];return!0};this.load=function(b,d){return w(b)?c.sounds[b].load(d):!1};this.unload=function(b){return w(b)?c.sounds[b].unload():!1};this.onposition=this.onPosition=function(b,d,e,a){return w(b)?c.sounds[b].onposition(d,e,a):!1};this.clearOnPosition=function(b,d,e){return w(b)?c.sounds[b].clearOnPosition(d,e):!1};this.start=this.play=
     28function(b,d){var e=null,a=d&&!(d instanceof Object);if(!q||!c.ok())return K("soundManager.play(): "+t(q?"notOK":"notReady")),!1;if(w(b,a))a&&(d={url:d});else{if(!a)return!1;a&&(d={url:d});d&&d.url&&(c._wD('soundManager.play(): Attempting to create "'+b+'"',1),d.id=b,e=c.createSound(d).play())}null===e&&(e=c.sounds[b].play(d));return e};this.setPlaybackRate=function(b,d,e){return w(b)?c.sounds[b].setPlaybackRate(d,e):!1};this.setPosition=function(b,d){return w(b)?c.sounds[b].setPosition(d):!1};this.stop=
     29function(b){if(!w(b))return!1;c._wD("soundManager.stop("+b+")",1);return c.sounds[b].stop()};this.stopAll=function(){var b;c._wD("soundManager.stopAll()",1);for(b in c.sounds)c.sounds.hasOwnProperty(b)&&c.sounds[b].stop()};this.pause=function(b){return w(b)?c.sounds[b].pause():!1};this.pauseAll=function(){var b;for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].pause()};this.resume=function(b){return w(b)?c.sounds[b].resume():!1};this.resumeAll=function(){var b;for(b=c.soundIDs.length-1;0<=
     30b;b--)c.sounds[c.soundIDs[b]].resume()};this.togglePause=function(b){return w(b)?c.sounds[b].togglePause():!1};this.setPan=function(b,d){return w(b)?c.sounds[b].setPan(d):!1};this.setVolume=function(b,d){var e,a;if(b!==g&&!isNaN(b)&&d===g){e=0;for(a=c.soundIDs.length;e<a;e++)c.sounds[c.soundIDs[e]].setVolume(b);return!1}return w(b)?c.sounds[b].setVolume(d):!1};this.mute=function(b){var d=0;b instanceof String&&(b=null);if(b){if(!w(b))return!1;c._wD('soundManager.mute(): Muting "'+b+'"');return c.sounds[b].mute()}c._wD("soundManager.mute(): Muting all sounds");
     31for(d=c.soundIDs.length-1;0<=d;d--)c.sounds[c.soundIDs[d]].mute();return c.muted=!0};this.muteAll=function(){c.mute()};this.unmute=function(b){b instanceof String&&(b=null);if(b){if(!w(b))return!1;c._wD('soundManager.unmute(): Unmuting "'+b+'"');return c.sounds[b].unmute()}c._wD("soundManager.unmute(): Unmuting all sounds");for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].unmute();c.muted=!1;return!0};this.unmuteAll=function(){c.unmute()};this.toggleMute=function(b){return w(b)?c.sounds[b].toggleMute():
     32!1};this.getMemoryUse=function(){var c=0;l&&8!==n&&(c=parseInt(l._getMemoryUse(),10));return c};this.disable=function(b){var d;b===g&&(b=!1);if(y)return!1;y=!0;p("shutdown",1);for(d=c.soundIDs.length-1;0<=d;d--)Ga(c.sounds[c.soundIDs[d]]);Ga(c);Y(b);x.remove(h,"load",R);return!0};this.canPlayMIME=function(b){var d;c.hasHTML5&&(d=ea({type:b}));!d&&u&&(d=b&&c.ok()?!!(8<n&&b.match(qb)||b.match(c.mimePattern)):null);return d};this.canPlayURL=function(b){var d;c.hasHTML5&&(d=ea({url:b}));!d&&u&&(d=b&&
     33c.ok()?!!b.match(c.filePattern):null);return d};this.canPlayLink=function(b){return b.type!==g&&b.type&&c.canPlayMIME(b.type)?!0:c.canPlayURL(b.href)};this.getSoundById=function(b,d){if(!b)return null;var e=c.sounds[b];e||d||c._wD('soundManager.getSoundById(): Sound "'+b+'" not found.',2);return e};this.onready=function(b,d){if("function"===typeof b)q&&c._wD(t("queue","onready")),d||(d=h),Ba("onready",b,d),O();else throw t("needFunction","onready");return!0};this.ontimeout=function(b,d){if("function"===
     34typeof b)q&&c._wD(t("queue","ontimeout")),d||(d=h),Ba("ontimeout",b,d),O({type:"ontimeout"});else throw t("needFunction","ontimeout");return!0};this._writeDebug=function(b,d){var e,a;if(!c.setupOptions.debugMode)return!1;if(Ua&&c.useConsole){if(d&&"object"===typeof d)console.log(b,d);else if(bb[d]!==g)console[bb[d]](b);else console.log(b);if(c.consoleOnly)return!0}e=E("soundmanager-debug");if(!e)return!1;a=m.createElement("div");0===++tb%2&&(a.className="sm2-alt");d=d===g?0:parseInt(d,10);a.appendChild(m.createTextNode(b));
     35d&&(2<=d&&(a.style.fontWeight="bold"),3===d&&(a.style.color="#ff3333"));e.insertBefore(a,e.firstChild);return!0};-1!==ia.indexOf("sm2-debug=alert")&&(this._writeDebug=function(c){h.alert(c)});this._wD=this._writeDebug;this._debug=function(){var b,d;p("currentObj",1);b=0;for(d=c.soundIDs.length;b<d;b++)c.sounds[c.soundIDs[b]]._debug()};this.reboot=function(b,d){c.soundIDs.length&&c._wD("Destroying "+c.soundIDs.length+" SMSound object"+(1!==c.soundIDs.length?"s":"")+"...");var e,a,f;for(e=c.soundIDs.length-
     361;0<=e;e--)c.sounds[c.soundIDs[e]].destruct();if(l)try{N&&(Ia=l.innerHTML),aa=l.parentNode.removeChild(l)}catch(g){p("badRemove",2)}Ia=aa=u=l=null;c.enabled=Z=q=ba=Ka=W=X=y=B=c.swfLoaded=!1;c.soundIDs=[];c.sounds={};nb=0;Pa=!1;if(b)H=[];else for(e in H)if(H.hasOwnProperty(e))for(a=0,f=H[e].length;a<f;a++)H[e][a].fired=!1;d||c._wD("soundManager: Rebooting...");c.html5={usingFlash:null};c.flash={};c.html5Only=!1;c.ignoreFlash=!1;h.setTimeout(function(){d||c.beginDelayedInit()},20);return c};this.reset=
     37function(){p("reset");return c.reboot(!0,!0)};this.getMoviePercent=function(){return l&&"PercentLoaded"in l?l.PercentLoaded():null};this.beginDelayedInit=function(){ja=!0;P();setTimeout(function(){if(Ka)return!1;na();la();return Ka=!0},20);S()};this.destruct=function(){c._wD("soundManager.destruct()");c.disable(!0)};V=function(b){var d,e,a=this,f,h,k,F,m,q,r=!1,D=[],v=0,Xa,y,u=null,z;e=d=null;this.sID=this.id=b.id;this.url=b.url;this._iO=this.instanceOptions=this.options=A(b);this.pan=this.options.pan;
     38this.volume=this.options.volume;this.isHTML5=!1;this._a=null;z=!this.url;this.id3={};this._debug=function(){c._wD(a.id+": Merged options:",a.options)};this.load=function(b){var d=null,e;b!==g?a._iO=A(b,a.options):(b=a.options,a._iO=b,u&&u!==a.url&&(p("manURL"),a._iO.url=a.url,a.url=null));a._iO.url||(a._iO.url=a.url);a._iO.url=ra(a._iO.url);e=a.instanceOptions=a._iO;c._wD(a.id+": load ("+e.url+")");if(!e.url&&!a.url)return c._wD(a.id+": load(): url is unassigned. Exiting.",2),a;a.isHTML5||8!==n||
     39a.url||e.autoPlay||c._wD(a.id+": Flash 8 load() limitation: Wait for onload() before calling play().",1);if(e.url===a.url&&0!==a.readyState&&2!==a.readyState)return p("onURL",1),3===a.readyState&&e.onload&&fa(a,function(){e.onload.apply(a,[!!a.duration])}),a;a.loaded=!1;a.readyState=1;a.playState=0;a.id3={};if(sa(e))d=a._setup_html5(e),d._called_load?c._wD(a.id+": Ignoring request to load again"):(a._html5_canplay=!1,a.url!==e.url&&(c._wD(p("manURL")+": "+e.url),a._a.src=e.url,a.setPosition(0)),a._a.autobuffer=
     40"auto",a._a.preload="auto",a._a._called_load=!0);else{if(c.html5Only)return c._wD(a.id+": No flash support. Exiting."),a;if(a._iO.url&&a._iO.url.match(/data:/i))return c._wD(a.id+": data: URIs not supported via Flash. Exiting."),a;try{a.isHTML5=!1,a._iO=pa(oa(e)),a._iO.autoPlay&&(a._iO.position||a._iO.from)&&(c._wD(a.id+": Disabling autoPlay because of non-zero offset case"),a._iO.autoPlay=!1),e=a._iO,8===n?l._load(a.id,e.url,e.stream,e.autoPlay,e.usePolicyFile):l._load(a.id,e.url,!!e.stream,!!e.autoPlay,
     41e.loops||1,!!e.autoLoad,e.usePolicyFile)}catch(f){p("smError",2),C("onload",!1),T({type:"SMSOUND_LOAD_JS_EXCEPTION",fatal:!0})}}a.url=e.url;return a};this.unload=function(){0!==a.readyState&&(c._wD(a.id+": unload()"),a.isHTML5?(F(),a._a&&(a._a.pause(),u=ta(a._a))):8===n?l._unload(a.id,"about:blank"):l._unload(a.id),f());return a};this.destruct=function(b){c._wD(a.id+": Destruct");a.isHTML5?(F(),a._a&&(a._a.pause(),ta(a._a),B||k(),a._a._s=null,a._a=null)):(a._iO.onfailure=null,l._destroySound(a.id));
     42b||c.destroySound(a.id,!0)};this.start=this.play=function(b,d){var e,f,k,F,h;f=!0;e=a.id+": play(): ";d=d===g?!0:d;b||(b={});a.url&&(a._iO.url=a.url);a._iO=A(a._iO,a.options);a._iO=A(b,a._iO);a._iO.url=ra(a._iO.url);a.instanceOptions=a._iO;if(!a.isHTML5&&a._iO.serverURL&&!a.connected)return a.getAutoPlay()||(c._wD(e+" Netstream not connected yet - setting autoPlay"),a.setAutoPlay(!0)),a;sa(a._iO)&&(a._setup_html5(a._iO),m());if(1===a.playState&&!a.paused){f=a._iO.multiShot;if(!f)return c._wD(e+"Already playing (one-shot)",
     431),a.isHTML5&&a.setPosition(a._iO.position),a;c._wD(e+"Already playing (multi-shot)",1)}b.url&&b.url!==a.url&&(a.readyState||a.isHTML5||8!==n||!z?a.load(a._iO):z=!1);if(a.loaded)c._wD(e.substr(0,e.lastIndexOf(":")));else if(0===a.readyState){c._wD(e+"Attempting to load");if(a.isHTML5||c.html5Only)if(a.isHTML5)a.load(a._iO);else return c._wD(e+"Unsupported type. Exiting."),a;else a._iO.autoPlay=!0,a.load(a._iO);a.instanceOptions=a._iO}else{if(2===a.readyState)return c._wD(e+"Could not load - exiting",
     442),a;c._wD(e+"Loading - attempting to play...")}!a.isHTML5&&9===n&&0<a.position&&a.position===a.duration&&(c._wD(e+"Sound at end, resetting to position: 0"),b.position=0);a.paused&&0<=a.position&&(!a._iO.serverURL||0<a.position)?(c._wD(e+"Resuming from paused state",1),a.resume()):(a._iO=A(b,a._iO),(!a.isHTML5&&null!==a._iO.position&&0<a._iO.position||null!==a._iO.from&&0<a._iO.from||null!==a._iO.to)&&0===a.instanceCount&&0===a.playState&&!a._iO.serverURL&&(f=function(){a._iO=A(b,a._iO);a.play(a._iO)},
     45a.isHTML5&&!a._html5_canplay?(c._wD(e+"Beginning load for non-zero offset case"),a.load({_oncanplay:f})):a.isHTML5||a.loaded||a.readyState&&2===a.readyState||(c._wD(e+"Preloading for non-zero offset case"),a.load({onload:f})),a._iO=y()),(!a.instanceCount||a._iO.multiShotEvents||a.isHTML5&&a._iO.multiShot&&!B||!a.isHTML5&&8<n&&!a.getAutoPlay())&&a.instanceCount++,a._iO.onposition&&0===a.playState&&q(a),a.playState=1,a.paused=!1,a.position=a._iO.position===g||isNaN(a._iO.position)?0:a._iO.position,
     46a.isHTML5||(a._iO=pa(oa(a._iO))),a._iO.onplay&&d&&(a._iO.onplay.apply(a),r=!0),a.setVolume(a._iO.volume,!0),a.setPan(a._iO.pan,!0),1!==a._iO.playbackRate&&a.setPlaybackRate(a._iO.playbackRate),a.isHTML5?2>a.instanceCount?(m(),e=a._setup_html5(),a.setPosition(a._iO.position),e.play()):(c._wD(a.id+": Cloning Audio() for instance #"+a.instanceCount+"..."),k=new Audio(a._iO.url),F=function(){x.remove(k,"ended",F);a._onfinish(a);ta(k);k=null},h=function(){x.remove(k,"canplay",h);try{k.currentTime=a._iO.position/
     471E3}catch(c){K(a.id+": multiShot play() failed to apply position of "+a._iO.position/1E3)}k.play()},x.add(k,"ended",F),a._iO.volume!==g&&(k.volume=Math.max(0,Math.min(1,a._iO.volume/100))),a.muted&&(k.muted=!0),a._iO.position?x.add(k,"canplay",h):k.play()):(f=l._start(a.id,a._iO.loops||1,9===n?a.position:a.position/1E3,a._iO.multiShot||!1),9!==n||f||(c._wD(e+"No sound hardware, or 32-sound ceiling hit",2),a._iO.onplayerror&&a._iO.onplayerror.apply(a))));return a};this.stop=function(b){var d=a._iO;
     481===a.playState&&(c._wD(a.id+": stop()"),a._onbufferchange(0),a._resetOnPosition(0),a.paused=!1,a.isHTML5||(a.playState=0),Xa(),d.to&&a.clearOnPosition(d.to),a.isHTML5?a._a&&(b=a.position,a.setPosition(0),a.position=b,a._a.pause(),a.playState=0,a._onTimer(),F()):(l._stop(a.id,b),d.serverURL&&a.unload()),a.instanceCount=0,a._iO={},d.onstop&&d.onstop.apply(a));return a};this.setAutoPlay=function(b){c._wD(a.id+": Autoplay turned "+(b?"on":"off"));a._iO.autoPlay=b;a.isHTML5||(l._setAutoPlay(a.id,b),b&&
     49!a.instanceCount&&1===a.readyState&&(a.instanceCount++,c._wD(a.id+": Incremented instance count to "+a.instanceCount)))};this.getAutoPlay=function(){return a._iO.autoPlay};this.setPlaybackRate=function(b){var d=Math.max(.5,Math.min(4,b));d!==b&&c._wD(a.id+": setPlaybackRate("+b+"): limiting rate to "+d,2);if(a.isHTML5)try{a._iO.playbackRate=d,a._a.playbackRate=d}catch(e){c._wD(a.id+": setPlaybackRate("+d+") failed: "+e.message,2)}return a};this.setPosition=function(b){b===g&&(b=0);var d=a.isHTML5?
     50Math.max(b,0):Math.min(a.duration||a._iO.duration,Math.max(b,0));a.position=d;b=a.position/1E3;a._resetOnPosition(a.position);a._iO.position=d;if(!a.isHTML5)b=9===n?a.position:b,a.readyState&&2!==a.readyState&&l._setPosition(a.id,b,a.paused||!a.playState,a._iO.multiShot);else if(a._a){if(a._html5_canplay){if(a._a.currentTime.toFixed(3)!==b.toFixed(3)){c._wD(a.id+": setPosition("+b+")");try{a._a.currentTime=b,(0===a.playState||a.paused)&&a._a.pause()}catch(e){c._wD(a.id+": setPosition("+b+") failed: "+
     51e.message,2)}}}else if(b)return c._wD(a.id+": setPosition("+b+"): Cannot seek yet, sound not ready",2),a;a.paused&&a._onTimer(!0)}return a};this.pause=function(b){if(a.paused||0===a.playState&&1!==a.readyState)return a;c._wD(a.id+": pause()");a.paused=!0;a.isHTML5?(a._setup_html5().pause(),F()):(b||b===g)&&l._pause(a.id,a._iO.multiShot);a._iO.onpause&&a._iO.onpause.apply(a);return a};this.resume=function(){var b=a._iO;if(!a.paused)return a;c._wD(a.id+": resume()");a.paused=!1;a.playState=1;a.isHTML5?
     52(a._setup_html5().play(),m()):(b.isMovieStar&&!b.serverURL&&a.setPosition(a.position),l._pause(a.id,b.multiShot));!r&&b.onplay?(b.onplay.apply(a),r=!0):b.onresume&&b.onresume.apply(a);return a};this.togglePause=function(){c._wD(a.id+": togglePause()");if(0===a.playState)return a.play({position:9!==n||a.isHTML5?a.position/1E3:a.position}),a;a.paused?a.resume():a.pause();return a};this.setPan=function(b,c){b===g&&(b=0);c===g&&(c=!1);a.isHTML5||l._setPan(a.id,b);a._iO.pan=b;c||(a.pan=b,a.options.pan=
     53b);return a};this.setVolume=function(b,d){b===g&&(b=100);d===g&&(d=!1);a.isHTML5?a._a&&(c.muted&&!a.muted&&(a.muted=!0,a._a.muted=!0),a._a.volume=Math.max(0,Math.min(1,b/100))):l._setVolume(a.id,c.muted&&!a.muted||a.muted?0:b);a._iO.volume=b;d||(a.volume=b,a.options.volume=b);return a};this.mute=function(){a.muted=!0;a.isHTML5?a._a&&(a._a.muted=!0):l._setVolume(a.id,0);return a};this.unmute=function(){a.muted=!1;var b=a._iO.volume!==g;a.isHTML5?a._a&&(a._a.muted=!1):l._setVolume(a.id,b?a._iO.volume:
     54a.options.volume);return a};this.toggleMute=function(){return a.muted?a.unmute():a.mute()};this.onposition=this.onPosition=function(b,c,d){D.push({position:parseInt(b,10),method:c,scope:d!==g?d:a,fired:!1});return a};this.clearOnPosition=function(a,b){var c;a=parseInt(a,10);if(!isNaN(a))for(c=0;c<D.length;c++)a!==D[c].position||b&&b!==D[c].method||(D[c].fired&&v--,D.splice(c,1))};this._processOnPosition=function(){var b,c;b=D.length;if(!b||!a.playState||v>=b)return!1;for(--b;0<=b;b--)c=D[b],!c.fired&&
     55a.position>=c.position&&(c.fired=!0,v++,c.method.apply(c.scope,[c.position]));return!0};this._resetOnPosition=function(a){var b,c;b=D.length;if(!b)return!1;for(--b;0<=b;b--)c=D[b],c.fired&&a<=c.position&&(c.fired=!1,v--);return!0};y=function(){var b=a._iO,d=b.from,e=b.to,f,g;g=function(){c._wD(a.id+': "To" time of '+e+" reached.");a.clearOnPosition(e,g);a.stop()};f=function(){c._wD(a.id+': Playing "from" '+d);if(null!==e&&!isNaN(e))a.onPosition(e,g)};null===d||isNaN(d)||(b.position=d,b.multiShot=
     56!1,f());return b};q=function(){var b,c=a._iO.onposition;if(c)for(b in c)if(c.hasOwnProperty(b))a.onPosition(parseInt(b,10),c[b])};Xa=function(){var b,c=a._iO.onposition;if(c)for(b in c)c.hasOwnProperty(b)&&a.clearOnPosition(parseInt(b,10))};m=function(){a.isHTML5&&eb(a)};F=function(){a.isHTML5&&fb(a)};f=function(b){b||(D=[],v=0);r=!1;a._hasTimer=null;a._a=null;a._html5_canplay=!1;a.bytesLoaded=null;a.bytesTotal=null;a.duration=a._iO&&a._iO.duration?a._iO.duration:null;a.durationEstimate=null;a.buffered=
     57[];a.eqData=[];a.eqData.left=[];a.eqData.right=[];a.failures=0;a.isBuffering=!1;a.instanceOptions={};a.instanceCount=0;a.loaded=!1;a.metadata={};a.readyState=0;a.muted=!1;a.paused=!1;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.playState=0;a.position=null;a.id3={}};f();this._onTimer=function(b){var c,f=!1,g={};(a._hasTimer||b)&&a._a&&(b||(0<a.playState||1===a.readyState)&&!a.paused)&&(c=a._get_html5_duration(),c!==d&&(d=c,a.duration=c,f=!0),a.durationEstimate=a.duration,c=1E3*a._a.currentTime||
     580,c!==e&&(e=c,f=!0),(f||b)&&a._whileplaying(c,g,g,g,g));return f};this._get_html5_duration=function(){var b=a._iO;return(b=a._a&&a._a.duration?1E3*a._a.duration:b&&b.duration?b.duration:null)&&!isNaN(b)&&Infinity!==b?b:null};this._apply_loop=function(a,b){!a.loop&&1<b&&c._wD("Note: Native HTML5 looping is infinite.",1);a.loop=1<b?"loop":""};this._setup_html5=function(b){b=A(a._iO,b);var c=B?Ya:a._a,d=decodeURI(b.url),e;B?d===decodeURI(Ma)&&(e=!0):d===decodeURI(u)&&(e=!0);if(c){if(c._s)if(B)c._s&&
     59c._s.playState&&!e&&c._s.stop();else if(!B&&d===decodeURI(u))return a._apply_loop(c,b.loops),c;e||(u&&f(!1),c.src=b.url,Ma=u=a.url=b.url,c._called_load=!1)}else b.autoLoad||b.autoPlay?(a._a=new Audio(b.url),a._a.load()):a._a=Sa&&10>opera.version()?new Audio(null):new Audio,c=a._a,c._called_load=!1,B&&(Ya=c);a.isHTML5=!0;a._a=c;c._s=a;h();a._apply_loop(c,b.loops);b.autoLoad||b.autoPlay?a.load():(c.autobuffer=!1,c.preload="auto");return c};h=function(){if(a._a._added_events)return!1;var b;a._a._added_events=
     60!0;for(b in I)I.hasOwnProperty(b)&&a._a&&a._a.addEventListener(b,I[b],!1);return!0};k=function(){var b;c._wD(a.id+": Removing event listeners");a._a._added_events=!1;for(b in I)I.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,I[b],!1)};this._onload=function(b){var d=!!b||!a.isHTML5&&8===n&&a.duration;b=a.id+": ";c._wD(b+(d?"onload()":"Failed to load / invalid sound?"+(a.duration?" -":" Zero-length duration reported.")+" ("+a.url+")"),d?1:2);d||a.isHTML5||(!0===c.sandbox.noRemote&&c._wD(b+t("noNet"),
     611),!0===c.sandbox.noLocal&&c._wD(b+t("noLocal"),1));a.loaded=d;a.readyState=d?3:2;a._onbufferchange(0);d||a.isHTML5||a._onerror();a._iO.onload&&fa(a,function(){a._iO.onload.apply(a,[d])});return!0};this._onerror=function(b,c){a._iO.onerror&&fa(a,function(){a._iO.onerror.apply(a,[b,c])})};this._onbufferchange=function(b){if(0===a.playState||b&&a.isBuffering||!b&&!a.isBuffering)return!1;a.isBuffering=1===b;a._iO.onbufferchange&&(c._wD(a.id+": Buffer state change: "+b),a._iO.onbufferchange.apply(a,[b]));
     62return!0};this._onsuspend=function(){a._iO.onsuspend&&(c._wD(a.id+": Playback suspended"),a._iO.onsuspend.apply(a));return!0};this._onfailure=function(b,d,e){a.failures++;c._wD(a.id+": Failure ("+a.failures+"): "+b);if(a._iO.onfailure&&1===a.failures)a._iO.onfailure(b,d,e);else c._wD(a.id+": Ignoring failure")};this._onwarning=function(b,c,d){if(a._iO.onwarning)a._iO.onwarning(b,c,d)};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0);a._resetOnPosition(0);a.instanceCount&&(a.instanceCount--,
     63a.instanceCount||(Xa(),a.playState=0,a.paused=!1,a.instanceCount=0,a.instanceOptions={},a._iO={},F(),a.isHTML5&&(a.position=0)),a.instanceCount&&!a._iO.multiShotEvents||!b||(c._wD(a.id+": onfinish()"),fa(a,function(){b.apply(a)})))};this._whileloading=function(b,c,d,e){var f=a._iO;a.bytesLoaded=b;a.bytesTotal=c;a.duration=Math.floor(d);a.bufferLength=e;a.durationEstimate=a.isHTML5||f.isMovieStar?a.duration:f.duration?a.duration>f.duration?a.duration:f.duration:parseInt(a.bytesTotal/a.bytesLoaded*
     64a.duration,10);a.isHTML5||(a.buffered=[{start:0,end:a.duration}]);(3!==a.readyState||a.isHTML5)&&f.whileloading&&f.whileloading.apply(a)};this._whileplaying=function(b,c,d,e,f){var k=a._iO;if(isNaN(b)||null===b)return!1;a.position=Math.max(0,b);a._processOnPosition();!a.isHTML5&&8<n&&(k.usePeakData&&c!==g&&c&&(a.peakData={left:c.leftPeak,right:c.rightPeak}),k.useWaveformData&&d!==g&&d&&(a.waveformData={left:d.split(","),right:e.split(",")}),k.useEQData&&f!==g&&f&&f.leftEQ&&(b=f.leftEQ.split(","),
     65a.eqData=b,a.eqData.left=b,f.rightEQ!==g&&f.rightEQ&&(a.eqData.right=f.rightEQ.split(","))));1===a.playState&&(a.isHTML5||8!==n||a.position||!a.isBuffering||a._onbufferchange(0),k.whileplaying&&k.whileplaying.apply(a));return!0};this._oncaptiondata=function(b){c._wD(a.id+": Caption data received.");a.captiondata=b;a._iO.oncaptiondata&&a._iO.oncaptiondata.apply(a,[b])};this._onmetadata=function(b,d){c._wD(a.id+": Metadata received.");var e={},f,g;f=0;for(g=b.length;f<g;f++)e[b[f]]=d[f];a.metadata=
     66e;a._iO.onmetadata&&a._iO.onmetadata.call(a,a.metadata)};this._onid3=function(b,d){c._wD(a.id+": ID3 data received.");var e=[],f,g;f=0;for(g=b.length;f<g;f++)e[b[f]]=d[f];a.id3=A(a.id3,e);a._iO.onid3&&a._iO.onid3.apply(a)};this._onconnect=function(b){b=1===b;c._wD(a.id+": "+(b?"Connected.":"Failed to connect? - "+a.url),b?1:2);if(a.connected=b)a.failures=0,w(a.id)&&(a.getAutoPlay()?a.play(g,a.getAutoPlay()):a._iO.autoLoad&&a.load()),a._iO.onconnect&&a._iO.onconnect.apply(a,[b])};this._ondataerror=
     67function(b){0<a.playState&&(c._wD(a.id+": Data error: "+b),a._iO.ondataerror&&a._iO.ondataerror.apply(a))};this._debug()};ma=function(){return m.body||m.getElementsByTagName("div")[0]};E=function(b){return m.getElementById(b)};A=function(b,d){var e=b||{},a,f;a=d===g?c.defaultOptions:d;for(f in a)a.hasOwnProperty(f)&&e[f]===g&&(e[f]="object"!==typeof a[f]||null===a[f]?a[f]:A(e[f],a[f]));return e};fa=function(b,c){b.isHTML5||8!==n?c():h.setTimeout(c,0)};Q={onready:1,ontimeout:1,defaultOptions:1,flash9Options:1,
     68movieStarOptions:1};Aa=function(b,d){var e,a=!0,f=d!==g,h=c.setupOptions;if(b===g){a=[];for(e in h)h.hasOwnProperty(e)&&a.push(e);for(e in Q)Q.hasOwnProperty(e)&&("object"===typeof c[e]?a.push(e+": {...}"):c[e]instanceof Function?a.push(e+": function() {...}"):a.push(e));c._wD(t("setup",a.join(", ")));return!1}for(e in b)if(b.hasOwnProperty(e))if("object"!==typeof b[e]||null===b[e]||b[e]instanceof Array||b[e]instanceof RegExp)f&&Q[d]!==g?c[d][e]=b[e]:h[e]!==g?(c.setupOptions[e]=b[e],c[e]=b[e]):Q[e]===
     69g?(K(t(c[e]===g?"setupUndef":"setupError",e),2),a=!1):c[e]instanceof Function?c[e].apply(c,b[e]instanceof Array?b[e]:[b[e]]):c[e]=b[e];else if(Q[e]===g)K(t(c[e]===g?"setupUndef":"setupError",e),2),a=!1;else return Aa(b[e],e);return a};x=function(){function b(a){a=kb.call(a);var b=a.length;e?(a[1]="on"+a[1],3<b&&a.pop()):3===b&&a.push(!1);return a}function c(b,d){var g=b.shift(),h=[a[d]];if(e)g[h](b[0],b[1]);else g[h].apply(g,b)}var e=h.attachEvent,a={add:e?"attachEvent":"addEventListener",remove:e?
     70"detachEvent":"removeEventListener"};return{add:function(){c(b(arguments),"add")},remove:function(){c(b(arguments),"remove")}}}();I={abort:r(function(){c._wD(this._s.id+": abort")}),canplay:r(function(){var b=this._s,d;if(!b._html5_canplay){b._html5_canplay=!0;c._wD(b.id+": canplay");b._onbufferchange(0);d=b._iO.position===g||isNaN(b._iO.position)?null:b._iO.position/1E3;if(this.currentTime!==d){c._wD(b.id+": canplay: Setting position to "+d);try{this.currentTime=d}catch(e){c._wD(b.id+": canplay: Setting position of "+
     71d+" failed: "+e.message,2)}}b._iO._oncanplay&&b._iO._oncanplay()}}),canplaythrough:r(function(){var b=this._s;b.loaded||(b._onbufferchange(0),b._whileloading(b.bytesLoaded,b.bytesTotal,b._get_html5_duration()),b._onload(!0))}),durationchange:r(function(){var b=this._s,d;d=b._get_html5_duration();isNaN(d)||d===b.duration||(c._wD(this._s.id+": durationchange ("+d+")"+(b.duration?", previously "+b.duration:"")),b.durationEstimate=b.duration=d)}),ended:r(function(){var b=this._s;c._wD(b.id+": ended");
     72b._onfinish()}),error:r(function(){var b=ib[this.error.code]||null;c._wD(this._s.id+": HTML5 error, code "+this.error.code+(b?" ("+b+")":""));this._s._onload(!1);this._s._onerror(this.error.code,b)}),loadeddata:r(function(){var b=this._s;c._wD(b.id+": loadeddata");b._loaded||ua||(b.duration=b._get_html5_duration())}),loadedmetadata:r(function(){c._wD(this._s.id+": loadedmetadata")}),loadstart:r(function(){c._wD(this._s.id+": loadstart");this._s._onbufferchange(1)}),play:r(function(){this._s._onbufferchange(0)}),
     73playing:r(function(){c._wD(this._s.id+": playing "+String.fromCharCode(9835));this._s._onbufferchange(0)}),progress:r(function(b){var d=this._s,e,a,f;e=0;var g="progress"===b.type,k=b.target.buffered,h=b.loaded||0,m=b.total||1;d.buffered=[];if(k&&k.length){e=0;for(a=k.length;e<a;e++)d.buffered.push({start:1E3*k.start(e),end:1E3*k.end(e)});e=1E3*(k.end(0)-k.start(0));h=Math.min(1,e/(1E3*b.target.duration));if(g&&1<k.length){f=[];a=k.length;for(e=0;e<a;e++)f.push(1E3*b.target.buffered.start(e)+"-"+
     741E3*b.target.buffered.end(e));c._wD(this._s.id+": progress, timeRanges: "+f.join(", "))}g&&!isNaN(h)&&c._wD(this._s.id+": progress, "+Math.floor(100*h)+"% loaded")}isNaN(h)||(d._whileloading(h,m,d._get_html5_duration()),h&&m&&h===m&&I.canplaythrough.call(this,b))}),ratechange:r(function(){c._wD(this._s.id+": ratechange")}),suspend:r(function(b){var d=this._s;c._wD(this._s.id+": suspend");I.progress.call(this,b);d._onsuspend()}),stalled:r(function(){c._wD(this._s.id+": stalled")}),timeupdate:r(function(){this._s._onTimer()}),
     75waiting:r(function(){var b=this._s;c._wD(this._s.id+": waiting");b._onbufferchange(1)})};sa=function(b){return b&&(b.type||b.url||b.serverURL)?b.serverURL||b.type&&ha(b.type)?!1:b.type?ea({type:b.type}):ea({url:b.url})||c.html5Only||b.url.match(/data:/i):!1};ta=function(b){var d;b&&(d=ua?"about:blank":c.html5.canPlayType("audio/wav")?"data:audio/wave;base64,/UklGRiYAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQIAAAD//w==":"about:blank",b.src=d,b._called_unload!==g&&(b._called_load=!1));B&&(Ma=null);
     76return d};ea=function(b){if(!c.useHTML5Audio||!c.hasHTML5)return!1;var d=b.url||null;b=b.type||null;var e=c.audioFormats,a;if(b&&c.html5[b]!==g)return c.html5[b]&&!ha(b);if(!M){M=[];for(a in e)e.hasOwnProperty(a)&&(M.push(a),e[a].related&&(M=M.concat(e[a].related)));M=new RegExp("\\.("+M.join("|")+")(\\?.*)?$","i")}(a=d?d.toLowerCase().match(M):null)&&a.length?a=a[1]:b&&(d=b.indexOf(";"),a=(-1!==d?b.substr(0,d):b).substr(6));a&&c.html5[a]!==g?d=c.html5[a]&&!ha(a):(b="audio/"+a,d=c.html5.canPlayType({type:b}),
     77d=(c.html5[a]=d)&&c.html5[b]&&!ha(b));return d};jb=function(){function b(a){var b,e=b=!1;if(!d||"function"!==typeof d.canPlayType)return b;if(a instanceof Array){k=0;for(b=a.length;k<b;k++)if(c.html5[a[k]]||d.canPlayType(a[k]).match(c.html5Test))e=!0,c.html5[a[k]]=!0,c.flash[a[k]]=!!a[k].match(pb);b=e}else a=d&&"function"===typeof d.canPlayType?d.canPlayType(a):!1,b=!(!a||!a.match(c.html5Test));return b}if(!c.useHTML5Audio||!c.hasHTML5)return u=c.html5.usingFlash=!0,!1;var d=Audio!==g?Sa&&10>opera.version()?
     78new Audio(null):new Audio:null,e,a,f={},h,k;h=c.audioFormats;for(e in h)if(h.hasOwnProperty(e)&&(a="audio/"+e,f[e]=b(h[e].type),f[a]=f[e],e.match(pb)?(c.flash[e]=!0,c.flash[a]=!0):(c.flash[e]=!1,c.flash[a]=!1),h[e]&&h[e].related))for(k=h[e].related.length-1;0<=k;k--)f["audio/"+h[e].related[k]]=f[e],c.html5[h[e].related[k]]=f[e],c.flash[h[e].related[k]]=f[e];f.canPlayType=d?b:null;c.html5=A(c.html5,f);c.html5.usingFlash=hb();u=c.html5.usingFlash;return!0};z={notReady:"Unavailable - wait until onready() has fired.",
     79notOK:"Audio support is not available.",domError:"soundManagerexception caught while appending SWF to DOM.",spcWmode:"Removing wmode, preventing known SWF loading issue(s)",swf404:"soundManager: Verify that %s is a valid path.",tryDebug:"Try soundManager.debugFlash = true for more security details (output goes to SWF.)",checkSWF:"See SWF output for more debug info.",localFail:"soundManager: Non-HTTP page ("+m.location.protocol+" URL?) Review Flash player security settings for this special case:\nhttp://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/",
     80waitFocus:"soundManager: Special case: Waiting for SWF to load with window focus...",waitForever:"soundManager: Waiting indefinitely for Flash (will recover if unblocked)...",waitSWF:"soundManager: Waiting for 100% SWF load...",needFunction:"soundManager: Function object expected for %s",badID:'Sound ID "%s" should be a string, starting with a non-numeric character',currentObj:"soundManager: _debug(): Current sound objects",waitOnload:"soundManager: Waiting for window.onload()",docLoaded:"soundManager: Document already loaded",
     81onload:"soundManager: initComplete(): calling soundManager.onload()",onloadOK:"soundManager.onload() complete",didInit:"soundManager: init(): Already called?",secNote:"Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html",badRemove:"soundManager: Failed to remove Flash node.",shutdown:"soundManager.disable(): Shutting down",
     82queue:"soundManager: Queueing %s handler",smError:"SMSound.load(): Exception: JS-Flash communication failed, or JS error.",fbTimeout:"No flash response, applying .swf_timedout CSS...",fbLoaded:"Flash loaded",fbHandler:"soundManager: flashBlockHandler()",manURL:"SMSound.load(): Using manually-assigned URL",onURL:"soundManager.load(): current URL already assigned.",badFV:'soundManager.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.',as2loop:"Note: Setting stream:false so looping can work (flash 8 limitation)",
     83noNSLoop:"Note: Looping not implemented for MovieStar formats",needfl9:"Note: Switching to flash 9, required for MP4 formats.",mfTimeout:"Setting flashLoadTimeout = 0 (infinite) for off-screen, mobile flash case",needFlash:"soundManager: Fatal error: Flash is needed to play some required formats, but is not available.",gotFocus:"soundManager: Got window focus.",policy:"Enabling usePolicyFile for data access",setup:"soundManager.setup(): allowed parameters: %s",setupError:'soundManager.setup(): "%s" cannot be assigned with this method.',
     84setupUndef:'soundManager.setup(): Could not find option "%s"',setupLate:"soundManager.setup(): url, flashVersion and html5Test property changes will not take effect until reboot().",noURL:"soundManager: Flash URL required. Call soundManager.setup({url:...}) to get started.",sm2Loaded:"SoundManager 2: Ready. "+String.fromCharCode(10003),reset:"soundManager.reset(): Removing event callbacks",mobileUA:"Mobile UA detected, preferring HTML5 by default.",globalHTML5:"Using singleton HTML5 Audio() pattern for this device.",
     85ignoreMobile:"Ignoring mobile restrictions for this device."};t=function(){var b,c,e,a;b=kb.call(arguments);c=b.shift();if((a=z&&z[c]?z[c]:"")&&b&&b.length)for(c=0,e=b.length;c<e;c++)a=a.replace("%s",b[c]);return a};oa=function(b){8===n&&1<b.loops&&b.stream&&(p("as2loop"),b.stream=!1);return b};pa=function(b,d){b&&!b.usePolicyFile&&(b.onid3||b.usePeakData||b.useWaveformData||b.useEQData)&&(c._wD((d||"")+t("policy")),b.usePolicyFile=!0);return b};K=function(b){Ua&&console.warn!==g?console.warn(b):
     86c._wD(b)};xa=function(){return!1};Ga=function(b){for(var c in b)b.hasOwnProperty(c)&&"function"===typeof b[c]&&(b[c]=xa)};Ha=function(b){b===g&&(b=!1);(y||b)&&c.disable(b)};cb=function(b){var d=null;if(b)if(b.match(/\.swf(\?.*)?$/i)){if(d=b.substr(b.toLowerCase().lastIndexOf(".swf?")+4))return b}else b.lastIndexOf("/")!==b.length-1&&(b+="/");b=(b&&-1!==b.lastIndexOf("/")?b.substr(0,b.lastIndexOf("/")+1):"./")+c.movieURL;c.noSWFCache&&(b+="?ts="+(new Date).getTime());return b};Da=function(){n=parseInt(c.flashVersion,
     8710);8!==n&&9!==n&&(c._wD(t("badFV",n,8)),c.flashVersion=n=8);var b=c.debugMode||c.debugFlash?"_debug.swf":".swf";c.useHTML5Audio&&!c.html5Only&&c.audioFormats.mp4.required&&9>n&&(c._wD(t("needfl9")),c.flashVersion=n=9);c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":9===n?" (AS3/Flash 9)":" (AS2/Flash 8)");8<n?(c.defaultOptions=A(c.defaultOptions,c.flash9Options),c.features.buffering=!0,c.defaultOptions=A(c.defaultOptions,c.movieStarOptions),c.filePatterns.flash9=new RegExp("\\.(mp3|"+
     88rb.join("|")+")(\\?.*)?$","i"),c.features.movieStar=!0):c.features.movieStar=!1;c.filePattern=c.filePatterns[8!==n?"flash9":"flash8"];c.movieURL=(8===n?"soundmanager2.swf":"soundmanager2_flash9.swf").replace(".swf",b);c.features.peakData=c.features.waveformData=c.features.eqData=8<n};ab=function(b,c){l&&l._setPolling(b,c)};Fa=function(){c.debugURLParam.test(ia)&&(c.setupOptions.debugMode=c.debugMode=!0);if(!E(c.debugID)){var b,d,e,a;if(!(!c.debugMode||E(c.debugID)||Ua&&c.useConsole&&c.consoleOnly)){b=
     89m.createElement("div");b.id=c.debugID+"-toggle";d={position:"fixed",bottom:"0px",right:"0px",width:"1.2em",height:"1.2em",lineHeight:"1.2em",margin:"2px",textAlign:"center",border:"1px solid #999",cursor:"pointer",background:"#fff",color:"#333",zIndex:10001};b.appendChild(m.createTextNode("-"));b.onclick=db;b.title="Toggle SM2 debug console";v.match(/msie 6/i)&&(b.style.position="absolute",b.style.cursor="hand");for(a in d)d.hasOwnProperty(a)&&(b.style[a]=d[a]);d=m.createElement("div");d.id=c.debugID;
     90d.style.display=c.debugMode?"block":"none";if(c.debugMode&&!E(b.id)){try{e=ma(),e.appendChild(b)}catch(f){throw Error(t("domError")+" \n"+f.toString());}e.appendChild(d)}}}};w=this.getSoundById;p=function(b,d){return b?c._wD(t(b),d):""};db=function(){var b=E(c.debugID),d=E(c.debugID+"-toggle");b&&(za?(d.innerHTML="+",b.style.display="none"):(d.innerHTML="-",b.style.display="block"),za=!za)};C=function(b,c,e){if(h.sm2Debugger!==g)try{sm2Debugger.handleEvent(b,c,e)}catch(a){return!1}return!0};U=function(){var b=
     91[];c.debugMode&&b.push("sm2_debug");c.debugFlash&&b.push("flash_debug");c.useHighPerformance&&b.push("high_performance");return b.join(" ")};Ja=function(){var b=t("fbHandler"),d=c.getMoviePercent(),e={type:"FLASHBLOCK"};c.html5Only||(c.ok()?(c.didFlashBlock&&c._wD(b+": Unblocked"),c.oMC&&(c.oMC.className=[U(),"movieContainer","swf_loaded"+(c.didFlashBlock?" swf_unblocked":"")].join(" "))):(u&&(c.oMC.className=U()+" movieContainer "+(null===d?"swf_timedout":"swf_error"),c._wD(b+": "+t("fbTimeout")+
     92(d?" ("+t("fbLoaded")+")":""))),c.didFlashBlock=!0,O({type:"ontimeout",ignoreInit:!0,error:e}),T(e)))};Ba=function(b,c,e){H[b]===g&&(H[b]=[]);H[b].push({method:c,scope:e||null,fired:!1})};O=function(b){b||(b={type:c.ok()?"onready":"ontimeout"});if(!q&&b&&!b.ignoreInit||"ontimeout"===b.type&&(c.ok()||y&&!b.ignoreInit))return!1;var d={success:b&&b.ignoreInit?c.ok():!y},e=b&&b.type?H[b.type]||[]:[],a=[],f,d=[d],g=u&&!c.ok();b.error&&(d[0].error=b.error);b=0;for(f=e.length;b<f;b++)!0!==e[b].fired&&a.push(e[b]);
     93if(a.length)for(b=0,f=a.length;b<f;b++)a[b].scope?a[b].method.apply(a[b].scope,d):a[b].method.apply(this,d),g||(a[b].fired=!0);return!0};R=function(){h.setTimeout(function(){c.useFlashBlock&&Ja();O();"function"===typeof c.onload&&(p("onload",1),c.onload.apply(h),p("onloadOK",1));c.waitForWindowLoad&&x.add(h,"load",R)},1)};Na=function(){if(G!==g)return G;var b=!1,c=navigator,e,a=h.ActiveXObject,f;try{f=c.plugins}catch(m){f=void 0}if(f&&f.length)(c=c.mimeTypes)&&c["application/x-shockwave-flash"]&&
     94c["application/x-shockwave-flash"].enabledPlugin&&c["application/x-shockwave-flash"].enabledPlugin.description&&(b=!0);else if(a!==g&&!v.match(/MSAppHost/i)){try{e=new a("ShockwaveFlash.ShockwaveFlash")}catch(k){e=null}b=!!e}return G=b};hb=function(){var b,d,e=c.audioFormats;Qa&&v.match(/os (1|2|3_0|3_1)\s/i)?(c.hasHTML5=!1,c.html5Only=!0,c.oMC&&(c.oMC.style.display="none")):c.useHTML5Audio&&(c.html5&&c.html5.canPlayType||(c._wD("SoundManager: No HTML5 Audio() support detected."),c.hasHTML5=!1),Ta&&
     95c._wD("soundManager: Note: Buggy HTML5 Audio in Safari on this OS X release, see https://bugs.webkit.org/show_bug.cgi?id=32159 - "+(G?"will use flash fallback for MP3/MP4, if available":" would use flash fallback for MP3/MP4, but none detected."),1));if(c.useHTML5Audio&&c.hasHTML5)for(d in da=!0,e)e.hasOwnProperty(d)&&e[d].required&&(c.html5.canPlayType(e[d].type)?c.preferFlash&&(c.flash[d]||c.flash[e[d].type])&&(b=!0):(da=!1,b=!0));c.ignoreFlash&&(b=!1,da=!0);c.html5Only=c.hasHTML5&&c.useHTML5Audio&&
     96!b;return!c.html5Only};ra=function(b){var d,e,a=0;if(b instanceof Array){d=0;for(e=b.length;d<e;d++)if(b[d]instanceof Object){if(c.canPlayMIME(b[d].type)){a=d;break}}else if(c.canPlayURL(b[d])){a=d;break}b[a].url&&(b[a]=b[a].url);b=b[a]}return b};eb=function(b){b._hasTimer||(b._hasTimer=!0,!va&&c.html5PollingInterval&&(null===ca&&0===qa&&(ca=setInterval(gb,c.html5PollingInterval)),qa++))};fb=function(b){b._hasTimer&&(b._hasTimer=!1,!va&&c.html5PollingInterval&&qa--)};gb=function(){var b;if(null===
     97ca||qa)for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].isHTML5&&c.sounds[c.soundIDs[b]]._hasTimer&&c.sounds[c.soundIDs[b]]._onTimer();else clearInterval(ca),ca=null};T=function(b){b=b!==g?b:{};"function"===typeof c.onerror&&c.onerror.apply(h,[{type:b.type!==g?b.type:null}]);b.fatal!==g&&b.fatal&&c.disable()};lb=function(){if(Ta&&Na()){var b=c.audioFormats,d,e;for(e in b)if(b.hasOwnProperty(e)&&("mp3"===e||"mp4"===e)&&(c._wD("soundManager: Using flash fallback for "+e+" format"),c.html5[e]=
     98!1,b[e]&&b[e].related))for(d=b[e].related.length-1;0<=d;d--)c.html5[b[e].related[d]]=!1}};this._setSandboxType=function(b){var d=c.sandbox;d.type=b;d.description=d.types[d.types[b]!==g?b:"unknown"];"localWithFile"===d.type?(d.noRemote=!0,d.noLocal=!1,p("secNote",2)):"localWithNetwork"===d.type?(d.noRemote=!1,d.noLocal=!0):"localTrusted"===d.type&&(d.noRemote=!1,d.noLocal=!1)};this._externalInterfaceOK=function(b){if(!c.swfLoaded){var d;C("swf",!0);C("flashtojs",!0);c.swfLoaded=!0;wa=!1;Ta&&lb();b&&
     99b.replace(/\+dev/i,"")===c.versionNumber.replace(/\+dev/i,"")?setTimeout(ya,N?100:1):(d='soundManager: Fatal: JavaScript file build "'+c.versionNumber+'" does not match Flash SWF build "'+b+'" at '+c.url+". Ensure both are up-to-date.",setTimeout(function(){throw Error(d);},0))}};na=function(b,d){function e(){var a=[],b,d=[];b="SoundManager "+c.version+(!c.html5Only&&c.useHTML5Audio?c.hasHTML5?" + HTML5 audio":", no HTML5 audio support":"");c.html5Only?c.html5PollingInterval&&a.push("html5PollingInterval ("+
     100c.html5PollingInterval+"ms)"):(c.preferFlash&&a.push("preferFlash"),c.useHighPerformance&&a.push("useHighPerformance"),c.flashPollingInterval&&a.push("flashPollingInterval ("+c.flashPollingInterval+"ms)"),c.html5PollingInterval&&a.push("html5PollingInterval ("+c.html5PollingInterval+"ms)"),c.wmode&&a.push("wmode ("+c.wmode+")"),c.debugFlash&&a.push("debugFlash"),c.useFlashBlock&&a.push("flashBlock"));a.length&&(d=d.concat([a.join(" + ")]));c._wD(b+(d.length?" + "+d.join(", "):""),1);mb()}function a(a,
     101b){return'<param name="'+a+'" value="'+b+'" />'}if(W&&X)return!1;if(c.html5Only)return Da(),e(),c.oMC=E(c.movieID),ya(),X=W=!0,!1;var f=d||c.url,h=c.altURL||f,k=ma(),l=U(),n=null,n=m.getElementsByTagName("html")[0],p,r,q,n=n&&n.dir&&n.dir.match(/rtl/i);b=b===g?c.id:b;Da();c.url=cb(ga?f:h);d=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;null!==c.wmode&&(v.match(/msie 8/i)||!N&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i)&&(L.push(z.spcWmode),c.wmode=null);k=
     102{name:b,id:b,src:d,quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:vb+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};c.debugFlash&&(k.FlashVars="debug=1");c.wmode||delete k.wmode;if(N)f=m.createElement("div"),r=['<object id="'+b+'" data="'+d+'" type="'+k.type+'" title="'+k.title+'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0">',
     103a("movie",d),a("AllowScriptAccess",c.allowScriptAccess),a("quality",k.quality),c.wmode?a("wmode",c.wmode):"",a("bgcolor",c.bgColor),a("hasPriority","true"),c.debugFlash?a("FlashVars",k.FlashVars):"","</object>"].join("");else for(p in f=m.createElement("embed"),k)k.hasOwnProperty(p)&&f.setAttribute(p,k[p]);Fa();l=U();if(k=ma())if(c.oMC=E(c.movieID)||m.createElement("div"),c.oMC.id)q=c.oMC.className,c.oMC.className=(q?q+" ":"movieContainer")+(l?" "+l:""),c.oMC.appendChild(f),N&&(p=c.oMC.appendChild(m.createElement("div")),
     104p.className="sm2-object-box",p.innerHTML=r),X=!0;else{c.oMC.id=c.movieID;c.oMC.className="movieContainer "+l;p=l=null;c.useFlashBlock||(c.useHighPerformance?l={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"}:(l={position:"absolute",width:"6px",height:"6px",top:"-9999px",left:"-9999px"},n&&(l.left=Math.abs(parseInt(l.left,10))+"px")));ub&&(c.oMC.style.zIndex=1E4);if(!c.debugFlash)for(q in l)l.hasOwnProperty(q)&&(c.oMC.style[q]=l[q]);try{N||c.oMC.appendChild(f),
     105k.appendChild(c.oMC),N&&(p=c.oMC.appendChild(m.createElement("div")),p.className="sm2-object-box",p.innerHTML=r),X=!0}catch(u){throw Error(t("domError")+" \n"+u.toString());}}W=!0;e();return!0};la=function(){if(c.html5Only)return na(),!1;if(l)return!1;if(!c.url)return p("noURL"),!1;l=c.getMovie(c.id);l||(aa?(N?c.oMC.innerHTML=Ia:c.oMC.appendChild(aa),aa=null,W=!0):na(c.id,c.url),l=c.getMovie(c.id));"function"===typeof c.oninitmovie&&setTimeout(c.oninitmovie,1);Oa();return!0};S=function(){setTimeout($a,
     1061E3)};Ca=function(){h.setTimeout(function(){K("soundManager: useFlashBlock is false, 100% HTML5 mode is possible. Rebooting with preferFlash: false...");c.setup({preferFlash:!1}).reboot();c.didFlashBlock=!0;c.beginDelayedInit()},1)};$a=function(){var b,d=!1;c.url&&!ba&&(ba=!0,x.remove(h,"load",S),G&&wa&&!Va?p("waitFocus"):(q||(b=c.getMoviePercent(),0<b&&100>b&&(d=!0)),setTimeout(function(){b=c.getMoviePercent();d?(ba=!1,c._wD(t("waitSWF")),h.setTimeout(S,1)):(q||(c._wD("soundManager: No Flash response within expected time. Likely causes: "+
     107(0===b?"SWF load failed, ":"")+"Flash blocked or JS-Flash security error."+(c.debugFlash?" "+t("checkSWF"):""),2),!ga&&b&&(p("localFail",2),c.debugFlash||p("tryDebug",2)),0===b&&c._wD(t("swf404",c.url),1),C("flashtojs",!1,": Timed out"+(ga?" (Check flash security or flash blockers)":" (No plugin/missing SWF?)"))),!q&&ob&&(null===b?c.useFlashBlock||0===c.flashLoadTimeout?(c.useFlashBlock&&Ja(),p("waitForever")):!c.useFlashBlock&&da?Ca():(p("waitForever"),O({type:"ontimeout",ignoreInit:!0,error:{type:"INIT_FLASHBLOCK"}})):
     1080===c.flashLoadTimeout?p("waitForever"):!c.useFlashBlock&&da?Ca():Ha(!0)))},c.flashLoadTimeout)))};ka=function(){if(Va||!wa)return x.remove(h,"focus",ka),!0;Va=ob=!0;p("gotFocus");ba=!1;S();x.remove(h,"focus",ka);return!0};Oa=function(){L.length&&(c._wD("SoundManager 2: "+L.join(" "),1),L=[])};mb=function(){Oa();var b,d=[];if(c.useHTML5Audio&&c.hasHTML5){for(b in c.audioFormats)c.audioFormats.hasOwnProperty(b)&&d.push(b+" = "+c.html5[b]+(!c.html5[b]&&u&&c.flash[b]?" (using flash)":c.preferFlash&&
     109c.flash[b]&&u?" (preferring flash)":c.html5[b]?"":" ("+(c.audioFormats[b].required?"required, ":"")+"and no flash support)"));c._wD("SoundManager 2 HTML5 support: "+d.join(", "),1)}};Y=function(b){if(q)return!1;if(c.html5Only)return p("sm2Loaded",1),q=!0,R(),C("onload",!0),!0;var d=!0,e;c.useFlashBlock&&c.flashLoadTimeout&&!c.getMoviePercent()||(q=!0);e={type:!G&&u?"NO_FLASH":"INIT_TIMEOUT"};c._wD("SoundManager 2 "+(y?"failed to load":"loaded")+" ("+(y?"Flash security/load error":"OK")+") "+String.fromCharCode(y?
     11010006:10003),y?2:1);y||b?(c.useFlashBlock&&c.oMC&&(c.oMC.className=U()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error")),O({type:"ontimeout",error:e,ignoreInit:!0}),C("onload",!1),T(e),d=!1):C("onload",!0);y||(c.waitForWindowLoad&&!ja?(p("waitOnload"),x.add(h,"load",R)):(c.waitForWindowLoad&&ja&&p("docLoaded"),R()));return d};Za=function(){var b,d=c.setupOptions;for(b in d)d.hasOwnProperty(b)&&(c[b]===g?c[b]=d[b]:c[b]!==d[b]&&(c.setupOptions[b]=c[b]))};ya=function(){if(q)return p("didInit"),
     111!1;if(c.html5Only)return q||(x.remove(h,"load",c.beginDelayedInit),c.enabled=!0,Y()),!0;la();try{l._externalInterfaceTest(!1),ab(!0,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||l._disableDebug(),c.enabled=!0,C("jstoflash",!0),c.html5Only||x.add(h,"unload",xa)}catch(b){return c._wD("js/flash exception: "+b.toString()),C("jstoflash",!1),T({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),Ha(!0),Y(),!1}Y();x.remove(h,"load",c.beginDelayedInit);return!0};P=function(){if(Z)return!1;Z=!0;Za();
     112Fa();!G&&c.hasHTML5&&(c._wD("SoundManager 2: No Flash detected"+(c.useHTML5Audio?". Trying HTML5-only mode.":", enabling HTML5."),1),c.setup({useHTML5Audio:!0,preferFlash:!1}));jb();!G&&u&&(L.push(z.needFlash),c.setup({flashLoadTimeout:1}));m.removeEventListener&&m.removeEventListener("DOMContentLoaded",P,!1);la();return!0};La=function(){"complete"===m.readyState&&(P(),m.detachEvent("onreadystatechange",La));return!0};Ea=function(){ja=!0;P();x.remove(h,"load",Ea)};Na();x.add(h,"focus",ka);x.add(h,
     113"load",S);x.add(h,"load",Ea);m.addEventListener?m.addEventListener("DOMContentLoaded",P,!1):m.attachEvent?m.attachEvent("onreadystatechange",La):(C("onload",!1),T({type:"NO_DOM2_EVENTS",fatal:!0}))}if(!h||!h.document)throw Error("SoundManager requires a browser with window and document objects.");var V=null;h.SM2_DEFER!==g&&SM2_DEFER||(V=new J);"object"===typeof module&&module&&"object"===typeof module.exports?(module.exports.SoundManager=J,module.exports.soundManager=V):"function"===typeof define&&
     114define.amd&&define(function(){return{constructor:J,getInstance:function(g){!h.soundManager&&g instanceof Function&&(g=g(J),g instanceof J&&(h.soundManager=g));return h.soundManager}}});h.SoundManager=J;h.soundManager=V})(window);
  • _plugins_/soundmanager/script/soundmanager2.js

    r74395 r104951  
    99 * http://schillmania.com/projects/soundmanager2/license.txt
    1010 *
    11  * V2.97a.20130512
     11 * V2.97a.20170601
    1212 */
    13 
    14 /*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio, opera */
    15 /*jslint regexp: true, sloppy: true, white: true, nomen: true, plusplus: true, todo: true */
    1613
    1714/**
     
    3128 */
    3229
    33 (function(window, _undefined) {
    34 
    35 "use strict";
     30(function SM2(window, _undefined) {
     31
     32/* global Audio, document, window, navigator, define, module, SM2_DEFER, opera, setTimeout, setInterval, clearTimeout, sm2Debugger */
     33
     34'use strict';
     35
     36if (!window || !window.document) {
     37
     38  // Don't cross the [environment] streams. SM2 expects to be running in a browser, not under node.js etc.
     39  // Additionally, if a browser somehow manages to fail this test, as Egon said: "It would be bad."
     40
     41  throw new Error('SoundManager requires a browser with window and document objects.');
     42
     43}
    3644
    3745var soundManager = null;
     
    5765  this.setupOptions = {
    5866
    59     'url': (smURL || null),             // path (directory) where SoundManager 2 SWFs exist, eg., /path/to/swfs/
    60     'flashVersion': 8,                  // flash build to use (8 or 9.) Some API features require 9.
    61     'debugMode': true,                  // enable debugging output (console.log() with HTML fallback)
    62     'debugFlash': false,                // enable debugging output inside SWF, troubleshoot Flash/browser issues
    63     'useConsole': true,                 // use console.log() if available (otherwise, writes to #soundmanager-debug element)
    64     'consoleOnly': true,                // if console is being used, do not create/write to #soundmanager-debug
    65     'waitForWindowLoad': false,         // force SM2 to wait for window.onload() before trying to call soundManager.onload()
    66     'bgColor': '#ffffff',               // SWF background color. N/A when wmode = 'transparent'
    67     'useHighPerformance': false,        // position:fixed flash movie can help increase js/flash speed, minimize lag
    68     'flashPollingInterval': null,       // msec affecting whileplaying/loading callback frequency. If null, default of 50 msec is used.
    69     'html5PollingInterval': null,       // msec affecting whileplaying() for HTML5 audio, excluding mobile devices. If null, native HTML5 update events are used.
    70     'flashLoadTimeout': 1000,           // msec to wait for flash movie to load before failing (0 = infinity)
    71     'wmode': null,                      // flash rendering mode - null, 'transparent', or 'opaque' (last two allow z-index to work)
    72     'allowScriptAccess': 'always',      // for scripting the SWF (object/embed property), 'always' or 'sameDomain'
    73     'useFlashBlock': false,             // *requires flashblock.css, see demos* - allow recovery from flash blockers. Wait indefinitely and apply timeout CSS to SWF, if applicable.
    74     'useHTML5Audio': true,              // use HTML5 Audio() where API is supported (most Safari, Chrome versions), Firefox (no MP3/MP4.) Ideally, transparent vs. Flash API where possible.
    75     'html5Test': /^(probably|maybe)$/i, // HTML5 Audio() format support test. Use /^probably$/i; if you want to be more conservative.
    76     'preferFlash': true,                // overrides useHTML5audio. if true and flash support present, will try to use flash for MP3/MP4 as needed since HTML5 audio support is still quirky in browsers.
    77     'noSWFCache': false,                // if true, appends ?ts={date} to break aggressive SWF caching.
    78     'idPrefix': 'sound'                 // if an id is not provided to createSound(), this prefix is used for generated IDs - 'sound0', 'sound1' etc.
     67    url: (smURL || null),             // path (directory) where SoundManager 2 SWFs exist, eg., /path/to/swfs/
     68    flashVersion: 8,                  // flash build to use (8 or 9.) Some API features require 9.
     69    debugMode: true,                  // enable debugging output (console.log() with HTML fallback)
     70    debugFlash: false,                // enable debugging output inside SWF, troubleshoot Flash/browser issues
     71    useConsole: true,                 // use console.log() if available (otherwise, writes to #soundmanager-debug element)
     72    consoleOnly: true,                // if console is being used, do not create/write to #soundmanager-debug
     73    waitForWindowLoad: false,         // force SM2 to wait for window.onload() before trying to call soundManager.onload()
     74    bgColor: '#ffffff',               // SWF background color. N/A when wmode = 'transparent'
     75    useHighPerformance: false,        // position:fixed flash movie can help increase js/flash speed, minimize lag
     76    flashPollingInterval: null,       // msec affecting whileplaying/loading callback frequency. If null, default of 50 msec is used.
     77    html5PollingInterval: null,       // msec affecting whileplaying() for HTML5 audio, excluding mobile devices. If null, native HTML5 update events are used.
     78    flashLoadTimeout: 1000,           // msec to wait for flash movie to load before failing (0 = infinity)
     79    wmode: null,                      // flash rendering mode - null, 'transparent', or 'opaque' (last two allow z-index to work)
     80    allowScriptAccess: 'always',      // for scripting the SWF (object/embed property), 'always' or 'sameDomain'
     81    useFlashBlock: false,             // *requires flashblock.css, see demos* - allow recovery from flash blockers. Wait indefinitely and apply timeout CSS to SWF, if applicable.
     82    useHTML5Audio: true,              // use HTML5 Audio() where API is supported (most Safari, Chrome versions), Firefox (MP3/MP4 support varies.) Ideally, transparent vs. Flash API where possible.
     83    forceUseGlobalHTML5Audio: false,  // if true, a single Audio() object is used for all sounds - and only one can play at a time.
     84    ignoreMobileRestrictions: false,  // if true, SM2 will not apply global HTML5 audio rules to mobile UAs. iOS > 7 and WebViews may allow multiple Audio() instances.
     85    html5Test: /^(probably|maybe)$/i, // HTML5 Audio() format support test. Use /^probably$/i; if you want to be more conservative.
     86    preferFlash: false,               // overrides useHTML5audio, will use Flash for MP3/MP4/AAC if present. Potential option if HTML5 playback with these formats is quirky.
     87    noSWFCache: false,                // if true, appends ?ts={date} to break aggressive SWF caching.
     88    idPrefix: 'sound'                 // if an id is not provided to createSound(), this prefix is used for generated IDs - 'sound0', 'sound1' etc.
    7989
    8090  };
     
    8797     */
    8898
    89     'autoLoad': false,        // enable automatic loading (otherwise .load() will be called on demand with .play(), the latter being nicer on bandwidth - if you want to .load yourself, you also can)
    90     'autoPlay': false,        // enable playing of file as soon as possible (much faster if "stream" is true)
    91     'from': null,             // position to start playback within a sound (msec), default = beginning
    92     'loops': 1,               // how many times to repeat the sound (position will wrap around to 0, setPosition() will break out of loop when >0)
    93     'onid3': null,            // callback function for "ID3 data is added/available"
    94     'onload': null,           // callback function for "load finished"
    95     'whileloading': null,     // callback function for "download progress update" (X of Y bytes received)
    96     'onplay': null,           // callback for "play" start
    97     'onpause': null,          // callback for "pause"
    98     'onresume': null,         // callback for "resume" (pause toggle)
    99     'whileplaying': null,     // callback during play (position update)
    100     'onposition': null,       // object containing times and function callbacks for positions of interest
    101     'onstop': null,           // callback for "user stop"
    102     'onfailure': null,        // callback function for when playing fails
    103     'onfinish': null,         // callback function for "sound finished playing"
    104     'multiShot': true,        // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time
    105     'multiShotEvents': false, // fire multiple sound events (currently onfinish() only) when multiShot is enabled
    106     'position': null,         // offset (milliseconds) to seek to within loaded sound data.
    107     'pan': 0,                 // "pan" settings, left-to-right, -100 to 100
    108     'stream': true,           // allows playing before entire file has loaded (recommended)
    109     'to': null,               // position to end playback within a sound (msec), default = end
    110     'type': null,             // MIME-like hint for file pattern / canPlay() tests, eg. audio/mp3
    111     'usePolicyFile': false,   // enable crossdomain.xml request for audio on remote domains (for ID3/waveform access)
    112     'volume': 100             // self-explanatory. 0-100, the latter being the max.
     99    autoLoad: false,        // enable automatic loading (otherwise .load() will be called on demand with .play(), the latter being nicer on bandwidth - if you want to .load yourself, you also can)
     100    autoPlay: false,        // enable playing of file as soon as possible (much faster if "stream" is true)
     101    from: null,             // position to start playback within a sound (msec), default = beginning
     102    loops: 1,               // how many times to repeat the sound (position will wrap around to 0, setPosition() will break out of loop when >0)
     103    onid3: null,            // callback function for "ID3 data is added/available"
     104    onerror: null,          // callback function for "load failed" (or, playback/network/decode error under HTML5.)
     105    onload: null,           // callback function for "load finished"
     106    whileloading: null,     // callback function for "download progress update" (X of Y bytes received)
     107    onplay: null,           // callback for "play" start
     108    onpause: null,          // callback for "pause"
     109    onresume: null,         // callback for "resume" (pause toggle)
     110    whileplaying: null,     // callback during play (position update)
     111    onposition: null,       // object containing times and function callbacks for positions of interest
     112    onstop: null,           // callback for "user stop"
     113    onfinish: null,         // callback function for "sound finished playing"
     114    multiShot: true,        // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time
     115    multiShotEvents: false, // fire multiple sound events (currently onfinish() only) when multiShot is enabled
     116    position: null,         // offset (milliseconds) to seek to within loaded sound data.
     117    pan: 0,                 // "pan" settings, left-to-right, -100 to 100
     118    playbackRate: 1,        // rate at which to play the sound (HTML5-only)
     119    stream: true,           // allows playing before entire file has loaded (recommended)
     120    to: null,               // position to end playback within a sound (msec), default = end
     121    type: null,             // MIME-like hint for file pattern / canPlay() tests, eg. audio/mp3
     122    usePolicyFile: false,   // enable crossdomain.xml request for audio on remote domains (for ID3/waveform access)
     123    volume: 100             // self-explanatory. 0-100, the latter being the max.
    113124
    114125  };
     
    121132     */
    122133
    123     'isMovieStar': null,      // "MovieStar" MPEG4 audio mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL
    124     'usePeakData': false,     // enable left/right channel peak (level) data
    125     'useWaveformData': false, // enable sound spectrum (raw waveform data) - NOTE: May increase CPU load.
    126     'useEQData': false,       // enable sound EQ (frequency spectrum data) - NOTE: May increase CPU load.
    127     'onbufferchange': null,   // callback for "isBuffering" property change
    128     'ondataerror': null       // callback for waveform/eq data access error (flash playing audio in other tabs/domains)
     134    onfailure: null,        // callback function for when playing fails (Flash 9, MovieStar + RTMP-only)
     135    isMovieStar: null,      // "MovieStar" MPEG4 audio mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL
     136    usePeakData: false,     // enable left/right channel peak (level) data
     137    useWaveformData: false, // enable sound spectrum (raw waveform data) - NOTE: May increase CPU load.
     138    useEQData: false,       // enable sound EQ (frequency spectrum data) - NOTE: May increase CPU load.
     139    onbufferchange: null,   // callback for "isBuffering" property change
     140    ondataerror: null       // callback for waveform/eq data access error (flash playing audio in other tabs/domains)
    129141
    130142  };
     
    137149     */
    138150
    139     'bufferTime': 3,          // seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try increasing.)
    140     'serverURL': null,        // rtmp: FMS or FMIS server to connect to, required when requesting media via RTMP or one of its variants
    141     'onconnect': null,        // rtmp: callback for connection to flash media server
    142     'duration': null          // rtmp: song duration (msec)
     151    bufferTime: 3,          // seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try increasing.)
     152    serverURL: null,        // rtmp: FMS or FMIS server to connect to, required when requesting media via RTMP or one of its variants
     153    onconnect: null,        // rtmp: callback for connection to flash media server
     154    duration: null          // rtmp: song duration (msec)
    143155
    144156  };
     
    152164     */
    153165
    154     'mp3': {
    155       'type': ['audio/mpeg; codecs="mp3"', 'audio/mpeg', 'audio/mp3', 'audio/MPA', 'audio/mpa-robust'],
    156       'required': true
     166    mp3: {
     167      type: ['audio/mpeg; codecs="mp3"', 'audio/mpeg', 'audio/mp3', 'audio/MPA', 'audio/mpa-robust'],
     168      required: true
    157169    },
    158170
    159     'mp4': {
    160       'related': ['aac','m4a','m4b'], // additional formats under the MP4 container
    161       'type': ['audio/mp4; codecs="mp4a.40.2"', 'audio/aac', 'audio/x-m4a', 'audio/MP4A-LATM', 'audio/mpeg4-generic'],
    162       'required': false
     171    mp4: {
     172      related: ['aac', 'm4a', 'm4b'], // additional formats under the MP4 container
     173      type: ['audio/mp4; codecs="mp4a.40.2"', 'audio/aac', 'audio/x-m4a', 'audio/MP4A-LATM', 'audio/mpeg4-generic'],
     174      required: false
    163175    },
    164176
    165     'ogg': {
    166       'type': ['audio/ogg; codecs=vorbis'],
    167       'required': false
     177    ogg: {
     178      type: ['audio/ogg; codecs=vorbis'],
     179      required: false
    168180    },
    169181
    170     'opus': {
    171       'type': ['audio/ogg; codecs=opus', 'audio/opus'],
    172       'required': false
     182    opus: {
     183      type: ['audio/ogg; codecs=opus', 'audio/opus'],
     184      required: false
    173185    },
    174186
    175     'wav': {
    176       'type': ['audio/wav; codecs="1"', 'audio/wav', 'audio/wave', 'audio/x-wav'],
    177       'required': false
     187    wav: {
     188      type: ['audio/wav; codecs="1"', 'audio/wav', 'audio/wave', 'audio/x-wav'],
     189      required: false
     190    },
     191
     192    flac: {
     193      type: ['audio/flac'],
     194      required: false
    178195    }
    179196
     
    190207  // dynamic attributes
    191208
    192   this.versionNumber = 'V2.97a.20130512';
     209  this.versionNumber = 'V2.97a.20170601';
    193210  this.version = null;
    194211  this.movieURL = null;
     
    204221
    205222  this.filePatterns = {
    206 
    207     'flash8': /\.mp3(\?.*)?$/i,
    208     'flash9': /\.mp3(\?.*)?$/i
    209 
     223    flash8: /\.mp3(\?.*)?$/i,
     224    flash9: /\.mp3(\?.*)?$/i
    210225  };
    211226
     
    213228
    214229  this.features = {
    215 
    216     'buffering': false,
    217     'peakData': false,
    218     'waveformData': false,
    219     'eqData': false,
    220     'movieStar': false
    221 
     230    buffering: false,
     231    peakData: false,
     232    waveformData: false,
     233    eqData: false,
     234    movieStar: false
    222235  };
    223236
     
    225238
    226239  this.sandbox = {
    227 
    228240    // <d>
    229     'type': null,
    230     'types': {
    231       'remote': 'remote (domain-based) rules',
    232       'localWithFile': 'local with file access (no internet access)',
    233       'localWithNetwork': 'local with network (internet access only, no local access)',
    234       'localTrusted': 'local, trusted (local+internet access)'
     241    type: null,
     242    types: {
     243      remote: 'remote (domain-based) rules',
     244      localWithFile: 'local with file access (no internet access)',
     245      localWithNetwork: 'local with network (internet access only, no local access)',
     246      localTrusted: 'local, trusted (local+internet access)'
    235247    },
    236     'description': null,
    237     'noRemote': null,
    238     'noLocal': null
     248    description: null,
     249    noRemote: null,
     250    noLocal: null
    239251    // </d>
    240 
    241252  };
    242253
     
    249260
    250261  this.html5 = {
    251     'usingFlash': null // set if/when flash fallback is needed
     262    usingFlash: null // set if/when flash fallback is needed
    252263  };
    253264
     
    266277
    267278  var SMSound,
    268   sm2 = this, globalHTML5Audio = null, flash = null, sm = 'soundManager', smc = sm + ': ', h5 = 'HTML5::', id, ua = navigator.userAgent, wl = window.location.href.toString(), doc = document, doNothing, setProperties, init, fV, on_queue = [], debugOpen = true, debugTS, didAppend = false, appendSuccess = false, didInit = false, disabled = false, windowLoaded = false, _wDS, wdCount = 0, initComplete, mixin, assign, extraOptions, addOnEvent, processOnEvents, initUserOnload, delayWaitForEI, waitForEI, setVersionInfo, handleFocus, strings, initMovie, preInit, domContentLoaded, winOnLoad, didDCLoaded, getDocument, createMovie, catchError, setPolling, initDebug, debugLevels = ['log', 'info', 'warn', 'error'], defaultFlashVersion = 8, disableObject, failSafely, normalizeMovieURL, oRemoved = null, oRemovedHTML = null, str, flashBlockHandler, getSWFCSS, swfCSS, toggleDebug, loopFix, policyFix, complain, idCheck, waitingForEI = false, initPending = false, startTimer, stopTimer, timerExecute, h5TimerCount = 0, h5IntervalTimer = null, parseURL, messages = [],
    269   canIgnoreFlash, needsFlash = null, featureCheck, html5OK, html5CanPlay, html5Ext, html5Unload, domContentLoadedIE, testHTML5, event, slice = Array.prototype.slice, useGlobalHTML5Audio = false, lastGlobalHTML5URL, hasFlash, detectFlash, badSafariFix, html5_events, showSupport, flushMessages, wrapCallback, idCounter = 0,
    270   is_iDevice = ua.match(/(ipad|iphone|ipod)/i), isAndroid = ua.match(/android/i), isIE = ua.match(/msie/i), isWebkit = ua.match(/webkit/i), isSafari = (ua.match(/safari/i) && !ua.match(/chrome/i)), isOpera = (ua.match(/opera/i)), isFirefox = (ua.match(/firefox/i)),
     279  sm2 = this, globalHTML5Audio = null, flash = null, sm = 'soundManager', smc = sm + ': ', h5 = 'HTML5::', id, ua = navigator.userAgent, wl = window.location.href.toString(), doc = document, doNothing, setProperties, init, fV, on_queue = [], debugOpen = true, debugTS, didAppend = false, appendSuccess = false, didInit = false, disabled = false, windowLoaded = false, _wDS, wdCount = 0, initComplete, mixin, assign, extraOptions, addOnEvent, processOnEvents, initUserOnload, delayWaitForEI, waitForEI, rebootIntoHTML5, setVersionInfo, handleFocus, strings, initMovie, domContentLoaded, winOnLoad, didDCLoaded, getDocument, createMovie, catchError, setPolling, initDebug, debugLevels = ['log', 'info', 'warn', 'error'], defaultFlashVersion = 8, disableObject, failSafely, normalizeMovieURL, oRemoved = null, oRemovedHTML = null, str, flashBlockHandler, getSWFCSS, swfCSS, toggleDebug, loopFix, policyFix, complain, idCheck, waitingForEI = false, initPending = false, startTimer, stopTimer, timerExecute, h5TimerCount = 0, h5IntervalTimer = null, parseURL, messages = [],
     280  canIgnoreFlash, needsFlash = null, featureCheck, html5OK, html5CanPlay, html5ErrorCodes, html5Ext, html5Unload, domContentLoadedIE, testHTML5, event, slice = Array.prototype.slice, useGlobalHTML5Audio = false, lastGlobalHTML5URL, hasFlash, detectFlash, badSafariFix, html5_events, showSupport, flushMessages, wrapCallback, idCounter = 0, didSetup, msecScale = 1000,
     281  is_iDevice = ua.match(/(ipad|iphone|ipod)/i), isAndroid = ua.match(/android/i), isIE = ua.match(/msie|trident/i),
     282  isWebkit = ua.match(/webkit/i),
     283  isSafari = (ua.match(/safari/i) && !ua.match(/chrome/i)),
     284  isOpera = (ua.match(/opera/i)),
    271285  mobileHTML5 = (ua.match(/(mobile|pre\/|xoom)/i) || is_iDevice || isAndroid),
    272   isBadSafari = (!wl.match(/usehtml5audio/i) && !wl.match(/sm2\-ignorebadua/i) && isSafari && !ua.match(/silk/i) && ua.match(/OS X 10_6_([3-7])/i)), // Safari 4 and 5 (excluding Kindle Fire, "Silk") occasionally fail to load/play HTML5 audio on Snow Leopard 10.6.3 through 10.6.7 due to bug(s) in QuickTime X and/or other underlying frameworks. :/ Confirmed bug. https://bugs.webkit.org/show_bug.cgi?id=32159
    273   hasConsole = (window.console !== _undefined && console.log !== _undefined), isFocused = (doc.hasFocus !== _undefined?doc.hasFocus():null), tryInitOnFocus = (isSafari && (doc.hasFocus === _undefined || !doc.hasFocus())), okToDisable = !tryInitOnFocus, flashMIME = /(mp3|mp4|mpa|m4a|m4b)/i, msecScale = 1000,
     286  isBadSafari = (!wl.match(/usehtml5audio/i) && !wl.match(/sm2-ignorebadua/i) && isSafari && !ua.match(/silk/i) && ua.match(/OS\sX\s10_6_([3-7])/i)), // Safari 4 and 5 (excluding Kindle Fire, "Silk") occasionally fail to load/play HTML5 audio on Snow Leopard 10.6.3 through 10.6.7 due to bug(s) in QuickTime X and/or other underlying frameworks. :/ Confirmed bug. https://bugs.webkit.org/show_bug.cgi?id=32159
     287  hasConsole = (window.console !== _undefined && console.log !== _undefined),
     288  isFocused = (doc.hasFocus !== _undefined ? doc.hasFocus() : null),
     289  tryInitOnFocus = (isSafari && (doc.hasFocus === _undefined || !doc.hasFocus())),
     290  okToDisable = !tryInitOnFocus,
     291  flashMIME = /(mp3|mp4|mpa|m4a|m4b)/i,
    274292  emptyURL = 'about:blank', // safe URL to unload, or load nothing from (flash 8 + most HTML5 UAs)
    275   overHTTP = (doc.location?doc.location.protocol.match(/http/i):null),
    276   http = (!overHTTP ? 'http:/'+'/' : ''),
     293  emptyWAV = 'data:audio/wave;base64,/UklGRiYAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQIAAAD//w==', // tiny WAV for HTML5 unloading
     294  overHTTP = (doc.location ? doc.location.protocol.match(/http/i) : null),
     295  http = (!overHTTP ? '//' : ''),
    277296  // mp3, mp4, aac etc.
    278   netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,
     297  netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4|m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,
    279298  // Flash v9.0r115+ "moviestar" formats
    280299  netStreamTypes = ['mpeg4', 'aac', 'flv', 'mov', 'mp4', 'm4v', 'f4v', 'm4a', 'm4b', 'mp4v', '3gp', '3g2'],
     
    287306
    288307  swfCSS = {
    289 
    290     'swfBox': 'sm2-object-box',
    291     'swfDefault': 'movieContainer',
    292     'swfError': 'swf_error', // SWF loaded, but SM2 couldn't start (other error)
    293     'swfTimedout': 'swf_timedout',
    294     'swfLoaded': 'swf_loaded',
    295     'swfUnblocked': 'swf_unblocked', // or loaded OK
    296     'sm2Debug': 'sm2_debug',
    297     'highPerf': 'high_performance',
    298     'flashDebug': 'flash_debug'
    299 
    300   };
     308    swfBox: 'sm2-object-box',
     309    swfDefault: 'movieContainer',
     310    swfError: 'swf_error', // SWF loaded, but SM2 couldn't start (other error)
     311    swfTimedout: 'swf_timedout',
     312    swfLoaded: 'swf_loaded',
     313    swfUnblocked: 'swf_unblocked', // or loaded OK
     314    sm2Debug: 'sm2_debug',
     315    highPerf: 'high_performance',
     316    flashDebug: 'flash_debug'
     317  };
     318
     319  /**
     320   * HTML5 error codes, per W3C
     321   * Error code 1, MEDIA_ERR_ABORTED: Client aborted download at user's request.
     322   * Error code 2, MEDIA_ERR_NETWORK: A network error of some description caused the user agent to stop fetching the media resource, after the resource was established to be usable.
     323   * Error code 3, MEDIA_ERR_DECODE: An error of some description occurred while decoding the media resource, after the resource was established to be usable.
     324   * Error code 4, MEDIA_ERR_SRC_NOT_SUPPORTED: Media (audio file) not supported ("not usable.")
     325   * Reference: https://html.spec.whatwg.org/multipage/embedded-content.html#error-codes
     326   */
     327  html5ErrorCodes = [
     328    null,
     329    'MEDIA_ERR_ABORTED',
     330    'MEDIA_ERR_NETWORK',
     331    'MEDIA_ERR_DECODE',
     332    'MEDIA_ERR_SRC_NOT_SUPPORTED'
     333  ];
    301334
    302335  /**
     
    341374    assign(options);
    342375
     376    if (!useGlobalHTML5Audio) {
     377
     378      if (mobileHTML5) {
     379
     380        // force the singleton HTML5 pattern on mobile, by default.
     381        if (!sm2.setupOptions.ignoreMobileRestrictions || sm2.setupOptions.forceUseGlobalHTML5Audio) {
     382          messages.push(strings.globalHTML5);
     383          useGlobalHTML5Audio = true;
     384        }
     385
     386      } else if (sm2.setupOptions.forceUseGlobalHTML5Audio) {
     387
     388        // only apply singleton HTML5 on desktop if forced.
     389        messages.push(strings.globalHTML5);
     390        useGlobalHTML5Audio = true;
     391
     392      }
     393
     394    }
     395
     396    if (!didSetup && mobileHTML5) {
     397
     398      if (sm2.setupOptions.ignoreMobileRestrictions) {
     399
     400        messages.push(strings.ignoreMobile);
     401
     402      } else {
     403
     404        // prefer HTML5 for mobile + tablet-like devices, probably more reliable vs. flash at this point.
     405
     406        // <d>
     407        if (!sm2.setupOptions.useHTML5Audio || sm2.setupOptions.preferFlash) {
     408          // notify that defaults are being changed.
     409          sm2._wD(strings.mobileUA);
     410        }
     411        // </d>
     412
     413        sm2.setupOptions.useHTML5Audio = true;
     414        sm2.setupOptions.preferFlash = false;
     415
     416        if (is_iDevice) {
     417
     418          // no flash here.
     419          sm2.ignoreFlash = true;
     420
     421        } else if ((isAndroid && !ua.match(/android\s2\.3/i)) || !isAndroid) {
     422
     423          /**
     424           * Android devices tend to work better with a single audio instance, specifically for chained playback of sounds in sequence.
     425           * Common use case: exiting sound onfinish() -> createSound() -> play()
     426           * Presuming similar restrictions for other mobile, non-Android, non-iOS devices.
     427           */
     428
     429          // <d>
     430          sm2._wD(strings.globalHTML5);
     431          // </d>
     432
     433          useGlobalHTML5Audio = true;
     434
     435        }
     436
     437      }
     438
     439    }
     440
    343441    // special case 1: "Late setup". SM2 loaded normally, but user didn't assign flash URL eg., setup({url:...}) before SM2 init. Treat as delayed init.
    344442
     
    357455    }
    358456
     457    didSetup = true;
     458
    359459    return sm2;
    360460
     
    369469  this.supported = this.ok; // legacy
    370470
    371   this.getMovie = function(smID) {
     471  this.getMovie = function(movie_id) {
    372472
    373473    // safety net: some old browsers differ on SWF references, possibly related to ExternalInterface / flash version
    374     return id(smID) || doc[smID] || window[smID];
     474    return id(movie_id) || doc[movie_id] || window[movie_id];
    375475
    376476  };
    377477
    378478  /**
    379    * Creates a SMSound sound object instance.
     479   * Creates a SMSound sound object instance. Can also be overloaded, e.g., createSound('mySound', '/some.mp3');
    380480   *
    381    * @param {object} oOptions Sound options (at minimum, id and url parameters are required.)
     481   * @param {object} oOptions Sound options (at minimum, url parameter is required.)
    382482   * @return {object} SMSound The new SMSound object.
    383483   */
     
    389489    // <d>
    390490    cs = sm + '.createSound(): ';
    391     cs_string = cs + str(!didInit?'notReady':'notOK');
     491    cs_string = cs + str(!didInit ? 'notReady' : 'notOK');
    392492    // </d>
    393493
     
    398498
    399499    if (_url !== _undefined) {
    400       // function overloading in JS! :) ..assume simple createSound(id, url) use case
     500      // function overloading in JS! :) ... assume simple createSound(id, url) use case.
    401501      oOptions = {
    402         'id': oOptions,
    403         'url': _url
     502        id: oOptions,
     503        url: _url
    404504      };
    405505    }
     
    411511
    412512    // generate an id, if needed.
    413     if (options.id === undefined) {
     513    if (options.id === _undefined) {
    414514      options.id = sm2.setupOptions.idPrefix + (idCounter++);
    415515    }
     
    440540
    441541      oSound = make();
    442       sm2._wD(options.id + ': Using HTML5');
     542      // <d>
     543      if (!sm2.html5Only) {
     544        sm2._wD(options.id + ': Using HTML5');
     545      }
     546      // </d>
    443547      oSound._setup_html5(options);
    444548
     
    452556      // TODO: Move HTML5/flash checks into generic URL parsing/handling function.
    453557
    454       if (sm2.html5.usingFlash && options.url && options.url.match(/data\:/i)) {
     558      if (sm2.html5.usingFlash && options.url && options.url.match(/data:/i)) {
    455559        // data: URIs not supported by Flash, either.
    456560        sm2._wD(options.id + ': data: URIs not supported via Flash. Exiting.');
     
    477581
    478582      if (fV === 8) {
    479         flash._createSound(options.id, options.loops||1, options.usePolicyFile);
     583        flash._createSound(options.id, options.loops || 1, options.usePolicyFile);
    480584      } else {
    481         flash._createSound(options.id, options.url, options.usePeakData, options.useWaveformData, options.useEQData, options.isMovieStar, (options.isMovieStar?options.bufferTime:false), options.loops||1, options.serverURL, options.duration||null, options.autoPlay, true, options.autoLoad, options.usePolicyFile);
     585        flash._createSound(options.id, options.url, options.usePeakData, options.useWaveformData, options.useEQData, options.isMovieStar, (options.isMovieStar ? options.bufferTime : false), options.loops || 1, options.serverURL, options.duration || null, options.autoPlay, true, options.autoLoad, options.usePolicyFile);
    482586        if (!options.serverURL) {
    483587          // We are connected immediately
     
    515619    // explicitly destroy a sound before normal page unload, etc.
    516620
    517     if (!idCheck(sID)) {
    518       return false;
    519     }
     621    if (!idCheck(sID)) return false;
    520622
    521623    var oS = sm2.sounds[sID], i;
    522624
    523     // Disable all callbacks while the sound is being destroyed
     625    oS.stop();
     626
     627    // Disable all callbacks after stop(), when the sound is being destroyed
    524628    oS._iO = {};
    525629
    526     oS.stop();
    527630    oS.unload();
    528631
     
    555658  this.load = function(sID, oOptions) {
    556659
    557     if (!idCheck(sID)) {
    558       return false;
    559     }
     660    if (!idCheck(sID)) return false;
     661
    560662    return sm2.sounds[sID].load(oOptions);
    561663
     
    570672  this.unload = function(sID) {
    571673
    572     if (!idCheck(sID)) {
    573       return false;
    574     }
     674    if (!idCheck(sID)) return false;
     675
    575676    return sm2.sounds[sID].unload();
    576677
     
    589690  this.onPosition = function(sID, nPosition, oMethod, oScope) {
    590691
    591     if (!idCheck(sID)) {
    592       return false;
    593     }
     692    if (!idCheck(sID)) return false;
     693
    594694    return sm2.sounds[sID].onposition(nPosition, oMethod, oScope);
    595695
     
    610710  this.clearOnPosition = function(sID, nPosition, oMethod) {
    611711
    612     if (!idCheck(sID)) {
    613       return false;
    614     }
     712    if (!idCheck(sID)) return false;
     713
    615714    return sm2.sounds[sID].clearOnPosition(nPosition, oMethod);
    616715
     
    632731
    633732    if (!didInit || !sm2.ok()) {
    634       complain(sm + '.play(): ' + str(!didInit?'notReady':'notOK'));
     733      complain(sm + '.play(): ' + str(!didInit ? 'notReady' : 'notOK'));
    635734      return false;
    636735    }
     
    638737    if (!idCheck(sID, overloaded)) {
    639738
    640       if (!overloaded) {
    641         // no sound found for the given ID. Bail.
    642         return false;
    643       }
     739      // no sound found for the given ID. Bail.
     740      if (!overloaded) return false;
    644741
    645742      if (overloaded) {
     
    674771  };
    675772
    676   this.start = this.play; // just for convenience
     773  // just for convenience
     774  this.start = this.play;
     775
     776  /**
     777   * Calls the setPlaybackRate() method of a SMSound object by ID.
     778   *
     779   * @param {string} sID The ID of the sound
     780   * @return {SMSound} The SMSound object
     781   */
     782
     783  this.setPlaybackRate = function(sID, rate, allowOverride) {
     784
     785    if (!idCheck(sID)) return false;
     786
     787    return sm2.sounds[sID].setPlaybackRate(rate, allowOverride);
     788
     789  };
    677790
    678791  /**
     
    686799  this.setPosition = function(sID, nMsecOffset) {
    687800
    688     if (!idCheck(sID)) {
    689       return false;
    690     }
     801    if (!idCheck(sID)) return false;
     802
    691803    return sm2.sounds[sID].setPosition(nMsecOffset);
    692804
     
    702814  this.stop = function(sID) {
    703815
    704     if (!idCheck(sID)) {
    705       return false;
    706     }
     816    if (!idCheck(sID)) return false;
    707817
    708818    sm2._wD(sm + '.stop(' + sID + ')', 1);
     819
    709820    return sm2.sounds[sID].stop();
    710821
     
    738849  this.pause = function(sID) {
    739850
    740     if (!idCheck(sID)) {
    741       return false;
    742     }
     851    if (!idCheck(sID)) return false;
     852
    743853    return sm2.sounds[sID].pause();
    744854
     
    752862
    753863    var i;
    754     for (i = sm2.soundIDs.length-1; i >= 0; i--) {
     864    for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
    755865      sm2.sounds[sm2.soundIDs[i]].pause();
    756866    }
     
    767877  this.resume = function(sID) {
    768878
    769     if (!idCheck(sID)) {
    770       return false;
    771     }
     879    if (!idCheck(sID)) return false;
     880
    772881    return sm2.sounds[sID].resume();
    773882
     
    781890
    782891    var i;
    783     for (i = sm2.soundIDs.length-1; i >= 0; i--) {
     892    for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
    784893      sm2.sounds[sm2.soundIDs[i]].resume();
    785894    }
     
    796905  this.togglePause = function(sID) {
    797906
    798     if (!idCheck(sID)) {
    799       return false;
    800     }
     907    if (!idCheck(sID)) return false;
     908
    801909    return sm2.sounds[sID].togglePause();
    802910
     
    813921  this.setPan = function(sID, nPan) {
    814922
    815     if (!idCheck(sID)) {
    816       return false;
    817     }
     923    if (!idCheck(sID)) return false;
     924
    818925    return sm2.sounds[sID].setPan(nPan);
    819926
     
    821928
    822929  /**
    823    * Calls the setVolume() method of a SMSound object by ID.
     930   * Calls the setVolume() method of a SMSound object by ID
     931   * Overloaded case: pass only volume argument eg., setVolume(50) to apply to all sounds.
    824932   *
    825933   * @param {string} sID The ID of the sound
     
    830938  this.setVolume = function(sID, nVol) {
    831939
    832     if (!idCheck(sID)) {
     940    // setVolume(50) function overloading case - apply to all sounds
     941
     942    var i, j;
     943
     944    if (sID !== _undefined && !isNaN(sID) && nVol === _undefined) {
     945      for (i = 0, j = sm2.soundIDs.length; i < j; i++) {
     946        sm2.sounds[sm2.soundIDs[i]].setVolume(sID);
     947      }
    833948      return false;
    834949    }
     950
     951    // setVolume('mySound', 50) case
     952
     953    if (!idCheck(sID)) return false;
     954
    835955    return sm2.sounds[sID].setVolume(nVol);
    836956
     
    854974
    855975      sm2._wD(sm + '.mute(): Muting all sounds');
    856       for (i = sm2.soundIDs.length-1; i >= 0; i--) {
     976      for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
    857977        sm2.sounds[sm2.soundIDs[i]].mute();
    858978      }
     
    861981    } else {
    862982
    863       if (!idCheck(sID)) {
    864         return false;
    865       }
     983      if (!idCheck(sID)) return false;
     984
    866985      sm2._wD(sm + '.mute(): Muting "' + sID + '"');
    867986      return sm2.sounds[sID].mute();
     
    9001019
    9011020      sm2._wD(sm + '.unmute(): Unmuting all sounds');
    902       for (i = sm2.soundIDs.length-1; i >= 0; i--) {
     1021      for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
    9031022        sm2.sounds[sm2.soundIDs[i]].unmute();
    9041023      }
     
    9071026    } else {
    9081027
    909       if (!idCheck(sID)) {
    910         return false;
    911       }
     1028      if (!idCheck(sID)) return false;
     1029
    9121030      sm2._wD(sm + '.unmute(): Unmuting "' + sID + '"');
     1031
    9131032      return sm2.sounds[sID].unmute();
    9141033
     
    9381057  this.toggleMute = function(sID) {
    9391058
    940     if (!idCheck(sID)) {
    941       return false;
    942     }
     1059    if (!idCheck(sID)) return false;
     1060
    9431061    return sm2.sounds[sID].toggleMute();
    9441062
     
    9771095    }
    9781096
    979     if (disabled) {
    980       return false;
    981     }
     1097    // already disabled?
     1098    if (disabled) return false;
    9821099
    9831100    disabled = true;
     1101
    9841102    _wDS('shutdown', 1);
    9851103
    986     for (i = sm2.soundIDs.length-1; i >= 0; i--) {
     1104    for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
    9871105      disableObject(sm2.sounds[sm2.soundIDs[i]]);
    9881106    }
     1107
     1108    disableObject(sm2);
    9891109
    9901110    // fire "complete", despite fail
    9911111    initComplete(bNoDisable);
     1112
    9921113    event.remove(window, 'load', initUserOnload);
    9931114
     
    10051126
    10061127    if (sm2.hasHTML5) {
    1007       result = html5CanPlay({type:sMIME});
     1128      result = html5CanPlay({
     1129        type: sMIME
     1130      });
    10081131    }
    10091132
    10101133    if (!result && needsFlash) {
    10111134      // if flash 9, test netStream (movieStar) types as well.
    1012       result = (sMIME && sm2.ok() ? !!((fV > 8 ? sMIME.match(netStreamMimeTypes) : null) || sMIME.match(sm2.mimePattern)) : null);
     1135      result = (sMIME && sm2.ok() ? !!((fV > 8 ? sMIME.match(netStreamMimeTypes) : null) || sMIME.match(sm2.mimePattern)) : null); // TODO: make less "weird" (per JSLint)
    10131136    }
    10141137
     
    10291152
    10301153    if (sm2.hasHTML5) {
    1031       result = html5CanPlay({url: sURL});
     1154      result = html5CanPlay({
     1155        url: sURL
     1156      });
    10321157    }
    10331158
     
    10491174  this.canPlayLink = function(oLink) {
    10501175
    1051     if (oLink.type !== _undefined && oLink.type) {
    1052       if (sm2.canPlayMIME(oLink.type)) {
    1053         return true;
    1054       }
    1055     }
     1176    if (oLink.type !== _undefined && oLink.type && sm2.canPlayMIME(oLink.type)) return true;
    10561177
    10571178    return sm2.canPlayURL(oLink.href);
     
    10681189  this.getSoundById = function(sID, _suppressDebug) {
    10691190
    1070     if (!sID) {
    1071       return null;
    1072     }
     1191    if (!sID) return null;
    10731192
    10741193    var result = sm2.sounds[sID];
     
    11481267
    11491268      addOnEvent(sType, oMethod, oScope);
    1150       processOnEvents({type:sType});
     1269      processOnEvents({ type: sType });
    11511270
    11521271      result = true;
     
    11771296    var sDID = 'soundmanager-debug', o, oItem;
    11781297
    1179     if (!sm2.debugMode) {
    1180       return false;
    1181     }
     1298    if (!sm2.setupOptions.debugMode) return false;
    11821299
    11831300    if (hasConsole && sm2.useConsole) {
     
    11901307        console.log(sText);
    11911308      }
    1192       if (sm2.consoleOnly) {
    1193         return true;
    1194       }
     1309      if (sm2.consoleOnly) return true;
    11951310    }
    11961311
    11971312    o = id(sDID);
    11981313
    1199     if (!o) {
    1200       return false;
    1201     }
     1314    if (!o) return false;
    12021315
    12031316    oItem = doc.createElement('div');
     
    12861399    var i, j, k;
    12871400
    1288     for (i = sm2.soundIDs.length-1; i >= 0; i--) {
     1401    for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
    12891402      sm2.sounds[sm2.soundIDs[i]].destruct();
    12901403    }
     
    13221435
    13231436    idCounter = 0;
     1437    didSetup = false;
    13241438
    13251439    if (!resetEvents) {
     
    13461460
    13471461    sm2.html5 = {
    1348       'usingFlash': null
     1462      usingFlash: null
    13491463    };
    13501464
     
    13571471
    13581472    window.setTimeout(function() {
    1359 
    1360       preInit();
    13611473
    13621474      // by default, re-init
     
    13811493
    13821494    _wDS('reset');
     1495
    13831496    return sm2.reboot(true, true);
    13841497
     
    13961509     * Interesting syntax notes...
    13971510     * Flash/ExternalInterface (ActiveX/NPAPI) bridge methods are not typeof "function" nor instanceof Function, but are still valid.
    1398      * Additionally, JSLint dislikes ('PercentLoaded' in flash)-style syntax and recommends hasOwnProperty(), which does not work in this case.
    13991511     * Furthermore, using (flash && flash.PercentLoaded) causes IE to throw "object doesn't support this property or method".
    14001512     * Thus, 'in' syntax must be used.
    14011513     */
    14021514
    1403     return (flash && 'PercentLoaded' in flash ? flash.PercentLoaded() : null); // Yes, JSLint. See nearby comment in source for explanation.
     1515    return (flash && 'PercentLoaded' in flash ? flash.PercentLoaded() : null);
    14041516
    14051517  };
     
    14161528    setTimeout(function() {
    14171529
    1418       if (initPending) {
    1419         return false;
    1420       }
     1530      if (initPending) return false;
    14211531
    14221532      createMovie();
     
    14861596
    14871597    // for flash 8 special-case createSound() without url, followed by load/play with url case
    1488     urlOmitted = (this.url ? false : true);
     1598    urlOmitted = (!this.url);
    14891599
    14901600    /**
     
    15101620     * Begins loading a sound per its *url*.
    15111621     *
    1512      * @param {object} oOptions Optional: Sound options
     1622     * @param {object} options Optional: Sound options
    15131623     * @return {SMSound} The SMSound object
    15141624     */
    15151625
    1516     this.load = function(oOptions) {
     1626    this.load = function(options) {
    15171627
    15181628      var oSound = null, instanceOptions;
    15191629
    1520       if (oOptions !== _undefined) {
    1521         s._iO = mixin(oOptions, s.options);
     1630      if (options !== _undefined) {
     1631        s._iO = mixin(options, s.options);
    15221632      } else {
    1523         oOptions = s.options;
    1524         s._iO = oOptions;
     1633        options = s.options;
     1634        s._iO = options;
    15251635        if (lastURL && lastURL !== s.url) {
    15261636          _wDS('manURL');
     
    16131723          s._a._called_load = true;
    16141724
    1615           if (instanceOptions.autoPlay) {
    1616             s.play();
    1617           }
    1618 
    16191725        } else {
    16201726
     
    16301736        }
    16311737
    1632         if (s._iO.url && s._iO.url.match(/data\:/i)) {
     1738        if (s._iO.url && s._iO.url.match(/data:/i)) {
    16331739          // data: URIs not supported by Flash, either.
    16341740          sm2._wD(s.id + ': data: URIs not supported via Flash. Exiting.');
     
    16391745          s.isHTML5 = false;
    16401746          s._iO = policyFix(loopFix(instanceOptions));
     1747          // if we have "position", disable auto-play as we'll be seeking to that position at onload().
     1748          if (s._iO.autoPlay && (s._iO.position || s._iO.from)) {
     1749            sm2._wD(s.id + ': Disabling autoPlay because of non-zero offset case');
     1750            s._iO.autoPlay = false;
     1751          }
    16411752          // re-assign local shortcut
    16421753          instanceOptions = s._iO;
     
    16441755            flash._load(s.id, instanceOptions.url, instanceOptions.stream, instanceOptions.autoPlay, instanceOptions.usePolicyFile);
    16451756          } else {
    1646             flash._load(s.id, instanceOptions.url, !!(instanceOptions.stream), !!(instanceOptions.autoPlay), instanceOptions.loops||1, !!(instanceOptions.autoLoad), instanceOptions.usePolicyFile);
     1757            flash._load(s.id, instanceOptions.url, !!(instanceOptions.stream), !!(instanceOptions.autoPlay), instanceOptions.loops || 1, !!(instanceOptions.autoLoad), instanceOptions.usePolicyFile);
    16471758          }
    16481759        } catch(e) {
    16491760          _wDS('smError', 2);
    16501761          debugTS('onload', false);
    1651           catchError({type:'SMSOUND_LOAD_JS_EXCEPTION', fatal:true});
     1762          catchError({
     1763            type: 'SMSOUND_LOAD_JS_EXCEPTION',
     1764            fatal: true
     1765          });
    16521766        }
    16531767
     
    17511865     * Begins playing a sound.
    17521866     *
    1753      * @param {object} oOptions Optional: Sound options
     1867     * @param {object} options Optional: Sound options
    17541868     * @return {SMSound} The SMSound object
    17551869     */
    17561870
    1757     this.play = function(oOptions, _updatePlayState) {
     1871    this.play = function(options, _updatePlayState) {
    17581872
    17591873      var fN, allowMulti, a, onready,
    17601874          audioClone, onended, oncanplay,
    1761           startOK = true,
    1762           exit = null;
     1875          startOK = true;
    17631876
    17641877      // <d>
     
    17691882      _updatePlayState = (_updatePlayState === _undefined ? true : _updatePlayState);
    17701883
    1771       if (!oOptions) {
    1772         oOptions = {};
     1884      if (!options) {
     1885        options = {};
    17731886      }
    17741887
     
    17821895
    17831896      // mix in any options specific to this method
    1784       s._iO = mixin(oOptions, s._iO);
     1897      s._iO = mixin(options, s._iO);
    17851898
    17861899      s._iO.url = parseURL(s._iO.url);
     
    17911904      if (!s.isHTML5 && s._iO.serverURL && !s.connected) {
    17921905        if (!s.getAutoPlay()) {
    1793           sm2._wD(fN +' Netstream not connected yet - setting autoPlay');
     1906          sm2._wD(fN + ' Netstream not connected yet - setting autoPlay');
    17941907          s.setAutoPlay(true);
    17951908        }
     
    18041917
    18051918      if (s.playState === 1 && !s.paused) {
     1919
    18061920        allowMulti = s._iO.multiShot;
     1921
    18071922        if (!allowMulti) {
     1923
    18081924          sm2._wD(fN + 'Already playing (one-shot)', 1);
     1925
    18091926          if (s.isHTML5) {
    18101927            // go back to original position.
    18111928            s.setPosition(s._iO.position);
    18121929          }
    1813           exit = s;
    1814         } else {
    1815           sm2._wD(fN + 'Already playing (multi-shot)', 1);
    1816         }
    1817       }
    1818 
    1819       if (exit !== null) {
    1820         return exit;
     1930
     1931          return s;
     1932
     1933        }
     1934
     1935        sm2._wD(fN + 'Already playing (multi-shot)', 1);
     1936
    18211937      }
    18221938
    18231939      // edge case: play() with explicit URL parameter
    1824       if (oOptions.url && oOptions.url !== s.url) {
     1940      if (options.url && options.url !== s.url) {
    18251941
    18261942        // special case for createSound() followed by load() / play() with url; avoid double-load case.
     
    18591975
    18601976            sm2._wD(fN + 'Unsupported type. Exiting.');
    1861             exit = s;
     1977
     1978            return s;
    18621979
    18631980          }
     
    18691986
    18701987          sm2._wD(fN + 'Could not load - exiting', 2);
    1871           exit = s;
     1988
     1989          return s;
    18721990
    18731991        } else {
     
    18842002      }
    18852003
    1886       if (exit !== null) {
    1887         return exit;
    1888       }
    1889 
    18902004      if (!s.isHTML5 && fV === 9 && s.position > 0 && s.position === s.duration) {
    18912005        // flash 9 needs a position reset if play() is called while at the end of a sound.
    1892         sm2._wD(fN + 'Sound at end, resetting to position:0');
    1893         oOptions.position = 0;
     2006        sm2._wD(fN + 'Sound at end, resetting to position: 0');
     2007        options.position = 0;
    18942008      }
    18952009
     
    19112025      } else {
    19122026
    1913         s._iO = mixin(oOptions, s._iO);
    1914 
    1915         // apply from/to parameters, if they exist (and not using RTMP)
    1916         if (s._iO.from !== null && s._iO.to !== null && s.instanceCount === 0 && s.playState === 0 && !s._iO.serverURL) {
     2027        s._iO = mixin(options, s._iO);
     2028
     2029        /**
     2030         * Preload in the event of play() with position under Flash,
     2031         * or from/to parameters and non-RTMP case
     2032         */
     2033        if (((!s.isHTML5 && s._iO.position !== null && s._iO.position > 0) || (s._iO.from !== null && s._iO.from > 0) || s._iO.to !== null) && s.instanceCount === 0 && s.playState === 0 && !s._iO.serverURL) {
    19172034
    19182035          onready = function() {
    19192036            // sound "canplay" or onload()
    1920             // re-apply from/to to instance options, and start playback
    1921             s._iO = mixin(oOptions, s._iO);
     2037            // re-apply position/from/to to instance options, and start playback
     2038            s._iO = mixin(options, s._iO);
    19222039            s.play(s._iO);
    19232040          };
     
    19272044
    19282045            // this hasn't been loaded yet. load it first, and then do this again.
    1929             sm2._wD(fN + 'Beginning load for from/to case');
     2046            sm2._wD(fN + 'Beginning load for non-zero offset case');
    19302047
    19312048            s.load({
    1932               // TODO: was _oncanplay. Sounds wrong.
    1933               oncanplay: onready
     2049              // note: custom HTML5-only event added for from/to implementation.
     2050              _oncanplay: onready
    19342051            });
    19352052
    1936             exit = false;
    1937 
    19382053          } else if (!s.isHTML5 && !s.loaded && (!s.readyState || s.readyState !== 2)) {
    19392054
    19402055            // to be safe, preload the whole thing in Flash.
    19412056
    1942             sm2._wD(fN + 'Preloading for from/to case');
     2057            sm2._wD(fN + 'Preloading for non-zero offset case');
    19432058
    19442059            s.load({
     
    19462061            });
    19472062
    1948             exit = false;
    1949 
    1950           }
    1951 
    1952           if (exit !== null) {
    1953             return exit;
    19542063          }
    19552064
     
    19882097        s.setVolume(s._iO.volume, true);
    19892098        s.setPan(s._iO.pan, true);
     2099
     2100        if (s._iO.playbackRate !== 1) {
     2101          s.setPlaybackRate(s._iO.playbackRate);
     2102        }
    19902103
    19912104        if (!s.isHTML5) {
     
    20042117          }
    20052118
    2006         } else {
    2007 
    2008           if (s.instanceCount < 2) {
     2119        } else if (s.instanceCount < 2) {
    20092120
    20102121            // HTML5 single-instance case
     
    20272138
    20282139            onended = function() {
    2029               event.remove(audioClone, 'onended', onended);
     2140              event.remove(audioClone, 'ended', onended);
    20302141              s._onfinish(s);
    20312142              // cleanup
     
    20372148              event.remove(audioClone, 'canplay', oncanplay);
    20382149              try {
    2039                 audioClone.currentTime = s._iO.position/msecScale;
     2150                audioClone.currentTime = s._iO.position / msecScale;
    20402151              } catch(err) {
    2041                 complain(s.id + ': multiShot play() failed to apply position of ' + (s._iO.position/msecScale));
     2152                complain(s.id + ': multiShot play() failed to apply position of ' + (s._iO.position / msecScale));
    20422153              }
    20432154              audioClone.play();
     
    20452156
    20462157            event.add(audioClone, 'ended', onended);
     2158
     2159            // apply volume to clones, too
     2160            if (s._iO.volume !== _undefined) {
     2161              audioClone.volume = Math.max(0, Math.min(1, s._iO.volume / 100));
     2162            }
     2163
     2164            // playing multiple muted sounds? if you do this, you're weird ;) - but let's cover it.
     2165            if (s.muted) {
     2166              audioClone.muted = true;
     2167            }
    20472168
    20482169            if (s._iO.position) {
     
    20572178          }
    20582179
    2059         }
    2060 
    20612180      }
    20622181
     
    21092228          }
    21102229
    2111         } else {
    2112 
    2113           if (s._a) {
     2230        } else if (s._a) {
    21142231
    21152232            originalPosition = s.position;
     
    21332250
    21342251          }
    2135 
    2136         }
    21372252
    21382253        s.instanceCount = 0;
     
    21662281          if (!s.instanceCount && s.readyState === 1) {
    21672282            s.instanceCount++;
    2168             sm2._wD(s.id + ': Incremented instance count to '+s.instanceCount);
     2283            sm2._wD(s.id + ': Incremented instance count to ' + s.instanceCount);
    21692284          }
    21702285        }
     
    21822297
    21832298      return s._iO.autoPlay;
     2299
     2300    };
     2301
     2302    /**
     2303     * Sets the playback rate of a sound (HTML5-only.)
     2304     *
     2305     * @param {number} playbackRate (+/-)
     2306     * @return {SMSound} The SMSound object
     2307     */
     2308
     2309    this.setPlaybackRate = function(playbackRate) {
     2310
     2311      // Per Mozilla, limit acceptable values to prevent playback from stopping (unless allowOverride is truthy.)
     2312      // https://developer.mozilla.org/en-US/Apps/Build/Audio_and_video_delivery/WebAudio_playbackRate_explained
     2313      var normalizedRate = Math.max(0.5, Math.min(4, playbackRate));
     2314
     2315      // <d>
     2316      if (normalizedRate !== playbackRate) {
     2317        sm2._wD(s.id + ': setPlaybackRate(' + playbackRate + '): limiting rate to ' + normalizedRate, 2);
     2318      }
     2319      // </d>
     2320
     2321      if (s.isHTML5) {
     2322        try {
     2323          s._iO.playbackRate = normalizedRate;
     2324          s._a.playbackRate = normalizedRate;
     2325        } catch(e) {
     2326          sm2._wD(s.id + ': setPlaybackRate(' + normalizedRate + ') failed: ' + e.message, 2);
     2327        }
     2328      }
     2329
     2330      return s;
    21842331
    21852332    };
     
    22042351
    22052352      s.position = offset;
    2206       position1K = s.position/msecScale;
     2353      position1K = s.position / msecScale;
    22072354      s._resetOnPosition(s.position);
    22082355      s._iO.position = offset;
     
    22222369        if (s._html5_canplay) {
    22232370
    2224           if (s._a.currentTime !== position1K) {
     2371          if (s._a.currentTime.toFixed(3) !== position1K.toFixed(3)) {
    22252372
    22262373            /**
     
    22292376             * "INDEX_SIZE_ERR": DOM exception 1
    22302377             */
    2231             sm2._wD(s.id + ': setPosition('+position1K+')');
     2378            sm2._wD(s.id + ': setPosition(' + position1K + ')');
    22322379
    22332380            try {
     
    22532400        if (s.paused) {
    22542401
    2255           // if paused, refresh UI right away
    2256           // force update
     2402          // if paused, refresh UI right away by forcing update
    22572403          s._onTimer(true);
    22582404
     
    22732419    this.pause = function(_bCallFlash) {
    22742420
    2275       if (s.paused || (s.playState === 0 && s.readyState !== 1)) {
    2276         return s;
    2277       }
     2421      if (s.paused || (s.playState === 0 && s.readyState !== 1)) return s;
    22782422
    22792423      sm2._wD(s.id + ': pause()');
     
    23152459      var instanceOptions = s._iO;
    23162460
    2317       if (!s.paused) {
    2318         return s;
    2319       }
     2461      if (!s.paused) return s;
    23202462
    23212463      sm2._wD(s.id + ': resume()');
     
    23242466
    23252467      if (!s.isHTML5) {
     2468
    23262469        if (instanceOptions.isMovieStar && !instanceOptions.serverURL) {
    23272470          // Bizarre Webkit bug (Chrome reported via 8tracks.com dudes): AAC content paused for 30+ seconds(?) will not resume without a reposition.
    23282471          s.setPosition(s.position);
    23292472        }
     2473
    23302474        // flash method is toggle-based (pause/resume)
    23312475        flash._pause(s.id, instanceOptions.multiShot);
     2476
    23322477      } else {
     2478
    23332479        s._setup_html5().play();
    23342480        start_html5_timer();
     2481
    23352482      }
    23362483
    23372484      if (!onplay_called && instanceOptions.onplay) {
     2485
    23382486        instanceOptions.onplay.apply(s);
    23392487        onplay_called = true;
     2488
    23402489      } else if (instanceOptions.onresume) {
     2490
    23412491        instanceOptions.onresume.apply(s);
     2492
    23422493      }
    23432494
     
    24302581
    24312582      if (!s.isHTML5) {
    2432         flash._setVolume(s.id, (sm2.muted && !s.muted) || s.muted?0:nVol);
     2583
     2584        flash._setVolume(s.id, (sm2.muted && !s.muted) || s.muted ? 0 : nVol);
     2585
    24332586      } else if (s._a) {
    2434         // valid range: 0-1
    2435         s._a.volume = Math.max(0, Math.min(1, nVol/100));
     2587
     2588        if (sm2.muted && !s.muted) {
     2589          s.muted = true;
     2590          s._a.muted = true;
     2591        }
     2592
     2593        // valid range for native HTML5 Audio(): 0-1
     2594        s._a.volume = Math.max(0, Math.min(1, nVol / 100));
     2595
    24362596      }
    24372597
     
    24792639
    24802640      if (!s.isHTML5) {
    2481         flash._setVolume(s.id, hasIO?s._iO.volume:s.options.volume);
     2641        flash._setVolume(s.id, hasIO ? s._iO.volume : s.options.volume);
    24822642      } else if (s._a) {
    24832643        s._a.muted = false;
     
    24962656    this.toggleMute = function() {
    24972657
    2498       return (s.muted?s.unmute():s.mute());
     2658      return (s.muted ? s.unmute() : s.mute());
    24992659
    25002660    };
     
    25432703      if (isNaN(nPosition)) {
    25442704        // safety check
    2545         return false;
    2546       }
    2547 
    2548       for (i=0; i < onPositionItems.length; i++) {
     2705        return;
     2706      }
     2707
     2708      for (i = 0; i < onPositionItems.length; i++) {
    25492709
    25502710        if (nPosition === onPositionItems[i].position) {
    25512711          // remove this item if no method was specified, or, if the method matches
     2712
    25522713          if (!oMethod || (oMethod === onPositionItems[i].method)) {
     2714
    25532715            if (onPositionItems[i].fired) {
    25542716              // decrement "fired" counter, too
    25552717              onPositionFired--;
    25562718            }
     2719
    25572720            onPositionItems.splice(i, 1);
     2721
    25582722          }
     2723
    25592724        }
    25602725
     
    25672732      var i, item, j = onPositionItems.length;
    25682733
    2569       if (!j || !s.playState || onPositionFired >= j) {
    2570         return false;
    2571       }
    2572 
    2573       for (i=j-1; i >= 0; i--) {
     2734      if (!j || !s.playState || onPositionFired >= j) return false;
     2735
     2736      for (i = j - 1; i >= 0; i--) {
     2737
    25742738        item = onPositionItems[i];
     2739
    25752740        if (!item.fired && s.position >= item.position) {
     2741
    25762742          item.fired = true;
    25772743          onPositionFired++;
    25782744          item.method.apply(item.scope, [item.position]);
    2579         }
     2745
     2746          //  reset j -- onPositionItems.length can be changed in the item callback above... occasionally breaking the loop.
     2747          j = onPositionItems.length;
     2748
     2749        }
     2750
    25802751      }
    25812752
     
    25892760      var i, item, j = onPositionItems.length;
    25902761
    2591       if (!j) {
    2592         return false;
    2593       }
    2594 
    2595       for (i=j-1; i >= 0; i--) {
     2762      if (!j) return false;
     2763
     2764      for (i = j - 1; i >= 0; i--) {
     2765
    25962766        item = onPositionItems[i];
     2767
    25972768        if (item.fired && nPosition <= item.position) {
    25982769          item.fired = false;
    25992770          onPositionFired--;
    26002771        }
     2772
    26012773      }
    26022774
     
    26692841        for (item in op) {
    26702842          if (op.hasOwnProperty(item)) {
    2671             s.onPosition(parseInt(item, 10), op[item]); 
     2843            s.onPosition(parseInt(item, 10), op[item]);
    26722844          }
    26732845        }
     
    28132985          if (isNew || bForce) {
    28142986
    2815             s._whileplaying(time,x,x,x,x);
     2987            s._whileplaying(time, x, x, x, x);
    28162988
    28172989          }
     
    28252997        }*/
    28262998
    2827         return isNew;
    2828 
    2829       }
     2999      }
     3000
     3001      return isNew;
    28303002
    28313003    };
     
    28353007      var instanceOptions = s._iO,
    28363008          // if audio object exists, use its duration - else, instance option duration (if provided - it's a hack, really, and should be retired) OR null
    2837           d = (s._a && s._a.duration ? s._a.duration*msecScale : (instanceOptions && instanceOptions.duration ? instanceOptions.duration : null)),
     3009          d = (s._a && s._a.duration ? s._a.duration * msecScale : (instanceOptions && instanceOptions.duration ? instanceOptions.duration : null)),
    28383010          result = (d && !isNaN(d) && d !== Infinity ? d : null);
    28393011
     
    28593031    };
    28603032
    2861     this._setup_html5 = function(oOptions) {
    2862 
    2863       var instanceOptions = mixin(s._iO, oOptions),
     3033    this._setup_html5 = function(options) {
     3034
     3035      var instanceOptions = mixin(s._iO, options),
    28643036          a = useGlobalHTML5Audio ? globalHTML5Audio : s._a,
    28653037          dURL = decodeURI(instanceOptions.url),
     
    29123084        if (!sameURL) {
    29133085
    2914           // don't retain onPosition() stuff with new URL.
    2915 
    2916           resetProperties(false);
     3086          // don't retain onPosition() stuff with new URLs.
     3087
     3088          if (lastURL) {
     3089            resetProperties(false);
     3090          }
    29173091
    29183092          // assign new HTML5 URL
     
    29353109
    29363110          s._a = new Audio(instanceOptions.url);
     3111          s._a.load();
    29373112
    29383113        } else {
     
    29883163    add_html5_events = function() {
    29893164
    2990       if (s._a._added_events) {
    2991         return false;
    2992       }
     3165      if (s._a._added_events) return false;
    29933166
    29943167      var f;
    29953168
    29963169      function add(oEvt, oFn, bCapture) {
    2997         return s._a ? s._a.addEventListener(oEvt, oFn, bCapture||false) : null;
     3170        return s._a ? s._a.addEventListener(oEvt, oFn, bCapture || false) : null;
    29983171      }
    29993172
     
    30173190
    30183191      function remove(oEvt, oFn, bCapture) {
    3019         return (s._a ? s._a.removeEventListener(oEvt, oFn, bCapture||false) : null);
     3192        return (s._a ? s._a.removeEventListener(oEvt, oFn, bCapture || false) : null);
    30203193      }
    30213194
     
    30453218      fN = s.id + ': ';
    30463219      sm2._wD(fN + (loadOK ? 'onload()' : 'Failed to load / invalid sound?' + (!s.duration ? ' Zero-length duration reported.' : ' -') + ' (' + s.url + ')'), (loadOK ? 1 : 2));
     3220
    30473221      if (!loadOK && !s.isHTML5) {
    30483222        if (sm2.sandbox.noRemote === true) {
     
    30563230
    30573231      s.loaded = loadOK;
    3058       s.readyState = loadOK?3:2;
     3232      s.readyState = (loadOK ? 3 : 2);
    30593233      s._onbufferchange(0);
     3234
     3235      if (!loadOK && !s.isHTML5) {
     3236        // note: no error code from Flash.
     3237        s._onerror();
     3238      }
    30603239
    30613240      if (s._iO.onload) {
     
    30693248    };
    30703249
     3250    this._onerror = function(errorCode, description) {
     3251
     3252      // https://html.spec.whatwg.org/multipage/embedded-content.html#error-codes
     3253      if (s._iO.onerror) {
     3254        wrapCallback(s, function() {
     3255          s._iO.onerror.apply(s, [errorCode, description]);
     3256        });
     3257      }
     3258
     3259    };
     3260
    30713261    this._onbufferchange = function(nIsBuffering) {
    30723262
    3073       if (s.playState === 0) {
    3074         // ignore if not playing
    3075         return false;
    3076       }
    3077 
    3078       if ((nIsBuffering && s.isBuffering) || (!nIsBuffering && !s.isBuffering)) {
    3079         return false;
    3080       }
     3263      // ignore if not playing
     3264      if (s.playState === 0) return false;
     3265
     3266      if ((nIsBuffering && s.isBuffering) || (!nIsBuffering && !s.isBuffering)) return false;
    30813267
    30823268      s.isBuffering = (nIsBuffering === 1);
     3269
    30833270      if (s._iO.onbufferchange) {
    30843271        sm2._wD(s.id + ': Buffer state change: ' + nIsBuffering);
    3085         s._iO.onbufferchange.apply(s);
     3272        s._iO.onbufferchange.apply(s, [nIsBuffering]);
    30863273      }
    30873274
     
    31143301
    31153302      s.failures++;
    3116       sm2._wD(s.id + ': Failures = ' + s.failures);
     3303      sm2._wD(s.id + ': Failure (' + s.failures + '): ' + msg);
    31173304
    31183305      if (s._iO.onfailure && s.failures === 1) {
    3119         s._iO.onfailure(s, msg, level, code);
     3306        s._iO.onfailure(msg, level, code);
    31203307      } else {
    31213308        sm2._wD(s.id + ': Ignoring failure');
     3309      }
     3310
     3311    };
     3312
     3313    /**
     3314     * flash 9/movieStar + RTMP-only method for unhandled warnings/exceptions from Flash
     3315     * e.g., RTMP "method missing" warning (non-fatal) for getStreamLength on server
     3316     */
     3317
     3318    this._onwarning = function(msg, level, code) {
     3319
     3320      if (s._iO.onwarning) {
     3321        s._iO.onwarning(msg, level, code);
    31223322      }
    31233323
     
    31983398      if (!s.isHTML5) {
    31993399        s.buffered = [{
    3200           'start': 0,
    3201           'end': s.duration
     3400          start: 0,
     3401          end: s.duration
    32023402        }];
    32033403      }
     
    32153415          eqLeft;
    32163416
    3217       if (isNaN(nPosition) || nPosition === null) {
    3218         // flash safety net
    3219         return false;
    3220       }
     3417      // flash safety net
     3418      if (isNaN(nPosition) || nPosition === null) return false;
    32213419
    32223420      // Safari HTML5 play() may return small -ve values when starting from position: 0, eg. -50.120396875. Unexpected/invalid per W3, I think. Normalize to 0.
     
    32763474      /**
    32773475       * internal: flash 9 + NetStream (MovieStar/RTMP-only) feature
    3278        * 
     3476       *
    32793477       * @param {object} oData
    32803478       */
     
    32953493       * internal: flash 9 + NetStream (MovieStar/RTMP-only) feature
    32963494       * RTMP may include song title, MovieStar content may include encoding info
    3297        * 
     3495       *
    32983496       * @param {array} oMDProps (names)
    32993497       * @param {array} oMDData (values)
     
    33073505        oData[oMDProps[i]] = oMDData[i];
    33083506      }
     3507
    33093508      s.metadata = oData;
    33103509
    33113510      if (s._iO.onmetadata) {
    3312         s._iO.onmetadata.apply(s);
     3511        s._iO.onmetadata.call(s, s.metadata);
    33133512      }
    33143513
     
    33203519       * internal: flash 8 + flash 9 ID3 feature
    33213520       * may include artist, song title etc.
    3322        * 
     3521       *
    33233522       * @param {array} oID3Props (names)
    33243523       * @param {array} oID3Data (values)
     
    33323531        oData[oID3Props[i]] = oID3Data[i];
    33333532      }
     3533
    33343534      s.id3 = mixin(s.id3, oData);
    33353535
     
    33953595  getDocument = function() {
    33963596
    3397     return (doc.body || doc._docElement || doc.getElementsByTagName('div')[0]);
     3597    return (doc.body || doc.getElementsByTagName('div')[0]);
    33983598
    33993599  };
     
    34573657
    34583658  extraOptions = {
    3459     'onready': 1,
    3460     'ontimeout': 1,
    3461     'defaultOptions': 1,
    3462     'flash9Options': 1,
    3463     'movieStarOptions': 1
     3659    onready: 1,
     3660    ontimeout: 1,
     3661    defaultOptions: 1,
     3662    flash9Options: 1,
     3663    movieStarOptions: 1
    34643664  };
    34653665
     
    34983698
    34993699          if (typeof sm2[i] === 'object') {
    3500 
    3501             result.push(i+': {...}');
    3502 
     3700            result.push(i + ': {...}');
    35033701          } else if (sm2[i] instanceof Function) {
    3504 
    3505             result.push(i+': function() {...}');
    3506 
     3702            result.push(i + ': function() {...}');
    35073703          } else {
    3508 
    35093704            result.push(i);
    3510 
    35113705          }
    35123706
     
    35533747            result = false;
    35543748
    3555           } else {
     3749          } else if (sm2[i] instanceof Function) {
    35563750
    35573751            /**
     
    35603754             * multiple parameters should be in an array, eg. soundManager.setup({onready: [myHandler, myScope]});
    35613755             */
    3562 
    3563             if (sm2[i] instanceof Function) {
    3564 
    3565               sm2[i].apply(sm2, (o[i] instanceof Array? o[i] : [o[i]]));
    3566 
    3567             } else {
    3568 
    3569               // good old-fashioned direct assignment
    3570               sm2[i] = o[i];
    3571 
    3572             }
     3756            sm2[i].apply(sm2, (o[i] instanceof Array ? o[i] : [o[i]]));
     3757
     3758          } else {
     3759
     3760            // good old-fashioned direct assignment
     3761            sm2[i] = o[i];
    35733762
    35743763          }
    35753764
     3765        } else if (bonusOptions[i] === _undefined) {
     3766
     3767          // recursion case, eg., { defaultOptions: { ... } }
     3768
     3769          // invalid or disallowed parameter. complain.
     3770          complain(str((sm2[i] === _undefined ? 'setupUndef' : 'setupError'), i), 2);
     3771
     3772          result = false;
     3773
    35763774        } else {
    35773775
    3578           // recursion case, eg., { defaultOptions: { ... } }
    3579 
    3580           if (bonusOptions[i] === _undefined) {
    3581 
    3582             // invalid or disallowed parameter. complain.
    3583             complain(str((sm2[i] === _undefined ? 'setupUndef' : 'setupError'), i), 2);
    3584 
    3585             result = false;
    3586 
    3587           } else {
    3588 
    3589             // recurse through object
    3590             return assign(o[i], i);
    3591 
    3592           }
     3776          // recurse through object
     3777          return assign(o[i], i);
    35933778
    35943779        }
     
    36193804    var old = (window.attachEvent),
    36203805    evt = {
    3621       add: (old?'attachEvent':'addEventListener'),
    3622       remove: (old?'detachEvent':'removeEventListener')
     3806      add: (old ? 'attachEvent' : 'addEventListener'),
     3807      remove: (old ? 'detachEvent' : 'removeEventListener')
    36233808    };
    36243809
     
    36603845
    36613846    function add() {
    3662 
    36633847      apply(getArgs(arguments), 'add');
    3664 
    36653848    }
    36663849
    36673850    function remove() {
    3668 
    36693851      apply(getArgs(arguments), 'remove');
    3670 
    36713852    }
    36723853
    36733854    return {
    3674       'add': add,
    3675       'remove': remove
     3855      add: add,
     3856      remove: remove
    36763857    };
    36773858
     
    37303911      if (s._html5_canplay) {
    37313912        // this event has already fired. ignore.
    3732         return true;
     3913        return;
    37333914      }
    37343915
     
    37383919
    37393920      // position according to instance options
    3740       position1K = (s._iO.position !== _undefined && !isNaN(s._iO.position)?s._iO.position/msecScale:null);
    3741 
    3742       // set the position if position was set before the sound loaded
    3743       if (s.position && this.currentTime !== position1K) {
     3921      position1K = (s._iO.position !== _undefined && !isNaN(s._iO.position) ? s._iO.position / msecScale : null);
     3922
     3923      // set the position if position was provided before the sound loaded
     3924      if (this.currentTime !== position1K) {
    37443925        sm2._wD(s.id + ': canplay: Setting position to ' + position1K);
    37453926        try {
     
    37693950    }),
    37703951
     3952    durationchange: html5_event(function() {
     3953
     3954      // durationchange may fire at various times, probably the safest way to capture accurate/final duration.
     3955
     3956      var s = this._s,
     3957          duration;
     3958
     3959      duration = s._get_html5_duration();
     3960
     3961      if (!isNaN(duration) && duration !== s.duration) {
     3962
     3963        sm2._wD(this._s.id + ': durationchange (' + duration + ')' + (s.duration ? ', previously ' + s.duration : ''));
     3964
     3965        s.durationEstimate = s.duration = duration;
     3966
     3967      }
     3968
     3969    }),
     3970
    37713971    // TODO: Reserved for potential use
    37723972    /*
     
    37903990    error: html5_event(function() {
    37913991
    3792       sm2._wD(this._s.id + ': HTML5 error, code ' + this.error.code);
    3793       /**
    3794        * HTML5 error codes, per W3C
    3795        * Error 1: Client aborted download at user's request.
    3796        * Error 2: Network error after load started.
    3797        * Error 3: Decoding issue.
    3798        * Error 4: Media (audio file) not supported.
    3799        * Reference: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#error-codes
    3800        */
    3801       // call load with error state?
     3992      var description = (html5ErrorCodes[this.error.code] || null);
     3993      sm2._wD(this._s.id + ': HTML5 error, code ' + this.error.code + (description ? ' (' + description + ')' : ''));
    38023994      this._s._onload(false);
     3995      this._s._onerror(this.error.code, description);
    38033996
    38043997    }),
     
    38414034    playing: html5_event(function() {
    38424035
    3843       sm2._wD(this._s.id + ': playing');
     4036      sm2._wD(this._s.id + ': playing ' + String.fromCharCode(9835));
    38444037      // once play starts, no buffering
    38454038      this._s._onbufferchange(0);
     
    38524045
    38534046      var s = this._s,
    3854           i, j, str, buffered = 0,
     4047          i, j, progStr, buffered = 0,
    38554048          isProgress = (e.type === 'progress'),
    38564049          ranges = e.target.buffered,
    38574050          // firefox 3.6 implements e.loaded/total (bytes)
    3858           loaded = (e.loaded||0),
    3859           total = (e.total||1);
     4051          loaded = (e.loaded || 0),
     4052          total = (e.total || 1);
    38604053
    38614054      // reset the "buffered" (loaded byte ranges) array
     
    38694062        // re-build "buffered" array
    38704063        // HTML5 returns seconds. SM2 API uses msec for setPosition() etc., whether Flash or HTML5.
    3871         for (i=0, j=ranges.length; i<j; i++) {
     4064        for (i = 0, j = ranges.length; i < j; i++) {
    38724065          s.buffered.push({
    3873             'start': ranges.start(i) * msecScale,
    3874             'end': ranges.end(i) * msecScale
     4066            start: ranges.start(i) * msecScale,
     4067            end: ranges.end(i) * msecScale
    38754068          });
    38764069        }
     
    38804073
    38814074        // linear case, buffer sum; does not account for seeking and HTTP partials / byte ranges
    3882         loaded = Math.min(1, buffered/(e.target.duration*msecScale));
     4075        loaded = Math.min(1, buffered / (e.target.duration * msecScale));
    38834076
    38844077        // <d>
    38854078        if (isProgress && ranges.length > 1) {
    3886           str = [];
     4079          progStr = [];
    38874080          j = ranges.length;
    3888           for (i=0; i<j; i++) {
    3889             str.push(e.target.buffered.start(i)*msecScale +'-'+ e.target.buffered.end(i)*msecScale);
     4081          for (i = 0; i < j; i++) {
     4082            progStr.push((e.target.buffered.start(i) * msecScale) + '-' + (e.target.buffered.end(i) * msecScale));
    38904083          }
    3891           sm2._wD(this._s.id + ': progress, timeRanges: ' + str.join(', '));
     4084          sm2._wD(this._s.id + ': progress, timeRanges: ' + progStr.join(', '));
    38924085        }
    38934086
    38944087        if (isProgress && !isNaN(loaded)) {
    3895           sm2._wD(this._s.id + ': progress, ' + Math.floor(loaded*100) + '% loaded');
     4088          sm2._wD(this._s.id + ': progress, ' + Math.floor(loaded * 100) + '% loaded');
    38964089        }
    38974090        // </d>
     
    39014094      if (!isNaN(loaded)) {
    39024095
    3903         // if progress, likely not buffering
    3904         s._onbufferchange(0);
    39054096        // TODO: prevent calls with duplicate values.
    39064097        s._whileloading(loaded, total, s._get_html5_duration());
     
    39764167
    39774168      // Use type, if specified. Pass data: URIs to HTML5. If HTML5-only mode, no other options, so just give 'er
    3978       result = ((iO.type ? html5CanPlay({type:iO.type}) : html5CanPlay({url:iO.url}) || sm2.html5Only || iO.url.match(/data\:/i)));
     4169      result = ((iO.type ? html5CanPlay({ type: iO.type }) : html5CanPlay({ url: iO.url }) || sm2.html5Only || iO.url.match(/data:/i)));
    39794170
    39804171    }
     
    39984189    if (oAudio) {
    39994190
    4000       // Firefox likes '' for unload (used to work, but no longer?) - however, may request hosting page URL (bad.) Most other UAs dislike '' and fail to unload.
    4001       url = (isSafari && !is_iDevice ? null : (isFirefox ? emptyURL : null));
     4191      // Firefox and Chrome accept short WAVe data: URIs. Chome dislikes audio/wav, but accepts audio/wav for data: MIME.
     4192      // Desktop Safari complains / fails on data: URI, so it gets about:blank.
     4193      url = (isSafari ? emptyURL : (sm2.html5.canPlayType('audio/wav') ? emptyWAV : emptyURL));
    40024194
    40034195      oAudio.src = url;
    40044196
    40054197      // reset some state, too
    4006       if (oAudio._called_unload !== undefined) {
     4198      if (oAudio._called_unload !== _undefined) {
    40074199        oAudio._called_load = false;
    40084200      }
     
    40314223     */
    40324224
    4033     if (!sm2.useHTML5Audio || !sm2.hasHTML5) {
    4034       return false;
    4035     }
     4225    if (!sm2.useHTML5Audio || !sm2.hasHTML5) return false;
    40364226
    40374227    var url = (o.url || null),
     
    40454235    // account for known cases like audio/mp3
    40464236
    4047     if (mime && sm2.html5[mime] !== _undefined) {
    4048       return (sm2.html5[mime] && !preferFlashCheck(mime));
    4049     }
     4237    if (mime && sm2.html5[mime] !== _undefined) return (sm2.html5[mime] && !preferFlashCheck(mime));
    40504238
    40514239    if (!html5Ext) {
     4240
    40524241      html5Ext = [];
     4242
    40534243      for (item in aF) {
     4244
    40544245        if (aF.hasOwnProperty(item)) {
     4246
    40554247          html5Ext.push(item);
     4248
    40564249          if (aF[item].related) {
    40574250            html5Ext = html5Ext.concat(aF[item].related);
    40584251          }
    4059         }
    4060       }
    4061       html5Ext = new RegExp('\\.('+html5Ext.join('|')+')(\\?.*)?$','i');
     4252
     4253        }
     4254
     4255      }
     4256
     4257      html5Ext = new RegExp('\\.(' + html5Ext.join('|') + ')(\\?.*)?$', 'i');
     4258
    40624259    }
    40634260
     
    40664263
    40674264    if (!fileExt || !fileExt.length) {
     4265
    40684266      if (!mime) {
     4267
    40694268        result = false;
     4269
    40704270      } else {
     4271
    40714272        // audio/mp3 -> mp3, result should be known
    40724273        offset = mime.indexOf(';');
     4274
    40734275        // strip "audio/X; codecs..."
    4074         fileExt = (offset !== -1?mime.substr(0,offset):mime).substr(6);
    4075       }
     4276        fileExt = (offset !== -1 ? mime.substr(0, offset) : mime).substr(6);
     4277
     4278      }
     4279
    40764280    } else {
     4281
    40774282      // match the raw extension name - "mp3", for example
    40784283      fileExt = fileExt[1];
     4284
    40794285    }
    40804286
    40814287    if (fileExt && sm2.html5[fileExt] !== _undefined) {
     4288
    40824289      // result known
    40834290      result = (sm2.html5[fileExt] && !preferFlashCheck(fileExt));
     4291
    40844292    } else {
    4085       mime = 'audio/'+fileExt;
    4086       result = sm2.html5.canPlayType({type:mime});
     4293
     4294      mime = 'audio/' + fileExt;
     4295      result = sm2.html5.canPlayType({ type: mime });
     4296
    40874297      sm2.html5[fileExt] = result;
     4298
    40884299      // sm2._wD('canPlayType, found result: ' + result);
    40894300      result = (result && sm2.html5[mime] && !preferFlashCheck(mime));
     
    41024313
    41034314    if (!sm2.useHTML5Audio || !sm2.hasHTML5) {
     4315
    41044316      // without HTML5, we need Flash.
    41054317      sm2.html5.usingFlash = true;
    41064318      needsFlash = true;
     4319
    41074320      return false;
     4321
    41084322    }
    41094323
     
    41144328    function cp(m) {
    41154329
    4116       var canPlay, i, j,
     4330      var canPlay, j,
    41174331          result = false,
    41184332          isOK = false;
    41194333
    4120       if (!a || typeof a.canPlayType !== 'function') {
    4121         return result;
    4122       }
     4334      if (!a || typeof a.canPlayType !== 'function') return result;
    41234335
    41244336      if (m instanceof Array) {
     4337
    41254338        // iterate through all mime types, return any successes
    4126         for (i=0, j=m.length; i<j; i++) {
     4339
     4340        for (i = 0, j = m.length; i < j; i++) {
     4341
    41274342          if (sm2.html5[m[i]] || a.canPlayType(m[i]).match(sm2.html5Test)) {
     4343
    41284344            isOK = true;
    41294345            sm2.html5[m[i]] = true;
     4346
    41304347            // note flash support, too
    41314348            sm2.flash[m[i]] = !!(m[i].match(flashMIME));
     4349
    41324350          }
    4133         }
     4351
     4352        }
     4353
    41344354        result = isOK;
     4355
    41354356      } else {
     4357
    41364358        canPlay = (a && typeof a.canPlayType === 'function' ? a.canPlayType(m) : false);
    41374359        result = !!(canPlay && (canPlay.match(sm2.html5Test)));
     4360
    41384361      }
    41394362
     
    41744397        if (aF[item] && aF[item].related) {
    41754398
    4176           for (i=aF[item].related.length-1; i >= 0; i--) {
     4399          for (i = aF[item].related.length - 1; i >= 0; i--) {
    41774400
    41784401            // eg. audio/m4a
    4179             support['audio/'+aF[item].related[i]] = support[item];
     4402            support['audio/' + aF[item].related[i]] = support[item];
    41804403            sm2.html5[aF[item].related[i]] = support[item];
    41814404            sm2.flash[aF[item].related[i]] = support[item];
     
    41894412    }
    41904413
    4191     support.canPlayType = (a?cp:null);
     4414    support.canPlayType = (a ? cp : null);
    41924415    sm2.html5 = mixin(sm2.html5, support);
    41934416
     
    42264449    queue: smc + 'Queueing %s handler',
    42274450    smError: 'SMSound.load(): Exception: JS-Flash communication failed, or JS error.',
    4228     fbTimeout: 'No flash response, applying .'+swfCSS.swfTimedout+' CSS...',
     4451    fbTimeout: 'No flash response, applying .' + swfCSS.swfTimedout + ' CSS...',
    42294452    fbLoaded: 'Flash loaded',
    42304453    fbHandler: smc + 'flashBlockHandler()',
     
    42444467    setupLate: sm + '.setup(): url, flashVersion and html5Test property changes will not take effect until reboot().',
    42454468    noURL: smc + 'Flash URL required. Call soundManager.setup({url:...}) to get started.',
    4246     sm2Loaded: 'SoundManager 2: Ready.',
     4469    sm2Loaded: 'SoundManager 2: Ready. ' + String.fromCharCode(10003),
    42474470    reset: sm + '.reset(): Removing event callbacks',
    42484471    mobileUA: 'Mobile UA detected, preferring HTML5 by default.',
    4249     globalHTML5: 'Using singleton HTML5 Audio() pattern for this device.'
     4472    globalHTML5: 'Using singleton HTML5 Audio() pattern for this device.',
     4473    ignoreMobile: 'Ignoring mobile restrictions for this device.'
    42504474    // </d>
    42514475
     
    42584482    // <d>
    42594483
     4484    var args,
     4485        i, j, o,
     4486        sstr;
     4487
    42604488    // real array, please
    4261     var args = slice.call(arguments),
    4262 
    4263     // first arg
    4264     o = args.shift(),
    4265 
    4266     str = (strings && strings[o]?strings[o]:''), i, j;
    4267     if (str && args && args.length) {
     4489    args = slice.call(arguments);
     4490
     4491    // first argument
     4492    o = args.shift();
     4493
     4494    sstr = (strings && strings[o] ? strings[o] : '');
     4495
     4496    if (sstr && args && args.length) {
    42684497      for (i = 0, j = args.length; i < j; i++) {
    4269         str = str.replace('%s', args[i]);
    4270       }
    4271     }
    4272 
    4273     return str;
     4498        sstr = sstr.replace('%s', args[i]);
     4499      }
     4500    }
     4501
     4502    return sstr;
    42744503    // </d>
    42754504
     
    43454574  };
    43464575
    4347   normalizeMovieURL = function(smURL) {
     4576  normalizeMovieURL = function(movieURL) {
    43484577
    43494578    var urlParams = null, url;
    43504579
    4351     if (smURL) {
    4352       if (smURL.match(/\.swf(\?.*)?$/i)) {
    4353         urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?') + 4);
    4354         if (urlParams) {
    4355           // assume user knows what they're doing
    4356           return smURL;
    4357         }
    4358       } else if (smURL.lastIndexOf('/') !== smURL.length - 1) {
     4580    if (movieURL) {
     4581
     4582      if (movieURL.match(/\.swf(\?.*)?$/i)) {
     4583
     4584        urlParams = movieURL.substr(movieURL.toLowerCase().lastIndexOf('.swf?') + 4);
     4585
     4586        // assume user knows what they're doing
     4587        if (urlParams) return movieURL;
     4588
     4589      } else if (movieURL.lastIndexOf('/') !== movieURL.length - 1) {
     4590
    43594591        // append trailing slash, if needed
    4360         smURL += '/';
    4361       }
    4362     }
    4363 
    4364     url = (smURL && smURL.lastIndexOf('/') !== - 1 ? smURL.substr(0, smURL.lastIndexOf('/') + 1) : './') + sm2.movieURL;
     4592        movieURL += '/';
     4593
     4594      }
     4595
     4596    }
     4597
     4598    url = (movieURL && movieURL.lastIndexOf('/') !== -1 ? movieURL.substr(0, movieURL.lastIndexOf('/') + 1) : './') + sm2.movieURL;
    43654599
    43664600    if (sm2.noSWFCache) {
     
    43854619    // debug flash movie, if applicable
    43864620
    4387     var isDebug = (sm2.debugMode || sm2.debugFlash?'_debug.swf':'.swf');
     4621    var isDebug = (sm2.debugMode || sm2.debugFlash ? '_debug.swf' : '.swf');
    43884622
    43894623    if (sm2.useHTML5Audio && !sm2.html5Only && sm2.audioFormats.mp4.required && fV < 9) {
     
    43924626    }
    43934627
    4394     sm2.version = sm2.versionNumber + (sm2.html5Only?' (HTML5-only mode)':(fV === 9?' (AS3/Flash 9)':' (AS2/Flash 8)'));
     4628    sm2.version = sm2.versionNumber + (sm2.html5Only ? ' (HTML5-only mode)' : (fV === 9 ? ' (AS3/Flash 9)' : ' (AS2/Flash 8)'));
    43954629
    43964630    // set up default options
    43974631    if (fV > 8) {
     4632
    43984633      // +flash 9 base options
    43994634      sm2.defaultOptions = mixin(sm2.defaultOptions, sm2.flash9Options);
    44004635      sm2.features.buffering = true;
     4636
    44014637      // +moviestar support
    44024638      sm2.defaultOptions = mixin(sm2.defaultOptions, sm2.movieStarOptions);
    44034639      sm2.filePatterns.flash9 = new RegExp('\\.(mp3|' + netStreamTypes.join('|') + ')(\\?.*)?$', 'i');
    44044640      sm2.features.movieStar = true;
     4641
    44054642    } else {
     4643
    44064644      sm2.features.movieStar = false;
     4645
    44074646    }
    44084647
    44094648    // regExp for flash canPlay(), etc.
    4410     sm2.filePattern = sm2.filePatterns[(fV !== 8?'flash9':'flash8')];
     4649    sm2.filePattern = sm2.filePatterns[(fV !== 8 ? 'flash9' : 'flash8')];
    44114650
    44124651    // if applicable, use _debug versions of SWFs
    4413     sm2.movieURL = (fV === 8?'soundmanager2.swf':'soundmanager2_flash9.swf').replace('.swf', isDebug);
     4652    sm2.movieURL = (fV === 8 ? 'soundmanager2.swf' : 'soundmanager2_flash9.swf').replace('.swf', isDebug);
    44144653
    44154654    sm2.features.peakData = sm2.features.waveformData = sm2.features.eqData = (fV > 8);
     
    44204659
    44214660    if (!flash) {
    4422       return false;
     4661      return;
    44234662    }
    44244663
     
    44344673    // <d>
    44354674    if (sm2.debugURLParam.test(wl)) {
    4436       sm2.debugMode = true;
     4675      sm2.setupOptions.debugMode = sm2.debugMode = true;
    44374676    }
    44384677
    44394678    if (id(sm2.debugID)) {
    4440       return false;
     4679      return;
    44414680    }
    44424681
     
    44494688
    44504689      oToggle = {
    4451         'position': 'fixed',
    4452         'bottom': '0px',
    4453         'right': '0px',
    4454         'width': '1.2em',
    4455         'height': '1.2em',
    4456         'lineHeight': '1.2em',
    4457         'margin': '2px',
    4458         'textAlign': 'center',
    4459         'border': '1px solid #999',
    4460         'cursor': 'pointer',
    4461         'background': '#fff',
    4462         'color': '#333',
    4463         'zIndex': 10001
     4690        position: 'fixed',
     4691        bottom: '0px',
     4692        right: '0px',
     4693        width: '1.2em',
     4694        height: '1.2em',
     4695        lineHeight: '1.2em',
     4696        margin: '2px',
     4697        textAlign: 'center',
     4698        border: '1px solid #999',
     4699        cursor: 'pointer',
     4700        background: '#fff',
     4701        color: '#333',
     4702        zIndex: 10001
    44644703      };
    44654704
     
    44814720      oDebug = doc.createElement('div');
    44824721      oDebug.id = sm2.debugID;
    4483       oDebug.style.display = (sm2.debugMode?'block':'none');
     4722      oDebug.style.display = (sm2.debugMode ? 'block' : 'none');
    44844723
    44854724      if (sm2.debugMode && !id(oD.id)) {
     
    44884727          oTarget.appendChild(oD);
    44894728        } catch(e2) {
    4490           throw new Error(str('domError')+' \n'+e2.toString());
     4729          throw new Error(str('domError') + ' \n' + e2.toString());
    44914730        }
    44924731        oTarget.appendChild(oDebug);
     
    45154754
    45164755    if (!o) {
    4517       return false;
     4756      return;
    45184757    }
    45194758
     
    45764815        p = sm2.getMoviePercent(),
    45774816        css = swfCSS,
    4578         error = {type:'FLASHBLOCK'};
     4817        error = {
     4818          type: 'FLASHBLOCK'
     4819        };
    45794820
    45804821    if (sm2.html5Only) {
    45814822      // no flash, or unused
    4582       return false;
     4823      return;
    45834824    }
    45844825
     
    45874828      if (needsFlash) {
    45884829        // make the movie more visible, so user can fix
    4589         sm2.oMC.className = getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null?css.swfTimedout:css.swfError);
     4830        sm2.oMC.className = getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null ? css.swfTimedout : css.swfError);
    45904831        sm2._wD(name + ': ' + str('fbTimeout') + (p ? ' (' + str('fbLoaded') + ')' : ''));
    45914832      }
     
    45944835
    45954836      // fire onready(), complain lightly
    4596       processOnEvents({type:'ontimeout', ignoreInit:true, error:error});
     4837      processOnEvents({
     4838        type: 'ontimeout',
     4839        ignoreInit: true,
     4840        error: error
     4841      });
     4842
    45974843      catchError(error);
    45984844
     
    46084854
    46094855      if (sm2.oMC) {
    4610         sm2.oMC.className = [getSWFCSS(), css.swfDefault, css.swfLoaded + (sm2.didFlashBlock?' '+css.swfUnblocked:'')].join(' ');
     4856        sm2.oMC.className = [getSWFCSS(), css.swfDefault, css.swfLoaded + (sm2.didFlashBlock ? ' ' + css.swfUnblocked : '')].join(' ');
    46114857      }
    46124858
     
    46224868
    46234869    on_queue[sType].push({
    4624       'method': oMethod,
    4625       'scope': (oScope || null),
    4626       'fired': false
     4870      method: oMethod,
     4871      scope: (oScope || null),
     4872      fired: false
    46274873    });
    46284874
     
    46394885    }
    46404886
    4641     if (!didInit && oOptions && !oOptions.ignoreInit) {
    4642       // not ready yet.
    4643       return false;
    4644     }
    4645 
    4646     if (oOptions.type === 'ontimeout' && (sm2.ok() || (disabled && !oOptions.ignoreInit))) {
    4647       // invalid case
    4648       return false;
    4649     }
     4887    // not ready yet.
     4888    if (!didInit && oOptions && !oOptions.ignoreInit) return false;
     4889
     4890    // invalid case
     4891    if (oOptions.type === 'ontimeout' && (sm2.ok() || (disabled && !oOptions.ignoreInit))) return false;
    46504892
    46514893    var status = {
    4652           success: (oOptions && oOptions.ignoreInit?sm2.ok():!disabled)
     4894          success: (oOptions && oOptions.ignoreInit ? sm2.ok() : !disabled)
    46534895        },
    46544896
    46554897        // queue specified by type, or none
    4656         srcQueue = (oOptions && oOptions.type?on_queue[oOptions.type]||[]:[]),
     4898        srcQueue = (oOptions && oOptions.type ? on_queue[oOptions.type] || [] : []),
    46574899
    46584900        queue = [], i, j,
     
    46714913
    46724914    if (queue.length) {
     4915
    46734916      // sm2._wD(sm + ': Firing ' + queue.length + ' ' + oOptions.type + '() item' + (queue.length === 1 ? '' : 's'));
    46744917      for (i = 0, j = queue.length; i < j; i++) {
     4918
    46754919        if (queue[i].scope) {
    46764920          queue[i].method.apply(queue[i].scope, args);
     
    46784922          queue[i].method.apply(this, args);
    46794923        }
     4924
    46804925        if (!canRetry) {
    46814926          // useFlashBlock and SWF timeout case doesn't count here.
    46824927          queue[i].fired = true;
    4683         }
    4684       }
     4928
     4929        }
     4930
     4931      }
     4932
    46854933    }
    46864934
     
    47114959      }
    47124960
    4713     },1);
     4961    }, 1);
    47144962
    47154963  };
     
    47174965  detectFlash = function() {
    47184966
    4719     // hat tip: Flash Detect library (BSD, (C) 2007) by Carl "DocYes" S. Yestrau - http://featureblend.com/javascript-flash-detection-library.html / http://featureblend.com/license.txt
    4720 
    4721     if (hasFlash !== _undefined) {
    4722       // this work has already been done.
    4723       return hasFlash;
    4724     }
    4725 
    4726     var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = window.ActiveXObject;
     4967    /**
     4968     * Hat tip: Flash Detect library (BSD, (C) 2007) by Carl "DocYes" S. Yestrau
     4969     * http://featureblend.com/javascript-flash-detection-library.html / http://featureblend.com/license.txt
     4970     */
     4971
     4972    // this work has already been done.
     4973    if (hasFlash !== _undefined) return hasFlash;
     4974
     4975    var hasPlugin = false, n = navigator, obj, type, types, AX = window.ActiveXObject;
     4976
     4977    // MS Edge 14 throws an "Unspecified Error" because n.plugins is inaccessible due to permissions
     4978    var nP;
     4979
     4980    try {
     4981      nP = n.plugins;
     4982    } catch(e) {
     4983      nP = undefined;
     4984    }
    47274985
    47284986    if (nP && nP.length) {
     4987
    47294988      type = 'application/x-shockwave-flash';
    47304989      types = n.mimeTypes;
     4990
    47314991      if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) {
    47324992        hasPlugin = true;
    47334993      }
     4994
    47344995    } else if (AX !== _undefined && !ua.match(/MSAppHost/i)) {
     4996
    47354997      // Windows 8 Store Apps (MSAppHost) are weird (compatibility?) and won't complain here, but will barf if Flash/ActiveX object is appended to the DOM.
    47364998      try {
     
    47405002        obj = null;
    47415003      }
     5004
    47425005      hasPlugin = (!!obj);
     5006
    47435007      // cleanup, because it is ActiveX after all
    47445008      obj = null;
     5009
    47455010    }
    47465011
     
    47575022        formats = sm2.audioFormats,
    47585023        // iPhone <= 3.1 has broken HTML5 audio(), but firmware 3.2 (original iPad) + iOS4 works.
    4759         isSpecial = (is_iDevice && !!(ua.match(/os (1|2|3_0|3_1)/i)));
     5024        isSpecial = (is_iDevice && !!(ua.match(/os (1|2|3_0|3_1)\s/i)));
    47605025
    47615026    if (isSpecial) {
     
    47725037      }
    47735038
    4774     } else {
    4775 
    4776       if (sm2.useHTML5Audio) {
     5039    } else if (sm2.useHTML5Audio) {
    47775040
    47785041        if (!sm2.html5 || !sm2.html5.canPlayType) {
     
    47835046        // <d>
    47845047        if (isBadSafari) {
    4785           sm2._wD(smc + 'Note: Buggy HTML5 Audio in Safari on this OS X release, see https://bugs.webkit.org/show_bug.cgi?id=32159 - ' + (!hasFlash ?' would use flash fallback for MP3/MP4, but none detected.' : 'will use flash fallback for MP3/MP4, if available'), 1);
     5048          sm2._wD(smc + 'Note: Buggy HTML5 Audio in Safari on this OS X release, see https://bugs.webkit.org/show_bug.cgi?id=32159 - ' + (!hasFlash ? ' would use flash fallback for MP3/MP4, but none detected.' : 'will use flash fallback for MP3/MP4, if available'), 1);
    47865049        }
    47875050        // </d>
    47885051
    47895052      }
    4790 
    4791     }
    47925053
    47935054    if (sm2.useHTML5Audio && sm2.hasHTML5) {
     
    47995060
    48005061      for (item in formats) {
     5062
    48015063        if (formats.hasOwnProperty(item)) {
     5064
    48025065          if (formats[item].required) {
     5066
    48035067            if (!sm2.html5.canPlayType(formats[item].type)) {
     5068
    48045069              // 100% HTML5 mode is not possible.
    48055070              canIgnoreFlash = false;
    48065071              flashNeeded = true;
     5072
    48075073            } else if (sm2.preferFlash && (sm2.flash[item] || sm2.flash[formats[item].type])) {
     5074
    48085075              // flash may be required, or preferred for this format.
    48095076              flashNeeded = true;
     5077
    48105078            }
     5079
    48115080          }
    4812         }
     5081
     5082        }
     5083
    48135084      }
    48145085
     
    48395110
    48405111      // find the first good one
    4841       for (i=0, j=url.length; i<j; i++) {
     5112      for (i = 0, j = url.length; i < j; i++) {
    48425113
    48435114        if (url[i] instanceof Object) {
     5115
    48445116          // MIME check
    48455117          if (sm2.canPlayMIME(url[i].type)) {
     
    48495121
    48505122        } else if (sm2.canPlayURL(url[i])) {
     5123
    48515124          // URL string check
    48525125          urlResult = i;
    48535126          break;
     5127
    48545128        }
    48555129
     
    48905164
    48915165          h5IntervalTimer = setInterval(timerExecute, sm2.html5PollingInterval);
    4892    
     5166
    48935167        }
    48945168
     
    49265200
    49275201    /**
    4928      * manual polling for HTML5 progress events, ie., whileplaying() (can achieve greater precision than conservative default HTML5 interval)
     5202     * manual polling for HTML5 progress events, ie., whileplaying()
     5203     * (can achieve greater precision than conservative default HTML5 interval)
    49295204     */
    49305205
     
    49395214      h5IntervalTimer = null;
    49405215
    4941       return false;
     5216      return;
    49425217
    49435218    }
     
    49455220    // check all HTML5 sounds with timers
    49465221
    4947     for (i = sm2.soundIDs.length-1; i >= 0; i--) {
     5222    for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
    49485223
    49495224      if (sm2.sounds[sm2.soundIDs[i]].isHTML5 && sm2.sounds[sm2.soundIDs[i]]._hasTimer) {
    4950 
    49515225        sm2.sounds[sm2.soundIDs[i]]._onTimer();
    4952 
    49535226      }
    49545227
     
    49625235
    49635236    if (typeof sm2.onerror === 'function') {
    4964       sm2.onerror.apply(window, [{type:(options.type !== _undefined ? options.type : null)}]);
     5237      sm2.onerror.apply(window, [{
     5238        type: (options.type !== _undefined ? options.type : null)
     5239      }]);
    49655240    }
    49665241
     
    49765251    if (!isBadSafari || !detectFlash()) {
    49775252      // doesn't apply
    4978       return false;
     5253      return;
    49795254    }
    49805255
     
    49825257
    49835258    for (item in aF) {
     5259
    49845260      if (aF.hasOwnProperty(item)) {
     5261
    49855262        if (item === 'mp3' || item === 'mp4') {
     5263
    49865264          sm2._wD(sm + ': Using flash fallback for ' + item + ' format');
    49875265          sm2.html5[item] = false;
     5266
    49885267          // assign result to related formats, too
    49895268          if (aF[item] && aF[item].related) {
    4990             for (i = aF[item].related.length-1; i >= 0; i--) {
     5269            for (i = aF[item].related.length - 1; i >= 0; i--) {
    49915270              sm2.html5[aF[item].related[i]] = false;
    49925271            }
    49935272          }
    4994         }
    4995       }
     5273
     5274        }
     5275
     5276      }
     5277
    49965278    }
    49975279
     
    50065288
    50075289    // <d>
     5290    // Security sandbox according to Flash plugin
    50085291    var sb = sm2.sandbox;
    50095292
    50105293    sb.type = sandboxType;
    5011     sb.description = sb.types[(sb.types[sandboxType] !== _undefined?sandboxType:'unknown')];
     5294    sb.description = sb.types[(sb.types[sandboxType] !== _undefined ? sandboxType : 'unknown')];
    50125295
    50135296    if (sb.type === 'localWithFile') {
     
    50385321
    50395322    if (sm2.swfLoaded) {
    5040       return false;
     5323      return;
    50415324    }
    50425325
     
    50545337    // complain if JS + SWF build/version strings don't match, excluding +DEV builds
    50555338    // <d>
    5056     if (!swfVersion || swfVersion.replace(/\+dev/i,'') !== sm2.versionNumber.replace(/\+dev/i, '')) {
     5339    if (!swfVersion || swfVersion.replace(/\+dev/i, '') !== sm2.versionNumber.replace(/\+dev/i, '')) {
    50575340
    50585341      e = sm + ': Fatal: JavaScript file build "' + sm2.versionNumber + '" does not match Flash SWF build "' + swfVersion + '" at ' + sm2.url + '. Ensure both are up-to-date.';
    50595342
    50605343      // escape flash -> JS stack so this error fires in window.
    5061       setTimeout(function versionMismatch() {
     5344      setTimeout(function() {
    50625345        throw new Error(e);
    50635346      }, 0);
    50645347
    50655348      // exit, init will fail with timeout
    5066       return false;
     5349      return;
    50675350
    50685351    }
     
    50795362   */
    50805363
    5081   createMovie = function(smID, smURL) {
    5082 
    5083     if (didAppend && appendSuccess) {
    5084       // ignore if already succeeded
    5085       return false;
    5086     }
     5364  createMovie = function(movieID, movieURL) {
     5365
     5366    // ignore if already connected
     5367    if (didAppend && appendSuccess) return false;
    50875368
    50885369    function initMsg() {
     
    50905371      // <d>
    50915372
    5092       var options = [], title, str = [], delimiter = ' + ';
     5373      var options = [],
     5374          title,
     5375          msg = [],
     5376          delimiter = ' + ';
    50935377
    50945378      title = 'SoundManager ' + sm2.version + (!sm2.html5Only && sm2.useHTML5Audio ? (sm2.hasHTML5 ? ' + HTML5 audio' : ', no HTML5 audio support') : '');
     
    51245408        }
    51255409
    5126       } else {
    5127 
    5128         if (sm2.html5PollingInterval) {
     5410      } else if (sm2.html5PollingInterval) {
    51295411          options.push('html5PollingInterval (' + sm2.html5PollingInterval + 'ms)');
    51305412        }
    51315413
    5132       }
    5133 
    51345414      if (options.length) {
    5135         str = str.concat([options.join(delimiter)]);
    5136       }
    5137 
    5138       sm2._wD(title + (str.length ? delimiter + str.join(', ') : ''), 1);
     5415        msg = msg.concat([options.join(delimiter)]);
     5416      }
     5417
     5418      sm2._wD(title + (msg.length ? delimiter + msg.join(', ') : ''), 1);
    51395419
    51405420      showSupport();
     
    51635443
    51645444    // flash path
    5165     var remoteURL = (smURL || sm2.url),
     5445    var remoteURL = (movieURL || sm2.url),
    51665446    localURL = (sm2.altURL || remoteURL),
    51675447    swfTitle = 'JS/Flash audio component (SoundManager 2)',
     
    51735453
    51745454    isRTL = (html && html.dir && html.dir.match(/rtl/i));
    5175     smID = (smID === _undefined?sm2.id:smID);
     5455    movieID = (movieID === _undefined ? sm2.id : movieID);
    51765456
    51775457    function param(name, value) {
    5178       return '<param name="'+name+'" value="'+value+'" />';
     5458      return '<param name="' + name + '" value="' + value + '" />';
    51795459    }
    51805460
    51815461    // safety check for legacy (change to Flash 9 URL)
    51825462    setVersionInfo();
    5183     sm2.url = normalizeMovieURL(overHTTP?remoteURL:localURL);
    5184     smURL = sm2.url;
     5463    sm2.url = normalizeMovieURL(overHTTP ? remoteURL : localURL);
     5464    movieURL = sm2.url;
    51855465
    51865466    sm2.wmode = (!sm2.wmode && sm2.useHighPerformance ? 'transparent' : sm2.wmode);
     
    51925472       * wmode breaks IE 8 on Vista + Win7 too in some cases, as of January 2011 (?)
    51935473       */
    5194        messages.push(strings.spcWmode);
     5474      messages.push(strings.spcWmode);
    51955475      sm2.wmode = null;
    51965476    }
    51975477
    51985478    oEmbed = {
    5199       'name': smID,
    5200       'id': smID,
    5201       'src': smURL,
    5202       'quality': 'high',
    5203       'allowScriptAccess': sm2.allowScriptAccess,
    5204       'bgcolor': sm2.bgColor,
    5205       'pluginspage': http+'www.macromedia.com/go/getflashplayer',
    5206       'title': swfTitle,
    5207       'type': 'application/x-shockwave-flash',
    5208       'wmode': sm2.wmode,
     5479      name: movieID,
     5480      id: movieID,
     5481      src: movieURL,
     5482      quality: 'high',
     5483      allowScriptAccess: sm2.allowScriptAccess,
     5484      bgcolor: sm2.bgColor,
     5485      pluginspage: http + 'www.macromedia.com/go/getflashplayer',
     5486      title: swfTitle,
     5487      type: 'application/x-shockwave-flash',
     5488      wmode: sm2.wmode,
    52095489      // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html
    5210       'hasPriority': 'true'
     5490      hasPriority: 'true'
    52115491    };
    52125492
     
    52255505      oMovie = doc.createElement('div');
    52265506      movieHTML = [
    5227         '<object id="' + smID + '" data="' + smURL + '" type="' + oEmbed.type + '" title="' + oEmbed.title +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="' + http+'download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0">',
    5228         param('movie', smURL),
     5507        '<object id="' + movieID + '" data="' + movieURL + '" type="' + oEmbed.type + '" title="' + oEmbed.title + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0">',
     5508        param('movie', movieURL),
    52295509        param('AllowScriptAccess', sm2.allowScriptAccess),
    52305510        param('quality', oEmbed.quality),
    5231         (sm2.wmode? param('wmode', sm2.wmode): ''),
     5511        (sm2.wmode ? param('wmode', sm2.wmode) : ''),
    52325512        param('bgcolor', sm2.bgColor),
    52335513        param('hasPriority', 'true'),
     
    52665546            // on-screen at all times
    52675547            s = {
    5268               'position': 'fixed',
    5269               'width': '8px',
    5270               'height': '8px',
     5548              position: 'fixed',
     5549              width: '8px',
     5550              height: '8px',
    52715551              // >= 6px for flash to run fast, >= 8px to start up under Firefox/win32 in some cases. odd? yes.
    5272               'bottom': '0px',
    5273               'left': '0px',
    5274               'overflow': 'hidden'
     5552              bottom: '0px',
     5553              left: '0px',
     5554              overflow: 'hidden'
    52755555            };
    52765556          } else {
    52775557            // hide off-screen, lower priority
    52785558            s = {
    5279               'position': 'absolute',
    5280               'width': '6px',
    5281               'height': '6px',
    5282               'top': '-9999px',
    5283               'left': '-9999px'
     5559              position: 'absolute',
     5560              width: '6px',
     5561              height: '6px',
     5562              top: '-9999px',
     5563              left: '-9999px'
    52845564            };
    52855565            if (isRTL) {
    5286               s.left = Math.abs(parseInt(s.left,10))+'px';
     5566              s.left = Math.abs(parseInt(s.left, 10)) + 'px';
    52875567            }
    52885568          }
     
    53035583
    53045584        try {
     5585
    53055586          if (!isIE) {
    53065587            sm2.oMC.appendChild(oMovie);
    53075588          }
     5589
    53085590          oTarget.appendChild(sm2.oMC);
     5591
    53095592          if (isIE) {
    53105593            oEl = sm2.oMC.appendChild(doc.createElement('div'));
     
    53125595            oEl.innerHTML = movieHTML;
    53135596          }
     5597
    53145598          appendSuccess = true;
     5599
    53155600        } catch(e) {
    5316           throw new Error(str('domError')+' \n'+e.toString());
     5601
     5602          throw new Error(str('domError') + ' \n' + e.toString());
     5603
    53175604        }
    53185605
     
    53215608        // SM2 container is already in the document (eg. flashblock use case)
    53225609        sClass = sm2.oMC.className;
    5323         sm2.oMC.className = (sClass?sClass+' ':swfCSS.swfDefault) + (extraClass?' '+extraClass:'');
     5610        sm2.oMC.className = (sClass ? sClass + ' ' : swfCSS.swfDefault) + (extraClass ? ' ' + extraClass : '');
    53245611        sm2.oMC.appendChild(oMovie);
     5612
    53255613        if (isIE) {
    53265614          oEl = sm2.oMC.appendChild(doc.createElement('div'));
     
    53285616          oEl.innerHTML = movieHTML;
    53295617        }
     5618
    53305619        appendSuccess = true;
    53315620
     
    53355624
    53365625    didAppend = true;
     5626
    53375627    initMsg();
    5338     // sm2._wD(sm + ': Trying to load ' + smURL + (!overHTTP && sm2.altURL ? ' (alternate URL)' : ''), 1);
     5628
     5629    // sm2._wD(sm + ': Trying to load ' + movieURL + (!overHTTP && sm2.altURL ? ' (alternate URL)' : ''), 1);
    53395630
    53405631    return true;
     
    53505641
    53515642    // attempt to get, or create, movie (may already exist)
    5352     if (flash) {
    5353       return false;
    5354     }
     5643    if (flash) return false;
    53555644
    53565645    if (!sm2.url) {
     
    53715660
    53725661    if (!flash) {
     5662
    53735663      if (!oRemoved) {
     5664
    53745665        // try to create
    53755666        createMovie(sm2.id, sm2.url);
     5667
    53765668      } else {
     5669
    53775670        // try to re-append removed movie after reboot()
    53785671        if (!isIE) {
     
    53815674          sm2.oMC.innerHTML = oRemovedHTML;
    53825675        }
     5676
    53835677        oRemoved = null;
    53845678        didAppend = true;
    5385       }
     5679
     5680      }
     5681
    53865682      flash = sm2.getMovie(sm2.id);
     5683
    53875684    }
    53885685
     
    54055702  };
    54065703
     5704  rebootIntoHTML5 = function() {
     5705
     5706    // special case: try for a reboot with preferFlash: false, if 100% HTML5 mode is possible and useFlashBlock is not enabled.
     5707
     5708    window.setTimeout(function() {
     5709
     5710      complain(smc + 'useFlashBlock is false, 100% HTML5 mode is possible. Rebooting with preferFlash: false...');
     5711
     5712      sm2.setup({
     5713        preferFlash: false
     5714      }).reboot();
     5715
     5716      // if for some reason you want to detect this case, use an ontimeout() callback and look for html5Only and didFlashBlock == true.
     5717      sm2.didFlashBlock = true;
     5718
     5719      sm2.beginDelayedInit();
     5720
     5721    }, 1);
     5722
     5723  };
     5724
    54075725  waitForEI = function() {
    54085726
     
    54125730    if (!sm2.url) {
    54135731      // No SWF url to load (noURL case) - exit for now. Will be retried when url is set.
    5414       return false;
     5732      return;
    54155733    }
    54165734
    54175735    if (waitingForEI) {
    5418       return false;
     5736      return;
    54195737    }
    54205738
     
    54225740    event.remove(window, 'load', delayWaitForEI);
    54235741
    5424     if (tryInitOnFocus && !isFocused) {
     5742    if (hasFlash && tryInitOnFocus && !isFocused) {
    54255743      // Safari won't load flash in background tabs, only when focused.
    54265744      _wDS('waitFocus');
    5427       return false;
     5745      return;
    54285746    }
    54295747
     
    54445762        sm2._wD(str('waitSWF'));
    54455763        window.setTimeout(delayWaitForEI, 1);
    5446         return false;
     5764        return;
    54475765      }
    54485766
    54495767      // <d>
    54505768      if (!didInit) {
    5451         sm2._wD(sm + ': No Flash response within expected time. Likely causes: ' + (p === 0 ? 'SWF load failed, ':'') + 'Flash blocked or JS-Flash security error.' + (sm2.debugFlash?' ' + str('checkSWF'):''), 2);
     5769
     5770        sm2._wD(sm + ': No Flash response within expected time. Likely causes: ' + (p === 0 ? 'SWF load failed, ' : '') + 'Flash blocked or JS-Flash security error.' + (sm2.debugFlash ? ' ' + str('checkSWF') : ''), 2);
     5771
    54525772        if (!overHTTP && p) {
     5773
    54535774          _wDS('localFail', 2);
     5775
    54545776          if (!sm2.debugFlash) {
    54555777            _wDS('tryDebug', 2);
    54565778          }
    5457         }
     5779
     5780        }
     5781
    54585782        if (p === 0) {
     5783
    54595784          // if 0 (not null), probably a 404.
    54605785          sm2._wD(str('swf404', sm2.url), 1);
    5461         }
    5462         debugTS('flashtojs', false, ': Timed out' + overHTTP?' (Check flash security or flash blockers)':' (No plugin/missing SWF?)');
     5786
     5787        }
     5788
     5789        debugTS('flashtojs', false, ': Timed out' + (overHTTP ? ' (Check flash security or flash blockers)' : ' (No plugin/missing SWF?)'));
     5790
    54635791      }
    54645792      // </d>
     
    54705798        if (p === null) {
    54715799
    5472           // SWF failed. Maybe blocked.
     5800          // SWF failed to report load progress. Possibly blocked.
    54735801
    54745802          if (sm2.useFlashBlock || sm2.flashLoadTimeout === 0) {
     
    54825810            _wDS('waitForever');
    54835811
     5812          } else if (!sm2.useFlashBlock && canIgnoreFlash) {
     5813
     5814            // no custom flash block handling, but SWF has timed out. Will recover if user unblocks / allows SWF load.
     5815            rebootIntoHTML5();
     5816
    54845817          } else {
    54855818
    5486             // no custom flash block handling, but SWF has timed out. Will recover if user unblocks / allows SWF load.
    5487 
    5488             if (!sm2.useFlashBlock && canIgnoreFlash) {
    5489 
    5490               // special case: try for a reboot with preferFlash: false, if 100% HTML5 mode is possible and useFlashBlock is not enabled.
    5491 
    5492               window.setTimeout(function() {
    5493 
    5494                 complain(smc + 'useFlashBlock is false, 100% HTML5 mode is possible. Rebooting with preferFlash: false...');
    5495 
    5496                 sm2.setup({
    5497                   preferFlash: false
    5498                 }).reboot();
    5499 
    5500                 // if for some reason you want to detect this case, use an ontimeout() callback and look for html5Only and didFlashBlock == true.
    5501                 sm2.didFlashBlock = true;
    5502  
    5503                 sm2.beginDelayedInit();
    5504 
    5505               }, 1);
    5506 
    5507             } else {
    5508 
    5509               _wDS('waitForever');
    5510 
    5511               // fire any regular registered ontimeout() listeners.
    5512               processOnEvents({type:'ontimeout', ignoreInit: true});
    5513 
    5514             }
     5819            _wDS('waitForever');
     5820
     5821            // fire any regular registered ontimeout() listeners.
     5822            processOnEvents({
     5823              type: 'ontimeout',
     5824              ignoreInit: true,
     5825              error: {
     5826                type: 'INIT_FLASHBLOCK'
     5827              }
     5828            });
    55155829
    55165830          }
    55175831
     5832        } else if (sm2.flashLoadTimeout === 0) {
     5833
     5834          // SWF loaded? Shouldn't be a blocking issue, then.
     5835
     5836          _wDS('waitForever');
     5837
     5838        } else if (!sm2.useFlashBlock && canIgnoreFlash) {
     5839
     5840          rebootIntoHTML5();
     5841
    55185842        } else {
    55195843
    5520           // flash loaded? Shouldn't be a blocking issue, then.
    5521 
    5522           if (sm2.flashLoadTimeout === 0) {
    5523 
    5524             _wDS('waitForever');
    5525 
    5526           } else {
    5527 
    5528             failSafely(true);
    5529 
    5530           }
    5531 
    5532         }
     5844          failSafely(true);
     5845
     5846        }
     5847
    55335848      }
    55345849
     
    55895904      for (item in sm2.audioFormats) {
    55905905        if (sm2.audioFormats.hasOwnProperty(item)) {
    5591           tests.push(item + ' = ' + sm2.html5[item] + (!sm2.html5[item] && needsFlash && sm2.flash[item] ? ' (using flash)' : (sm2.preferFlash && sm2.flash[item] && needsFlash ? ' (preferring flash)': (!sm2.html5[item] ? ' (' + (sm2.audioFormats[item].required ? 'required, ':'') + 'and no flash support)' : ''))));
     5906          tests.push(item + ' = ' + sm2.html5[item] + (!sm2.html5[item] && needsFlash && sm2.flash[item] ? ' (using flash)' : (sm2.preferFlash && sm2.flash[item] && needsFlash ? ' (preferring flash)' : (!sm2.html5[item] ? ' (' + (sm2.audioFormats[item].required ? 'required, ' : '') + 'and no flash support)' : ''))));
    55925907        }
    55935908      }
     
    56015916  initComplete = function(bNoDisable) {
    56025917
    5603     if (didInit) {
    5604       return false;
    5605     }
     5918    if (didInit) return false;
    56065919
    56075920    if (sm2.html5Only) {
    56085921      // all good.
    5609       _wDS('sm2Loaded');
     5922      _wDS('sm2Loaded', 1);
    56105923      didInit = true;
    56115924      initUserOnload();
     
    56205933    if (!wasTimeout) {
    56215934      didInit = true;
    5622       if (disabled) {
    5623         error = {type: (!hasFlash && needsFlash ? 'NO_FLASH' : 'INIT_TIMEOUT')};
    5624       }
    5625     }
    5626 
    5627     sm2._wD('SoundManager 2 ' + (disabled ? 'failed to load' : 'loaded') + ' (' + (disabled ? 'Flash security/load error' : 'OK') + ')', disabled ? 2: 1);
     5935    }
     5936
     5937    error = {
     5938      type: (!hasFlash && needsFlash ? 'NO_FLASH' : 'INIT_TIMEOUT')
     5939    };
     5940
     5941    sm2._wD('SoundManager 2 ' + (disabled ? 'failed to load' : 'loaded') + ' (' + (disabled ? 'Flash security/load error' : 'OK') + ') ' + String.fromCharCode(disabled ? 10006 : 10003), disabled ? 2 : 1);
    56285942
    56295943    if (disabled || bNoDisable) {
     5944
    56305945      if (sm2.useFlashBlock && sm2.oMC) {
    5631