soundmanager2-rails 2.97.20140901 → 2.97.20150601

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.20140901
11
+ * V2.97a.20150601
12
12
  */
13
13
 
14
14
  /*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio, opera, module, define */
@@ -80,7 +80,9 @@ function SoundManager(smURL, smID) {
80
80
  'wmode': null, // flash rendering mode - null, 'transparent', or 'opaque' (last two allow z-index to work)
81
81
  'allowScriptAccess': 'always', // for scripting the SWF (object/embed property), 'always' or 'sameDomain'
82
82
  'useFlashBlock': false, // *requires flashblock.css, see demos* - allow recovery from flash blockers. Wait indefinitely and apply timeout CSS to SWF, if applicable.
83
- 'useHTML5Audio': true, // use HTML5 Audio() where API is supported (most Safari, Chrome versions), Firefox (no MP3/MP4.) Ideally, transparent vs. Flash API where possible.
83
+ '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.
84
+ 'forceUseGlobalHTML5Audio': false, // if true, a single Audio() object is used for all sounds - and only one can play at a time.
85
+ 'ignoreMobileRestrictions': false, // if true, SM2 will not apply global HTML5 audio rules to mobile UAs. iOS > 7 and WebViews may allow multiple Audio() instances.
84
86
  'html5Test': /^(probably|maybe)$/i, // HTML5 Audio() format support test. Use /^probably$/i; if you want to be more conservative.
85
87
  'preferFlash': false, // overrides useHTML5audio, will use Flash for MP3/MP4/AAC if present. Potential option if HTML5 playback with these formats is quirky.
86
88
  'noSWFCache': false, // if true, appends ?ts={date} to break aggressive SWF caching.
@@ -198,7 +200,7 @@ function SoundManager(smURL, smID) {
198
200
 
199
201
  // dynamic attributes
200
202
 
201
- this.versionNumber = 'V2.97a.20140901';
203
+ this.versionNumber = 'V2.97a.20150601';
202
204
  this.version = null;
203
205
  this.movieURL = null;
204
206
  this.altURL = null;
@@ -212,28 +214,23 @@ function SoundManager(smURL, smID) {
212
214
  this.filePattern = null;
213
215
 
214
216
  this.filePatterns = {
215
-
216
217
  'flash8': /\.mp3(\?.*)?$/i,
217
218
  'flash9': /\.mp3(\?.*)?$/i
218
-
219
219
  };
220
220
 
221
221
  // support indicators, set at init
222
222
 
223
223
  this.features = {
224
-
225
224
  'buffering': false,
226
225
  'peakData': false,
227
226
  'waveformData': false,
228
227
  'eqData': false,
229
228
  'movieStar': false
230
-
231
229
  };
232
230
 
233
231
  // flash sandbox info, used primarily in troubleshooting
234
232
 
235
233
  this.sandbox = {
236
-
237
234
  // <d>
238
235
  'type': null,
239
236
  'types': {
@@ -246,7 +243,6 @@ function SoundManager(smURL, smID) {
246
243
  'noRemote': null,
247
244
  'noLocal': null
248
245
  // </d>
249
-
250
246
  };
251
247
 
252
248
  /**
@@ -274,15 +270,22 @@ function SoundManager(smURL, smID) {
274
270
  */
275
271
 
276
272
  var SMSound,
277
- 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, 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 = [],
278
- 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,
279
- 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)),
273
+ 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 = [],
274
+ 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, didSetup, msecScale = 1000,
275
+ is_iDevice = ua.match(/(ipad|iphone|ipod)/i), isAndroid = ua.match(/android/i), isIE = ua.match(/msie/i),
276
+ isWebkit = ua.match(/webkit/i),
277
+ isSafari = (ua.match(/safari/i) && !ua.match(/chrome/i)),
278
+ isOpera = (ua.match(/opera/i)),
280
279
  mobileHTML5 = (ua.match(/(mobile|pre\/|xoom)/i) || is_iDevice || isAndroid),
281
280
  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
282
- 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,
281
+ hasConsole = (window.console !== _undefined && console.log !== _undefined),
282
+ isFocused = (doc.hasFocus !== _undefined ? doc.hasFocus() : null),
283
+ tryInitOnFocus = (isSafari && (doc.hasFocus === _undefined || !doc.hasFocus())),
284
+ okToDisable = !tryInitOnFocus,
285
+ flashMIME = /(mp3|mp4|mpa|m4a|m4b)/i,
283
286
  emptyURL = 'about:blank', // safe URL to unload, or load nothing from (flash 8 + most HTML5 UAs)
284
287
  emptyWAV = 'data:audio/wave;base64,/UklGRiYAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQIAAAD//w==', // tiny WAV for HTML5 unloading
285
- overHTTP = (doc.location?doc.location.protocol.match(/http/i):null),
288
+ overHTTP = (doc.location ? doc.location.protocol.match(/http/i) : null),
286
289
  http = (!overHTTP ? 'http:/'+'/' : ''),
287
290
  // mp3, mp4, aac etc.
288
291
  netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,
@@ -296,7 +299,6 @@ function SoundManager(smURL, smID) {
296
299
  this.useAltURL = !overHTTP;
297
300
 
298
301
  swfCSS = {
299
-
300
302
  'swfBox': 'sm2-object-box',
301
303
  'swfDefault': 'movieContainer',
302
304
  'swfError': 'swf_error', // SWF loaded, but SM2 couldn't start (other error)
@@ -306,7 +308,6 @@ function SoundManager(smURL, smID) {
306
308
  'sm2Debug': 'sm2_debug',
307
309
  'highPerf': 'high_performance',
308
310
  'flashDebug': 'flash_debug'
309
-
310
311
  };
311
312
 
312
313
  /**
@@ -350,6 +351,73 @@ function SoundManager(smURL, smID) {
350
351
 
351
352
  assign(options);
352
353
 
354
+ if (!useGlobalHTML5Audio) {
355
+
356
+ if (mobileHTML5) {
357
+
358
+ // force the singleton HTML5 pattern on mobile, by default.
359
+ if (!sm2.setupOptions.ignoreMobileRestrictions || sm2.setupOptions.forceUseGlobalHTML5Audio) {
360
+ messages.push(strings.globalHTML5);
361
+ useGlobalHTML5Audio = true;
362
+ }
363
+
364
+ } else {
365
+
366
+ // only apply singleton HTML5 on desktop if forced.
367
+ if (sm2.setupOptions.forceUseGlobalHTML5Audio) {
368
+ messages.push(strings.globalHTML5);
369
+ useGlobalHTML5Audio = true;
370
+ }
371
+
372
+ }
373
+
374
+ }
375
+
376
+ if (!didSetup && mobileHTML5) {
377
+
378
+ if (sm2.setupOptions.ignoreMobileRestrictions) {
379
+
380
+ messages.push(strings.ignoreMobile);
381
+
382
+ } else {
383
+
384
+ // prefer HTML5 for mobile + tablet-like devices, probably more reliable vs. flash at this point.
385
+
386
+ // <d>
387
+ if (!sm2.setupOptions.useHTML5Audio || sm2.setupOptions.preferFlash) {
388
+ // notify that defaults are being changed.
389
+ sm2._wD(strings.mobileUA);
390
+ }
391
+ // </d>
392
+
393
+ sm2.setupOptions.useHTML5Audio = true;
394
+ sm2.setupOptions.preferFlash = false;
395
+
396
+ if (is_iDevice) {
397
+
398
+ // no flash here.
399
+ sm2.ignoreFlash = true;
400
+
401
+ } else if ((isAndroid && !ua.match(/android\s2\.3/i)) || !isAndroid) {
402
+
403
+ /**
404
+ * Android devices tend to work better with a single audio instance, specifically for chained playback of sounds in sequence.
405
+ * Common use case: exiting sound onfinish() -> createSound() -> play()
406
+ * Presuming similar restrictions for other mobile, non-Android, non-iOS devices.
407
+ */
408
+
409
+ // <d>
410
+ sm2._wD(strings.globalHTML5);
411
+ // </d>
412
+
413
+ useGlobalHTML5Audio = true;
414
+
415
+ }
416
+
417
+ }
418
+
419
+ }
420
+
353
421
  // 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.
354
422
 
355
423
  if (options) {
@@ -366,6 +434,8 @@ function SoundManager(smURL, smID) {
366
434
 
367
435
  }
368
436
 
437
+ didSetup = true;
438
+
369
439
  return sm2;
370
440
 
371
441
  };
@@ -386,9 +456,9 @@ function SoundManager(smURL, smID) {
386
456
  };
387
457
 
388
458
  /**
389
- * Creates a SMSound sound object instance.
459
+ * Creates a SMSound sound object instance. Can also be overloaded, e.g., createSound('mySound', '/some.mp3');
390
460
  *
391
- * @param {object} oOptions Sound options (at minimum, id and url parameters are required.)
461
+ * @param {object} oOptions Sound options (at minimum, url parameter is required.)
392
462
  * @return {object} SMSound The new SMSound object.
393
463
  */
394
464
 
@@ -398,7 +468,7 @@ function SoundManager(smURL, smID) {
398
468
 
399
469
  // <d>
400
470
  cs = sm + '.createSound(): ';
401
- cs_string = cs + str(!didInit?'notReady':'notOK');
471
+ cs_string = cs + str(!didInit ? 'notReady' : 'notOK');
402
472
  // </d>
403
473
 
404
474
  if (!didInit || !sm2.ok()) {
@@ -407,7 +477,7 @@ function SoundManager(smURL, smID) {
407
477
  }
408
478
 
409
479
  if (_url !== _undefined) {
410
- // function overloading in JS! :) ..assume simple createSound(id, url) use case
480
+ // function overloading in JS! :) ... assume simple createSound(id, url) use case.
411
481
  oOptions = {
412
482
  'id': oOptions,
413
483
  'url': _url
@@ -420,7 +490,7 @@ function SoundManager(smURL, smID) {
420
490
  options.url = parseURL(options.url);
421
491
 
422
492
  // generate an id, if needed.
423
- if (options.id === undefined) {
493
+ if (options.id === _undefined) {
424
494
  options.id = sm2.setupOptions.idPrefix + (idCounter++);
425
495
  }
426
496
 
@@ -449,7 +519,11 @@ function SoundManager(smURL, smID) {
449
519
  if (html5OK(options)) {
450
520
 
451
521
  oSound = make();
452
- sm2._wD(options.id + ': Using HTML5');
522
+ // <d>
523
+ if (!sm2.html5Only) {
524
+ sm2._wD(options.id + ': Using HTML5');
525
+ }
526
+ // </d>
453
527
  oSound._setup_html5(options);
454
528
 
455
529
  } else {
@@ -486,9 +560,9 @@ function SoundManager(smURL, smID) {
486
560
  oSound = make();
487
561
 
488
562
  if (fV === 8) {
489
- flash._createSound(options.id, options.loops||1, options.usePolicyFile);
563
+ flash._createSound(options.id, options.loops || 1, options.usePolicyFile);
490
564
  } else {
491
- 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);
565
+ 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);
492
566
  if (!options.serverURL) {
493
567
  // We are connected immediately
494
568
  oSound.connected = true;
@@ -530,10 +604,11 @@ function SoundManager(smURL, smID) {
530
604
 
531
605
  var oS = sm2.sounds[sID], i;
532
606
 
533
- // Disable all callbacks while the sound is being destroyed
534
- oS._iO = {};
535
-
536
607
  oS.stop();
608
+
609
+ // Disable all callbacks after stop(), when the sound is being destroyed
610
+ oS._iO = {};
611
+
537
612
  oS.unload();
538
613
 
539
614
  for (i = 0; i < sm2.soundIDs.length; i++) {
@@ -683,7 +758,8 @@ function SoundManager(smURL, smID) {
683
758
 
684
759
  };
685
760
 
686
- this.start = this.play; // just for convenience
761
+ // just for convenience
762
+ this.start = this.play;
687
763
 
688
764
  /**
689
765
  * Calls the setPosition() method of a SMSound object by ID.
@@ -761,7 +837,7 @@ function SoundManager(smURL, smID) {
761
837
  this.pauseAll = function() {
762
838
 
763
839
  var i;
764
- for (i = sm2.soundIDs.length-1; i >= 0; i--) {
840
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
765
841
  sm2.sounds[sm2.soundIDs[i]].pause();
766
842
  }
767
843
 
@@ -790,7 +866,7 @@ function SoundManager(smURL, smID) {
790
866
  this.resumeAll = function() {
791
867
 
792
868
  var i;
793
- for (i = sm2.soundIDs.length-1; i >= 0; i--) {
869
+ for (i = sm2.soundIDs.length- 1 ; i >= 0; i--) {
794
870
  sm2.sounds[sm2.soundIDs[i]].resume();
795
871
  }
796
872
 
@@ -830,7 +906,8 @@ function SoundManager(smURL, smID) {
830
906
  };
831
907
 
832
908
  /**
833
- * Calls the setVolume() method of a SMSound object by ID.
909
+ * Calls the setVolume() method of a SMSound object by ID
910
+ * Overloaded case: pass only volume argument eg., setVolume(50) to apply to all sounds.
834
911
  *
835
912
  * @param {string} sID The ID of the sound
836
913
  * @param {number} nVol The volume value (0 to 100)
@@ -839,9 +916,23 @@ function SoundManager(smURL, smID) {
839
916
 
840
917
  this.setVolume = function(sID, nVol) {
841
918
 
919
+ // setVolume(50) function overloading case - apply to all sounds
920
+
921
+ var i, j;
922
+
923
+ if (sID !== _undefined && !isNaN(sID) && nVol === _undefined) {
924
+ for (i = 0, j = sm2.soundIDs.length; i < j; i++) {
925
+ sm2.sounds[sm2.soundIDs[i]].setVolume(sID);
926
+ }
927
+ return;
928
+ }
929
+
930
+ // setVolume('mySound', 50) case
931
+
842
932
  if (!idCheck(sID)) {
843
933
  return false;
844
934
  }
935
+
845
936
  return sm2.sounds[sID].setVolume(nVol);
846
937
 
847
938
  };
@@ -863,7 +954,7 @@ function SoundManager(smURL, smID) {
863
954
  if (!sID) {
864
955
 
865
956
  sm2._wD(sm + '.mute(): Muting all sounds');
866
- for (i = sm2.soundIDs.length-1; i >= 0; i--) {
957
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
867
958
  sm2.sounds[sm2.soundIDs[i]].mute();
868
959
  }
869
960
  sm2.muted = true;
@@ -909,7 +1000,7 @@ function SoundManager(smURL, smID) {
909
1000
  if (!sID) {
910
1001
 
911
1002
  sm2._wD(sm + '.unmute(): Unmuting all sounds');
912
- for (i = sm2.soundIDs.length-1; i >= 0; i--) {
1003
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
913
1004
  sm2.sounds[sm2.soundIDs[i]].unmute();
914
1005
  }
915
1006
  sm2.muted = false;
@@ -993,7 +1084,7 @@ function SoundManager(smURL, smID) {
993
1084
  disabled = true;
994
1085
  _wDS('shutdown', 1);
995
1086
 
996
- for (i = sm2.soundIDs.length-1; i >= 0; i--) {
1087
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
997
1088
  disableObject(sm2.sounds[sm2.soundIDs[i]]);
998
1089
  }
999
1090
 
@@ -1014,7 +1105,9 @@ function SoundManager(smURL, smID) {
1014
1105
  var result;
1015
1106
 
1016
1107
  if (sm2.hasHTML5) {
1017
- result = html5CanPlay({type:sMIME});
1108
+ result = html5CanPlay({
1109
+ type: sMIME
1110
+ });
1018
1111
  }
1019
1112
 
1020
1113
  if (!result && needsFlash) {
@@ -1038,7 +1131,9 @@ function SoundManager(smURL, smID) {
1038
1131
  var result;
1039
1132
 
1040
1133
  if (sm2.hasHTML5) {
1041
- result = html5CanPlay({url: sURL});
1134
+ result = html5CanPlay({
1135
+ url: sURL
1136
+ });
1042
1137
  }
1043
1138
 
1044
1139
  if (!result && needsFlash) {
@@ -1186,7 +1281,7 @@ function SoundManager(smURL, smID) {
1186
1281
 
1187
1282
  var sDID = 'soundmanager-debug', o, oItem;
1188
1283
 
1189
- if (!sm2.debugMode) {
1284
+ if (!sm2.setupOptions.debugMode) {
1190
1285
  return false;
1191
1286
  }
1192
1287
 
@@ -1295,7 +1390,7 @@ function SoundManager(smURL, smID) {
1295
1390
 
1296
1391
  var i, j, k;
1297
1392
 
1298
- for (i = sm2.soundIDs.length-1; i >= 0; i--) {
1393
+ for (i = sm2.soundIDs.length- 1 ; i >= 0; i--) {
1299
1394
  sm2.sounds[sm2.soundIDs[i]].destruct();
1300
1395
  }
1301
1396
 
@@ -1331,6 +1426,7 @@ function SoundManager(smURL, smID) {
1331
1426
  sm2.sounds = {};
1332
1427
 
1333
1428
  idCounter = 0;
1429
+ didSetup = false;
1334
1430
 
1335
1431
  if (!resetEvents) {
1336
1432
  // reset callbacks for onready, ontimeout etc. so that they will fire again on re-init
@@ -1367,8 +1463,6 @@ function SoundManager(smURL, smID) {
1367
1463
 
1368
1464
  window.setTimeout(function() {
1369
1465
 
1370
- preInit();
1371
-
1372
1466
  // by default, re-init
1373
1467
 
1374
1468
  if (!excludeInit) {
@@ -1654,12 +1748,15 @@ function SoundManager(smURL, smID) {
1654
1748
  if (fV === 8) {
1655
1749
  flash._load(s.id, instanceOptions.url, instanceOptions.stream, instanceOptions.autoPlay, instanceOptions.usePolicyFile);
1656
1750
  } else {
1657
- flash._load(s.id, instanceOptions.url, !!(instanceOptions.stream), !!(instanceOptions.autoPlay), instanceOptions.loops||1, !!(instanceOptions.autoLoad), instanceOptions.usePolicyFile);
1751
+ flash._load(s.id, instanceOptions.url, !!(instanceOptions.stream), !!(instanceOptions.autoPlay), instanceOptions.loops || 1, !!(instanceOptions.autoLoad), instanceOptions.usePolicyFile);
1658
1752
  }
1659
1753
  } catch(e) {
1660
1754
  _wDS('smError', 2);
1661
1755
  debugTS('onload', false);
1662
- catchError({type:'SMSOUND_LOAD_JS_EXCEPTION', fatal:true});
1756
+ catchError({
1757
+ type: 'SMSOUND_LOAD_JS_EXCEPTION',
1758
+ fatal: true
1759
+ });
1663
1760
  }
1664
1761
 
1665
1762
  }
@@ -1814,17 +1911,24 @@ function SoundManager(smURL, smID) {
1814
1911
  }
1815
1912
 
1816
1913
  if (s.playState === 1 && !s.paused) {
1914
+
1817
1915
  allowMulti = s._iO.multiShot;
1916
+
1818
1917
  if (!allowMulti) {
1918
+
1819
1919
  sm2._wD(fN + 'Already playing (one-shot)', 1);
1920
+
1820
1921
  if (s.isHTML5) {
1821
1922
  // go back to original position.
1822
1923
  s.setPosition(s._iO.position);
1823
1924
  }
1925
+
1824
1926
  exit = s;
1927
+
1825
1928
  } else {
1826
1929
  sm2._wD(fN + 'Already playing (multi-shot)', 1);
1827
1930
  }
1931
+
1828
1932
  }
1829
1933
 
1830
1934
  if (exit !== null) {
@@ -1900,7 +2004,7 @@ function SoundManager(smURL, smID) {
1900
2004
 
1901
2005
  if (!s.isHTML5 && fV === 9 && s.position > 0 && s.position === s.duration) {
1902
2006
  // flash 9 needs a position reset if play() is called while at the end of a sound.
1903
- sm2._wD(fN + 'Sound at end, resetting to position:0');
2007
+ sm2._wD(fN + 'Sound at end, resetting to position: 0');
1904
2008
  oOptions.position = 0;
1905
2009
  }
1906
2010
 
@@ -2060,7 +2164,7 @@ function SoundManager(smURL, smID) {
2060
2164
  event.add(audioClone, 'ended', onended);
2061
2165
 
2062
2166
  // apply volume to clones, too
2063
- if (s._iO.volume !== undefined) {
2167
+ if (s._iO.volume !== _undefined) {
2064
2168
  audioClone.volume = Math.max(0, Math.min(1, s._iO.volume/100));
2065
2169
  }
2066
2170
 
@@ -2252,7 +2356,7 @@ function SoundManager(smURL, smID) {
2252
2356
  * if seek is beyond (loaded?) position, "DOM exception 11"
2253
2357
  * "INDEX_SIZE_ERR": DOM exception 1
2254
2358
  */
2255
- sm2._wD(s.id + ': setPosition('+position1K+')');
2359
+ sm2._wD(s.id + ': setPosition(' + position1K + ')');
2256
2360
 
2257
2361
  try {
2258
2362
  s._a.currentTime = position1K;
@@ -2276,8 +2380,7 @@ function SoundManager(smURL, smID) {
2276
2380
 
2277
2381
  if (s.paused) {
2278
2382
 
2279
- // if paused, refresh UI right away
2280
- // force update
2383
+ // if paused, refresh UI right away by forcing update
2281
2384
  s._onTimer(true);
2282
2385
 
2283
2386
  }
@@ -2347,22 +2450,31 @@ function SoundManager(smURL, smID) {
2347
2450
  s.playState = 1;
2348
2451
 
2349
2452
  if (!s.isHTML5) {
2453
+
2350
2454
  if (instanceOptions.isMovieStar && !instanceOptions.serverURL) {
2351
2455
  // Bizarre Webkit bug (Chrome reported via 8tracks.com dudes): AAC content paused for 30+ seconds(?) will not resume without a reposition.
2352
2456
  s.setPosition(s.position);
2353
2457
  }
2458
+
2354
2459
  // flash method is toggle-based (pause/resume)
2355
2460
  flash._pause(s.id, instanceOptions.multiShot);
2461
+
2356
2462
  } else {
2463
+
2357
2464
  s._setup_html5().play();
2358
2465
  start_html5_timer();
2466
+
2359
2467
  }
2360
2468
 
2361
2469
  if (!onplay_called && instanceOptions.onplay) {
2470
+
2362
2471
  instanceOptions.onplay.apply(s);
2363
2472
  onplay_called = true;
2473
+
2364
2474
  } else if (instanceOptions.onresume) {
2475
+
2365
2476
  instanceOptions.onresume.apply(s);
2477
+
2366
2478
  }
2367
2479
 
2368
2480
  return s;
@@ -2453,14 +2565,19 @@ function SoundManager(smURL, smID) {
2453
2565
  }
2454
2566
 
2455
2567
  if (!s.isHTML5) {
2456
- flash._setVolume(s.id, (sm2.muted && !s.muted) || s.muted?0:nVol);
2568
+
2569
+ flash._setVolume(s.id, (sm2.muted && !s.muted) || s.muted ? 0 : nVol);
2570
+
2457
2571
  } else if (s._a) {
2572
+
2458
2573
  if (sm2.muted && !s.muted) {
2459
2574
  s.muted = true;
2460
2575
  s._a.muted = true;
2461
2576
  }
2462
- // valid range: 0-1
2577
+
2578
+ // valid range for native HTML5 Audio(): 0-1
2463
2579
  s._a.volume = Math.max(0, Math.min(1, nVol/100));
2580
+
2464
2581
  }
2465
2582
 
2466
2583
  s._iO.volume = nVol;
@@ -2506,7 +2623,7 @@ function SoundManager(smURL, smID) {
2506
2623
  var hasIO = (s._iO.volume !== _undefined);
2507
2624
 
2508
2625
  if (!s.isHTML5) {
2509
- flash._setVolume(s.id, hasIO?s._iO.volume:s.options.volume);
2626
+ flash._setVolume(s.id, hasIO ? s._iO.volume : s.options.volume);
2510
2627
  } else if (s._a) {
2511
2628
  s._a.muted = false;
2512
2629
  }
@@ -2523,7 +2640,7 @@ function SoundManager(smURL, smID) {
2523
2640
 
2524
2641
  this.toggleMute = function() {
2525
2642
 
2526
- return (s.muted?s.unmute():s.mute());
2643
+ return (s.muted ? s.unmute() : s.mute());
2527
2644
 
2528
2645
  };
2529
2646
 
@@ -2577,13 +2694,18 @@ function SoundManager(smURL, smID) {
2577
2694
 
2578
2695
  if (nPosition === onPositionItems[i].position) {
2579
2696
  // remove this item if no method was specified, or, if the method matches
2697
+
2580
2698
  if (!oMethod || (oMethod === onPositionItems[i].method)) {
2699
+
2581
2700
  if (onPositionItems[i].fired) {
2582
2701
  // decrement "fired" counter, too
2583
2702
  onPositionFired--;
2584
2703
  }
2704
+
2585
2705
  onPositionItems.splice(i, 1);
2706
+
2586
2707
  }
2708
+
2587
2709
  }
2588
2710
 
2589
2711
  }
@@ -2593,21 +2715,28 @@ function SoundManager(smURL, smID) {
2593
2715
  this._processOnPosition = function() {
2594
2716
 
2595
2717
  var i, item, j = onPositionItems.length;
2596
-
2718
+
2597
2719
  if (!j || !s.playState || onPositionFired >= j) {
2598
2720
  return false;
2599
2721
  }
2600
2722
 
2601
- for (i=j-1; i >= 0; i--) {
2723
+ for (i = j - 1; i >= 0; i--) {
2724
+
2602
2725
  item = onPositionItems[i];
2726
+
2603
2727
  if (!item.fired && s.position >= item.position) {
2728
+
2604
2729
  item.fired = true;
2605
2730
  onPositionFired++;
2606
2731
  item.method.apply(item.scope, [item.position]);
2607
- j = onPositionItems.length; // reset j -- onPositionItems.length can be changed in the item callback above... occasionally breaking the loop.
2732
+
2733
+ // reset j -- onPositionItems.length can be changed in the item callback above... occasionally breaking the loop.
2734
+ j = onPositionItems.length;
2735
+
2608
2736
  }
2737
+
2609
2738
  }
2610
-
2739
+
2611
2740
  return true;
2612
2741
 
2613
2742
  };
@@ -2621,12 +2750,15 @@ function SoundManager(smURL, smID) {
2621
2750
  return false;
2622
2751
  }
2623
2752
 
2624
- for (i=j-1; i >= 0; i--) {
2753
+ for (i = j - 1; i >= 0; i--) {
2754
+
2625
2755
  item = onPositionItems[i];
2756
+
2626
2757
  if (item.fired && nPosition <= item.position) {
2627
2758
  item.fired = false;
2628
2759
  onPositionFired--;
2629
2760
  }
2761
+
2630
2762
  }
2631
2763
 
2632
2764
  return true;
@@ -2841,7 +2973,7 @@ function SoundManager(smURL, smID) {
2841
2973
 
2842
2974
  if (isNew || bForce) {
2843
2975
 
2844
- s._whileplaying(time,x,x,x,x);
2976
+ s._whileplaying(time, x, x, x, x);
2845
2977
 
2846
2978
  }
2847
2979
 
@@ -2863,7 +2995,7 @@ function SoundManager(smURL, smID) {
2863
2995
 
2864
2996
  var instanceOptions = s._iO,
2865
2997
  // if audio object exists, use its duration - else, instance option duration (if provided - it's a hack, really, and should be retired) OR null
2866
- d = (s._a && s._a.duration ? s._a.duration*msecScale : (instanceOptions && instanceOptions.duration ? instanceOptions.duration : null)),
2998
+ d = (s._a && s._a.duration ? s._a.duration * msecScale : (instanceOptions && instanceOptions.duration ? instanceOptions.duration : null)),
2867
2999
  result = (d && !isNaN(d) && d !== Infinity ? d : null);
2868
3000
 
2869
3001
  return result;
@@ -3026,7 +3158,7 @@ function SoundManager(smURL, smID) {
3026
3158
  var f;
3027
3159
 
3028
3160
  function add(oEvt, oFn, bCapture) {
3029
- return s._a ? s._a.addEventListener(oEvt, oFn, bCapture||false) : null;
3161
+ return s._a ? s._a.addEventListener(oEvt, oFn, bCapture || false) : null;
3030
3162
  }
3031
3163
 
3032
3164
  s._a._added_events = true;
@@ -3048,7 +3180,7 @@ function SoundManager(smURL, smID) {
3048
3180
  var f;
3049
3181
 
3050
3182
  function remove(oEvt, oFn, bCapture) {
3051
- return (s._a ? s._a.removeEventListener(oEvt, oFn, bCapture||false) : null);
3183
+ return (s._a ? s._a.removeEventListener(oEvt, oFn, bCapture || false) : null);
3052
3184
  }
3053
3185
 
3054
3186
  sm2._wD(s.id + ': Removing event listeners');
@@ -3076,6 +3208,7 @@ function SoundManager(smURL, smID) {
3076
3208
  // <d>
3077
3209
  fN = s.id + ': ';
3078
3210
  sm2._wD(fN + (loadOK ? 'onload()' : 'Failed to load / invalid sound?' + (!s.duration ? ' Zero-length duration reported.' : ' -') + ' (' + s.url + ')'), (loadOK ? 1 : 2));
3211
+
3079
3212
  if (!loadOK && !s.isHTML5) {
3080
3213
  if (sm2.sandbox.noRemote === true) {
3081
3214
  sm2._wD(fN + str('noNet'), 1);
@@ -3087,7 +3220,7 @@ function SoundManager(smURL, smID) {
3087
3220
  // </d>
3088
3221
 
3089
3222
  s.loaded = loadOK;
3090
- s.readyState = loadOK?3:2;
3223
+ s.readyState = (loadOK ? 3 : 2);
3091
3224
  s._onbufferchange(0);
3092
3225
 
3093
3226
  if (s._iO.onload) {
@@ -3112,6 +3245,7 @@ function SoundManager(smURL, smID) {
3112
3245
  }
3113
3246
 
3114
3247
  s.isBuffering = (nIsBuffering === 1);
3248
+
3115
3249
  if (s._iO.onbufferchange) {
3116
3250
  sm2._wD(s.id + ': Buffer state change: ' + nIsBuffering);
3117
3251
  s._iO.onbufferchange.apply(s, [nIsBuffering]);
@@ -3351,9 +3485,8 @@ function SoundManager(smURL, smID) {
3351
3485
  for (i = 0, j = oMDProps.length; i < j; i++) {
3352
3486
  oData[oMDProps[i]] = oMDData[i];
3353
3487
  }
3354
- s.metadata = oData;
3355
3488
 
3356
- console.log('updated metadata', s.metadata);
3489
+ s.metadata = oData;
3357
3490
 
3358
3491
  if (s._iO.onmetadata) {
3359
3492
  s._iO.onmetadata.call(s, s.metadata);
@@ -3378,6 +3511,7 @@ console.log('updated metadata', s.metadata);
3378
3511
  for (i = 0, j = oID3Props.length; i < j; i++) {
3379
3512
  oData[oID3Props[i]] = oID3Data[i];
3380
3513
  }
3514
+
3381
3515
  s.id3 = mixin(s.id3, oData);
3382
3516
 
3383
3517
  if (s._iO.onid3) {
@@ -3544,17 +3678,11 @@ console.log('updated metadata', s.metadata);
3544
3678
  if (bonusOptions.hasOwnProperty(i)) {
3545
3679
 
3546
3680
  if (typeof sm2[i] === 'object') {
3547
-
3548
- result.push(i+': {...}');
3549
-
3681
+ result.push(i + ': {...}');
3550
3682
  } else if (sm2[i] instanceof Function) {
3551
-
3552
- result.push(i+': function() {...}');
3553
-
3683
+ result.push(i + ': function() {...}');
3554
3684
  } else {
3555
-
3556
3685
  result.push(i);
3557
-
3558
3686
  }
3559
3687
 
3560
3688
  }
@@ -3609,7 +3737,7 @@ console.log('updated metadata', s.metadata);
3609
3737
 
3610
3738
  if (sm2[i] instanceof Function) {
3611
3739
 
3612
- sm2[i].apply(sm2, (o[i] instanceof Array? o[i] : [o[i]]));
3740
+ sm2[i].apply(sm2, (o[i] instanceof Array ? o[i] : [o[i]]));
3613
3741
 
3614
3742
  } else {
3615
3743
 
@@ -3665,8 +3793,8 @@ console.log('updated metadata', s.metadata);
3665
3793
  // normalize event methods
3666
3794
  var old = (window.attachEvent),
3667
3795
  evt = {
3668
- add: (old?'attachEvent':'addEventListener'),
3669
- remove: (old?'detachEvent':'removeEventListener')
3796
+ add: (old ? 'attachEvent' : 'addEventListener'),
3797
+ remove: (old ? 'detachEvent' : 'removeEventListener')
3670
3798
  };
3671
3799
 
3672
3800
  // normalize "on" event prefix, optional capture argument
@@ -3706,15 +3834,11 @@ console.log('updated metadata', s.metadata);
3706
3834
  }
3707
3835
 
3708
3836
  function add() {
3709
-
3710
3837
  apply(getArgs(arguments), 'add');
3711
-
3712
3838
  }
3713
3839
 
3714
3840
  function remove() {
3715
-
3716
3841
  apply(getArgs(arguments), 'remove');
3717
-
3718
3842
  }
3719
3843
 
3720
3844
  return {
@@ -3921,8 +4045,8 @@ console.log('updated metadata', s.metadata);
3921
4045
  isProgress = (e.type === 'progress'),
3922
4046
  ranges = e.target.buffered,
3923
4047
  // firefox 3.6 implements e.loaded/total (bytes)
3924
- loaded = (e.loaded||0),
3925
- total = (e.total||1);
4048
+ loaded = (e.loaded || 0),
4049
+ total = (e.total || 1);
3926
4050
 
3927
4051
  // reset the "buffered" (loaded byte ranges) array
3928
4052
  s.buffered = [];
@@ -3934,7 +4058,7 @@ console.log('updated metadata', s.metadata);
3934
4058
 
3935
4059
  // re-build "buffered" array
3936
4060
  // HTML5 returns seconds. SM2 API uses msec for setPosition() etc., whether Flash or HTML5.
3937
- for (i=0, j=ranges.length; i<j; i++) {
4061
+ for (i = 0, j = ranges.length; i < j; i++) {
3938
4062
  s.buffered.push({
3939
4063
  'start': ranges.start(i) * msecScale,
3940
4064
  'end': ranges.end(i) * msecScale
@@ -3945,20 +4069,20 @@ console.log('updated metadata', s.metadata);
3945
4069
  buffered = (ranges.end(0) - ranges.start(0)) * msecScale;
3946
4070
 
3947
4071
  // linear case, buffer sum; does not account for seeking and HTTP partials / byte ranges
3948
- loaded = Math.min(1, buffered/(e.target.duration*msecScale));
4072
+ loaded = Math.min(1, buffered / (e.target.duration * msecScale));
3949
4073
 
3950
4074
  // <d>
3951
4075
  if (isProgress && ranges.length > 1) {
3952
4076
  progStr = [];
3953
4077
  j = ranges.length;
3954
- for (i=0; i<j; i++) {
3955
- progStr.push(e.target.buffered.start(i)*msecScale +'-'+ e.target.buffered.end(i)*msecScale);
4078
+ for (i = 0; i < j; i++) {
4079
+ progStr.push((e.target.buffered.start(i) * msecScale) + '-' + (e.target.buffered.end(i) * msecScale));
3956
4080
  }
3957
4081
  sm2._wD(this._s.id + ': progress, timeRanges: ' + progStr.join(', '));
3958
4082
  }
3959
4083
 
3960
4084
  if (isProgress && !isNaN(loaded)) {
3961
- sm2._wD(this._s.id + ': progress, ' + Math.floor(loaded*100) + '% loaded');
4085
+ sm2._wD(this._s.id + ': progress, ' + Math.floor(loaded * 100) + '% loaded');
3962
4086
  }
3963
4087
  // </d>
3964
4088
 
@@ -4068,7 +4192,7 @@ console.log('updated metadata', s.metadata);
4068
4192
  oAudio.src = url;
4069
4193
 
4070
4194
  // reset some state, too
4071
- if (oAudio._called_unload !== undefined) {
4195
+ if (oAudio._called_unload !== _undefined) {
4072
4196
  oAudio._called_load = false;
4073
4197
  }
4074
4198
 
@@ -4114,42 +4238,65 @@ console.log('updated metadata', s.metadata);
4114
4238
  }
4115
4239
 
4116
4240
  if (!html5Ext) {
4241
+
4117
4242
  html5Ext = [];
4243
+
4118
4244
  for (item in aF) {
4245
+
4119
4246
  if (aF.hasOwnProperty(item)) {
4247
+
4120
4248
  html5Ext.push(item);
4249
+
4121
4250
  if (aF[item].related) {
4122
4251
  html5Ext = html5Ext.concat(aF[item].related);
4123
4252
  }
4253
+
4124
4254
  }
4255
+
4125
4256
  }
4257
+
4126
4258
  html5Ext = new RegExp('\\.('+html5Ext.join('|')+')(\\?.*)?$','i');
4259
+
4127
4260
  }
4128
4261
 
4129
4262
  // TODO: Strip URL queries, etc.
4130
4263
  fileExt = (url ? url.toLowerCase().match(html5Ext) : null);
4131
4264
 
4132
4265
  if (!fileExt || !fileExt.length) {
4266
+
4133
4267
  if (!mime) {
4268
+
4134
4269
  result = false;
4270
+
4135
4271
  } else {
4272
+
4136
4273
  // audio/mp3 -> mp3, result should be known
4137
4274
  offset = mime.indexOf(';');
4275
+
4138
4276
  // strip "audio/X; codecs..."
4139
- fileExt = (offset !== -1?mime.substr(0,offset):mime).substr(6);
4277
+ fileExt = (offset !== -1 ? mime.substr(0,offset) : mime).substr(6);
4278
+
4140
4279
  }
4280
+
4141
4281
  } else {
4282
+
4142
4283
  // match the raw extension name - "mp3", for example
4143
4284
  fileExt = fileExt[1];
4285
+
4144
4286
  }
4145
4287
 
4146
4288
  if (fileExt && sm2.html5[fileExt] !== _undefined) {
4289
+
4147
4290
  // result known
4148
4291
  result = (sm2.html5[fileExt] && !preferFlashCheck(fileExt));
4292
+
4149
4293
  } else {
4150
- mime = 'audio/'+fileExt;
4294
+
4295
+ mime = 'audio/' + fileExt;
4151
4296
  result = sm2.html5.canPlayType({type:mime});
4297
+
4152
4298
  sm2.html5[fileExt] = result;
4299
+
4153
4300
  // sm2._wD('canPlayType, found result: ' + result);
4154
4301
  result = (result && sm2.html5[mime] && !preferFlashCheck(mime));
4155
4302
  }
@@ -4166,10 +4313,13 @@ console.log('updated metadata', s.metadata);
4166
4313
  */
4167
4314
 
4168
4315
  if (!sm2.useHTML5Audio || !sm2.hasHTML5) {
4316
+
4169
4317
  // without HTML5, we need Flash.
4170
4318
  sm2.html5.usingFlash = true;
4171
4319
  needsFlash = true;
4320
+
4172
4321
  return false;
4322
+
4173
4323
  }
4174
4324
 
4175
4325
  // double-whammy: Opera 9.64 throws WRONG_ARGUMENTS_ERR if no parameter passed to Audio(), and Webkit + iOS happily tries to load "null" as a URL. :/
@@ -4187,19 +4337,30 @@ console.log('updated metadata', s.metadata);
4187
4337
  }
4188
4338
 
4189
4339
  if (m instanceof Array) {
4340
+
4190
4341
  // iterate through all mime types, return any successes
4191
- for (i=0, j=m.length; i<j; i++) {
4342
+
4343
+ for (i = 0, j = m.length; i < j; i++) {
4344
+
4192
4345
  if (sm2.html5[m[i]] || a.canPlayType(m[i]).match(sm2.html5Test)) {
4346
+
4193
4347
  isOK = true;
4194
4348
  sm2.html5[m[i]] = true;
4349
+
4195
4350
  // note flash support, too
4196
4351
  sm2.flash[m[i]] = !!(m[i].match(flashMIME));
4352
+
4197
4353
  }
4354
+
4198
4355
  }
4356
+
4199
4357
  result = isOK;
4358
+
4200
4359
  } else {
4360
+
4201
4361
  canPlay = (a && typeof a.canPlayType === 'function' ? a.canPlayType(m) : false);
4202
4362
  result = !!(canPlay && (canPlay.match(sm2.html5Test)));
4363
+
4203
4364
  }
4204
4365
 
4205
4366
  return result;
@@ -4238,10 +4399,10 @@ console.log('updated metadata', s.metadata);
4238
4399
 
4239
4400
  if (aF[item] && aF[item].related) {
4240
4401
 
4241
- for (i=aF[item].related.length-1; i >= 0; i--) {
4402
+ for (i = aF[item].related.length - 1; i >= 0; i--) {
4242
4403
 
4243
4404
  // eg. audio/m4a
4244
- support['audio/'+aF[item].related[i]] = support[item];
4405
+ support['audio/' + aF[item].related[i]] = support[item];
4245
4406
  sm2.html5[aF[item].related[i]] = support[item];
4246
4407
  sm2.flash[aF[item].related[i]] = support[item];
4247
4408
 
@@ -4253,7 +4414,7 @@ console.log('updated metadata', s.metadata);
4253
4414
 
4254
4415
  }
4255
4416
 
4256
- support.canPlayType = (a?cp:null);
4417
+ support.canPlayType = (a ? cp : null);
4257
4418
  sm2.html5 = mixin(sm2.html5, support);
4258
4419
 
4259
4420
  sm2.html5.usingFlash = featureCheck();
@@ -4290,7 +4451,7 @@ console.log('updated metadata', s.metadata);
4290
4451
  shutdown: sm + '.disable(): Shutting down',
4291
4452
  queue: smc + 'Queueing %s handler',
4292
4453
  smError: 'SMSound.load(): Exception: JS-Flash communication failed, or JS error.',
4293
- fbTimeout: 'No flash response, applying .'+swfCSS.swfTimedout+' CSS...',
4454
+ fbTimeout: 'No flash response, applying .' + swfCSS.swfTimedout + ' CSS...',
4294
4455
  fbLoaded: 'Flash loaded',
4295
4456
  fbHandler: smc + 'flashBlockHandler()',
4296
4457
  manURL: 'SMSound.load(): Using manually-assigned URL',
@@ -4311,7 +4472,8 @@ console.log('updated metadata', s.metadata);
4311
4472
  sm2Loaded: 'SoundManager 2: Ready. ' + String.fromCharCode(10003),
4312
4473
  reset: sm + '.reset(): Removing event callbacks',
4313
4474
  mobileUA: 'Mobile UA detected, preferring HTML5 by default.',
4314
- globalHTML5: 'Using singleton HTML5 Audio() pattern for this device.'
4475
+ globalHTML5: 'Using singleton HTML5 Audio() pattern for this device.',
4476
+ ignoreMobile: 'Ignoring mobile restrictions for this device.'
4315
4477
  // </d>
4316
4478
 
4317
4479
  };
@@ -4419,16 +4581,23 @@ console.log('updated metadata', s.metadata);
4419
4581
  var urlParams = null, url;
4420
4582
 
4421
4583
  if (smURL) {
4584
+
4422
4585
  if (smURL.match(/\.swf(\?.*)?$/i)) {
4586
+
4423
4587
  urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?') + 4);
4588
+
4424
4589
  if (urlParams) {
4425
4590
  // assume user knows what they're doing
4426
4591
  return smURL;
4427
4592
  }
4593
+
4428
4594
  } else if (smURL.lastIndexOf('/') !== smURL.length - 1) {
4595
+
4429
4596
  // append trailing slash, if needed
4430
4597
  smURL += '/';
4598
+
4431
4599
  }
4600
+
4432
4601
  }
4433
4602
 
4434
4603
  url = (smURL && smURL.lastIndexOf('/') !== - 1 ? smURL.substr(0, smURL.lastIndexOf('/') + 1) : './') + sm2.movieURL;
@@ -4454,33 +4623,38 @@ console.log('updated metadata', s.metadata);
4454
4623
 
4455
4624
  // debug flash movie, if applicable
4456
4625
 
4457
- var isDebug = (sm2.debugMode || sm2.debugFlash?'_debug.swf':'.swf');
4626
+ var isDebug = (sm2.debugMode || sm2.debugFlash ? '_debug.swf' : '.swf');
4458
4627
 
4459
4628
  if (sm2.useHTML5Audio && !sm2.html5Only && sm2.audioFormats.mp4.required && fV < 9) {
4460
4629
  sm2._wD(str('needfl9'));
4461
4630
  sm2.flashVersion = fV = 9;
4462
4631
  }
4463
4632
 
4464
- sm2.version = sm2.versionNumber + (sm2.html5Only?' (HTML5-only mode)':(fV === 9?' (AS3/Flash 9)':' (AS2/Flash 8)'));
4633
+ sm2.version = sm2.versionNumber + (sm2.html5Only ? ' (HTML5-only mode)' : (fV === 9 ? ' (AS3/Flash 9)' : ' (AS2/Flash 8)'));
4465
4634
 
4466
4635
  // set up default options
4467
4636
  if (fV > 8) {
4637
+
4468
4638
  // +flash 9 base options
4469
4639
  sm2.defaultOptions = mixin(sm2.defaultOptions, sm2.flash9Options);
4470
4640
  sm2.features.buffering = true;
4641
+
4471
4642
  // +moviestar support
4472
4643
  sm2.defaultOptions = mixin(sm2.defaultOptions, sm2.movieStarOptions);
4473
4644
  sm2.filePatterns.flash9 = new RegExp('\\.(mp3|' + netStreamTypes.join('|') + ')(\\?.*)?$', 'i');
4474
4645
  sm2.features.movieStar = true;
4646
+
4475
4647
  } else {
4648
+
4476
4649
  sm2.features.movieStar = false;
4650
+
4477
4651
  }
4478
4652
 
4479
4653
  // regExp for flash canPlay(), etc.
4480
- sm2.filePattern = sm2.filePatterns[(fV !== 8?'flash9':'flash8')];
4654
+ sm2.filePattern = sm2.filePatterns[(fV !== 8 ? 'flash9' : 'flash8')];
4481
4655
 
4482
4656
  // if applicable, use _debug versions of SWFs
4483
- sm2.movieURL = (fV === 8?'soundmanager2.swf':'soundmanager2_flash9.swf').replace('.swf', isDebug);
4657
+ sm2.movieURL = (fV === 8 ? 'soundmanager2.swf' : 'soundmanager2_flash9.swf').replace('.swf', isDebug);
4484
4658
 
4485
4659
  sm2.features.peakData = sm2.features.waveformData = sm2.features.eqData = (fV > 8);
4486
4660
 
@@ -4503,7 +4677,7 @@ console.log('updated metadata', s.metadata);
4503
4677
  // allow force of debug mode via URL
4504
4678
  // <d>
4505
4679
  if (sm2.debugURLParam.test(wl)) {
4506
- sm2.debugMode = true;
4680
+ sm2.setupOptions.debugMode = sm2.debugMode = true;
4507
4681
  }
4508
4682
 
4509
4683
  if (id(sm2.debugID)) {
@@ -4550,14 +4724,14 @@ console.log('updated metadata', s.metadata);
4550
4724
 
4551
4725
  oDebug = doc.createElement('div');
4552
4726
  oDebug.id = sm2.debugID;
4553
- oDebug.style.display = (sm2.debugMode?'block':'none');
4727
+ oDebug.style.display = (sm2.debugMode ? 'block' : 'none');
4554
4728
 
4555
4729
  if (sm2.debugMode && !id(oD.id)) {
4556
4730
  try {
4557
4731
  oTarget = getDocument();
4558
4732
  oTarget.appendChild(oD);
4559
4733
  } catch(e2) {
4560
- throw new Error(str('domError')+' \n'+e2.toString());
4734
+ throw new Error(str('domError') + ' \n' + e2.toString());
4561
4735
  }
4562
4736
  oTarget.appendChild(oDebug);
4563
4737
  }
@@ -4645,7 +4819,9 @@ console.log('updated metadata', s.metadata);
4645
4819
  var name = str('fbHandler'),
4646
4820
  p = sm2.getMoviePercent(),
4647
4821
  css = swfCSS,
4648
- error = {type:'FLASHBLOCK'};
4822
+ error = {
4823
+ type:'FLASHBLOCK'
4824
+ };
4649
4825
 
4650
4826
  if (sm2.html5Only) {
4651
4827
  // no flash, or unused
@@ -4656,14 +4832,19 @@ console.log('updated metadata', s.metadata);
4656
4832
 
4657
4833
  if (needsFlash) {
4658
4834
  // make the movie more visible, so user can fix
4659
- sm2.oMC.className = getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null?css.swfTimedout:css.swfError);
4835
+ sm2.oMC.className = getSWFCSS() + ' ' + css.swfDefault + ' ' + (p === null ? css.swfTimedout : css.swfError);
4660
4836
  sm2._wD(name + ': ' + str('fbTimeout') + (p ? ' (' + str('fbLoaded') + ')' : ''));
4661
4837
  }
4662
4838
 
4663
4839
  sm2.didFlashBlock = true;
4664
4840
 
4665
4841
  // fire onready(), complain lightly
4666
- processOnEvents({type:'ontimeout', ignoreInit:true, error:error});
4842
+ processOnEvents({
4843
+ type: 'ontimeout',
4844
+ ignoreInit: true,
4845
+ error: error
4846
+ });
4847
+
4667
4848
  catchError(error);
4668
4849
 
4669
4850
  } else {
@@ -4677,7 +4858,7 @@ console.log('updated metadata', s.metadata);
4677
4858
  // </d>
4678
4859
 
4679
4860
  if (sm2.oMC) {
4680
- sm2.oMC.className = [getSWFCSS(), css.swfDefault, css.swfLoaded + (sm2.didFlashBlock?' '+css.swfUnblocked:'')].join(' ');
4861
+ sm2.oMC.className = [getSWFCSS(), css.swfDefault, css.swfLoaded + (sm2.didFlashBlock ? ' ' + css.swfUnblocked : '')].join(' ');
4681
4862
  }
4682
4863
 
4683
4864
  }
@@ -4719,11 +4900,11 @@ console.log('updated metadata', s.metadata);
4719
4900
  }
4720
4901
 
4721
4902
  var status = {
4722
- success: (oOptions && oOptions.ignoreInit?sm2.ok():!disabled)
4903
+ success: (oOptions && oOptions.ignoreInit ? sm2.ok() : !disabled)
4723
4904
  },
4724
4905
 
4725
4906
  // queue specified by type, or none
4726
- srcQueue = (oOptions && oOptions.type?on_queue[oOptions.type]||[]:[]),
4907
+ srcQueue = (oOptions && oOptions.type ? on_queue[oOptions.type] || [] : []),
4727
4908
 
4728
4909
  queue = [], i, j,
4729
4910
  args = [status],
@@ -4740,18 +4921,24 @@ console.log('updated metadata', s.metadata);
4740
4921
  }
4741
4922
 
4742
4923
  if (queue.length) {
4743
- // sm2._wD(sm + ': Firing ' + queue.length + ' ' + oOptions.type + '() item' + (queue.length === 1 ? '' : 's'));
4924
+
4925
+ // sm2._wD(sm + ': Firing ' + queue.length + ' ' + oOptions.type + '() item' + (queue.length === 1 ? '' : 's'));
4744
4926
  for (i = 0, j = queue.length; i < j; i++) {
4927
+
4745
4928
  if (queue[i].scope) {
4746
4929
  queue[i].method.apply(queue[i].scope, args);
4747
4930
  } else {
4748
4931
  queue[i].method.apply(this, args);
4749
4932
  }
4933
+
4750
4934
  if (!canRetry) {
4751
4935
  // useFlashBlock and SWF timeout case doesn't count here.
4752
4936
  queue[i].fired = true;
4937
+
4753
4938
  }
4939
+
4754
4940
  }
4941
+
4755
4942
  }
4756
4943
 
4757
4944
  return true;
@@ -4780,13 +4967,16 @@ console.log('updated metadata', s.metadata);
4780
4967
  event.add(window, 'load', initUserOnload);
4781
4968
  }
4782
4969
 
4783
- },1);
4970
+ }, 1);
4784
4971
 
4785
4972
  };
4786
4973
 
4787
4974
  detectFlash = function() {
4788
4975
 
4789
- // 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
4976
+ /**
4977
+ * Hat tip: Flash Detect library (BSD, (C) 2007) by Carl "DocYes" S. Yestrau
4978
+ * http://featureblend.com/javascript-flash-detection-library.html / http://featureblend.com/license.txt
4979
+ */
4790
4980
 
4791
4981
  if (hasFlash !== _undefined) {
4792
4982
  // this work has already been done.
@@ -4796,12 +4986,16 @@ console.log('updated metadata', s.metadata);
4796
4986
  var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = window.ActiveXObject;
4797
4987
 
4798
4988
  if (nP && nP.length) {
4989
+
4799
4990
  type = 'application/x-shockwave-flash';
4800
4991
  types = n.mimeTypes;
4992
+
4801
4993
  if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) {
4802
4994
  hasPlugin = true;
4803
4995
  }
4996
+
4804
4997
  } else if (AX !== _undefined && !ua.match(/MSAppHost/i)) {
4998
+
4805
4999
  // 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.
4806
5000
  try {
4807
5001
  obj = new AX('ShockwaveFlash.ShockwaveFlash');
@@ -4809,9 +5003,12 @@ console.log('updated metadata', s.metadata);
4809
5003
  // oh well
4810
5004
  obj = null;
4811
5005
  }
5006
+
4812
5007
  hasPlugin = (!!obj);
5008
+
4813
5009
  // cleanup, because it is ActiveX after all
4814
5010
  obj = null;
5011
+
4815
5012
  }
4816
5013
 
4817
5014
  hasFlash = hasPlugin;
@@ -4852,7 +5049,7 @@ featureCheck = function() {
4852
5049
 
4853
5050
  // <d>
4854
5051
  if (isBadSafari) {
4855
- 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);
5052
+ 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);
4856
5053
  }
4857
5054
  // </d>
4858
5055
 
@@ -4868,18 +5065,28 @@ featureCheck = function() {
4868
5065
  canIgnoreFlash = true;
4869
5066
 
4870
5067
  for (item in formats) {
5068
+
4871
5069
  if (formats.hasOwnProperty(item)) {
5070
+
4872
5071
  if (formats[item].required) {
5072
+
4873
5073
  if (!sm2.html5.canPlayType(formats[item].type)) {
5074
+
4874
5075
  // 100% HTML5 mode is not possible.
4875
5076
  canIgnoreFlash = false;
4876
5077
  flashNeeded = true;
5078
+
4877
5079
  } else if (sm2.preferFlash && (sm2.flash[item] || sm2.flash[formats[item].type])) {
5080
+
4878
5081
  // flash may be required, or preferred for this format.
4879
5082
  flashNeeded = true;
5083
+
4880
5084
  }
5085
+
4881
5086
  }
5087
+
4882
5088
  }
5089
+
4883
5090
  }
4884
5091
 
4885
5092
  }
@@ -4908,9 +5115,10 @@ featureCheck = function() {
4908
5115
  if (url instanceof Array) {
4909
5116
 
4910
5117
  // find the first good one
4911
- for (i=0, j=url.length; i<j; i++) {
5118
+ for (i = 0, j = url.length; i < j; i++) {
4912
5119
 
4913
5120
  if (url[i] instanceof Object) {
5121
+
4914
5122
  // MIME check
4915
5123
  if (sm2.canPlayMIME(url[i].type)) {
4916
5124
  urlResult = i;
@@ -4918,9 +5126,11 @@ featureCheck = function() {
4918
5126
  }
4919
5127
 
4920
5128
  } else if (sm2.canPlayURL(url[i])) {
5129
+
4921
5130
  // URL string check
4922
5131
  urlResult = i;
4923
5132
  break;
5133
+
4924
5134
  }
4925
5135
 
4926
5136
  }
@@ -4995,7 +5205,8 @@ featureCheck = function() {
4995
5205
  timerExecute = function() {
4996
5206
 
4997
5207
  /**
4998
- * manual polling for HTML5 progress events, ie., whileplaying() (can achieve greater precision than conservative default HTML5 interval)
5208
+ * manual polling for HTML5 progress events, ie., whileplaying()
5209
+ * (can achieve greater precision than conservative default HTML5 interval)
4999
5210
  */
5000
5211
 
5001
5212
  var i;
@@ -5014,12 +5225,10 @@ featureCheck = function() {
5014
5225
 
5015
5226
  // check all HTML5 sounds with timers
5016
5227
 
5017
- for (i = sm2.soundIDs.length-1; i >= 0; i--) {
5228
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
5018
5229
 
5019
5230
  if (sm2.sounds[sm2.soundIDs[i]].isHTML5 && sm2.sounds[sm2.soundIDs[i]]._hasTimer) {
5020
-
5021
5231
  sm2.sounds[sm2.soundIDs[i]]._onTimer();
5022
-
5023
5232
  }
5024
5233
 
5025
5234
  }
@@ -5031,7 +5240,9 @@ featureCheck = function() {
5031
5240
  options = (options !== _undefined ? options : {});
5032
5241
 
5033
5242
  if (typeof sm2.onerror === 'function') {
5034
- sm2.onerror.apply(window, [{type:(options.type !== _undefined ? options.type : null)}]);
5243
+ sm2.onerror.apply(window, [{
5244
+ type: (options.type !== _undefined ? options.type : null)
5245
+ }]);
5035
5246
  }
5036
5247
 
5037
5248
  if (options.fatal !== _undefined && options.fatal) {
@@ -5051,18 +5262,25 @@ featureCheck = function() {
5051
5262
  var aF = sm2.audioFormats, i, item;
5052
5263
 
5053
5264
  for (item in aF) {
5265
+
5054
5266
  if (aF.hasOwnProperty(item)) {
5267
+
5055
5268
  if (item === 'mp3' || item === 'mp4') {
5269
+
5056
5270
  sm2._wD(sm + ': Using flash fallback for ' + item + ' format');
5057
5271
  sm2.html5[item] = false;
5272
+
5058
5273
  // assign result to related formats, too
5059
5274
  if (aF[item] && aF[item].related) {
5060
- for (i = aF[item].related.length-1; i >= 0; i--) {
5275
+ for (i = aF[item].related.length - 1; i >= 0; i--) {
5061
5276
  sm2.html5[aF[item].related[i]] = false;
5062
5277
  }
5063
5278
  }
5279
+
5064
5280
  }
5281
+
5065
5282
  }
5283
+
5066
5284
  }
5067
5285
 
5068
5286
  };
@@ -5075,10 +5293,11 @@ featureCheck = function() {
5075
5293
  this._setSandboxType = function(sandboxType) {
5076
5294
 
5077
5295
  // <d>
5296
+ // Security sandbox according to Flash plugin
5078
5297
  var sb = sm2.sandbox;
5079
5298
 
5080
5299
  sb.type = sandboxType;
5081
- sb.description = sb.types[(sb.types[sandboxType] !== _undefined?sandboxType:'unknown')];
5300
+ sb.description = sb.types[(sb.types[sandboxType] !== _undefined?sandboxType : 'unknown')];
5082
5301
 
5083
5302
  if (sb.type === 'localWithFile') {
5084
5303
 
@@ -5245,15 +5464,15 @@ featureCheck = function() {
5245
5464
  oEmbed, oMovie, tmp, movieHTML, oEl, s, x, sClass;
5246
5465
 
5247
5466
  isRTL = (html && html.dir && html.dir.match(/rtl/i));
5248
- smID = (smID === _undefined?sm2.id:smID);
5467
+ smID = (smID === _undefined ? sm2.id : smID);
5249
5468
 
5250
5469
  function param(name, value) {
5251
- return '<param name="'+name+'" value="'+value+'" />';
5470
+ return '<param name="' + name + '" value="' + value + '" />';
5252
5471
  }
5253
5472
 
5254
5473
  // safety check for legacy (change to Flash 9 URL)
5255
5474
  setVersionInfo();
5256
- sm2.url = normalizeMovieURL(overHTTP?remoteURL:localURL);
5475
+ sm2.url = normalizeMovieURL(overHTTP ? remoteURL : localURL);
5257
5476
  smURL = sm2.url;
5258
5477
 
5259
5478
  sm2.wmode = (!sm2.wmode && sm2.useHighPerformance ? 'transparent' : sm2.wmode);
@@ -5275,7 +5494,7 @@ featureCheck = function() {
5275
5494
  'quality': 'high',
5276
5495
  'allowScriptAccess': sm2.allowScriptAccess,
5277
5496
  'bgcolor': sm2.bgColor,
5278
- 'pluginspage': http+'www.macromedia.com/go/getflashplayer',
5497
+ 'pluginspage': http + 'www.macromedia.com/go/getflashplayer',
5279
5498
  'title': swfTitle,
5280
5499
  'type': 'application/x-shockwave-flash',
5281
5500
  'wmode': sm2.wmode,
@@ -5297,7 +5516,7 @@ featureCheck = function() {
5297
5516
  // IE is "special".
5298
5517
  oMovie = doc.createElement('div');
5299
5518
  movieHTML = [
5300
- '<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">',
5519
+ '<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">',
5301
5520
  param('movie', smURL),
5302
5521
  param('AllowScriptAccess', sm2.allowScriptAccess),
5303
5522
  param('quality', oEmbed.quality),
@@ -5356,7 +5575,7 @@ featureCheck = function() {
5356
5575
  'left': '-9999px'
5357
5576
  };
5358
5577
  if (isRTL) {
5359
- s.left = Math.abs(parseInt(s.left,10))+'px';
5578
+ s.left = Math.abs(parseInt(s.left, 10)) + 'px';
5360
5579
  }
5361
5580
  }
5362
5581
  }
@@ -5375,31 +5594,40 @@ featureCheck = function() {
5375
5594
  }
5376
5595
 
5377
5596
  try {
5597
+
5378
5598
  if (!isIE) {
5379
5599
  sm2.oMC.appendChild(oMovie);
5380
5600
  }
5601
+
5381
5602
  oTarget.appendChild(sm2.oMC);
5603
+
5382
5604
  if (isIE) {
5383
5605
  oEl = sm2.oMC.appendChild(doc.createElement('div'));
5384
5606
  oEl.className = swfCSS.swfBox;
5385
5607
  oEl.innerHTML = movieHTML;
5386
5608
  }
5609
+
5387
5610
  appendSuccess = true;
5611
+
5388
5612
  } catch(e) {
5389
- throw new Error(str('domError')+' \n'+e.toString());
5613
+
5614
+ throw new Error(str('domError') + ' \n' + e.toString());
5615
+
5390
5616
  }
5391
5617
 
5392
5618
  } else {
5393
5619
 
5394
5620
  // SM2 container is already in the document (eg. flashblock use case)
5395
5621
  sClass = sm2.oMC.className;
5396
- sm2.oMC.className = (sClass?sClass+' ':swfCSS.swfDefault) + (extraClass?' '+extraClass:'');
5622
+ sm2.oMC.className = (sClass ? sClass + ' ' : swfCSS.swfDefault) + (extraClass ? ' ' + extraClass : '');
5397
5623
  sm2.oMC.appendChild(oMovie);
5624
+
5398
5625
  if (isIE) {
5399
5626
  oEl = sm2.oMC.appendChild(doc.createElement('div'));
5400
5627
  oEl.className = swfCSS.swfBox;
5401
5628
  oEl.innerHTML = movieHTML;
5402
5629
  }
5630
+
5403
5631
  appendSuccess = true;
5404
5632
 
5405
5633
  }
@@ -5407,7 +5635,9 @@ featureCheck = function() {
5407
5635
  }
5408
5636
 
5409
5637
  didAppend = true;
5638
+
5410
5639
  initMsg();
5640
+
5411
5641
  // sm2._wD(sm + ': Trying to load ' + smURL + (!overHTTP && sm2.altURL ? ' (alternate URL)' : ''), 1);
5412
5642
 
5413
5643
  return true;
@@ -5443,20 +5673,28 @@ featureCheck = function() {
5443
5673
  flash = sm2.getMovie(sm2.id);
5444
5674
 
5445
5675
  if (!flash) {
5676
+
5446
5677
  if (!oRemoved) {
5678
+
5447
5679
  // try to create
5448
5680
  createMovie(sm2.id, sm2.url);
5681
+
5449
5682
  } else {
5683
+
5450
5684
  // try to re-append removed movie after reboot()
5451
5685
  if (!isIE) {
5452
5686
  sm2.oMC.appendChild(oRemoved);
5453
5687
  } else {
5454
5688
  sm2.oMC.innerHTML = oRemovedHTML;
5455
5689
  }
5690
+
5456
5691
  oRemoved = null;
5457
5692
  didAppend = true;
5693
+
5458
5694
  }
5695
+
5459
5696
  flash = sm2.getMovie(sm2.id);
5697
+
5460
5698
  }
5461
5699
 
5462
5700
  if (typeof sm2.oninitmovie === 'function') {
@@ -5543,7 +5781,7 @@ featureCheck = function() {
5543
5781
  // <d>
5544
5782
  if (!didInit) {
5545
5783
 
5546
- 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);
5784
+ 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);
5547
5785
 
5548
5786
  if (!overHTTP && p) {
5549
5787
 
@@ -5562,7 +5800,7 @@ featureCheck = function() {
5562
5800
 
5563
5801
  }
5564
5802
 
5565
- debugTS('flashtojs', false, ': Timed out' + overHTTP?' (Check flash security or flash blockers)':' (No plugin/missing SWF?)');
5803
+ debugTS('flashtojs', false, ': Timed out' + (overHTTP ? ' (Check flash security or flash blockers)':' (No plugin/missing SWF?)'));
5566
5804
 
5567
5805
  }
5568
5806
  // </d>
@@ -5598,7 +5836,13 @@ featureCheck = function() {
5598
5836
  _wDS('waitForever');
5599
5837
 
5600
5838
  // fire any regular registered ontimeout() listeners.
5601
- processOnEvents({type:'ontimeout', ignoreInit: true, error: {type: 'INIT_FLASHBLOCK'}});
5839
+ processOnEvents({
5840
+ type: 'ontimeout',
5841
+ ignoreInit: true,
5842
+ error: {
5843
+ type: 'INIT_FLASHBLOCK'
5844
+ }
5845
+ });
5602
5846
 
5603
5847
  }
5604
5848
 
@@ -5686,7 +5930,7 @@ featureCheck = function() {
5686
5930
  if (sm2.useHTML5Audio && sm2.hasHTML5) {
5687
5931
  for (item in sm2.audioFormats) {
5688
5932
  if (sm2.audioFormats.hasOwnProperty(item)) {
5689
- 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)' : ''))));
5933
+ 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)' : ''))));
5690
5934
  }
5691
5935
  }
5692
5936
  sm2._wD('SoundManager 2 HTML5 support: ' + tests.join(', '), 1);
@@ -5719,34 +5963,54 @@ featureCheck = function() {
5719
5963
  didInit = true;
5720
5964
  }
5721
5965
 
5722
- error = {type: (!hasFlash && needsFlash ? 'NO_FLASH' : 'INIT_TIMEOUT')};
5966
+ error = {
5967
+ type: (!hasFlash && needsFlash ? 'NO_FLASH' : 'INIT_TIMEOUT')
5968
+ };
5723
5969
 
5724
5970
  sm2._wD('SoundManager 2 ' + (disabled ? 'failed to load' : 'loaded') + ' (' + (disabled ? 'Flash security/load error' : 'OK') + ') ' + String.fromCharCode(disabled ? 10006 : 10003), disabled ? 2: 1);
5725
5971
 
5726
5972
  if (disabled || bNoDisable) {
5973
+
5727
5974
  if (sm2.useFlashBlock && sm2.oMC) {
5728
- sm2.oMC.className = getSWFCSS() + ' ' + (sm2.getMoviePercent() === null?swfCSS.swfTimedout:swfCSS.swfError);
5975
+ sm2.oMC.className = getSWFCSS() + ' ' + (sm2.getMoviePercent() === null ? swfCSS.swfTimedout : swfCSS.swfError);
5729
5976
  }
5730
- processOnEvents({type:'ontimeout', error:error, ignoreInit: true});
5977
+
5978
+ processOnEvents({
5979
+ type: 'ontimeout',
5980
+ error: error,
5981
+ ignoreInit: true
5982
+ });
5983
+
5731
5984
  debugTS('onload', false);
5732
5985
  catchError(error);
5986
+
5733
5987
  result = false;
5988
+
5734
5989
  } else {
5990
+
5735
5991
  debugTS('onload', true);
5992
+
5736
5993
  }
5737
5994
 
5738
5995
  if (!disabled) {
5996
+
5739
5997
  if (sm2.waitForWindowLoad && !windowLoaded) {
5998
+
5740
5999
  _wDS('waitOnload');
5741
6000
  event.add(window, 'load', initUserOnload);
6001
+
5742
6002
  } else {
6003
+
5743
6004
  // <d>
5744
6005
  if (sm2.waitForWindowLoad && windowLoaded) {
5745
6006
  _wDS('docLoaded');
5746
6007
  }
5747
6008
  // </d>
6009
+
5748
6010
  initUserOnload();
6011
+
5749
6012
  }
6013
+
5750
6014
  }
5751
6015
 
5752
6016
  return result;
@@ -5801,13 +6065,16 @@ featureCheck = function() {
5801
6065
  }
5802
6066
 
5803
6067
  if (sm2.html5Only) {
6068
+
5804
6069
  if (!didInit) {
5805
6070
  // we don't need no steenking flash!
5806
6071
  cleanup();
5807
6072
  sm2.enabled = true;
5808
6073
  initComplete();
5809
6074
  }
6075
+
5810
6076
  return true;
6077
+
5811
6078
  }
5812
6079
 
5813
6080
  // flash path
@@ -5818,8 +6085,10 @@ featureCheck = function() {
5818
6085
  // attempt to talk to Flash
5819
6086
  flash._externalInterfaceTest(false);
5820
6087
 
5821
- // apply user-specified polling interval, OR, if "high performance" set, faster vs. default polling
5822
- // (determines frequency of whileloading/whileplaying callbacks, effectively driving UI framerates)
6088
+ /**
6089
+ * Apply user-specified polling interval, OR, if "high performance" set, faster vs. default polling
6090
+ * (determines frequency of whileloading/whileplaying callbacks, effectively driving UI framerates)
6091
+ */
5823
6092
  setPolling(true, (sm2.flashPollingInterval || (sm2.useHighPerformance ? 10 : 50)));
5824
6093
 
5825
6094
  if (!sm2.debugMode) {
@@ -5839,10 +6108,17 @@ featureCheck = function() {
5839
6108
  } catch(e) {
5840
6109
 
5841
6110
  sm2._wD('js/flash exception: ' + e.toString());
6111
+
5842
6112
  debugTS('jstoflash', false);
5843
- catchError({type:'JS_TO_FLASH_EXCEPTION', fatal:true});
6113
+
6114
+ catchError({
6115
+ type: 'JS_TO_FLASH_EXCEPTION',
6116
+ fatal: true
6117
+ });
6118
+
5844
6119
  // don't disable, for reboot()
5845
6120
  failSafely(true);
6121
+
5846
6122
  initComplete();
5847
6123
 
5848
6124
  return false;
@@ -5871,61 +6147,31 @@ featureCheck = function() {
5871
6147
 
5872
6148
  initDebug();
5873
6149
 
5874
- /**
5875
- * Temporary feature: allow force of HTML5 via URL params: sm2-usehtml5audio=0 or 1
5876
- * Ditto for sm2-preferFlash, too.
5877
- */
5878
- // <d>
5879
- (function(){
5880
-
5881
- var a = 'sm2-usehtml5audio=',
5882
- a2 = 'sm2-preferflash=',
5883
- b = null,
5884
- b2 = null,
5885
- l = wl.toLowerCase();
5886
-
5887
- if (l.indexOf(a) !== -1) {
5888
- b = (l.charAt(l.indexOf(a)+a.length) === '1');
5889
- if (hasConsole) {
5890
- console.log((b?'Enabling ':'Disabling ')+'useHTML5Audio via URL parameter');
5891
- }
5892
- sm2.setup({
5893
- 'useHTML5Audio': b
5894
- });
5895
- }
5896
-
5897
- if (l.indexOf(a2) !== -1) {
5898
- b2 = (l.charAt(l.indexOf(a2)+a2.length) === '1');
5899
- if (hasConsole) {
5900
- console.log((b2?'Enabling ':'Disabling ')+'preferFlash via URL parameter');
5901
- }
5902
- sm2.setup({
5903
- 'preferFlash': b2
5904
- });
5905
- }
5906
-
5907
- }());
5908
- // </d>
5909
-
5910
6150
  if (!hasFlash && sm2.hasHTML5) {
6151
+
5911
6152
  sm2._wD('SoundManager 2: No Flash detected' + (!sm2.useHTML5Audio ? ', enabling HTML5.' : '. Trying HTML5-only mode.'), 1);
6153
+
5912
6154
  sm2.setup({
5913
6155
  'useHTML5Audio': true,
5914
6156
  // make sure we aren't preferring flash, either
5915
6157
  // TODO: preferFlash should not matter if flash is not installed. Currently, stuff breaks without the below tweak.
5916
6158
  'preferFlash': false
5917
6159
  });
6160
+
5918
6161
  }
5919
6162
 
5920
6163
  testHTML5();
5921
6164
 
5922
6165
  if (!hasFlash && needsFlash) {
6166
+
5923
6167
  messages.push(strings.needFlash);
6168
+
5924
6169
  // TODO: Fatal here vs. timeout approach, etc.
5925
6170
  // hack: fail sooner.
5926
6171
  sm2.setup({
5927
6172
  'flashLoadTimeout': 1
5928
6173
  });
6174
+
5929
6175
  }
5930
6176
 
5931
6177
  if (doc.removeEventListener) {
@@ -5961,44 +6207,6 @@ featureCheck = function() {
5961
6207
 
5962
6208
  };
5963
6209
 
5964
- /**
5965
- * miscellaneous run-time, pre-init stuff
5966
- */
5967
-
5968
- preInit = function() {
5969
-
5970
- if (mobileHTML5) {
5971
-
5972
- // prefer HTML5 for mobile + tablet-like devices, probably more reliable vs. flash at this point.
5973
-
5974
- // <d>
5975
- if (!sm2.setupOptions.useHTML5Audio || sm2.setupOptions.preferFlash) {
5976
- // notify that defaults are being changed.
5977
- messages.push(strings.mobileUA);
5978
- }
5979
- // </d>
5980
-
5981
- sm2.setupOptions.useHTML5Audio = true;
5982
- sm2.setupOptions.preferFlash = false;
5983
-
5984
- if (is_iDevice || (isAndroid && !ua.match(/android\s2\.3/i))) {
5985
- // iOS and Android devices tend to work better with a single audio instance, specifically for chained playback of sounds in sequence.
5986
- // common use case: exiting sound onfinish() -> createSound() -> play()
5987
- // <d>
5988
- messages.push(strings.globalHTML5);
5989
- // </d>
5990
- if (is_iDevice) {
5991
- sm2.ignoreFlash = true;
5992
- }
5993
- useGlobalHTML5Audio = true;
5994
- }
5995
-
5996
- }
5997
-
5998
- };
5999
-
6000
- preInit();
6001
-
6002
6210
  // sniff up-front
6003
6211
  detectFlash();
6004
6212
 
@@ -6019,7 +6227,10 @@ featureCheck = function() {
6019
6227
 
6020
6228
  // no add/attachevent support - safe to assume no JS -> Flash either
6021
6229
  debugTS('onload', false);
6022
- catchError({type:'NO_DOM2_EVENTS', fatal:true});
6230
+ catchError({
6231
+ type: 'NO_DOM2_EVENTS',
6232
+ fatal: true
6233
+ });
6023
6234
 
6024
6235
  }
6025
6236
 
@@ -6027,7 +6238,7 @@ featureCheck = function() {
6027
6238
 
6028
6239
  // SM2_DEFER details: http://www.schillmania.com/projects/soundmanager2/doc/getstarted/#lazy-loading
6029
6240
 
6030
- if (window.SM2_DEFER === undefined || !SM2_DEFER) {
6241
+ if (window.SM2_DEFER === _undefined || !SM2_DEFER) {
6031
6242
  soundManager = new SoundManager();
6032
6243
  }
6033
6244
 
@@ -6040,33 +6251,75 @@ if (typeof module === 'object' && module && typeof module.exports === 'object')
6040
6251
 
6041
6252
  /**
6042
6253
  * commonJS module
6043
- * note: SM2 requires a window global due to Flash, which makes calls to window.soundManager.
6044
- * flash may not always be needed, but this is not known until async init and SM2 may even "reboot" into Flash mode.
6045
6254
  */
6046
6255
 
6047
- window.soundManager = soundManager;
6048
-
6049
6256
  module.exports.SoundManager = SoundManager;
6050
6257
  module.exports.soundManager = soundManager;
6051
6258
 
6052
6259
  } else if (typeof define === 'function' && define.amd) {
6053
6260
 
6054
- // AMD - requireJS
6261
+ /**
6262
+ * AMD - requireJS
6263
+ * basic usage:
6264
+ * require(["/path/to/soundmanager2.js"], function(SoundManager) {
6265
+ * SoundManager.getInstance().setup({
6266
+ * url: '/swf/',
6267
+ * onready: function() { ... }
6268
+ * })
6269
+ * });
6270
+ *
6271
+ * SM2_DEFER usage:
6272
+ * window.SM2_DEFER = true;
6273
+ * require(["/path/to/soundmanager2.js"], function(SoundManager) {
6274
+ * SoundManager.getInstance(function() {
6275
+ * var soundManager = new SoundManager.constructor();
6276
+ * soundManager.setup({
6277
+ * url: '/swf/',
6278
+ * ...
6279
+ * });
6280
+ * ...
6281
+ * soundManager.beginDelayedInit();
6282
+ * return soundManager;
6283
+ * })
6284
+ * });
6285
+ */
6055
6286
 
6056
- define('SoundManager', [], function() {
6287
+ define(function() {
6288
+ /**
6289
+ * Retrieve the global instance of SoundManager.
6290
+ * If a global instance does not exist it can be created using a callback.
6291
+ *
6292
+ * @param {Function} smBuilder Optional: Callback used to create a new SoundManager instance
6293
+ * @return {SoundManager} The global SoundManager instance
6294
+ */
6295
+ function getInstance(smBuilder) {
6296
+ if (!window.soundManager && smBuilder instanceof Function) {
6297
+ var instance = smBuilder(SoundManager);
6298
+ if (instance instanceof SoundManager) {
6299
+ window.soundManager = instance;
6300
+ }
6301
+ }
6302
+ return window.soundManager;
6303
+ }
6057
6304
  return {
6058
- SoundManager: SoundManager,
6059
- soundManager: soundManager
6060
- };
6305
+ constructor: SoundManager,
6306
+ getInstance: getInstance
6307
+ }
6061
6308
  });
6062
6309
 
6063
- } else {
6310
+ }
6064
6311
 
6065
- // standard browser case
6312
+ // standard browser case
6066
6313
 
6067
- window.SoundManager = SoundManager; // constructor
6068
- window.soundManager = soundManager; // public API, flash callbacks etc.
6314
+ // constructor
6315
+ window.SoundManager = SoundManager;
6069
6316
 
6070
- }
6317
+ /**
6318
+ * note: SM2 requires a window global due to Flash, which makes calls to window.soundManager.
6319
+ * Flash may not always be needed, but this is not known until async init and SM2 may even "reboot" into Flash mode.
6320
+ */
6321
+
6322
+ // public API, flash callbacks etc.
6323
+ window.soundManager = soundManager;
6071
6324
 
6072
6325
  }(window));