soundmanager2-rails 2.97.20140901 → 2.97.20150601

Sign up to get free protection for your applications and to get access to all the features.
@@ -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));