soundmanager2-rails 2.97.20130324 → 2.97.20130512

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,7 @@
8
8
  * Code provided under the BSD License:
9
9
  * http://schillmania.com/projects/soundmanager2/license.txt
10
10
  *
11
- * V2.97a.20130324 ("Mahalo" Edition)
11
+ * V2.97a.20130512
12
12
  */
13
13
 
14
14
  /*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio, opera */
@@ -74,7 +74,8 @@ function SoundManager(smURL, smID) {
74
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
75
  'html5Test': /^(probably|maybe)$/i, // HTML5 Audio() format support test. Use /^probably$/i; if you want to be more conservative.
76
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.
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.
78
79
 
79
80
  };
80
81
 
@@ -188,7 +189,7 @@ function SoundManager(smURL, smID) {
188
189
 
189
190
  // dynamic attributes
190
191
 
191
- this.versionNumber = 'V2.97a.20130324';
192
+ this.versionNumber = 'V2.97a.20130512';
192
193
  this.version = null;
193
194
  this.movieURL = null;
194
195
  this.altURL = null;
@@ -265,11 +266,11 @@ function SoundManager(smURL, smID) {
265
266
 
266
267
  var SMSound,
267
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 = [],
268
- 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,
269
- 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)),
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)),
270
271
  mobileHTML5 = (ua.match(/(mobile|pre\/|xoom)/i) || is_iDevice || isAndroid),
271
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
272
- 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,
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,
273
274
  emptyURL = 'about:blank', // safe URL to unload, or load nothing from (flash 8 + most HTML5 UAs)
274
275
  overHTTP = (doc.location?doc.location.protocol.match(/http/i):null),
275
276
  http = (!overHTTP ? 'http:/'+'/' : ''),
@@ -341,14 +342,18 @@ function SoundManager(smURL, smID) {
341
342
 
342
343
  // 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.
343
344
 
344
- if (noURL && didDCLoaded && options.url !== _undefined) {
345
- sm2.beginDelayedInit();
346
- }
345
+ if (options) {
346
+
347
+ if (noURL && didDCLoaded && options.url !== _undefined) {
348
+ sm2.beginDelayedInit();
349
+ }
350
+
351
+ // special case 2: If lazy-loading SM2 (DOMContentLoaded has already happened) and user calls setup() with url: parameter, try to init ASAP.
347
352
 
348
- // special case 2: If lazy-loading SM2 (DOMContentLoaded has already happened) and user calls setup() with url: parameter, try to init ASAP.
353
+ if (!didDCLoaded && options.url !== _undefined && doc.readyState === 'complete') {
354
+ setTimeout(domContentLoaded, 1);
355
+ }
349
356
 
350
- if (!didDCLoaded && options.url !== _undefined && doc.readyState === 'complete') {
351
- setTimeout(domContentLoaded, 1);
352
357
  }
353
358
 
354
359
  return sm2;
@@ -357,7 +362,7 @@ function SoundManager(smURL, smID) {
357
362
 
358
363
  this.ok = function() {
359
364
 
360
- return (needsFlash?(didInit && !disabled):(sm2.useHTML5Audio && sm2.hasHTML5));
365
+ return (needsFlash ? (didInit && !disabled) : (sm2.useHTML5Audio && sm2.hasHTML5));
361
366
 
362
367
  };
363
368
 
@@ -392,7 +397,7 @@ function SoundManager(smURL, smID) {
392
397
  }
393
398
 
394
399
  if (_url !== _undefined) {
395
- // function overloading in JS! :) ..assume simple createSound(id,url) use case
400
+ // function overloading in JS! :) ..assume simple createSound(id, url) use case
396
401
  oOptions = {
397
402
  'id': oOptions,
398
403
  'url': _url
@@ -404,12 +409,17 @@ function SoundManager(smURL, smID) {
404
409
 
405
410
  options.url = parseURL(options.url);
406
411
 
412
+ // generate an id, if needed.
413
+ if (options.id === undefined) {
414
+ options.id = sm2.setupOptions.idPrefix + (idCounter++);
415
+ }
416
+
407
417
  // <d>
408
418
  if (options.id.toString().charAt(0).match(/^[0-9]$/)) {
409
419
  sm2._wD(cs + str('badID', options.id), 2);
410
420
  }
411
421
 
412
- sm2._wD(cs + options.id + ' (' + options.url + ')', 1);
422
+ sm2._wD(cs + options.id + (options.url ? ' (' + options.url + ')' : ''), 1);
413
423
  // </d>
414
424
 
415
425
  if (idCheck(options.id, true)) {
@@ -434,10 +444,23 @@ function SoundManager(smURL, smID) {
434
444
 
435
445
  } else {
436
446
 
447
+ if (sm2.html5Only) {
448
+ sm2._wD(options.id + ': No HTML5 support for this sound, and no Flash. Exiting.');
449
+ return make();
450
+ }
451
+
452
+ // TODO: Move HTML5/flash checks into generic URL parsing/handling function.
453
+
454
+ if (sm2.html5.usingFlash && options.url && options.url.match(/data\:/i)) {
455
+ // data: URIs not supported by Flash, either.
456
+ sm2._wD(options.id + ': data: URIs not supported via Flash. Exiting.');
457
+ return make();
458
+ }
459
+
437
460
  if (fV > 8) {
438
461
  if (options.isMovieStar === null) {
439
462
  // attempt to detect MPEG-4 formats
440
- options.isMovieStar = !!(options.serverURL || (options.type ? options.type.match(netStreamMimeTypes) : false) || options.url.match(netStreamPattern));
463
+ options.isMovieStar = !!(options.serverURL || (options.type ? options.type.match(netStreamMimeTypes) : false) || (options.url && options.url.match(netStreamPattern)));
441
464
  }
442
465
  // <d>
443
466
  if (options.isMovieStar) {
@@ -603,30 +626,50 @@ function SoundManager(smURL, smID) {
603
626
 
604
627
  this.play = function(sID, oOptions) {
605
628
 
606
- var result = false;
629
+ var result = null,
630
+ // legacy function-overloading use case: play('mySound', '/path/to/some.mp3');
631
+ overloaded = (oOptions && !(oOptions instanceof Object));
607
632
 
608
633
  if (!didInit || !sm2.ok()) {
609
634
  complain(sm + '.play(): ' + str(!didInit?'notReady':'notOK'));
610
- return result;
635
+ return false;
611
636
  }
612
637
 
613
- if (!idCheck(sID)) {
614
- if (!(oOptions instanceof Object)) {
615
- // overloading use case: play('mySound','/path/to/some.mp3');
638
+ if (!idCheck(sID, overloaded)) {
639
+
640
+ if (!overloaded) {
641
+ // no sound found for the given ID. Bail.
642
+ return false;
643
+ }
644
+
645
+ if (overloaded) {
616
646
  oOptions = {
617
647
  url: oOptions
618
648
  };
619
649
  }
650
+
620
651
  if (oOptions && oOptions.url) {
621
- // overloading use case, create+play: .play('someID',{url:'/path/to.mp3'});
622
- sm2._wD(sm + '.play(): attempting to create "' + sID + '"', 1);
652
+ // overloading use case, create+play: .play('someID', {url:'/path/to.mp3'});
653
+ sm2._wD(sm + '.play(): Attempting to create "' + sID + '"', 1);
623
654
  oOptions.id = sID;
624
655
  result = sm2.createSound(oOptions).play();
625
656
  }
626
- return result;
657
+
658
+ } else if (overloaded) {
659
+
660
+ // existing sound object case
661
+ oOptions = {
662
+ url: oOptions
663
+ };
664
+
627
665
  }
628
666
 
629
- return sm2.sounds[sID].play(oOptions);
667
+ if (result === null) {
668
+ // default case
669
+ result = sm2.sounds[sID].play(oOptions);
670
+ }
671
+
672
+ return result;
630
673
 
631
674
  };
632
675
 
@@ -1025,14 +1068,14 @@ function SoundManager(smURL, smID) {
1025
1068
  this.getSoundById = function(sID, _suppressDebug) {
1026
1069
 
1027
1070
  if (!sID) {
1028
- throw new Error(sm + '.getSoundById(): sID is null/_undefined');
1071
+ return null;
1029
1072
  }
1030
1073
 
1031
1074
  var result = sm2.sounds[sID];
1032
1075
 
1033
1076
  // <d>
1034
1077
  if (!result && !_suppressDebug) {
1035
- sm2._wD('"' + sID + '" is an invalid sound ID.', 2);
1078
+ sm2._wD(sm + '.getSoundById(): Sound "' + sID + '" not found.', 2);
1036
1079
  }
1037
1080
  // </d>
1038
1081
 
@@ -1236,7 +1279,7 @@ function SoundManager(smURL, smID) {
1236
1279
 
1237
1280
  // <d>
1238
1281
  if (sm2.soundIDs.length) {
1239
- sm2._wD('Destroying ' + sm2.soundIDs.length + ' SMSound objects...');
1282
+ sm2._wD('Destroying ' + sm2.soundIDs.length + ' SMSound object' + (sm2.soundIDs.length !== 1 ? 's' : '') + '...');
1240
1283
  }
1241
1284
  // </d>
1242
1285
 
@@ -1246,7 +1289,7 @@ function SoundManager(smURL, smID) {
1246
1289
  sm2.sounds[sm2.soundIDs[i]].destruct();
1247
1290
  }
1248
1291
 
1249
- // trash ze flash
1292
+ // trash ze flash (remove from the DOM)
1250
1293
 
1251
1294
  if (flash) {
1252
1295
 
@@ -1258,8 +1301,6 @@ function SoundManager(smURL, smID) {
1258
1301
 
1259
1302
  oRemoved = flash.parentNode.removeChild(flash);
1260
1303
 
1261
- _wDS('flRemoved');
1262
-
1263
1304
  } catch(e) {
1264
1305
 
1265
1306
  // Remove failed? May be due to flash blockers silently removing the SWF object/embed node from the DOM. Warn and continue.
@@ -1279,6 +1320,8 @@ function SoundManager(smURL, smID) {
1279
1320
  sm2.soundIDs = [];
1280
1321
  sm2.sounds = {};
1281
1322
 
1323
+ idCounter = 0;
1324
+
1282
1325
  if (!resetEvents) {
1283
1326
  // reset callbacks for onready, ontimeout etc. so that they will fire again on re-init
1284
1327
  for (i in on_queue) {
@@ -1409,7 +1452,7 @@ function SoundManager(smURL, smID) {
1409
1452
 
1410
1453
  SMSound = function(oOptions) {
1411
1454
 
1412
- var s = this, resetProperties, add_html5_events, remove_html5_events, stop_html5_timer, start_html5_timer, attachOnPosition, onplay_called = false, onPositionItems = [], onPositionFired = 0, detachOnPosition, applyFromTo, lastURL = null, lastHTML5State;
1455
+ var s = this, resetProperties, add_html5_events, remove_html5_events, stop_html5_timer, start_html5_timer, attachOnPosition, onplay_called = false, onPositionItems = [], onPositionFired = 0, detachOnPosition, applyFromTo, lastURL = null, lastHTML5State, urlOmitted;
1413
1456
 
1414
1457
  lastHTML5State = {
1415
1458
  // tracks duration + position (time)
@@ -1441,6 +1484,9 @@ function SoundManager(smURL, smID) {
1441
1484
  // internal HTML5 Audio() object reference
1442
1485
  this._a = null;
1443
1486
 
1487
+ // for flash 8 special-case createSound() without url, followed by load/play with url case
1488
+ urlOmitted = (this.url ? false : true);
1489
+
1444
1490
  /**
1445
1491
  * SMSound() public methods
1446
1492
  * ------------------------
@@ -1497,6 +1543,18 @@ function SoundManager(smURL, smID) {
1497
1543
 
1498
1544
  sm2._wD(s.id + ': load (' + instanceOptions.url + ')');
1499
1545
 
1546
+ if (!instanceOptions.url && !s.url) {
1547
+ sm2._wD(s.id + ': load(): url is unassigned. Exiting.', 2);
1548
+ return s;
1549
+ }
1550
+
1551
+ // <d>
1552
+ if (!s.isHTML5 && fV === 8 && !s.url && !instanceOptions.autoPlay) {
1553
+ // flash 8 load() -> play() won't work before onload has fired.
1554
+ sm2._wD(s.id + ': Flash 8 load() limitation: Wait for onload() before calling play().', 1);
1555
+ }
1556
+ // </d>
1557
+
1500
1558
  if (instanceOptions.url === s.url && s.readyState !== 0 && s.readyState !== 2) {
1501
1559
  _wDS('onURL', 1);
1502
1560
  // if loaded and an onload() exists, fire immediately.
@@ -1548,7 +1606,8 @@ function SoundManager(smURL, smID) {
1548
1606
  // early HTML5 implementation (non-standard)
1549
1607
  s._a.autobuffer = 'auto';
1550
1608
 
1551
- // standard
1609
+ // standard property, values: none / metadata / auto
1610
+ // reference: http://msdn.microsoft.com/en-us/library/ie/ff974759%28v=vs.85%29.aspx
1552
1611
  s._a.preload = 'auto';
1553
1612
 
1554
1613
  s._a._called_load = true;
@@ -1565,6 +1624,17 @@ function SoundManager(smURL, smID) {
1565
1624
 
1566
1625
  } else {
1567
1626
 
1627
+ if (sm2.html5Only) {
1628
+ sm2._wD(s.id + ': No flash support. Exiting.');
1629
+ return s;
1630
+ }
1631
+
1632
+ if (s._iO.url && s._iO.url.match(/data\:/i)) {
1633
+ // data: URIs not supported by Flash, either.
1634
+ sm2._wD(s.id + ': data: URIs not supported via Flash. Exiting.');
1635
+ return s;
1636
+ }
1637
+
1568
1638
  try {
1569
1639
  s.isHTML5 = false;
1570
1640
  s._iO = policyFix(loopFix(instanceOptions));
@@ -1621,10 +1691,9 @@ function SoundManager(smURL, smID) {
1621
1691
  if (s._a) {
1622
1692
 
1623
1693
  s._a.pause();
1624
- html5Unload(s._a, emptyURL);
1625
1694
 
1626
1695
  // update empty URL, too
1627
- lastURL = emptyURL;
1696
+ lastURL = html5Unload(s._a);
1628
1697
 
1629
1698
  }
1630
1699
 
@@ -1674,7 +1743,6 @@ function SoundManager(smURL, smID) {
1674
1743
  if (!_bFromSM) {
1675
1744
  // ensure deletion from controller
1676
1745
  sm2.destroySound(s.id, true);
1677
-
1678
1746
  }
1679
1747
 
1680
1748
  };
@@ -1688,7 +1756,9 @@ function SoundManager(smURL, smID) {
1688
1756
 
1689
1757
  this.play = function(oOptions, _updatePlayState) {
1690
1758
 
1691
- var fN, allowMulti, a, onready, startOK = true,
1759
+ var fN, allowMulti, a, onready,
1760
+ audioClone, onended, oncanplay,
1761
+ startOK = true,
1692
1762
  exit = null;
1693
1763
 
1694
1764
  // <d>
@@ -1718,7 +1788,7 @@ function SoundManager(smURL, smID) {
1718
1788
  s.instanceOptions = s._iO;
1719
1789
 
1720
1790
  // RTMP-only
1721
- if (s._iO.serverURL && !s.connected) {
1791
+ if (!s.isHTML5 && s._iO.serverURL && !s.connected) {
1722
1792
  if (!s.getAutoPlay()) {
1723
1793
  sm2._wD(fN +' Netstream not connected yet - setting autoPlay');
1724
1794
  s.setAutoPlay(true);
@@ -1736,6 +1806,10 @@ function SoundManager(smURL, smID) {
1736
1806
  allowMulti = s._iO.multiShot;
1737
1807
  if (!allowMulti) {
1738
1808
  sm2._wD(fN + 'Already playing (one-shot)', 1);
1809
+ if (s.isHTML5) {
1810
+ // go back to original position.
1811
+ s.setPosition(s._iO.position);
1812
+ }
1739
1813
  exit = s;
1740
1814
  } else {
1741
1815
  sm2._wD(fN + 'Already playing (multi-shot)', 1);
@@ -1748,8 +1822,19 @@ function SoundManager(smURL, smID) {
1748
1822
 
1749
1823
  // edge case: play() with explicit URL parameter
1750
1824
  if (oOptions.url && oOptions.url !== s.url) {
1751
- // load using merged options
1752
- s.load(s._iO);
1825
+
1826
+ // special case for createSound() followed by load() / play() with url; avoid double-load case.
1827
+ if (!s.readyState && !s.isHTML5 && fV === 8 && urlOmitted) {
1828
+
1829
+ urlOmitted = false;
1830
+
1831
+ } else {
1832
+
1833
+ // load using merged options
1834
+ s.load(s._iO);
1835
+
1836
+ }
1837
+
1753
1838
  }
1754
1839
 
1755
1840
  if (!s.loaded) {
@@ -1759,13 +1844,22 @@ function SoundManager(smURL, smID) {
1759
1844
  sm2._wD(fN + 'Attempting to load');
1760
1845
 
1761
1846
  // try to get this sound playing ASAP
1762
- if (!s.isHTML5) {
1763
- // assign directly because setAutoPlay() increments the instanceCount
1847
+ if (!s.isHTML5 && !sm2.html5Only) {
1848
+
1849
+ // flash: assign directly because setAutoPlay() increments the instanceCount
1764
1850
  s._iO.autoPlay = true;
1765
1851
  s.load(s._iO);
1766
- } else {
1852
+
1853
+ } else if (s.isHTML5) {
1854
+
1767
1855
  // iOS needs this when recycling sounds, loading a new URL on an existing object.
1768
1856
  s.load(s._iO);
1857
+
1858
+ } else {
1859
+
1860
+ sm2._wD(fN + 'Unsupported type. Exiting.');
1861
+ exit = s;
1862
+
1769
1863
  }
1770
1864
 
1771
1865
  // HTML5 hack - re-set instanceOptions?
@@ -1865,9 +1959,10 @@ function SoundManager(smURL, smID) {
1865
1959
 
1866
1960
  }
1867
1961
 
1868
- sm2._wD(fN + 'Starting to play');
1962
+ // sm2._wD(fN + 'Starting to play');
1869
1963
 
1870
- if (!s.instanceCount || s._iO.multiShotEvents || (!s.isHTML5 && fV > 8 && !s.getAutoPlay())) {
1964
+ // increment instance counter, where enabled + supported
1965
+ if (!s.instanceCount || s._iO.multiShotEvents || (s.isHTML5 && s._iO.multiShot && !useGlobalHTML5Audio) || (!s.isHTML5 && fV > 8 && !s.getAutoPlay())) {
1871
1966
  s.instanceCount++;
1872
1967
  }
1873
1968
 
@@ -1895,13 +1990,13 @@ function SoundManager(smURL, smID) {
1895
1990
 
1896
1991
  if (!s.isHTML5) {
1897
1992
 
1898
- startOK = flash._start(s.id, s._iO.loops || 1, (fV === 9 ? s.position : s.position / 1000), s._iO.multiShot || false);
1993
+ startOK = flash._start(s.id, s._iO.loops || 1, (fV === 9 ? s.position : s.position / msecScale), s._iO.multiShot || false);
1899
1994
 
1900
1995
  if (fV === 9 && !startOK) {
1901
1996
  // edge case: no sound hardware, or 32-channel flash ceiling hit.
1902
1997
  // applies only to Flash 9, non-NetStream/MovieStar sounds.
1903
1998
  // http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#play%28%29
1904
- sm2._wD(fN + 'No sound hardware, or 32-sound ceiling hit');
1999
+ sm2._wD(fN + 'No sound hardware, or 32-sound ceiling hit', 2);
1905
2000
  if (s._iO.onplayerror) {
1906
2001
  s._iO.onplayerror.apply(s);
1907
2002
  }
@@ -1910,13 +2005,56 @@ function SoundManager(smURL, smID) {
1910
2005
 
1911
2006
  } else {
1912
2007
 
1913
- start_html5_timer();
2008
+ if (s.instanceCount < 2) {
1914
2009
 
1915
- a = s._setup_html5();
2010
+ // HTML5 single-instance case
1916
2011
 
1917
- s.setPosition(s._iO.position);
2012
+ start_html5_timer();
2013
+
2014
+ a = s._setup_html5();
2015
+
2016
+ s.setPosition(s._iO.position);
2017
+
2018
+ a.play();
2019
+
2020
+ } else {
1918
2021
 
1919
- a.play();
2022
+ // HTML5 multi-shot case
2023
+
2024
+ sm2._wD(s.id + ': Cloning Audio() for instance #' + s.instanceCount + '...');
2025
+
2026
+ audioClone = new Audio(s._iO.url);
2027
+
2028
+ onended = function() {
2029
+ event.remove(audioClone, 'onended', onended);
2030
+ s._onfinish(s);
2031
+ // cleanup
2032
+ html5Unload(audioClone);
2033
+ audioClone = null;
2034
+ };
2035
+
2036
+ oncanplay = function() {
2037
+ event.remove(audioClone, 'canplay', oncanplay);
2038
+ try {
2039
+ audioClone.currentTime = s._iO.position/msecScale;
2040
+ } catch(err) {
2041
+ complain(s.id + ': multiShot play() failed to apply position of ' + (s._iO.position/msecScale));
2042
+ }
2043
+ audioClone.play();
2044
+ };
2045
+
2046
+ event.add(audioClone, 'ended', onended);
2047
+
2048
+ if (s._iO.position) {
2049
+ // HTML5 audio can't seek before onplay() event has fired.
2050
+ // wait for canplay, then seek to position and start playback.
2051
+ event.add(audioClone, 'canplay', oncanplay);
2052
+ } else {
2053
+ // begin playback at currentTime: 0
2054
+ audioClone.play();
2055
+ }
2056
+
2057
+ }
1920
2058
 
1921
2059
  }
1922
2060
 
@@ -2059,21 +2197,20 @@ function SoundManager(smURL, smID) {
2059
2197
  nMsecOffset = 0;
2060
2198
  }
2061
2199
 
2062
- var original_pos,
2063
- position, position1K,
2200
+ var position, position1K,
2064
2201
  // Use the duration from the instance options, if we don't have a track duration yet.
2065
2202
  // position >= 0 and <= current available (loaded) duration
2066
2203
  offset = (s.isHTML5 ? Math.max(nMsecOffset, 0) : Math.min(s.duration || s._iO.duration, Math.max(nMsecOffset, 0)));
2067
2204
 
2068
- original_pos = s.position;
2069
2205
  s.position = offset;
2070
- position1K = s.position/1000;
2206
+ position1K = s.position/msecScale;
2071
2207
  s._resetOnPosition(s.position);
2072
2208
  s._iO.position = offset;
2073
2209
 
2074
2210
  if (!s.isHTML5) {
2075
2211
 
2076
2212
  position = (fV === 9 ? s.position : position1K);
2213
+
2077
2214
  if (s.readyState && s.readyState !== 2) {
2078
2215
  // if paused or not playing, will not resume (by playing)
2079
2216
  flash._setPosition(s.id, position, (s.paused || !s.playState), s._iO.multiShot);
@@ -2083,13 +2220,16 @@ function SoundManager(smURL, smID) {
2083
2220
 
2084
2221
  // Set the position in the canplay handler if the sound is not ready yet
2085
2222
  if (s._html5_canplay) {
2223
+
2086
2224
  if (s._a.currentTime !== position1K) {
2225
+
2087
2226
  /**
2088
2227
  * DOM/JS errors/exceptions to watch out for:
2089
2228
  * if seek is beyond (loaded?) position, "DOM exception 11"
2090
2229
  * "INDEX_SIZE_ERR": DOM exception 1
2091
2230
  */
2092
2231
  sm2._wD(s.id + ': setPosition('+position1K+')');
2232
+
2093
2233
  try {
2094
2234
  s._a.currentTime = position1K;
2095
2235
  if (s.playState === 0 || s.paused) {
@@ -2099,19 +2239,25 @@ function SoundManager(smURL, smID) {
2099
2239
  } catch(e) {
2100
2240
  sm2._wD(s.id + ': setPosition(' + position1K + ') failed: ' + e.message, 2);
2101
2241
  }
2242
+
2102
2243
  }
2103
- } else {
2104
- sm2._wD(s.id + ': setPosition(' + position1K + '): Cannot seek yet, sound not ready');
2105
- }
2106
2244
 
2107
- }
2245
+ } else if (position1K) {
2246
+
2247
+ // warn on non-zero seek attempts
2248
+ sm2._wD(s.id + ': setPosition(' + position1K + '): Cannot seek yet, sound not ready', 2);
2249
+ return s;
2250
+
2251
+ }
2108
2252
 
2109
- if (s.isHTML5) {
2110
2253
  if (s.paused) {
2254
+
2111
2255
  // if paused, refresh UI right away
2112
2256
  // force update
2113
2257
  s._onTimer(true);
2258
+
2114
2259
  }
2260
+
2115
2261
  }
2116
2262
 
2117
2263
  return s;
@@ -2211,7 +2357,7 @@ function SoundManager(smURL, smID) {
2211
2357
 
2212
2358
  if (s.playState === 0) {
2213
2359
  s.play({
2214
- position: (fV === 9 && !s.isHTML5 ? s.position : s.position / 1000)
2360
+ position: (fV === 9 && !s.isHTML5 ? s.position : s.position / msecScale)
2215
2361
  });
2216
2362
  return s;
2217
2363
  }
@@ -2655,7 +2801,7 @@ function SoundManager(smURL, smID) {
2655
2801
  // TODO: investigate why this goes wack if not set/re-set each time.
2656
2802
  s.durationEstimate = s.duration;
2657
2803
 
2658
- time = (s._a.currentTime * 1000 || 0);
2804
+ time = (s._a.currentTime * msecScale || 0);
2659
2805
 
2660
2806
  if (time !== lastHTML5State.time) {
2661
2807
 
@@ -2688,7 +2834,7 @@ function SoundManager(smURL, smID) {
2688
2834
 
2689
2835
  var instanceOptions = s._iO,
2690
2836
  // if audio object exists, use its duration - else, instance option duration (if provided - it's a hack, really, and should be retired) OR null
2691
- d = (s._a && s._a.duration ? s._a.duration*1000 : (instanceOptions && instanceOptions.duration ? instanceOptions.duration : null)),
2837
+ d = (s._a && s._a.duration ? s._a.duration*msecScale : (instanceOptions && instanceOptions.duration ? instanceOptions.duration : null)),
2692
2838
  result = (d && !isNaN(d) && d !== Infinity ? d : null);
2693
2839
 
2694
2840
  return result;
@@ -2897,7 +3043,7 @@ function SoundManager(smURL, smID) {
2897
3043
 
2898
3044
  // <d>
2899
3045
  fN = s.id + ': ';
2900
- sm2._wD(fN + (loadOK ? 'onload()' : 'Failed to load? - ' + s.url), (loadOK ? 1 : 2));
3046
+ sm2._wD(fN + (loadOK ? 'onload()' : 'Failed to load / invalid sound?' + (!s.duration ? ' Zero-length duration reported.' : ' -') + ' (' + s.url + ')'), (loadOK ? 1 : 2));
2901
3047
  if (!loadOK && !s.isHTML5) {
2902
3048
  if (sm2.sandbox.noRemote === true) {
2903
3049
  sm2._wD(fN + str('noNet'), 1);
@@ -3591,7 +3737,7 @@ function SoundManager(smURL, smID) {
3591
3737
  s._onbufferchange(0);
3592
3738
 
3593
3739
  // position according to instance options
3594
- position1K = (s._iO.position !== _undefined && !isNaN(s._iO.position)?s._iO.position/1000:null);
3740
+ position1K = (s._iO.position !== _undefined && !isNaN(s._iO.position)?s._iO.position/msecScale:null);
3595
3741
 
3596
3742
  // set the position if position was set before the sound loaded
3597
3743
  if (s.position && this.currentTime !== position1K) {
@@ -3644,6 +3790,14 @@ function SoundManager(smURL, smID) {
3644
3790
  error: html5_event(function() {
3645
3791
 
3646
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
+ */
3647
3801
  // call load with error state?
3648
3802
  this._s._onload(false);
3649
3803
 
@@ -3678,7 +3832,7 @@ function SoundManager(smURL, smID) {
3678
3832
 
3679
3833
  play: html5_event(function() {
3680
3834
 
3681
- sm2._wD(this._s.id + ': play()');
3835
+ // sm2._wD(this._s.id + ': play()');
3682
3836
  // once play starts, no buffering
3683
3837
  this._s._onbufferchange(0);
3684
3838
 
@@ -3702,9 +3856,7 @@ function SoundManager(smURL, smID) {
3702
3856
  ranges = e.target.buffered,
3703
3857
  // firefox 3.6 implements e.loaded/total (bytes)
3704
3858
  loaded = (e.loaded||0),
3705
- total = (e.total||1),
3706
- // HTML5 returns msec. SM2 API uses seconds for setPosition() etc., whether Flash or HTML5.
3707
- scale = 1000;
3859
+ total = (e.total||1);
3708
3860
 
3709
3861
  // reset the "buffered" (loaded byte ranges) array
3710
3862
  s.buffered = [];
@@ -3715,25 +3867,26 @@ function SoundManager(smURL, smID) {
3715
3867
  // https://developer.mozilla.org/en/DOM/TimeRanges
3716
3868
 
3717
3869
  // re-build "buffered" array
3870
+ // HTML5 returns seconds. SM2 API uses msec for setPosition() etc., whether Flash or HTML5.
3718
3871
  for (i=0, j=ranges.length; i<j; i++) {
3719
3872
  s.buffered.push({
3720
- 'start': ranges.start(i) * scale,
3721
- 'end': ranges.end(i) * scale
3873
+ 'start': ranges.start(i) * msecScale,
3874
+ 'end': ranges.end(i) * msecScale
3722
3875
  });
3723
3876
  }
3724
3877
 
3725
3878
  // use the last value locally
3726
- buffered = (ranges.end(0) - ranges.start(0)) * scale;
3879
+ buffered = (ranges.end(0) - ranges.start(0)) * msecScale;
3727
3880
 
3728
3881
  // linear case, buffer sum; does not account for seeking and HTTP partials / byte ranges
3729
- loaded = buffered/(e.target.duration*scale);
3882
+ loaded = Math.min(1, buffered/(e.target.duration*msecScale));
3730
3883
 
3731
3884
  // <d>
3732
3885
  if (isProgress && ranges.length > 1) {
3733
3886
  str = [];
3734
3887
  j = ranges.length;
3735
3888
  for (i=0; i<j; i++) {
3736
- str.push(e.target.buffered.start(i)*scale +'-'+ e.target.buffered.end(i)*scale);
3889
+ str.push(e.target.buffered.start(i)*msecScale +'-'+ e.target.buffered.end(i)*msecScale);
3737
3890
  }
3738
3891
  sm2._wD(this._s.id + ': progress, timeRanges: ' + str.join(', '));
3739
3892
  }
@@ -3809,15 +3962,20 @@ function SoundManager(smURL, smID) {
3809
3962
 
3810
3963
  var result;
3811
3964
 
3812
- if (iO.serverURL || (iO.type && preferFlashCheck(iO.type))) {
3965
+ if (!iO || (!iO.type && !iO.url && !iO.serverURL)) {
3966
+
3967
+ // nothing to check
3968
+ result = false;
3969
+
3970
+ } else if (iO.serverURL || (iO.type && preferFlashCheck(iO.type))) {
3813
3971
 
3814
3972
  // RTMP, or preferring flash
3815
3973
  result = false;
3816
3974
 
3817
3975
  } else {
3818
3976
 
3819
- // Use type, if specified. If HTML5-only mode, no other options, so just give 'er
3820
- result = ((iO.type ? html5CanPlay({type:iO.type}) : html5CanPlay({url:iO.url}) || sm2.html5Only));
3977
+ // 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)));
3821
3979
 
3822
3980
  }
3823
3981
 
@@ -3825,7 +3983,7 @@ function SoundManager(smURL, smID) {
3825
3983
 
3826
3984
  };
3827
3985
 
3828
- html5Unload = function(oAudio, url) {
3986
+ html5Unload = function(oAudio) {
3829
3987
 
3830
3988
  /**
3831
3989
  * Internal method: Unload media, and cancel any current/pending network requests.
@@ -3835,13 +3993,19 @@ function SoundManager(smURL, smID) {
3835
3993
  * Other UA behaviour is unclear, so everyone else gets an about:blank-style URL.
3836
3994
  */
3837
3995
 
3996
+ var url;
3997
+
3838
3998
  if (oAudio) {
3839
3999
 
3840
- // Firefox likes '' for unload (used to work?) - however, may request hosting page URL (bad.) Most other UAs dislike '' and fail to unload.
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));
4002
+
3841
4003
  oAudio.src = url;
3842
4004
 
3843
4005
  // reset some state, too
3844
- oAudio._called_load = false;
4006
+ if (oAudio._called_unload !== undefined) {
4007
+ oAudio._called_load = false;
4008
+ }
3845
4009
 
3846
4010
  }
3847
4011
 
@@ -3852,6 +4016,8 @@ function SoundManager(smURL, smID) {
3852
4016
 
3853
4017
  }
3854
4018
 
4019
+ return url;
4020
+
3855
4021
  };
3856
4022
 
3857
4023
  html5CanPlay = function(o) {
@@ -3935,6 +4101,9 @@ function SoundManager(smURL, smID) {
3935
4101
  */
3936
4102
 
3937
4103
  if (!sm2.useHTML5Audio || !sm2.hasHTML5) {
4104
+ // without HTML5, we need Flash.
4105
+ sm2.html5.usingFlash = true;
4106
+ needsFlash = true;
3938
4107
  return false;
3939
4108
  }
3940
4109
 
@@ -4022,6 +4191,9 @@ function SoundManager(smURL, smID) {
4022
4191
  support.canPlayType = (a?cp:null);
4023
4192
  sm2.html5 = mixin(sm2.html5, support);
4024
4193
 
4194
+ sm2.html5.usingFlash = featureCheck();
4195
+ needsFlash = sm2.html5.usingFlash;
4196
+
4025
4197
  return true;
4026
4198
 
4027
4199
  };
@@ -4041,7 +4213,7 @@ function SoundManager(smURL, smID) {
4041
4213
  waitForever: smc + 'Waiting indefinitely for Flash (will recover if unblocked)...',
4042
4214
  waitSWF: smc + 'Waiting for 100% SWF load...',
4043
4215
  needFunction: smc + 'Function object expected for %s',
4044
- badID: 'Warning: Sound ID "%s" should be a string, starting with a non-numeric character',
4216
+ badID: 'Sound ID "%s" should be a string, starting with a non-numeric character',
4045
4217
  currentObj: smc + '_debug(): Current sound objects',
4046
4218
  waitOnload: smc + 'Waiting for window.onload()',
4047
4219
  docLoaded: smc + 'Document already loaded',
@@ -4055,7 +4227,6 @@ function SoundManager(smURL, smID) {
4055
4227
  smError: 'SMSound.load(): Exception: JS-Flash communication failed, or JS error.',
4056
4228
  fbTimeout: 'No flash response, applying .'+swfCSS.swfTimedout+' CSS...',
4057
4229
  fbLoaded: 'Flash loaded',
4058
- flRemoved: smc + 'Flash movie removed.',
4059
4230
  fbHandler: smc + 'flashBlockHandler()',
4060
4231
  manURL: 'SMSound.load(): Using manually-assigned URL',
4061
4232
  onURL: sm + '.load(): current URL already assigned.',
@@ -4130,7 +4301,7 @@ function SoundManager(smURL, smID) {
4130
4301
  complain = function(sMsg) {
4131
4302
 
4132
4303
  // <d>
4133
- if (console !== _undefined && console.warn !== _undefined) {
4304
+ if (hasConsole && console.warn !== _undefined) {
4134
4305
  console.warn(sMsg);
4135
4306
  } else {
4136
4307
  sm2._wD(sMsg);
@@ -4260,11 +4431,11 @@ function SoundManager(smURL, smID) {
4260
4431
  // starts debug mode, creating output <div> for UAs without console object
4261
4432
 
4262
4433
  // allow force of debug mode via URL
4434
+ // <d>
4263
4435
  if (sm2.debugURLParam.test(wl)) {
4264
4436
  sm2.debugMode = true;
4265
4437
  }
4266
4438
 
4267
- // <d>
4268
4439
  if (id(sm2.debugID)) {
4269
4440
  return false;
4270
4441
  }
@@ -4368,6 +4539,7 @@ function SoundManager(smURL, smID) {
4368
4539
  sm2Debugger.handleEvent(sEventType, bSuccess, sMessage);
4369
4540
  } catch(e) {
4370
4541
  // oh well
4542
+ return false;
4371
4543
  }
4372
4544
  }
4373
4545
 
@@ -4406,6 +4578,7 @@ function SoundManager(smURL, smID) {
4406
4578
  error = {type:'FLASHBLOCK'};
4407
4579
 
4408
4580
  if (sm2.html5Only) {
4581
+ // no flash, or unused
4409
4582
  return false;
4410
4583
  }
4411
4584
 
@@ -4564,6 +4737,7 @@ function SoundManager(smURL, smID) {
4564
4737
  obj = new AX('ShockwaveFlash.ShockwaveFlash');
4565
4738
  } catch(e) {
4566
4739
  // oh well
4740
+ obj = null;
4567
4741
  }
4568
4742
  hasPlugin = (!!obj);
4569
4743
  // cleanup, because it is ActiveX after all
@@ -4578,9 +4752,8 @@ function SoundManager(smURL, smID) {
4578
4752
 
4579
4753
  featureCheck = function() {
4580
4754
 
4581
- var needsFlash,
4755
+ var flashNeeded,
4582
4756
  item,
4583
- result = true,
4584
4757
  formats = sm2.audioFormats,
4585
4758
  // iPhone <= 3.1 has broken HTML5 audio(), but firmware 3.2 (original iPad) + iOS4 works.
4586
4759
  isSpecial = (is_iDevice && !!(ua.match(/os (1|2|3_0|3_1)/i)));
@@ -4593,12 +4766,11 @@ function SoundManager(smURL, smID) {
4593
4766
  // ignore flash case, however
4594
4767
  sm2.html5Only = true;
4595
4768
 
4769
+ // hide the SWF, if present
4596
4770
  if (sm2.oMC) {
4597
4771
  sm2.oMC.style.display = 'none';
4598
4772
  }
4599
4773
 
4600
- result = false;
4601
-
4602
4774
  } else {
4603
4775
 
4604
4776
  if (sm2.useHTML5Audio) {
@@ -4620,11 +4792,22 @@ function SoundManager(smURL, smID) {
4620
4792
 
4621
4793
  if (sm2.useHTML5Audio && sm2.hasHTML5) {
4622
4794
 
4795
+ // sort out whether flash is optional, required or can be ignored.
4796
+
4797
+ // innocent until proven guilty.
4798
+ canIgnoreFlash = true;
4799
+
4623
4800
  for (item in formats) {
4624
4801
  if (formats.hasOwnProperty(item)) {
4625
- if ((formats[item].required && !sm2.html5.canPlayType(formats[item].type)) || (sm2.preferFlash && (sm2.flash[item] || sm2.flash[formats[item].type]))) {
4626
- // flash may be required, or preferred for this format
4627
- needsFlash = true;
4802
+ if (formats[item].required) {
4803
+ if (!sm2.html5.canPlayType(formats[item].type)) {
4804
+ // 100% HTML5 mode is not possible.
4805
+ canIgnoreFlash = false;
4806
+ flashNeeded = true;
4807
+ } else if (sm2.preferFlash && (sm2.flash[item] || sm2.flash[formats[item].type])) {
4808
+ // flash may be required, or preferred for this format.
4809
+ flashNeeded = true;
4810
+ }
4628
4811
  }
4629
4812
  }
4630
4813
  }
@@ -4633,10 +4816,11 @@ function SoundManager(smURL, smID) {
4633
4816
 
4634
4817
  // sanity check...
4635
4818
  if (sm2.ignoreFlash) {
4636
- needsFlash = false;
4819
+ flashNeeded = false;
4820
+ canIgnoreFlash = true;
4637
4821
  }
4638
4822
 
4639
- sm2.html5Only = (sm2.hasHTML5 && sm2.useHTML5Audio && !needsFlash);
4823
+ sm2.html5Only = (sm2.hasHTML5 && sm2.useHTML5Audio && !flashNeeded);
4640
4824
 
4641
4825
  return (!sm2.html5Only);
4642
4826
 
@@ -4847,10 +5031,9 @@ function SoundManager(smURL, smID) {
4847
5031
 
4848
5032
  };
4849
5033
 
4850
- this._externalInterfaceOK = function(flashDate, swfVersion) {
5034
+ this._externalInterfaceOK = function(swfVersion) {
4851
5035
 
4852
5036
  // flash callback confirming flash loaded, EI working etc.
4853
- // flashDate = approx. timing/delay info for JS/flash bridge
4854
5037
  // swfVersion: SWF build string
4855
5038
 
4856
5039
  if (sm2.swfLoaded) {
@@ -4885,7 +5068,7 @@ function SoundManager(smURL, smID) {
4885
5068
  }
4886
5069
  // </d>
4887
5070
 
4888
- // slight delay before init
5071
+ // IE needs a larger timeout
4889
5072
  setTimeout(init, isIE ? 100 : 1);
4890
5073
 
4891
5074
  };
@@ -5283,26 +5466,69 @@ function SoundManager(smURL, smID) {
5283
5466
  // give up / time-out, depending
5284
5467
 
5285
5468
  if (!didInit && okToDisable) {
5469
+
5286
5470
  if (p === null) {
5471
+
5287
5472
  // SWF failed. Maybe blocked.
5473
+
5288
5474
  if (sm2.useFlashBlock || sm2.flashLoadTimeout === 0) {
5475
+
5289
5476
  if (sm2.useFlashBlock) {
5477
+
5290
5478
  flashBlockHandler();
5479
+
5291
5480
  }
5481
+
5292
5482
  _wDS('waitForever');
5483
+
5293
5484
  } else {
5485
+
5294
5486
  // no custom flash block handling, but SWF has timed out. Will recover if user unblocks / allows SWF load.
5295
- _wDS('waitForever');
5296
- // fire any regular registered ontimeout() listeners.
5297
- processOnEvents({type:'ontimeout', ignoreInit: true});
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
+ }
5515
+
5298
5516
  }
5517
+
5299
5518
  } else {
5519
+
5300
5520
  // flash loaded? Shouldn't be a blocking issue, then.
5521
+
5301
5522
  if (sm2.flashLoadTimeout === 0) {
5302
- _wDS('waitForever');
5523
+
5524
+ _wDS('waitForever');
5525
+
5303
5526
  } else {
5527
+
5304
5528
  failSafely(true);
5529
+
5305
5530
  }
5531
+
5306
5532
  }
5307
5533
  }
5308
5534
 
@@ -5362,7 +5588,7 @@ function SoundManager(smURL, smID) {
5362
5588
  if (sm2.useHTML5Audio && sm2.hasHTML5) {
5363
5589
  for (item in sm2.audioFormats) {
5364
5590
  if (sm2.audioFormats.hasOwnProperty(item)) {
5365
- tests.push(item + ' = ' + sm2.html5[item] + (!sm2.html5[item] && hasFlash && sm2.flash[item] ? ' (using flash)' : (sm2.preferFlash && sm2.flash[item] && hasFlash ? ' (preferring flash)': (!sm2.html5[item] ? ' (' + (sm2.audioFormats[item].required ? 'required, ':'') + 'and no flash support)' : ''))));
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)' : ''))));
5366
5592
  }
5367
5593
  }
5368
5594
  sm2._wD('SoundManager 2 HTML5 support: ' + tests.join(', '), 1);
@@ -5559,12 +5785,11 @@ function SoundManager(smURL, smID) {
5559
5785
  a2 = 'sm2-preferflash=',
5560
5786
  b = null,
5561
5787
  b2 = null,
5562
- hasCon = (window.console !== _undefined && typeof console.log === 'function'),
5563
5788
  l = wl.toLowerCase();
5564
5789
 
5565
5790
  if (l.indexOf(a) !== -1) {
5566
5791
  b = (l.charAt(l.indexOf(a)+a.length) === '1');
5567
- if (hasCon) {
5792
+ if (hasConsole) {
5568
5793
  console.log((b?'Enabling ':'Disabling ')+'useHTML5Audio via URL parameter');
5569
5794
  }
5570
5795
  sm2.setup({
@@ -5574,7 +5799,7 @@ function SoundManager(smURL, smID) {
5574
5799
 
5575
5800
  if (l.indexOf(a2) !== -1) {
5576
5801
  b2 = (l.charAt(l.indexOf(a2)+a2.length) === '1');
5577
- if (hasCon) {
5802
+ if (hasConsole) {
5578
5803
  console.log((b2?'Enabling ':'Disabling ')+'preferFlash via URL parameter');
5579
5804
  }
5580
5805
  sm2.setup({
@@ -5596,8 +5821,6 @@ function SoundManager(smURL, smID) {
5596
5821
  }
5597
5822
 
5598
5823
  testHTML5();
5599
- sm2.html5.usingFlash = featureCheck();
5600
- needsFlash = sm2.html5.usingFlash;
5601
5824
 
5602
5825
  if (!hasFlash && needsFlash) {
5603
5826
  messages.push(strings.needFlash);