soundmanager2-rails 2.97.20150601 → 2.97.20170601

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,12 +8,9 @@
8
8
  * Code provided under the BSD License:
9
9
  * http://schillmania.com/projects/soundmanager2/license.txt
10
10
  *
11
- * V2.97a.20150601
11
+ * V2.97a.20170601
12
12
  */
13
13
 
14
- /*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio, opera, module, define */
15
- /*jslint regexp: true, sloppy: true, white: true, nomen: true, plusplus: true, todo: true */
16
-
17
14
  /**
18
15
  * About this file
19
16
  * -------------------------------------------------------------------------------------
@@ -30,9 +27,11 @@
30
27
  * Also, as you may note: Whoa, reliable cross-platform/device audio support is hard! ;)
31
28
  */
32
29
 
33
- (function(window, _undefined) {
30
+ (function SM2(window, _undefined) {
31
+
32
+ /* global Audio, document, window, navigator, define, module, SM2_DEFER, opera, setTimeout, setInterval, clearTimeout, sm2Debugger */
34
33
 
35
- "use strict";
34
+ 'use strict';
36
35
 
37
36
  if (!window || !window.document) {
38
37
 
@@ -65,28 +64,28 @@ function SoundManager(smURL, smID) {
65
64
 
66
65
  this.setupOptions = {
67
66
 
68
- 'url': (smURL || null), // path (directory) where SoundManager 2 SWFs exist, eg., /path/to/swfs/
69
- 'flashVersion': 8, // flash build to use (8 or 9.) Some API features require 9.
70
- 'debugMode': true, // enable debugging output (console.log() with HTML fallback)
71
- 'debugFlash': false, // enable debugging output inside SWF, troubleshoot Flash/browser issues
72
- 'useConsole': true, // use console.log() if available (otherwise, writes to #soundmanager-debug element)
73
- 'consoleOnly': true, // if console is being used, do not create/write to #soundmanager-debug
74
- 'waitForWindowLoad': false, // force SM2 to wait for window.onload() before trying to call soundManager.onload()
75
- 'bgColor': '#ffffff', // SWF background color. N/A when wmode = 'transparent'
76
- 'useHighPerformance': false, // position:fixed flash movie can help increase js/flash speed, minimize lag
77
- 'flashPollingInterval': null, // msec affecting whileplaying/loading callback frequency. If null, default of 50 msec is used.
78
- 'html5PollingInterval': null, // msec affecting whileplaying() for HTML5 audio, excluding mobile devices. If null, native HTML5 update events are used.
79
- 'flashLoadTimeout': 1000, // msec to wait for flash movie to load before failing (0 = infinity)
80
- 'wmode': null, // flash rendering mode - null, 'transparent', or 'opaque' (last two allow z-index to work)
81
- 'allowScriptAccess': 'always', // for scripting the SWF (object/embed property), 'always' or 'sameDomain'
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 (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.
86
- 'html5Test': /^(probably|maybe)$/i, // HTML5 Audio() format support test. Use /^probably$/i; if you want to be more conservative.
87
- 'preferFlash': false, // overrides useHTML5audio, will use Flash for MP3/MP4/AAC if present. Potential option if HTML5 playback with these formats is quirky.
88
- 'noSWFCache': false, // if true, appends ?ts={date} to break aggressive SWF caching.
89
- 'idPrefix': 'sound' // if an id is not provided to createSound(), this prefix is used for generated IDs - 'sound0', 'sound1' etc.
67
+ url: (smURL || null), // path (directory) where SoundManager 2 SWFs exist, eg., /path/to/swfs/
68
+ flashVersion: 8, // flash build to use (8 or 9.) Some API features require 9.
69
+ debugMode: true, // enable debugging output (console.log() with HTML fallback)
70
+ debugFlash: false, // enable debugging output inside SWF, troubleshoot Flash/browser issues
71
+ useConsole: true, // use console.log() if available (otherwise, writes to #soundmanager-debug element)
72
+ consoleOnly: true, // if console is being used, do not create/write to #soundmanager-debug
73
+ waitForWindowLoad: false, // force SM2 to wait for window.onload() before trying to call soundManager.onload()
74
+ bgColor: '#ffffff', // SWF background color. N/A when wmode = 'transparent'
75
+ useHighPerformance: false, // position:fixed flash movie can help increase js/flash speed, minimize lag
76
+ flashPollingInterval: null, // msec affecting whileplaying/loading callback frequency. If null, default of 50 msec is used.
77
+ html5PollingInterval: null, // msec affecting whileplaying() for HTML5 audio, excluding mobile devices. If null, native HTML5 update events are used.
78
+ flashLoadTimeout: 1000, // msec to wait for flash movie to load before failing (0 = infinity)
79
+ wmode: null, // flash rendering mode - null, 'transparent', or 'opaque' (last two allow z-index to work)
80
+ allowScriptAccess: 'always', // for scripting the SWF (object/embed property), 'always' or 'sameDomain'
81
+ useFlashBlock: false, // *requires flashblock.css, see demos* - allow recovery from flash blockers. Wait indefinitely and apply timeout CSS to SWF, if applicable.
82
+ useHTML5Audio: true, // use HTML5 Audio() where API is supported (most Safari, Chrome versions), Firefox (MP3/MP4 support varies.) Ideally, transparent vs. Flash API where possible.
83
+ forceUseGlobalHTML5Audio: false, // if true, a single Audio() object is used for all sounds - and only one can play at a time.
84
+ ignoreMobileRestrictions: false, // if true, SM2 will not apply global HTML5 audio rules to mobile UAs. iOS > 7 and WebViews may allow multiple Audio() instances.
85
+ html5Test: /^(probably|maybe)$/i, // HTML5 Audio() format support test. Use /^probably$/i; if you want to be more conservative.
86
+ preferFlash: false, // overrides useHTML5audio, will use Flash for MP3/MP4/AAC if present. Potential option if HTML5 playback with these formats is quirky.
87
+ noSWFCache: false, // if true, appends ?ts={date} to break aggressive SWF caching.
88
+ idPrefix: 'sound' // if an id is not provided to createSound(), this prefix is used for generated IDs - 'sound0', 'sound1' etc.
90
89
 
91
90
  };
92
91
 
@@ -97,30 +96,31 @@ function SoundManager(smURL, smID) {
97
96
  * eg., volume, auto-load behaviour and so forth
98
97
  */
99
98
 
100
- 'autoLoad': false, // enable automatic loading (otherwise .load() will be called on demand with .play(), the latter being nicer on bandwidth - if you want to .load yourself, you also can)
101
- 'autoPlay': false, // enable playing of file as soon as possible (much faster if "stream" is true)
102
- 'from': null, // position to start playback within a sound (msec), default = beginning
103
- 'loops': 1, // how many times to repeat the sound (position will wrap around to 0, setPosition() will break out of loop when >0)
104
- 'onid3': null, // callback function for "ID3 data is added/available"
105
- 'onload': null, // callback function for "load finished"
106
- 'whileloading': null, // callback function for "download progress update" (X of Y bytes received)
107
- 'onplay': null, // callback for "play" start
108
- 'onpause': null, // callback for "pause"
109
- 'onresume': null, // callback for "resume" (pause toggle)
110
- 'whileplaying': null, // callback during play (position update)
111
- 'onposition': null, // object containing times and function callbacks for positions of interest
112
- 'onstop': null, // callback for "user stop"
113
- 'onfailure': null, // callback function for when playing fails
114
- 'onfinish': null, // callback function for "sound finished playing"
115
- 'multiShot': true, // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time
116
- 'multiShotEvents': false, // fire multiple sound events (currently onfinish() only) when multiShot is enabled
117
- 'position': null, // offset (milliseconds) to seek to within loaded sound data.
118
- 'pan': 0, // "pan" settings, left-to-right, -100 to 100
119
- 'stream': true, // allows playing before entire file has loaded (recommended)
120
- 'to': null, // position to end playback within a sound (msec), default = end
121
- 'type': null, // MIME-like hint for file pattern / canPlay() tests, eg. audio/mp3
122
- 'usePolicyFile': false, // enable crossdomain.xml request for audio on remote domains (for ID3/waveform access)
123
- 'volume': 100 // self-explanatory. 0-100, the latter being the max.
99
+ autoLoad: false, // enable automatic loading (otherwise .load() will be called on demand with .play(), the latter being nicer on bandwidth - if you want to .load yourself, you also can)
100
+ autoPlay: false, // enable playing of file as soon as possible (much faster if "stream" is true)
101
+ from: null, // position to start playback within a sound (msec), default = beginning
102
+ loops: 1, // how many times to repeat the sound (position will wrap around to 0, setPosition() will break out of loop when >0)
103
+ onid3: null, // callback function for "ID3 data is added/available"
104
+ onerror: null, // callback function for "load failed" (or, playback/network/decode error under HTML5.)
105
+ onload: null, // callback function for "load finished"
106
+ whileloading: null, // callback function for "download progress update" (X of Y bytes received)
107
+ onplay: null, // callback for "play" start
108
+ onpause: null, // callback for "pause"
109
+ onresume: null, // callback for "resume" (pause toggle)
110
+ whileplaying: null, // callback during play (position update)
111
+ onposition: null, // object containing times and function callbacks for positions of interest
112
+ onstop: null, // callback for "user stop"
113
+ onfinish: null, // callback function for "sound finished playing"
114
+ multiShot: true, // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time
115
+ multiShotEvents: false, // fire multiple sound events (currently onfinish() only) when multiShot is enabled
116
+ position: null, // offset (milliseconds) to seek to within loaded sound data.
117
+ pan: 0, // "pan" settings, left-to-right, -100 to 100
118
+ playbackRate: 1, // rate at which to play the sound (HTML5-only)
119
+ stream: true, // allows playing before entire file has loaded (recommended)
120
+ to: null, // position to end playback within a sound (msec), default = end
121
+ type: null, // MIME-like hint for file pattern / canPlay() tests, eg. audio/mp3
122
+ usePolicyFile: false, // enable crossdomain.xml request for audio on remote domains (for ID3/waveform access)
123
+ volume: 100 // self-explanatory. 0-100, the latter being the max.
124
124
 
125
125
  };
126
126
 
@@ -131,12 +131,13 @@ function SoundManager(smURL, smID) {
131
131
  * merged into defaultOptions if flash 9 is being used
132
132
  */
133
133
 
134
- 'isMovieStar': null, // "MovieStar" MPEG4 audio mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL
135
- 'usePeakData': false, // enable left/right channel peak (level) data
136
- 'useWaveformData': false, // enable sound spectrum (raw waveform data) - NOTE: May increase CPU load.
137
- 'useEQData': false, // enable sound EQ (frequency spectrum data) - NOTE: May increase CPU load.
138
- 'onbufferchange': null, // callback for "isBuffering" property change
139
- 'ondataerror': null // callback for waveform/eq data access error (flash playing audio in other tabs/domains)
134
+ onfailure: null, // callback function for when playing fails (Flash 9, MovieStar + RTMP-only)
135
+ isMovieStar: null, // "MovieStar" MPEG4 audio mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL
136
+ usePeakData: false, // enable left/right channel peak (level) data
137
+ useWaveformData: false, // enable sound spectrum (raw waveform data) - NOTE: May increase CPU load.
138
+ useEQData: false, // enable sound EQ (frequency spectrum data) - NOTE: May increase CPU load.
139
+ onbufferchange: null, // callback for "isBuffering" property change
140
+ ondataerror: null // callback for waveform/eq data access error (flash playing audio in other tabs/domains)
140
141
 
141
142
  };
142
143
 
@@ -147,10 +148,10 @@ function SoundManager(smURL, smID) {
147
148
  * merged into defaultOptions if flash 9+movieStar mode is enabled
148
149
  */
149
150
 
150
- 'bufferTime': 3, // seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try increasing.)
151
- 'serverURL': null, // rtmp: FMS or FMIS server to connect to, required when requesting media via RTMP or one of its variants
152
- 'onconnect': null, // rtmp: callback for connection to flash media server
153
- 'duration': null // rtmp: song duration (msec)
151
+ bufferTime: 3, // seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try increasing.)
152
+ serverURL: null, // rtmp: FMS or FMIS server to connect to, required when requesting media via RTMP or one of its variants
153
+ onconnect: null, // rtmp: callback for connection to flash media server
154
+ duration: null // rtmp: song duration (msec)
154
155
 
155
156
  };
156
157
 
@@ -162,30 +163,35 @@ function SoundManager(smURL, smID) {
162
163
  * flash fallback is used for MP3 or MP4 if HTML5 can't play it (or if preferFlash = true)
163
164
  */
164
165
 
165
- 'mp3': {
166
- 'type': ['audio/mpeg; codecs="mp3"', 'audio/mpeg', 'audio/mp3', 'audio/MPA', 'audio/mpa-robust'],
167
- 'required': true
166
+ mp3: {
167
+ type: ['audio/mpeg; codecs="mp3"', 'audio/mpeg', 'audio/mp3', 'audio/MPA', 'audio/mpa-robust'],
168
+ required: true
169
+ },
170
+
171
+ mp4: {
172
+ related: ['aac', 'm4a', 'm4b'], // additional formats under the MP4 container
173
+ type: ['audio/mp4; codecs="mp4a.40.2"', 'audio/aac', 'audio/x-m4a', 'audio/MP4A-LATM', 'audio/mpeg4-generic'],
174
+ required: false
168
175
  },
169
176
 
170
- 'mp4': {
171
- 'related': ['aac','m4a','m4b'], // additional formats under the MP4 container
172
- 'type': ['audio/mp4; codecs="mp4a.40.2"', 'audio/aac', 'audio/x-m4a', 'audio/MP4A-LATM', 'audio/mpeg4-generic'],
173
- 'required': false
177
+ ogg: {
178
+ type: ['audio/ogg; codecs=vorbis'],
179
+ required: false
174
180
  },
175
181
 
176
- 'ogg': {
177
- 'type': ['audio/ogg; codecs=vorbis'],
178
- 'required': false
182
+ opus: {
183
+ type: ['audio/ogg; codecs=opus', 'audio/opus'],
184
+ required: false
179
185
  },
180
186
 
181
- 'opus': {
182
- 'type': ['audio/ogg; codecs=opus', 'audio/opus'],
183
- 'required': false
187
+ wav: {
188
+ type: ['audio/wav; codecs="1"', 'audio/wav', 'audio/wave', 'audio/x-wav'],
189
+ required: false
184
190
  },
185
191
 
186
- 'wav': {
187
- 'type': ['audio/wav; codecs="1"', 'audio/wav', 'audio/wave', 'audio/x-wav'],
188
- 'required': false
192
+ flac: {
193
+ type: ['audio/flac'],
194
+ required: false
189
195
  }
190
196
 
191
197
  };
@@ -200,7 +206,7 @@ function SoundManager(smURL, smID) {
200
206
 
201
207
  // dynamic attributes
202
208
 
203
- this.versionNumber = 'V2.97a.20150601';
209
+ this.versionNumber = 'V2.97a.20170601';
204
210
  this.version = null;
205
211
  this.movieURL = null;
206
212
  this.altURL = null;
@@ -214,34 +220,34 @@ function SoundManager(smURL, smID) {
214
220
  this.filePattern = null;
215
221
 
216
222
  this.filePatterns = {
217
- 'flash8': /\.mp3(\?.*)?$/i,
218
- 'flash9': /\.mp3(\?.*)?$/i
223
+ flash8: /\.mp3(\?.*)?$/i,
224
+ flash9: /\.mp3(\?.*)?$/i
219
225
  };
220
226
 
221
227
  // support indicators, set at init
222
228
 
223
229
  this.features = {
224
- 'buffering': false,
225
- 'peakData': false,
226
- 'waveformData': false,
227
- 'eqData': false,
228
- 'movieStar': false
230
+ buffering: false,
231
+ peakData: false,
232
+ waveformData: false,
233
+ eqData: false,
234
+ movieStar: false
229
235
  };
230
236
 
231
237
  // flash sandbox info, used primarily in troubleshooting
232
238
 
233
239
  this.sandbox = {
234
240
  // <d>
235
- 'type': null,
236
- 'types': {
237
- 'remote': 'remote (domain-based) rules',
238
- 'localWithFile': 'local with file access (no internet access)',
239
- 'localWithNetwork': 'local with network (internet access only, no local access)',
240
- 'localTrusted': 'local, trusted (local+internet access)'
241
+ type: null,
242
+ types: {
243
+ remote: 'remote (domain-based) rules',
244
+ localWithFile: 'local with file access (no internet access)',
245
+ localWithNetwork: 'local with network (internet access only, no local access)',
246
+ localTrusted: 'local, trusted (local+internet access)'
241
247
  },
242
- 'description': null,
243
- 'noRemote': null,
244
- 'noLocal': null
248
+ description: null,
249
+ noRemote: null,
250
+ noLocal: null
245
251
  // </d>
246
252
  };
247
253
 
@@ -253,7 +259,7 @@ function SoundManager(smURL, smID) {
253
259
  */
254
260
 
255
261
  this.html5 = {
256
- 'usingFlash': null // set if/when flash fallback is needed
262
+ usingFlash: null // set if/when flash fallback is needed
257
263
  };
258
264
 
259
265
  // file type support hash
@@ -271,13 +277,13 @@ function SoundManager(smURL, smID) {
271
277
 
272
278
  var SMSound,
273
279
  sm2 = this, globalHTML5Audio = null, flash = null, sm = 'soundManager', smc = sm + ': ', h5 = 'HTML5::', id, ua = navigator.userAgent, wl = window.location.href.toString(), doc = document, doNothing, setProperties, init, fV, on_queue = [], debugOpen = true, debugTS, didAppend = false, appendSuccess = false, didInit = false, disabled = false, windowLoaded = false, _wDS, wdCount = 0, initComplete, mixin, assign, extraOptions, addOnEvent, processOnEvents, initUserOnload, delayWaitForEI, waitForEI, rebootIntoHTML5, setVersionInfo, handleFocus, strings, initMovie, domContentLoaded, winOnLoad, didDCLoaded, getDocument, createMovie, catchError, setPolling, initDebug, debugLevels = ['log', 'info', 'warn', 'error'], defaultFlashVersion = 8, disableObject, failSafely, normalizeMovieURL, oRemoved = null, oRemovedHTML = null, str, flashBlockHandler, getSWFCSS, swfCSS, toggleDebug, loopFix, policyFix, complain, idCheck, waitingForEI = false, initPending = false, startTimer, stopTimer, timerExecute, h5TimerCount = 0, h5IntervalTimer = null, parseURL, messages = [],
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),
280
+ canIgnoreFlash, needsFlash = null, featureCheck, html5OK, html5CanPlay, html5ErrorCodes, html5Ext, html5Unload, domContentLoadedIE, testHTML5, event, slice = Array.prototype.slice, useGlobalHTML5Audio = false, lastGlobalHTML5URL, hasFlash, detectFlash, badSafariFix, html5_events, showSupport, flushMessages, wrapCallback, idCounter = 0, didSetup, msecScale = 1000,
281
+ is_iDevice = ua.match(/(ipad|iphone|ipod)/i), isAndroid = ua.match(/android/i), isIE = ua.match(/msie|trident/i),
276
282
  isWebkit = ua.match(/webkit/i),
277
283
  isSafari = (ua.match(/safari/i) && !ua.match(/chrome/i)),
278
284
  isOpera = (ua.match(/opera/i)),
279
285
  mobileHTML5 = (ua.match(/(mobile|pre\/|xoom)/i) || is_iDevice || isAndroid),
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
286
+ isBadSafari = (!wl.match(/usehtml5audio/i) && !wl.match(/sm2-ignorebadua/i) && isSafari && !ua.match(/silk/i) && ua.match(/OS\sX\s10_6_([3-7])/i)), // Safari 4 and 5 (excluding Kindle Fire, "Silk") occasionally fail to load/play HTML5 audio on Snow Leopard 10.6.3 through 10.6.7 due to bug(s) in QuickTime X and/or other underlying frameworks. :/ Confirmed bug. https://bugs.webkit.org/show_bug.cgi?id=32159
281
287
  hasConsole = (window.console !== _undefined && console.log !== _undefined),
282
288
  isFocused = (doc.hasFocus !== _undefined ? doc.hasFocus() : null),
283
289
  tryInitOnFocus = (isSafari && (doc.hasFocus === _undefined || !doc.hasFocus())),
@@ -286,9 +292,9 @@ function SoundManager(smURL, smID) {
286
292
  emptyURL = 'about:blank', // safe URL to unload, or load nothing from (flash 8 + most HTML5 UAs)
287
293
  emptyWAV = 'data:audio/wave;base64,/UklGRiYAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQIAAAD//w==', // tiny WAV for HTML5 unloading
288
294
  overHTTP = (doc.location ? doc.location.protocol.match(/http/i) : null),
289
- http = (!overHTTP ? 'http:/'+'/' : ''),
295
+ http = (!overHTTP ? '//' : ''),
290
296
  // mp3, mp4, aac etc.
291
- netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,
297
+ netStreamMimeTypes = /^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4|m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,
292
298
  // Flash v9.0r115+ "moviestar" formats
293
299
  netStreamTypes = ['mpeg4', 'aac', 'flv', 'mov', 'mp4', 'm4v', 'f4v', 'm4a', 'm4b', 'mp4v', '3gp', '3g2'],
294
300
  netStreamPattern = new RegExp('\\.(' + netStreamTypes.join('|') + ')(\\?.*)?$', 'i');
@@ -299,17 +305,33 @@ function SoundManager(smURL, smID) {
299
305
  this.useAltURL = !overHTTP;
300
306
 
301
307
  swfCSS = {
302
- 'swfBox': 'sm2-object-box',
303
- 'swfDefault': 'movieContainer',
304
- 'swfError': 'swf_error', // SWF loaded, but SM2 couldn't start (other error)
305
- 'swfTimedout': 'swf_timedout',
306
- 'swfLoaded': 'swf_loaded',
307
- 'swfUnblocked': 'swf_unblocked', // or loaded OK
308
- 'sm2Debug': 'sm2_debug',
309
- 'highPerf': 'high_performance',
310
- 'flashDebug': 'flash_debug'
308
+ swfBox: 'sm2-object-box',
309
+ swfDefault: 'movieContainer',
310
+ swfError: 'swf_error', // SWF loaded, but SM2 couldn't start (other error)
311
+ swfTimedout: 'swf_timedout',
312
+ swfLoaded: 'swf_loaded',
313
+ swfUnblocked: 'swf_unblocked', // or loaded OK
314
+ sm2Debug: 'sm2_debug',
315
+ highPerf: 'high_performance',
316
+ flashDebug: 'flash_debug'
311
317
  };
312
318
 
319
+ /**
320
+ * HTML5 error codes, per W3C
321
+ * Error code 1, MEDIA_ERR_ABORTED: Client aborted download at user's request.
322
+ * Error code 2, MEDIA_ERR_NETWORK: A network error of some description caused the user agent to stop fetching the media resource, after the resource was established to be usable.
323
+ * Error code 3, MEDIA_ERR_DECODE: An error of some description occurred while decoding the media resource, after the resource was established to be usable.
324
+ * Error code 4, MEDIA_ERR_SRC_NOT_SUPPORTED: Media (audio file) not supported ("not usable.")
325
+ * Reference: https://html.spec.whatwg.org/multipage/embedded-content.html#error-codes
326
+ */
327
+ html5ErrorCodes = [
328
+ null,
329
+ 'MEDIA_ERR_ABORTED',
330
+ 'MEDIA_ERR_NETWORK',
331
+ 'MEDIA_ERR_DECODE',
332
+ 'MEDIA_ERR_SRC_NOT_SUPPORTED'
333
+ ];
334
+
313
335
  /**
314
336
  * basic HTML5 Audio() support test
315
337
  * try...catch because of IE 9 "not implemented" nonsense
@@ -361,13 +383,11 @@ function SoundManager(smURL, smID) {
361
383
  useGlobalHTML5Audio = true;
362
384
  }
363
385
 
364
- } else {
386
+ } else if (sm2.setupOptions.forceUseGlobalHTML5Audio) {
365
387
 
366
388
  // only apply singleton HTML5 on desktop if forced.
367
- if (sm2.setupOptions.forceUseGlobalHTML5Audio) {
368
- messages.push(strings.globalHTML5);
369
- useGlobalHTML5Audio = true;
370
- }
389
+ messages.push(strings.globalHTML5);
390
+ useGlobalHTML5Audio = true;
371
391
 
372
392
  }
373
393
 
@@ -376,9 +396,9 @@ function SoundManager(smURL, smID) {
376
396
  if (!didSetup && mobileHTML5) {
377
397
 
378
398
  if (sm2.setupOptions.ignoreMobileRestrictions) {
379
-
399
+
380
400
  messages.push(strings.ignoreMobile);
381
-
401
+
382
402
  } else {
383
403
 
384
404
  // prefer HTML5 for mobile + tablet-like devices, probably more reliable vs. flash at this point.
@@ -399,7 +419,7 @@ function SoundManager(smURL, smID) {
399
419
  sm2.ignoreFlash = true;
400
420
 
401
421
  } else if ((isAndroid && !ua.match(/android\s2\.3/i)) || !isAndroid) {
402
-
422
+
403
423
  /**
404
424
  * Android devices tend to work better with a single audio instance, specifically for chained playback of sounds in sequence.
405
425
  * Common use case: exiting sound onfinish() -> createSound() -> play()
@@ -448,10 +468,10 @@ function SoundManager(smURL, smID) {
448
468
 
449
469
  this.supported = this.ok; // legacy
450
470
 
451
- this.getMovie = function(smID) {
471
+ this.getMovie = function(movie_id) {
452
472
 
453
473
  // safety net: some old browsers differ on SWF references, possibly related to ExternalInterface / flash version
454
- return id(smID) || doc[smID] || window[smID];
474
+ return id(movie_id) || doc[movie_id] || window[movie_id];
455
475
 
456
476
  };
457
477
 
@@ -479,8 +499,8 @@ function SoundManager(smURL, smID) {
479
499
  if (_url !== _undefined) {
480
500
  // function overloading in JS! :) ... assume simple createSound(id, url) use case.
481
501
  oOptions = {
482
- 'id': oOptions,
483
- 'url': _url
502
+ id: oOptions,
503
+ url: _url
484
504
  };
485
505
  }
486
506
 
@@ -535,7 +555,7 @@ function SoundManager(smURL, smID) {
535
555
 
536
556
  // TODO: Move HTML5/flash checks into generic URL parsing/handling function.
537
557
 
538
- if (sm2.html5.usingFlash && options.url && options.url.match(/data\:/i)) {
558
+ if (sm2.html5.usingFlash && options.url && options.url.match(/data:/i)) {
539
559
  // data: URIs not supported by Flash, either.
540
560
  sm2._wD(options.id + ': data: URIs not supported via Flash. Exiting.');
541
561
  return make();
@@ -598,17 +618,15 @@ function SoundManager(smURL, smID) {
598
618
 
599
619
  // explicitly destroy a sound before normal page unload, etc.
600
620
 
601
- if (!idCheck(sID)) {
602
- return false;
603
- }
621
+ if (!idCheck(sID)) return false;
604
622
 
605
623
  var oS = sm2.sounds[sID], i;
606
624
 
607
625
  oS.stop();
608
-
626
+
609
627
  // Disable all callbacks after stop(), when the sound is being destroyed
610
628
  oS._iO = {};
611
-
629
+
612
630
  oS.unload();
613
631
 
614
632
  for (i = 0; i < sm2.soundIDs.length; i++) {
@@ -639,9 +657,8 @@ function SoundManager(smURL, smID) {
639
657
 
640
658
  this.load = function(sID, oOptions) {
641
659
 
642
- if (!idCheck(sID)) {
643
- return false;
644
- }
660
+ if (!idCheck(sID)) return false;
661
+
645
662
  return sm2.sounds[sID].load(oOptions);
646
663
 
647
664
  };
@@ -654,9 +671,8 @@ function SoundManager(smURL, smID) {
654
671
 
655
672
  this.unload = function(sID) {
656
673
 
657
- if (!idCheck(sID)) {
658
- return false;
659
- }
674
+ if (!idCheck(sID)) return false;
675
+
660
676
  return sm2.sounds[sID].unload();
661
677
 
662
678
  };
@@ -673,9 +689,8 @@ function SoundManager(smURL, smID) {
673
689
 
674
690
  this.onPosition = function(sID, nPosition, oMethod, oScope) {
675
691
 
676
- if (!idCheck(sID)) {
677
- return false;
678
- }
692
+ if (!idCheck(sID)) return false;
693
+
679
694
  return sm2.sounds[sID].onposition(nPosition, oMethod, oScope);
680
695
 
681
696
  };
@@ -694,9 +709,8 @@ function SoundManager(smURL, smID) {
694
709
 
695
710
  this.clearOnPosition = function(sID, nPosition, oMethod) {
696
711
 
697
- if (!idCheck(sID)) {
698
- return false;
699
- }
712
+ if (!idCheck(sID)) return false;
713
+
700
714
  return sm2.sounds[sID].clearOnPosition(nPosition, oMethod);
701
715
 
702
716
  };
@@ -716,16 +730,14 @@ function SoundManager(smURL, smID) {
716
730
  overloaded = (oOptions && !(oOptions instanceof Object));
717
731
 
718
732
  if (!didInit || !sm2.ok()) {
719
- complain(sm + '.play(): ' + str(!didInit?'notReady':'notOK'));
733
+ complain(sm + '.play(): ' + str(!didInit ? 'notReady' : 'notOK'));
720
734
  return false;
721
735
  }
722
736
 
723
737
  if (!idCheck(sID, overloaded)) {
724
738
 
725
- if (!overloaded) {
726
- // no sound found for the given ID. Bail.
727
- return false;
728
- }
739
+ // no sound found for the given ID. Bail.
740
+ if (!overloaded) return false;
729
741
 
730
742
  if (overloaded) {
731
743
  oOptions = {
@@ -761,6 +773,21 @@ function SoundManager(smURL, smID) {
761
773
  // just for convenience
762
774
  this.start = this.play;
763
775
 
776
+ /**
777
+ * Calls the setPlaybackRate() method of a SMSound object by ID.
778
+ *
779
+ * @param {string} sID The ID of the sound
780
+ * @return {SMSound} The SMSound object
781
+ */
782
+
783
+ this.setPlaybackRate = function(sID, rate, allowOverride) {
784
+
785
+ if (!idCheck(sID)) return false;
786
+
787
+ return sm2.sounds[sID].setPlaybackRate(rate, allowOverride);
788
+
789
+ };
790
+
764
791
  /**
765
792
  * Calls the setPosition() method of a SMSound object by ID.
766
793
  *
@@ -771,9 +798,8 @@ function SoundManager(smURL, smID) {
771
798
 
772
799
  this.setPosition = function(sID, nMsecOffset) {
773
800
 
774
- if (!idCheck(sID)) {
775
- return false;
776
- }
801
+ if (!idCheck(sID)) return false;
802
+
777
803
  return sm2.sounds[sID].setPosition(nMsecOffset);
778
804
 
779
805
  };
@@ -787,11 +813,10 @@ function SoundManager(smURL, smID) {
787
813
 
788
814
  this.stop = function(sID) {
789
815
 
790
- if (!idCheck(sID)) {
791
- return false;
792
- }
816
+ if (!idCheck(sID)) return false;
793
817
 
794
818
  sm2._wD(sm + '.stop(' + sID + ')', 1);
819
+
795
820
  return sm2.sounds[sID].stop();
796
821
 
797
822
  };
@@ -823,9 +848,8 @@ function SoundManager(smURL, smID) {
823
848
 
824
849
  this.pause = function(sID) {
825
850
 
826
- if (!idCheck(sID)) {
827
- return false;
828
- }
851
+ if (!idCheck(sID)) return false;
852
+
829
853
  return sm2.sounds[sID].pause();
830
854
 
831
855
  };
@@ -852,9 +876,8 @@ function SoundManager(smURL, smID) {
852
876
 
853
877
  this.resume = function(sID) {
854
878
 
855
- if (!idCheck(sID)) {
856
- return false;
857
- }
879
+ if (!idCheck(sID)) return false;
880
+
858
881
  return sm2.sounds[sID].resume();
859
882
 
860
883
  };
@@ -866,7 +889,7 @@ function SoundManager(smURL, smID) {
866
889
  this.resumeAll = function() {
867
890
 
868
891
  var i;
869
- for (i = sm2.soundIDs.length- 1 ; i >= 0; i--) {
892
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
870
893
  sm2.sounds[sm2.soundIDs[i]].resume();
871
894
  }
872
895
 
@@ -881,9 +904,8 @@ function SoundManager(smURL, smID) {
881
904
 
882
905
  this.togglePause = function(sID) {
883
906
 
884
- if (!idCheck(sID)) {
885
- return false;
886
- }
907
+ if (!idCheck(sID)) return false;
908
+
887
909
  return sm2.sounds[sID].togglePause();
888
910
 
889
911
  };
@@ -898,9 +920,8 @@ function SoundManager(smURL, smID) {
898
920
 
899
921
  this.setPan = function(sID, nPan) {
900
922
 
901
- if (!idCheck(sID)) {
902
- return false;
903
- }
923
+ if (!idCheck(sID)) return false;
924
+
904
925
  return sm2.sounds[sID].setPan(nPan);
905
926
 
906
927
  };
@@ -924,14 +945,12 @@ function SoundManager(smURL, smID) {
924
945
  for (i = 0, j = sm2.soundIDs.length; i < j; i++) {
925
946
  sm2.sounds[sm2.soundIDs[i]].setVolume(sID);
926
947
  }
927
- return;
948
+ return false;
928
949
  }
929
950
 
930
951
  // setVolume('mySound', 50) case
931
952
 
932
- if (!idCheck(sID)) {
933
- return false;
934
- }
953
+ if (!idCheck(sID)) return false;
935
954
 
936
955
  return sm2.sounds[sID].setVolume(nVol);
937
956
 
@@ -961,9 +980,8 @@ function SoundManager(smURL, smID) {
961
980
 
962
981
  } else {
963
982
 
964
- if (!idCheck(sID)) {
965
- return false;
966
- }
983
+ if (!idCheck(sID)) return false;
984
+
967
985
  sm2._wD(sm + '.mute(): Muting "' + sID + '"');
968
986
  return sm2.sounds[sID].mute();
969
987
 
@@ -1007,10 +1025,10 @@ function SoundManager(smURL, smID) {
1007
1025
 
1008
1026
  } else {
1009
1027
 
1010
- if (!idCheck(sID)) {
1011
- return false;
1012
- }
1028
+ if (!idCheck(sID)) return false;
1029
+
1013
1030
  sm2._wD(sm + '.unmute(): Unmuting "' + sID + '"');
1031
+
1014
1032
  return sm2.sounds[sID].unmute();
1015
1033
 
1016
1034
  }
@@ -1038,9 +1056,8 @@ function SoundManager(smURL, smID) {
1038
1056
 
1039
1057
  this.toggleMute = function(sID) {
1040
1058
 
1041
- if (!idCheck(sID)) {
1042
- return false;
1043
- }
1059
+ if (!idCheck(sID)) return false;
1060
+
1044
1061
  return sm2.sounds[sID].toggleMute();
1045
1062
 
1046
1063
  };
@@ -1077,19 +1094,22 @@ function SoundManager(smURL, smID) {
1077
1094
  bNoDisable = false;
1078
1095
  }
1079
1096
 
1080
- if (disabled) {
1081
- return false;
1082
- }
1097
+ // already disabled?
1098
+ if (disabled) return false;
1083
1099
 
1084
1100
  disabled = true;
1101
+
1085
1102
  _wDS('shutdown', 1);
1086
1103
 
1087
1104
  for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
1088
1105
  disableObject(sm2.sounds[sm2.soundIDs[i]]);
1089
1106
  }
1090
1107
 
1108
+ disableObject(sm2);
1109
+
1091
1110
  // fire "complete", despite fail
1092
1111
  initComplete(bNoDisable);
1112
+
1093
1113
  event.remove(window, 'load', initUserOnload);
1094
1114
 
1095
1115
  return true;
@@ -1153,11 +1173,7 @@ function SoundManager(smURL, smID) {
1153
1173
 
1154
1174
  this.canPlayLink = function(oLink) {
1155
1175
 
1156
- if (oLink.type !== _undefined && oLink.type) {
1157
- if (sm2.canPlayMIME(oLink.type)) {
1158
- return true;
1159
- }
1160
- }
1176
+ if (oLink.type !== _undefined && oLink.type && sm2.canPlayMIME(oLink.type)) return true;
1161
1177
 
1162
1178
  return sm2.canPlayURL(oLink.href);
1163
1179
 
@@ -1172,9 +1188,7 @@ function SoundManager(smURL, smID) {
1172
1188
 
1173
1189
  this.getSoundById = function(sID, _suppressDebug) {
1174
1190
 
1175
- if (!sID) {
1176
- return null;
1177
- }
1191
+ if (!sID) return null;
1178
1192
 
1179
1193
  var result = sm2.sounds[sID];
1180
1194
 
@@ -1252,7 +1266,7 @@ function SoundManager(smURL, smID) {
1252
1266
  }
1253
1267
 
1254
1268
  addOnEvent(sType, oMethod, oScope);
1255
- processOnEvents({type:sType});
1269
+ processOnEvents({ type: sType });
1256
1270
 
1257
1271
  result = true;
1258
1272
 
@@ -1281,9 +1295,7 @@ function SoundManager(smURL, smID) {
1281
1295
 
1282
1296
  var sDID = 'soundmanager-debug', o, oItem;
1283
1297
 
1284
- if (!sm2.setupOptions.debugMode) {
1285
- return false;
1286
- }
1298
+ if (!sm2.setupOptions.debugMode) return false;
1287
1299
 
1288
1300
  if (hasConsole && sm2.useConsole) {
1289
1301
  if (sTypeOrObject && typeof sTypeOrObject === 'object') {
@@ -1294,16 +1306,12 @@ function SoundManager(smURL, smID) {
1294
1306
  } else {
1295
1307
  console.log(sText);
1296
1308
  }
1297
- if (sm2.consoleOnly) {
1298
- return true;
1299
- }
1309
+ if (sm2.consoleOnly) return true;
1300
1310
  }
1301
1311
 
1302
1312
  o = id(sDID);
1303
1313
 
1304
- if (!o) {
1305
- return false;
1306
- }
1314
+ if (!o) return false;
1307
1315
 
1308
1316
  oItem = doc.createElement('div');
1309
1317
 
@@ -1390,7 +1398,7 @@ function SoundManager(smURL, smID) {
1390
1398
 
1391
1399
  var i, j, k;
1392
1400
 
1393
- for (i = sm2.soundIDs.length- 1 ; i >= 0; i--) {
1401
+ for (i = sm2.soundIDs.length - 1; i >= 0; i--) {
1394
1402
  sm2.sounds[sm2.soundIDs[i]].destruct();
1395
1403
  }
1396
1404
 
@@ -1451,7 +1459,7 @@ function SoundManager(smURL, smID) {
1451
1459
  // reset HTML5 and flash canPlay test results
1452
1460
 
1453
1461
  sm2.html5 = {
1454
- 'usingFlash': null
1462
+ usingFlash: null
1455
1463
  };
1456
1464
 
1457
1465
  sm2.flash = {};
@@ -1484,6 +1492,7 @@ function SoundManager(smURL, smID) {
1484
1492
  */
1485
1493
 
1486
1494
  _wDS('reset');
1495
+
1487
1496
  return sm2.reboot(true, true);
1488
1497
 
1489
1498
  };
@@ -1499,12 +1508,11 @@ function SoundManager(smURL, smID) {
1499
1508
  /**
1500
1509
  * Interesting syntax notes...
1501
1510
  * Flash/ExternalInterface (ActiveX/NPAPI) bridge methods are not typeof "function" nor instanceof Function, but are still valid.
1502
- * Additionally, JSLint dislikes ('PercentLoaded' in flash)-style syntax and recommends hasOwnProperty(), which does not work in this case.
1503
1511
  * Furthermore, using (flash && flash.PercentLoaded) causes IE to throw "object doesn't support this property or method".
1504
1512
  * Thus, 'in' syntax must be used.
1505
1513
  */
1506
1514
 
1507
- return (flash && 'PercentLoaded' in flash ? flash.PercentLoaded() : null); // Yes, JSLint. See nearby comment in source for explanation.
1515
+ return (flash && 'PercentLoaded' in flash ? flash.PercentLoaded() : null);
1508
1516
 
1509
1517
  };
1510
1518
 
@@ -1519,9 +1527,7 @@ function SoundManager(smURL, smID) {
1519
1527
 
1520
1528
  setTimeout(function() {
1521
1529
 
1522
- if (initPending) {
1523
- return false;
1524
- }
1530
+ if (initPending) return false;
1525
1531
 
1526
1532
  createMovie();
1527
1533
  initMovie();
@@ -1589,7 +1595,7 @@ function SoundManager(smURL, smID) {
1589
1595
  this._a = null;
1590
1596
 
1591
1597
  // for flash 8 special-case createSound() without url, followed by load/play with url case
1592
- urlOmitted = (this.url ? false : true);
1598
+ urlOmitted = (!this.url);
1593
1599
 
1594
1600
  /**
1595
1601
  * SMSound() public methods
@@ -1613,19 +1619,19 @@ function SoundManager(smURL, smID) {
1613
1619
  /**
1614
1620
  * Begins loading a sound per its *url*.
1615
1621
  *
1616
- * @param {object} oOptions Optional: Sound options
1622
+ * @param {object} options Optional: Sound options
1617
1623
  * @return {SMSound} The SMSound object
1618
1624
  */
1619
1625
 
1620
- this.load = function(oOptions) {
1626
+ this.load = function(options) {
1621
1627
 
1622
1628
  var oSound = null, instanceOptions;
1623
1629
 
1624
- if (oOptions !== _undefined) {
1625
- s._iO = mixin(oOptions, s.options);
1630
+ if (options !== _undefined) {
1631
+ s._iO = mixin(options, s.options);
1626
1632
  } else {
1627
- oOptions = s.options;
1628
- s._iO = oOptions;
1633
+ options = s.options;
1634
+ s._iO = options;
1629
1635
  if (lastURL && lastURL !== s.url) {
1630
1636
  _wDS('manURL');
1631
1637
  s._iO.url = s.url;
@@ -1729,7 +1735,7 @@ function SoundManager(smURL, smID) {
1729
1735
  return s;
1730
1736
  }
1731
1737
 
1732
- if (s._iO.url && s._iO.url.match(/data\:/i)) {
1738
+ if (s._iO.url && s._iO.url.match(/data:/i)) {
1733
1739
  // data: URIs not supported by Flash, either.
1734
1740
  sm2._wD(s.id + ': data: URIs not supported via Flash. Exiting.');
1735
1741
  return s;
@@ -1858,16 +1864,15 @@ function SoundManager(smURL, smID) {
1858
1864
  /**
1859
1865
  * Begins playing a sound.
1860
1866
  *
1861
- * @param {object} oOptions Optional: Sound options
1867
+ * @param {object} options Optional: Sound options
1862
1868
  * @return {SMSound} The SMSound object
1863
1869
  */
1864
1870
 
1865
- this.play = function(oOptions, _updatePlayState) {
1871
+ this.play = function(options, _updatePlayState) {
1866
1872
 
1867
1873
  var fN, allowMulti, a, onready,
1868
1874
  audioClone, onended, oncanplay,
1869
- startOK = true,
1870
- exit = null;
1875
+ startOK = true;
1871
1876
 
1872
1877
  // <d>
1873
1878
  fN = s.id + ': play(): ';
@@ -1876,8 +1881,8 @@ function SoundManager(smURL, smID) {
1876
1881
  // default to true
1877
1882
  _updatePlayState = (_updatePlayState === _undefined ? true : _updatePlayState);
1878
1883
 
1879
- if (!oOptions) {
1880
- oOptions = {};
1884
+ if (!options) {
1885
+ options = {};
1881
1886
  }
1882
1887
 
1883
1888
  // first, use local URL (if specified)
@@ -1889,7 +1894,7 @@ function SoundManager(smURL, smID) {
1889
1894
  s._iO = mixin(s._iO, s.options);
1890
1895
 
1891
1896
  // mix in any options specific to this method
1892
- s._iO = mixin(oOptions, s._iO);
1897
+ s._iO = mixin(options, s._iO);
1893
1898
 
1894
1899
  s._iO.url = parseURL(s._iO.url);
1895
1900
 
@@ -1898,7 +1903,7 @@ function SoundManager(smURL, smID) {
1898
1903
  // RTMP-only
1899
1904
  if (!s.isHTML5 && s._iO.serverURL && !s.connected) {
1900
1905
  if (!s.getAutoPlay()) {
1901
- sm2._wD(fN +' Netstream not connected yet - setting autoPlay');
1906
+ sm2._wD(fN + ' Netstream not connected yet - setting autoPlay');
1902
1907
  s.setAutoPlay(true);
1903
1908
  }
1904
1909
  // play will be called in onconnect()
@@ -1923,20 +1928,16 @@ function SoundManager(smURL, smID) {
1923
1928
  s.setPosition(s._iO.position);
1924
1929
  }
1925
1930
 
1926
- exit = s;
1931
+ return s;
1927
1932
 
1928
- } else {
1929
- sm2._wD(fN + 'Already playing (multi-shot)', 1);
1930
1933
  }
1931
1934
 
1932
- }
1935
+ sm2._wD(fN + 'Already playing (multi-shot)', 1);
1933
1936
 
1934
- if (exit !== null) {
1935
- return exit;
1936
1937
  }
1937
1938
 
1938
1939
  // edge case: play() with explicit URL parameter
1939
- if (oOptions.url && oOptions.url !== s.url) {
1940
+ if (options.url && options.url !== s.url) {
1940
1941
 
1941
1942
  // special case for createSound() followed by load() / play() with url; avoid double-load case.
1942
1943
  if (!s.readyState && !s.isHTML5 && fV === 8 && urlOmitted) {
@@ -1973,7 +1974,8 @@ function SoundManager(smURL, smID) {
1973
1974
  } else {
1974
1975
 
1975
1976
  sm2._wD(fN + 'Unsupported type. Exiting.');
1976
- exit = s;
1977
+
1978
+ return s;
1977
1979
 
1978
1980
  }
1979
1981
 
@@ -1983,7 +1985,8 @@ function SoundManager(smURL, smID) {
1983
1985
  } else if (s.readyState === 2) {
1984
1986
 
1985
1987
  sm2._wD(fN + 'Could not load - exiting', 2);
1986
- exit = s;
1988
+
1989
+ return s;
1987
1990
 
1988
1991
  } else {
1989
1992
 
@@ -1998,14 +2001,10 @@ function SoundManager(smURL, smID) {
1998
2001
 
1999
2002
  }
2000
2003
 
2001
- if (exit !== null) {
2002
- return exit;
2003
- }
2004
-
2005
2004
  if (!s.isHTML5 && fV === 9 && s.position > 0 && s.position === s.duration) {
2006
2005
  // flash 9 needs a position reset if play() is called while at the end of a sound.
2007
2006
  sm2._wD(fN + 'Sound at end, resetting to position: 0');
2008
- oOptions.position = 0;
2007
+ options.position = 0;
2009
2008
  }
2010
2009
 
2011
2010
  /**
@@ -2025,7 +2024,7 @@ function SoundManager(smURL, smID) {
2025
2024
 
2026
2025
  } else {
2027
2026
 
2028
- s._iO = mixin(oOptions, s._iO);
2027
+ s._iO = mixin(options, s._iO);
2029
2028
 
2030
2029
  /**
2031
2030
  * Preload in the event of play() with position under Flash,
@@ -2036,7 +2035,7 @@ function SoundManager(smURL, smID) {
2036
2035
  onready = function() {
2037
2036
  // sound "canplay" or onload()
2038
2037
  // re-apply position/from/to to instance options, and start playback
2039
- s._iO = mixin(oOptions, s._iO);
2038
+ s._iO = mixin(options, s._iO);
2040
2039
  s.play(s._iO);
2041
2040
  };
2042
2041
 
@@ -2051,8 +2050,6 @@ function SoundManager(smURL, smID) {
2051
2050
  _oncanplay: onready
2052
2051
  });
2053
2052
 
2054
- exit = false;
2055
-
2056
2053
  } else if (!s.isHTML5 && !s.loaded && (!s.readyState || s.readyState !== 2)) {
2057
2054
 
2058
2055
  // to be safe, preload the whole thing in Flash.
@@ -2063,12 +2060,6 @@ function SoundManager(smURL, smID) {
2063
2060
  onload: onready
2064
2061
  });
2065
2062
 
2066
- exit = false;
2067
-
2068
- }
2069
-
2070
- if (exit !== null) {
2071
- return exit;
2072
2063
  }
2073
2064
 
2074
2065
  // otherwise, we're ready to go. re-apply local options, and continue
@@ -2106,6 +2097,10 @@ function SoundManager(smURL, smID) {
2106
2097
  s.setVolume(s._iO.volume, true);
2107
2098
  s.setPan(s._iO.pan, true);
2108
2099
 
2100
+ if (s._iO.playbackRate !== 1) {
2101
+ s.setPlaybackRate(s._iO.playbackRate);
2102
+ }
2103
+
2109
2104
  if (!s.isHTML5) {
2110
2105
 
2111
2106
  startOK = flash._start(s.id, s._iO.loops || 1, (fV === 9 ? s.position : s.position / msecScale), s._iO.multiShot || false);
@@ -2121,9 +2116,7 @@ function SoundManager(smURL, smID) {
2121
2116
 
2122
2117
  }
2123
2118
 
2124
- } else {
2125
-
2126
- if (s.instanceCount < 2) {
2119
+ } else if (s.instanceCount < 2) {
2127
2120
 
2128
2121
  // HTML5 single-instance case
2129
2122
 
@@ -2154,9 +2147,9 @@ function SoundManager(smURL, smID) {
2154
2147
  oncanplay = function() {
2155
2148
  event.remove(audioClone, 'canplay', oncanplay);
2156
2149
  try {
2157
- audioClone.currentTime = s._iO.position/msecScale;
2150
+ audioClone.currentTime = s._iO.position / msecScale;
2158
2151
  } catch(err) {
2159
- complain(s.id + ': multiShot play() failed to apply position of ' + (s._iO.position/msecScale));
2152
+ complain(s.id + ': multiShot play() failed to apply position of ' + (s._iO.position / msecScale));
2160
2153
  }
2161
2154
  audioClone.play();
2162
2155
  };
@@ -2165,7 +2158,7 @@ function SoundManager(smURL, smID) {
2165
2158
 
2166
2159
  // apply volume to clones, too
2167
2160
  if (s._iO.volume !== _undefined) {
2168
- audioClone.volume = Math.max(0, Math.min(1, s._iO.volume/100));
2161
+ audioClone.volume = Math.max(0, Math.min(1, s._iO.volume / 100));
2169
2162
  }
2170
2163
 
2171
2164
  // playing multiple muted sounds? if you do this, you're weird ;) - but let's cover it.
@@ -2184,8 +2177,6 @@ function SoundManager(smURL, smID) {
2184
2177
 
2185
2178
  }
2186
2179
 
2187
- }
2188
-
2189
2180
  }
2190
2181
 
2191
2182
  return s;
@@ -2236,9 +2227,7 @@ function SoundManager(smURL, smID) {
2236
2227
  s.unload();
2237
2228
  }
2238
2229
 
2239
- } else {
2240
-
2241
- if (s._a) {
2230
+ } else if (s._a) {
2242
2231
 
2243
2232
  originalPosition = s.position;
2244
2233
 
@@ -2261,8 +2250,6 @@ function SoundManager(smURL, smID) {
2261
2250
 
2262
2251
  }
2263
2252
 
2264
- }
2265
-
2266
2253
  s.instanceCount = 0;
2267
2254
  s._iO = {};
2268
2255
 
@@ -2293,7 +2280,7 @@ function SoundManager(smURL, smID) {
2293
2280
  // only increment the instanceCount if the sound isn't loaded (TODO: verify RTMP)
2294
2281
  if (!s.instanceCount && s.readyState === 1) {
2295
2282
  s.instanceCount++;
2296
- sm2._wD(s.id + ': Incremented instance count to '+s.instanceCount);
2283
+ sm2._wD(s.id + ': Incremented instance count to ' + s.instanceCount);
2297
2284
  }
2298
2285
  }
2299
2286
  }
@@ -2312,6 +2299,38 @@ function SoundManager(smURL, smID) {
2312
2299
 
2313
2300
  };
2314
2301
 
2302
+ /**
2303
+ * Sets the playback rate of a sound (HTML5-only.)
2304
+ *
2305
+ * @param {number} playbackRate (+/-)
2306
+ * @return {SMSound} The SMSound object
2307
+ */
2308
+
2309
+ this.setPlaybackRate = function(playbackRate) {
2310
+
2311
+ // Per Mozilla, limit acceptable values to prevent playback from stopping (unless allowOverride is truthy.)
2312
+ // https://developer.mozilla.org/en-US/Apps/Build/Audio_and_video_delivery/WebAudio_playbackRate_explained
2313
+ var normalizedRate = Math.max(0.5, Math.min(4, playbackRate));
2314
+
2315
+ // <d>
2316
+ if (normalizedRate !== playbackRate) {
2317
+ sm2._wD(s.id + ': setPlaybackRate(' + playbackRate + '): limiting rate to ' + normalizedRate, 2);
2318
+ }
2319
+ // </d>
2320
+
2321
+ if (s.isHTML5) {
2322
+ try {
2323
+ s._iO.playbackRate = normalizedRate;
2324
+ s._a.playbackRate = normalizedRate;
2325
+ } catch(e) {
2326
+ sm2._wD(s.id + ': setPlaybackRate(' + normalizedRate + ') failed: ' + e.message, 2);
2327
+ }
2328
+ }
2329
+
2330
+ return s;
2331
+
2332
+ };
2333
+
2315
2334
  /**
2316
2335
  * Sets the position of a sound.
2317
2336
  *
@@ -2331,7 +2350,7 @@ function SoundManager(smURL, smID) {
2331
2350
  offset = (s.isHTML5 ? Math.max(nMsecOffset, 0) : Math.min(s.duration || s._iO.duration, Math.max(nMsecOffset, 0)));
2332
2351
 
2333
2352
  s.position = offset;
2334
- position1K = s.position/msecScale;
2353
+ position1K = s.position / msecScale;
2335
2354
  s._resetOnPosition(s.position);
2336
2355
  s._iO.position = offset;
2337
2356
 
@@ -2349,7 +2368,7 @@ function SoundManager(smURL, smID) {
2349
2368
  // Set the position in the canplay handler if the sound is not ready yet
2350
2369
  if (s._html5_canplay) {
2351
2370
 
2352
- if (s._a.currentTime !== position1K) {
2371
+ if (s._a.currentTime.toFixed(3) !== position1K.toFixed(3)) {
2353
2372
 
2354
2373
  /**
2355
2374
  * DOM/JS errors/exceptions to watch out for:
@@ -2399,9 +2418,7 @@ function SoundManager(smURL, smID) {
2399
2418
 
2400
2419
  this.pause = function(_bCallFlash) {
2401
2420
 
2402
- if (s.paused || (s.playState === 0 && s.readyState !== 1)) {
2403
- return s;
2404
- }
2421
+ if (s.paused || (s.playState === 0 && s.readyState !== 1)) return s;
2405
2422
 
2406
2423
  sm2._wD(s.id + ': pause()');
2407
2424
  s.paused = true;
@@ -2441,9 +2458,7 @@ function SoundManager(smURL, smID) {
2441
2458
 
2442
2459
  var instanceOptions = s._iO;
2443
2460
 
2444
- if (!s.paused) {
2445
- return s;
2446
- }
2461
+ if (!s.paused) return s;
2447
2462
 
2448
2463
  sm2._wD(s.id + ': resume()');
2449
2464
  s.paused = false;
@@ -2576,7 +2591,7 @@ function SoundManager(smURL, smID) {
2576
2591
  }
2577
2592
 
2578
2593
  // valid range for native HTML5 Audio(): 0-1
2579
- s._a.volume = Math.max(0, Math.min(1, nVol/100));
2594
+ s._a.volume = Math.max(0, Math.min(1, nVol / 100));
2580
2595
 
2581
2596
  }
2582
2597
 
@@ -2687,25 +2702,25 @@ function SoundManager(smURL, smID) {
2687
2702
 
2688
2703
  if (isNaN(nPosition)) {
2689
2704
  // safety check
2690
- return false;
2705
+ return;
2691
2706
  }
2692
2707
 
2693
- for (i=0; i < onPositionItems.length; i++) {
2708
+ for (i = 0; i < onPositionItems.length; i++) {
2694
2709
 
2695
2710
  if (nPosition === onPositionItems[i].position) {
2696
2711
  // remove this item if no method was specified, or, if the method matches
2697
-
2712
+
2698
2713
  if (!oMethod || (oMethod === onPositionItems[i].method)) {
2699
-
2714
+
2700
2715
  if (onPositionItems[i].fired) {
2701
2716
  // decrement "fired" counter, too
2702
2717
  onPositionFired--;
2703
2718
  }
2704
-
2719
+
2705
2720
  onPositionItems.splice(i, 1);
2706
-
2721
+
2707
2722
  }
2708
-
2723
+
2709
2724
  }
2710
2725
 
2711
2726
  }
@@ -2716,25 +2731,23 @@ function SoundManager(smURL, smID) {
2716
2731
 
2717
2732
  var i, item, j = onPositionItems.length;
2718
2733
 
2719
- if (!j || !s.playState || onPositionFired >= j) {
2720
- return false;
2721
- }
2734
+ if (!j || !s.playState || onPositionFired >= j) return false;
2722
2735
 
2723
2736
  for (i = j - 1; i >= 0; i--) {
2724
-
2737
+
2725
2738
  item = onPositionItems[i];
2726
-
2739
+
2727
2740
  if (!item.fired && s.position >= item.position) {
2728
-
2741
+
2729
2742
  item.fired = true;
2730
2743
  onPositionFired++;
2731
2744
  item.method.apply(item.scope, [item.position]);
2732
-
2745
+
2733
2746
  // reset j -- onPositionItems.length can be changed in the item callback above... occasionally breaking the loop.
2734
- j = onPositionItems.length;
2735
-
2747
+ j = onPositionItems.length;
2748
+
2736
2749
  }
2737
-
2750
+
2738
2751
  }
2739
2752
 
2740
2753
  return true;
@@ -2746,19 +2759,17 @@ function SoundManager(smURL, smID) {
2746
2759
  // reset "fired" for items interested in this position
2747
2760
  var i, item, j = onPositionItems.length;
2748
2761
 
2749
- if (!j) {
2750
- return false;
2751
- }
2762
+ if (!j) return false;
2752
2763
 
2753
2764
  for (i = j - 1; i >= 0; i--) {
2754
-
2765
+
2755
2766
  item = onPositionItems[i];
2756
-
2767
+
2757
2768
  if (item.fired && nPosition <= item.position) {
2758
2769
  item.fired = false;
2759
2770
  onPositionFired--;
2760
2771
  }
2761
-
2772
+
2762
2773
  }
2763
2774
 
2764
2775
  return true;
@@ -2985,10 +2996,10 @@ function SoundManager(smURL, smID) {
2985
2996
 
2986
2997
  }*/
2987
2998
 
2988
- return isNew;
2989
-
2990
2999
  }
2991
3000
 
3001
+ return isNew;
3002
+
2992
3003
  };
2993
3004
 
2994
3005
  this._get_html5_duration = function() {
@@ -3019,9 +3030,9 @@ function SoundManager(smURL, smID) {
3019
3030
 
3020
3031
  };
3021
3032
 
3022
- this._setup_html5 = function(oOptions) {
3033
+ this._setup_html5 = function(options) {
3023
3034
 
3024
- var instanceOptions = mixin(s._iO, oOptions),
3035
+ var instanceOptions = mixin(s._iO, options),
3025
3036
  a = useGlobalHTML5Audio ? globalHTML5Audio : s._a,
3026
3037
  dURL = decodeURI(instanceOptions.url),
3027
3038
  sameURL;
@@ -3151,9 +3162,7 @@ function SoundManager(smURL, smID) {
3151
3162
 
3152
3163
  add_html5_events = function() {
3153
3164
 
3154
- if (s._a._added_events) {
3155
- return false;
3156
- }
3165
+ if (s._a._added_events) return false;
3157
3166
 
3158
3167
  var f;
3159
3168
 
@@ -3223,6 +3232,11 @@ function SoundManager(smURL, smID) {
3223
3232
  s.readyState = (loadOK ? 3 : 2);
3224
3233
  s._onbufferchange(0);
3225
3234
 
3235
+ if (!loadOK && !s.isHTML5) {
3236
+ // note: no error code from Flash.
3237
+ s._onerror();
3238
+ }
3239
+
3226
3240
  if (s._iO.onload) {
3227
3241
  wrapCallback(s, function() {
3228
3242
  s._iO.onload.apply(s, [loadOK]);
@@ -3233,19 +3247,26 @@ function SoundManager(smURL, smID) {
3233
3247
 
3234
3248
  };
3235
3249
 
3236
- this._onbufferchange = function(nIsBuffering) {
3250
+ this._onerror = function(errorCode, description) {
3237
3251
 
3238
- if (s.playState === 0) {
3239
- // ignore if not playing
3240
- return false;
3252
+ // https://html.spec.whatwg.org/multipage/embedded-content.html#error-codes
3253
+ if (s._iO.onerror) {
3254
+ wrapCallback(s, function() {
3255
+ s._iO.onerror.apply(s, [errorCode, description]);
3256
+ });
3241
3257
  }
3242
3258
 
3243
- if ((nIsBuffering && s.isBuffering) || (!nIsBuffering && !s.isBuffering)) {
3244
- return false;
3245
- }
3259
+ };
3260
+
3261
+ this._onbufferchange = function(nIsBuffering) {
3262
+
3263
+ // ignore if not playing
3264
+ if (s.playState === 0) return false;
3265
+
3266
+ if ((nIsBuffering && s.isBuffering) || (!nIsBuffering && !s.isBuffering)) return false;
3246
3267
 
3247
3268
  s.isBuffering = (nIsBuffering === 1);
3248
-
3269
+
3249
3270
  if (s._iO.onbufferchange) {
3250
3271
  sm2._wD(s.id + ': Buffer state change: ' + nIsBuffering);
3251
3272
  s._iO.onbufferchange.apply(s, [nIsBuffering]);
@@ -3376,8 +3397,8 @@ function SoundManager(smURL, smID) {
3376
3397
  // for flash, reflect sequential-load-style buffering
3377
3398
  if (!s.isHTML5) {
3378
3399
  s.buffered = [{
3379
- 'start': 0,
3380
- 'end': s.duration
3400
+ start: 0,
3401
+ end: s.duration
3381
3402
  }];
3382
3403
  }
3383
3404
 
@@ -3393,10 +3414,8 @@ function SoundManager(smURL, smID) {
3393
3414
  var instanceOptions = s._iO,
3394
3415
  eqLeft;
3395
3416
 
3396
- if (isNaN(nPosition) || nPosition === null) {
3397
- // flash safety net
3398
- return false;
3399
- }
3417
+ // flash safety net
3418
+ if (isNaN(nPosition) || nPosition === null) return false;
3400
3419
 
3401
3420
  // Safari HTML5 play() may return small -ve values when starting from position: 0, eg. -50.120396875. Unexpected/invalid per W3, I think. Normalize to 0.
3402
3421
  s.position = Math.max(0, nPosition);
@@ -3637,11 +3656,11 @@ function SoundManager(smURL, smID) {
3637
3656
  // additional soundManager properties that soundManager.setup() will accept
3638
3657
 
3639
3658
  extraOptions = {
3640
- 'onready': 1,
3641
- 'ontimeout': 1,
3642
- 'defaultOptions': 1,
3643
- 'flash9Options': 1,
3644
- 'movieStarOptions': 1
3659
+ onready: 1,
3660
+ ontimeout: 1,
3661
+ defaultOptions: 1,
3662
+ flash9Options: 1,
3663
+ movieStarOptions: 1
3645
3664
  };
3646
3665
 
3647
3666
  assign = function(o, oParent) {
@@ -3727,44 +3746,35 @@ function SoundManager(smURL, smID) {
3727
3746
 
3728
3747
  result = false;
3729
3748
 
3730
- } else {
3749
+ } else if (sm2[i] instanceof Function) {
3731
3750
 
3732
3751
  /**
3733
3752
  * valid extraOptions (bonusOptions) parameter.
3734
3753
  * is it a method, like onready/ontimeout? call it.
3735
3754
  * multiple parameters should be in an array, eg. soundManager.setup({onready: [myHandler, myScope]});
3736
3755
  */
3756
+ sm2[i].apply(sm2, (o[i] instanceof Array ? o[i] : [o[i]]));
3737
3757
 
3738
- if (sm2[i] instanceof Function) {
3739
-
3740
- sm2[i].apply(sm2, (o[i] instanceof Array ? o[i] : [o[i]]));
3741
-
3742
- } else {
3743
-
3744
- // good old-fashioned direct assignment
3745
- sm2[i] = o[i];
3758
+ } else {
3746
3759
 
3747
- }
3760
+ // good old-fashioned direct assignment
3761
+ sm2[i] = o[i];
3748
3762
 
3749
3763
  }
3750
3764
 
3751
- } else {
3765
+ } else if (bonusOptions[i] === _undefined) {
3752
3766
 
3753
3767
  // recursion case, eg., { defaultOptions: { ... } }
3754
3768
 
3755
- if (bonusOptions[i] === _undefined) {
3769
+ // invalid or disallowed parameter. complain.
3770
+ complain(str((sm2[i] === _undefined ? 'setupUndef' : 'setupError'), i), 2);
3756
3771
 
3757
- // invalid or disallowed parameter. complain.
3758
- complain(str((sm2[i] === _undefined ? 'setupUndef' : 'setupError'), i), 2);
3772
+ result = false;
3759
3773
 
3760
- result = false;
3761
-
3762
- } else {
3763
-
3764
- // recurse through object
3765
- return assign(o[i], i);
3774
+ } else {
3766
3775
 
3767
- }
3776
+ // recurse through object
3777
+ return assign(o[i], i);
3768
3778
 
3769
3779
  }
3770
3780
 
@@ -3842,8 +3852,8 @@ function SoundManager(smURL, smID) {
3842
3852
  }
3843
3853
 
3844
3854
  return {
3845
- 'add': add,
3846
- 'remove': remove
3855
+ add: add,
3856
+ remove: remove
3847
3857
  };
3848
3858
 
3849
3859
  }());
@@ -3900,7 +3910,7 @@ function SoundManager(smURL, smID) {
3900
3910
 
3901
3911
  if (s._html5_canplay) {
3902
3912
  // this event has already fired. ignore.
3903
- return true;
3913
+ return;
3904
3914
  }
3905
3915
 
3906
3916
  s._html5_canplay = true;
@@ -3908,7 +3918,7 @@ function SoundManager(smURL, smID) {
3908
3918
  s._onbufferchange(0);
3909
3919
 
3910
3920
  // position according to instance options
3911
- position1K = (s._iO.position !== _undefined && !isNaN(s._iO.position) ? s._iO.position/msecScale : null);
3921
+ position1K = (s._iO.position !== _undefined && !isNaN(s._iO.position) ? s._iO.position / msecScale : null);
3912
3922
 
3913
3923
  // set the position if position was provided before the sound loaded
3914
3924
  if (this.currentTime !== position1K) {
@@ -3979,17 +3989,10 @@ function SoundManager(smURL, smID) {
3979
3989
 
3980
3990
  error: html5_event(function() {
3981
3991
 
3982
- sm2._wD(this._s.id + ': HTML5 error, code ' + this.error.code);
3983
- /**
3984
- * HTML5 error codes, per W3C
3985
- * Error 1: Client aborted download at user's request.
3986
- * Error 2: Network error after load started.
3987
- * Error 3: Decoding issue.
3988
- * Error 4: Media (audio file) not supported.
3989
- * Reference: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#error-codes
3990
- */
3991
- // call load with error state?
3992
+ var description = (html5ErrorCodes[this.error.code] || null);
3993
+ sm2._wD(this._s.id + ': HTML5 error, code ' + this.error.code + (description ? ' (' + description + ')' : ''));
3992
3994
  this._s._onload(false);
3995
+ this._s._onerror(this.error.code, description);
3993
3996
 
3994
3997
  }),
3995
3998
 
@@ -4060,8 +4063,8 @@ function SoundManager(smURL, smID) {
4060
4063
  // HTML5 returns seconds. SM2 API uses msec for setPosition() etc., whether Flash or HTML5.
4061
4064
  for (i = 0, j = ranges.length; i < j; i++) {
4062
4065
  s.buffered.push({
4063
- 'start': ranges.start(i) * msecScale,
4064
- 'end': ranges.end(i) * msecScale
4066
+ start: ranges.start(i) * msecScale,
4067
+ end: ranges.end(i) * msecScale
4065
4068
  });
4066
4069
  }
4067
4070
 
@@ -4163,7 +4166,7 @@ function SoundManager(smURL, smID) {
4163
4166
  } else {
4164
4167
 
4165
4168
  // Use type, if specified. Pass data: URIs to HTML5. If HTML5-only mode, no other options, so just give 'er
4166
- result = ((iO.type ? html5CanPlay({type:iO.type}) : html5CanPlay({url:iO.url}) || sm2.html5Only || iO.url.match(/data\:/i)));
4169
+ result = ((iO.type ? html5CanPlay({ type: iO.type }) : html5CanPlay({ url: iO.url }) || sm2.html5Only || iO.url.match(/data:/i)));
4167
4170
 
4168
4171
  }
4169
4172
 
@@ -4219,9 +4222,7 @@ function SoundManager(smURL, smID) {
4219
4222
  * }
4220
4223
  */
4221
4224
 
4222
- if (!sm2.useHTML5Audio || !sm2.hasHTML5) {
4223
- return false;
4224
- }
4225
+ if (!sm2.useHTML5Audio || !sm2.hasHTML5) return false;
4225
4226
 
4226
4227
  var url = (o.url || null),
4227
4228
  mime = (o.type || null),
@@ -4233,70 +4234,68 @@ function SoundManager(smURL, smID) {
4233
4234
 
4234
4235
  // account for known cases like audio/mp3
4235
4236
 
4236
- if (mime && sm2.html5[mime] !== _undefined) {
4237
- return (sm2.html5[mime] && !preferFlashCheck(mime));
4238
- }
4237
+ if (mime && sm2.html5[mime] !== _undefined) return (sm2.html5[mime] && !preferFlashCheck(mime));
4239
4238
 
4240
4239
  if (!html5Ext) {
4241
-
4240
+
4242
4241
  html5Ext = [];
4243
-
4242
+
4244
4243
  for (item in aF) {
4245
-
4244
+
4246
4245
  if (aF.hasOwnProperty(item)) {
4247
-
4246
+
4248
4247
  html5Ext.push(item);
4249
-
4248
+
4250
4249
  if (aF[item].related) {
4251
4250
  html5Ext = html5Ext.concat(aF[item].related);
4252
4251
  }
4253
-
4252
+
4254
4253
  }
4255
-
4254
+
4256
4255
  }
4257
-
4258
- html5Ext = new RegExp('\\.('+html5Ext.join('|')+')(\\?.*)?$','i');
4259
-
4256
+
4257
+ html5Ext = new RegExp('\\.(' + html5Ext.join('|') + ')(\\?.*)?$', 'i');
4258
+
4260
4259
  }
4261
4260
 
4262
4261
  // TODO: Strip URL queries, etc.
4263
4262
  fileExt = (url ? url.toLowerCase().match(html5Ext) : null);
4264
4263
 
4265
4264
  if (!fileExt || !fileExt.length) {
4266
-
4265
+
4267
4266
  if (!mime) {
4268
-
4267
+
4269
4268
  result = false;
4270
-
4269
+
4271
4270
  } else {
4272
-
4271
+
4273
4272
  // audio/mp3 -> mp3, result should be known
4274
4273
  offset = mime.indexOf(';');
4275
-
4274
+
4276
4275
  // strip "audio/X; codecs..."
4277
- fileExt = (offset !== -1 ? mime.substr(0,offset) : mime).substr(6);
4278
-
4276
+ fileExt = (offset !== -1 ? mime.substr(0, offset) : mime).substr(6);
4277
+
4279
4278
  }
4280
-
4279
+
4281
4280
  } else {
4282
-
4281
+
4283
4282
  // match the raw extension name - "mp3", for example
4284
4283
  fileExt = fileExt[1];
4285
-
4284
+
4286
4285
  }
4287
4286
 
4288
4287
  if (fileExt && sm2.html5[fileExt] !== _undefined) {
4289
-
4288
+
4290
4289
  // result known
4291
4290
  result = (sm2.html5[fileExt] && !preferFlashCheck(fileExt));
4292
-
4291
+
4293
4292
  } else {
4294
-
4293
+
4295
4294
  mime = 'audio/' + fileExt;
4296
- result = sm2.html5.canPlayType({type:mime});
4297
-
4295
+ result = sm2.html5.canPlayType({ type: mime });
4296
+
4298
4297
  sm2.html5[fileExt] = result;
4299
-
4298
+
4300
4299
  // sm2._wD('canPlayType, found result: ' + result);
4301
4300
  result = (result && sm2.html5[mime] && !preferFlashCheck(mime));
4302
4301
  }
@@ -4313,13 +4312,13 @@ function SoundManager(smURL, smID) {
4313
4312
  */
4314
4313
 
4315
4314
  if (!sm2.useHTML5Audio || !sm2.hasHTML5) {
4316
-
4315
+
4317
4316
  // without HTML5, we need Flash.
4318
4317
  sm2.html5.usingFlash = true;
4319
4318
  needsFlash = true;
4320
-
4319
+
4321
4320
  return false;
4322
-
4321
+
4323
4322
  }
4324
4323
 
4325
4324
  // 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. :/
@@ -4332,35 +4331,33 @@ function SoundManager(smURL, smID) {
4332
4331
  result = false,
4333
4332
  isOK = false;
4334
4333
 
4335
- if (!a || typeof a.canPlayType !== 'function') {
4336
- return result;
4337
- }
4334
+ if (!a || typeof a.canPlayType !== 'function') return result;
4338
4335
 
4339
4336
  if (m instanceof Array) {
4340
-
4337
+
4341
4338
  // iterate through all mime types, return any successes
4342
-
4339
+
4343
4340
  for (i = 0, j = m.length; i < j; i++) {
4344
-
4341
+
4345
4342
  if (sm2.html5[m[i]] || a.canPlayType(m[i]).match(sm2.html5Test)) {
4346
-
4343
+
4347
4344
  isOK = true;
4348
4345
  sm2.html5[m[i]] = true;
4349
-
4346
+
4350
4347
  // note flash support, too
4351
4348
  sm2.flash[m[i]] = !!(m[i].match(flashMIME));
4352
-
4349
+
4353
4350
  }
4354
-
4351
+
4355
4352
  }
4356
-
4353
+
4357
4354
  result = isOK;
4358
-
4355
+
4359
4356
  } else {
4360
-
4357
+
4361
4358
  canPlay = (a && typeof a.canPlayType === 'function' ? a.canPlayType(m) : false);
4362
4359
  result = !!(canPlay && (canPlay.match(sm2.html5Test)));
4363
-
4360
+
4364
4361
  }
4365
4362
 
4366
4363
  return result;
@@ -4576,31 +4573,29 @@ function SoundManager(smURL, smID) {
4576
4573
 
4577
4574
  };
4578
4575
 
4579
- normalizeMovieURL = function(smURL) {
4576
+ normalizeMovieURL = function(movieURL) {
4580
4577
 
4581
4578
  var urlParams = null, url;
4582
4579
 
4583
- if (smURL) {
4584
-
4585
- if (smURL.match(/\.swf(\?.*)?$/i)) {
4586
-
4587
- urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?') + 4);
4588
-
4589
- if (urlParams) {
4590
- // assume user knows what they're doing
4591
- return smURL;
4592
- }
4593
-
4594
- } else if (smURL.lastIndexOf('/') !== smURL.length - 1) {
4595
-
4580
+ if (movieURL) {
4581
+
4582
+ if (movieURL.match(/\.swf(\?.*)?$/i)) {
4583
+
4584
+ urlParams = movieURL.substr(movieURL.toLowerCase().lastIndexOf('.swf?') + 4);
4585
+
4586
+ // assume user knows what they're doing
4587
+ if (urlParams) return movieURL;
4588
+
4589
+ } else if (movieURL.lastIndexOf('/') !== movieURL.length - 1) {
4590
+
4596
4591
  // append trailing slash, if needed
4597
- smURL += '/';
4598
-
4592
+ movieURL += '/';
4593
+
4599
4594
  }
4600
-
4595
+
4601
4596
  }
4602
4597
 
4603
- url = (smURL && smURL.lastIndexOf('/') !== - 1 ? smURL.substr(0, smURL.lastIndexOf('/') + 1) : './') + sm2.movieURL;
4598
+ url = (movieURL && movieURL.lastIndexOf('/') !== -1 ? movieURL.substr(0, movieURL.lastIndexOf('/') + 1) : './') + sm2.movieURL;
4604
4599
 
4605
4600
  if (sm2.noSWFCache) {
4606
4601
  url += ('?ts=' + new Date().getTime());
@@ -4634,20 +4629,20 @@ function SoundManager(smURL, smID) {
4634
4629
 
4635
4630
  // set up default options
4636
4631
  if (fV > 8) {
4637
-
4632
+
4638
4633
  // +flash 9 base options
4639
4634
  sm2.defaultOptions = mixin(sm2.defaultOptions, sm2.flash9Options);
4640
4635
  sm2.features.buffering = true;
4641
-
4636
+
4642
4637
  // +moviestar support
4643
4638
  sm2.defaultOptions = mixin(sm2.defaultOptions, sm2.movieStarOptions);
4644
4639
  sm2.filePatterns.flash9 = new RegExp('\\.(mp3|' + netStreamTypes.join('|') + ')(\\?.*)?$', 'i');
4645
4640
  sm2.features.movieStar = true;
4646
-
4641
+
4647
4642
  } else {
4648
-
4643
+
4649
4644
  sm2.features.movieStar = false;
4650
-
4645
+
4651
4646
  }
4652
4647
 
4653
4648
  // regExp for flash canPlay(), etc.
@@ -4663,7 +4658,7 @@ function SoundManager(smURL, smID) {
4663
4658
  setPolling = function(bPolling, bHighPerformance) {
4664
4659
 
4665
4660
  if (!flash) {
4666
- return false;
4661
+ return;
4667
4662
  }
4668
4663
 
4669
4664
  flash._setPolling(bPolling, bHighPerformance);
@@ -4681,7 +4676,7 @@ function SoundManager(smURL, smID) {
4681
4676
  }
4682
4677
 
4683
4678
  if (id(sm2.debugID)) {
4684
- return false;
4679
+ return;
4685
4680
  }
4686
4681
 
4687
4682
  var oD, oDebug, oTarget, oToggle, tmp;
@@ -4692,19 +4687,19 @@ function SoundManager(smURL, smID) {
4692
4687
  oD.id = sm2.debugID + '-toggle';
4693
4688
 
4694
4689
  oToggle = {
4695
- 'position': 'fixed',
4696
- 'bottom': '0px',
4697
- 'right': '0px',
4698
- 'width': '1.2em',
4699
- 'height': '1.2em',
4700
- 'lineHeight': '1.2em',
4701
- 'margin': '2px',
4702
- 'textAlign': 'center',
4703
- 'border': '1px solid #999',
4704
- 'cursor': 'pointer',
4705
- 'background': '#fff',
4706
- 'color': '#333',
4707
- 'zIndex': 10001
4690
+ position: 'fixed',
4691
+ bottom: '0px',
4692
+ right: '0px',
4693
+ width: '1.2em',
4694
+ height: '1.2em',
4695
+ lineHeight: '1.2em',
4696
+ margin: '2px',
4697
+ textAlign: 'center',
4698
+ border: '1px solid #999',
4699
+ cursor: 'pointer',
4700
+ background: '#fff',
4701
+ color: '#333',
4702
+ zIndex: 10001
4708
4703
  };
4709
4704
 
4710
4705
  oD.appendChild(doc.createTextNode('-'));
@@ -4758,7 +4753,7 @@ function SoundManager(smURL, smID) {
4758
4753
  oT = id(sm2.debugID + '-toggle');
4759
4754
 
4760
4755
  if (!o) {
4761
- return false;
4756
+ return;
4762
4757
  }
4763
4758
 
4764
4759
  if (debugOpen) {
@@ -4820,12 +4815,12 @@ function SoundManager(smURL, smID) {
4820
4815
  p = sm2.getMoviePercent(),
4821
4816
  css = swfCSS,
4822
4817
  error = {
4823
- type:'FLASHBLOCK'
4818
+ type: 'FLASHBLOCK'
4824
4819
  };
4825
4820
 
4826
4821
  if (sm2.html5Only) {
4827
4822
  // no flash, or unused
4828
- return false;
4823
+ return;
4829
4824
  }
4830
4825
 
4831
4826
  if (!sm2.ok()) {
@@ -4872,9 +4867,9 @@ function SoundManager(smURL, smID) {
4872
4867
  }
4873
4868
 
4874
4869
  on_queue[sType].push({
4875
- 'method': oMethod,
4876
- 'scope': (oScope || null),
4877
- 'fired': false
4870
+ method: oMethod,
4871
+ scope: (oScope || null),
4872
+ fired: false
4878
4873
  });
4879
4874
 
4880
4875
  };
@@ -4889,15 +4884,11 @@ function SoundManager(smURL, smID) {
4889
4884
  };
4890
4885
  }
4891
4886
 
4892
- if (!didInit && oOptions && !oOptions.ignoreInit) {
4893
- // not ready yet.
4894
- return false;
4895
- }
4887
+ // not ready yet.
4888
+ if (!didInit && oOptions && !oOptions.ignoreInit) return false;
4896
4889
 
4897
- if (oOptions.type === 'ontimeout' && (sm2.ok() || (disabled && !oOptions.ignoreInit))) {
4898
- // invalid case
4899
- return false;
4900
- }
4890
+ // invalid case
4891
+ if (oOptions.type === 'ontimeout' && (sm2.ok() || (disabled && !oOptions.ignoreInit))) return false;
4901
4892
 
4902
4893
  var status = {
4903
4894
  success: (oOptions && oOptions.ignoreInit ? sm2.ok() : !disabled)
@@ -4921,24 +4912,24 @@ function SoundManager(smURL, smID) {
4921
4912
  }
4922
4913
 
4923
4914
  if (queue.length) {
4924
-
4925
- // sm2._wD(sm + ': Firing ' + queue.length + ' ' + oOptions.type + '() item' + (queue.length === 1 ? '' : 's'));
4915
+
4916
+ // sm2._wD(sm + ': Firing ' + queue.length + ' ' + oOptions.type + '() item' + (queue.length === 1 ? '' : 's'));
4926
4917
  for (i = 0, j = queue.length; i < j; i++) {
4927
-
4918
+
4928
4919
  if (queue[i].scope) {
4929
4920
  queue[i].method.apply(queue[i].scope, args);
4930
4921
  } else {
4931
4922
  queue[i].method.apply(this, args);
4932
4923
  }
4933
-
4924
+
4934
4925
  if (!canRetry) {
4935
4926
  // useFlashBlock and SWF timeout case doesn't count here.
4936
4927
  queue[i].fired = true;
4937
-
4928
+
4938
4929
  }
4939
-
4930
+
4940
4931
  }
4941
-
4932
+
4942
4933
  }
4943
4934
 
4944
4935
  return true;
@@ -4978,24 +4969,31 @@ function SoundManager(smURL, smID) {
4978
4969
  * http://featureblend.com/javascript-flash-detection-library.html / http://featureblend.com/license.txt
4979
4970
  */
4980
4971
 
4981
- if (hasFlash !== _undefined) {
4982
- // this work has already been done.
4983
- return hasFlash;
4984
- }
4972
+ // this work has already been done.
4973
+ if (hasFlash !== _undefined) return hasFlash;
4974
+
4975
+ var hasPlugin = false, n = navigator, obj, type, types, AX = window.ActiveXObject;
4985
4976
 
4986
- var hasPlugin = false, n = navigator, nP = n.plugins, obj, type, types, AX = window.ActiveXObject;
4977
+ // MS Edge 14 throws an "Unspecified Error" because n.plugins is inaccessible due to permissions
4978
+ var nP;
4979
+
4980
+ try {
4981
+ nP = n.plugins;
4982
+ } catch(e) {
4983
+ nP = undefined;
4984
+ }
4987
4985
 
4988
4986
  if (nP && nP.length) {
4989
-
4987
+
4990
4988
  type = 'application/x-shockwave-flash';
4991
4989
  types = n.mimeTypes;
4992
-
4990
+
4993
4991
  if (types && types[type] && types[type].enabledPlugin && types[type].enabledPlugin.description) {
4994
4992
  hasPlugin = true;
4995
4993
  }
4996
-
4994
+
4997
4995
  } else if (AX !== _undefined && !ua.match(/MSAppHost/i)) {
4998
-
4996
+
4999
4997
  // 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.
5000
4998
  try {
5001
4999
  obj = new AX('ShockwaveFlash.ShockwaveFlash');
@@ -5003,12 +5001,12 @@ function SoundManager(smURL, smID) {
5003
5001
  // oh well
5004
5002
  obj = null;
5005
5003
  }
5006
-
5004
+
5007
5005
  hasPlugin = (!!obj);
5008
-
5006
+
5009
5007
  // cleanup, because it is ActiveX after all
5010
5008
  obj = null;
5011
-
5009
+
5012
5010
  }
5013
5011
 
5014
5012
  hasFlash = hasPlugin;
@@ -5017,7 +5015,7 @@ function SoundManager(smURL, smID) {
5017
5015
 
5018
5016
  };
5019
5017
 
5020
- featureCheck = function() {
5018
+ featureCheck = function() {
5021
5019
 
5022
5020
  var flashNeeded,
5023
5021
  item,
@@ -5038,9 +5036,7 @@ featureCheck = function() {
5038
5036
  sm2.oMC.style.display = 'none';
5039
5037
  }
5040
5038
 
5041
- } else {
5042
-
5043
- if (sm2.useHTML5Audio) {
5039
+ } else if (sm2.useHTML5Audio) {
5044
5040
 
5045
5041
  if (!sm2.html5 || !sm2.html5.canPlayType) {
5046
5042
  sm2._wD('SoundManager: No HTML5 Audio() support detected.');
@@ -5055,8 +5051,6 @@ featureCheck = function() {
5055
5051
 
5056
5052
  }
5057
5053
 
5058
- }
5059
-
5060
5054
  if (sm2.useHTML5Audio && sm2.hasHTML5) {
5061
5055
 
5062
5056
  // sort out whether flash is optional, required or can be ignored.
@@ -5065,24 +5059,24 @@ featureCheck = function() {
5065
5059
  canIgnoreFlash = true;
5066
5060
 
5067
5061
  for (item in formats) {
5068
-
5062
+
5069
5063
  if (formats.hasOwnProperty(item)) {
5070
-
5064
+
5071
5065
  if (formats[item].required) {
5072
-
5066
+
5073
5067
  if (!sm2.html5.canPlayType(formats[item].type)) {
5074
-
5068
+
5075
5069
  // 100% HTML5 mode is not possible.
5076
5070
  canIgnoreFlash = false;
5077
5071
  flashNeeded = true;
5078
-
5072
+
5079
5073
  } else if (sm2.preferFlash && (sm2.flash[item] || sm2.flash[formats[item].type])) {
5080
-
5074
+
5081
5075
  // flash may be required, or preferred for this format.
5082
5076
  flashNeeded = true;
5083
-
5077
+
5084
5078
  }
5085
-
5079
+
5086
5080
  }
5087
5081
 
5088
5082
  }
@@ -5219,7 +5213,7 @@ featureCheck = function() {
5219
5213
 
5220
5214
  h5IntervalTimer = null;
5221
5215
 
5222
- return false;
5216
+ return;
5223
5217
 
5224
5218
  }
5225
5219
 
@@ -5256,7 +5250,7 @@ featureCheck = function() {
5256
5250
  // special case: "bad" Safari (OS X 10.3 - 10.7) must fall back to flash for MP3/MP4
5257
5251
  if (!isBadSafari || !detectFlash()) {
5258
5252
  // doesn't apply
5259
- return false;
5253
+ return;
5260
5254
  }
5261
5255
 
5262
5256
  var aF = sm2.audioFormats, i, item;
@@ -5297,7 +5291,7 @@ featureCheck = function() {
5297
5291
  var sb = sm2.sandbox;
5298
5292
 
5299
5293
  sb.type = sandboxType;
5300
- sb.description = sb.types[(sb.types[sandboxType] !== _undefined?sandboxType : 'unknown')];
5294
+ sb.description = sb.types[(sb.types[sandboxType] !== _undefined ? sandboxType : 'unknown')];
5301
5295
 
5302
5296
  if (sb.type === 'localWithFile') {
5303
5297
 
@@ -5326,7 +5320,7 @@ featureCheck = function() {
5326
5320
  // swfVersion: SWF build string
5327
5321
 
5328
5322
  if (sm2.swfLoaded) {
5329
- return false;
5323
+ return;
5330
5324
  }
5331
5325
 
5332
5326
  var e;
@@ -5342,17 +5336,17 @@ featureCheck = function() {
5342
5336
 
5343
5337
  // complain if JS + SWF build/version strings don't match, excluding +DEV builds
5344
5338
  // <d>
5345
- if (!swfVersion || swfVersion.replace(/\+dev/i,'') !== sm2.versionNumber.replace(/\+dev/i, '')) {
5339
+ if (!swfVersion || swfVersion.replace(/\+dev/i, '') !== sm2.versionNumber.replace(/\+dev/i, '')) {
5346
5340
 
5347
5341
  e = sm + ': Fatal: JavaScript file build "' + sm2.versionNumber + '" does not match Flash SWF build "' + swfVersion + '" at ' + sm2.url + '. Ensure both are up-to-date.';
5348
5342
 
5349
5343
  // escape flash -> JS stack so this error fires in window.
5350
- setTimeout(function versionMismatch() {
5344
+ setTimeout(function() {
5351
5345
  throw new Error(e);
5352
5346
  }, 0);
5353
5347
 
5354
5348
  // exit, init will fail with timeout
5355
- return false;
5349
+ return;
5356
5350
 
5357
5351
  }
5358
5352
  // </d>
@@ -5367,12 +5361,10 @@ featureCheck = function() {
5367
5361
  * ------------------------------
5368
5362
  */
5369
5363
 
5370
- createMovie = function(smID, smURL) {
5364
+ createMovie = function(movieID, movieURL) {
5371
5365
 
5372
- if (didAppend && appendSuccess) {
5373
- // ignore if already succeeded
5374
- return false;
5375
- }
5366
+ // ignore if already connected
5367
+ if (didAppend && appendSuccess) return false;
5376
5368
 
5377
5369
  function initMsg() {
5378
5370
 
@@ -5415,14 +5407,10 @@ featureCheck = function() {
5415
5407
  options.push('flashBlock');
5416
5408
  }
5417
5409
 
5418
- } else {
5419
-
5420
- if (sm2.html5PollingInterval) {
5410
+ } else if (sm2.html5PollingInterval) {
5421
5411
  options.push('html5PollingInterval (' + sm2.html5PollingInterval + 'ms)');
5422
5412
  }
5423
5413
 
5424
- }
5425
-
5426
5414
  if (options.length) {
5427
5415
  msg = msg.concat([options.join(delimiter)]);
5428
5416
  }
@@ -5454,7 +5442,7 @@ featureCheck = function() {
5454
5442
  }
5455
5443
 
5456
5444
  // flash path
5457
- var remoteURL = (smURL || sm2.url),
5445
+ var remoteURL = (movieURL || sm2.url),
5458
5446
  localURL = (sm2.altURL || remoteURL),
5459
5447
  swfTitle = 'JS/Flash audio component (SoundManager 2)',
5460
5448
  oTarget = getDocument(),
@@ -5464,7 +5452,7 @@ featureCheck = function() {
5464
5452
  oEmbed, oMovie, tmp, movieHTML, oEl, s, x, sClass;
5465
5453
 
5466
5454
  isRTL = (html && html.dir && html.dir.match(/rtl/i));
5467
- smID = (smID === _undefined ? sm2.id : smID);
5455
+ movieID = (movieID === _undefined ? sm2.id : movieID);
5468
5456
 
5469
5457
  function param(name, value) {
5470
5458
  return '<param name="' + name + '" value="' + value + '" />';
@@ -5473,7 +5461,7 @@ featureCheck = function() {
5473
5461
  // safety check for legacy (change to Flash 9 URL)
5474
5462
  setVersionInfo();
5475
5463
  sm2.url = normalizeMovieURL(overHTTP ? remoteURL : localURL);
5476
- smURL = sm2.url;
5464
+ movieURL = sm2.url;
5477
5465
 
5478
5466
  sm2.wmode = (!sm2.wmode && sm2.useHighPerformance ? 'transparent' : sm2.wmode);
5479
5467
 
@@ -5488,18 +5476,18 @@ featureCheck = function() {
5488
5476
  }
5489
5477
 
5490
5478
  oEmbed = {
5491
- 'name': smID,
5492
- 'id': smID,
5493
- 'src': smURL,
5494
- 'quality': 'high',
5495
- 'allowScriptAccess': sm2.allowScriptAccess,
5496
- 'bgcolor': sm2.bgColor,
5497
- 'pluginspage': http + 'www.macromedia.com/go/getflashplayer',
5498
- 'title': swfTitle,
5499
- 'type': 'application/x-shockwave-flash',
5500
- 'wmode': sm2.wmode,
5479
+ name: movieID,
5480
+ id: movieID,
5481
+ src: movieURL,
5482
+ quality: 'high',
5483
+ allowScriptAccess: sm2.allowScriptAccess,
5484
+ bgcolor: sm2.bgColor,
5485
+ pluginspage: http + 'www.macromedia.com/go/getflashplayer',
5486
+ title: swfTitle,
5487
+ type: 'application/x-shockwave-flash',
5488
+ wmode: sm2.wmode,
5501
5489
  // http://help.adobe.com/en_US/as3/mobile/WS4bebcd66a74275c36cfb8137124318eebc6-7ffd.html
5502
- 'hasPriority': 'true'
5490
+ hasPriority: 'true'
5503
5491
  };
5504
5492
 
5505
5493
  if (sm2.debugFlash) {
@@ -5516,11 +5504,11 @@ featureCheck = function() {
5516
5504
  // IE is "special".
5517
5505
  oMovie = doc.createElement('div');
5518
5506
  movieHTML = [
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">',
5520
- param('movie', smURL),
5507
+ '<object id="' + movieID + '" data="' + movieURL + '" type="' + oEmbed.type + '" title="' + oEmbed.title + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0">',
5508
+ param('movie', movieURL),
5521
5509
  param('AllowScriptAccess', sm2.allowScriptAccess),
5522
5510
  param('quality', oEmbed.quality),
5523
- (sm2.wmode? param('wmode', sm2.wmode): ''),
5511
+ (sm2.wmode ? param('wmode', sm2.wmode) : ''),
5524
5512
  param('bgcolor', sm2.bgColor),
5525
5513
  param('hasPriority', 'true'),
5526
5514
  (sm2.debugFlash ? param('FlashVars', oEmbed.FlashVars) : ''),
@@ -5557,22 +5545,22 @@ featureCheck = function() {
5557
5545
  if (sm2.useHighPerformance) {
5558
5546
  // on-screen at all times
5559
5547
  s = {
5560
- 'position': 'fixed',
5561
- 'width': '8px',
5562
- 'height': '8px',
5548
+ position: 'fixed',
5549
+ width: '8px',
5550
+ height: '8px',
5563
5551
  // >= 6px for flash to run fast, >= 8px to start up under Firefox/win32 in some cases. odd? yes.
5564
- 'bottom': '0px',
5565
- 'left': '0px',
5566
- 'overflow': 'hidden'
5552
+ bottom: '0px',
5553
+ left: '0px',
5554
+ overflow: 'hidden'
5567
5555
  };
5568
5556
  } else {
5569
5557
  // hide off-screen, lower priority
5570
5558
  s = {
5571
- 'position': 'absolute',
5572
- 'width': '6px',
5573
- 'height': '6px',
5574
- 'top': '-9999px',
5575
- 'left': '-9999px'
5559
+ position: 'absolute',
5560
+ width: '6px',
5561
+ height: '6px',
5562
+ top: '-9999px',
5563
+ left: '-9999px'
5576
5564
  };
5577
5565
  if (isRTL) {
5578
5566
  s.left = Math.abs(parseInt(s.left, 10)) + 'px';
@@ -5638,7 +5626,7 @@ featureCheck = function() {
5638
5626
 
5639
5627
  initMsg();
5640
5628
 
5641
- // sm2._wD(sm + ': Trying to load ' + smURL + (!overHTTP && sm2.altURL ? ' (alternate URL)' : ''), 1);
5629
+ // sm2._wD(sm + ': Trying to load ' + movieURL + (!overHTTP && sm2.altURL ? ' (alternate URL)' : ''), 1);
5642
5630
 
5643
5631
  return true;
5644
5632
 
@@ -5652,9 +5640,7 @@ featureCheck = function() {
5652
5640
  }
5653
5641
 
5654
5642
  // attempt to get, or create, movie (may already exist)
5655
- if (flash) {
5656
- return false;
5657
- }
5643
+ if (flash) return false;
5658
5644
 
5659
5645
  if (!sm2.url) {
5660
5646
 
@@ -5743,11 +5729,11 @@ featureCheck = function() {
5743
5729
 
5744
5730
  if (!sm2.url) {
5745
5731
  // No SWF url to load (noURL case) - exit for now. Will be retried when url is set.
5746
- return false;
5732
+ return;
5747
5733
  }
5748
5734
 
5749
5735
  if (waitingForEI) {
5750
- return false;
5736
+ return;
5751
5737
  }
5752
5738
 
5753
5739
  waitingForEI = true;
@@ -5756,7 +5742,7 @@ featureCheck = function() {
5756
5742
  if (hasFlash && tryInitOnFocus && !isFocused) {
5757
5743
  // Safari won't load flash in background tabs, only when focused.
5758
5744
  _wDS('waitFocus');
5759
- return false;
5745
+ return;
5760
5746
  }
5761
5747
 
5762
5748
  if (!didInit) {
@@ -5775,7 +5761,7 @@ featureCheck = function() {
5775
5761
  waitingForEI = false;
5776
5762
  sm2._wD(str('waitSWF'));
5777
5763
  window.setTimeout(delayWaitForEI, 1);
5778
- return false;
5764
+ return;
5779
5765
  }
5780
5766
 
5781
5767
  // <d>
@@ -5800,7 +5786,7 @@ featureCheck = function() {
5800
5786
 
5801
5787
  }
5802
5788
 
5803
- debugTS('flashtojs', false, ': Timed out' + (overHTTP ? ' (Check flash security or flash blockers)':' (No plugin/missing SWF?)'));
5789
+ debugTS('flashtojs', false, ': Timed out' + (overHTTP ? ' (Check flash security or flash blockers)' : ' (No plugin/missing SWF?)'));
5804
5790
 
5805
5791
  }
5806
5792
  // </d>
@@ -5823,52 +5809,39 @@ featureCheck = function() {
5823
5809
 
5824
5810
  _wDS('waitForever');
5825
5811
 
5826
- } else {
5812
+ } else if (!sm2.useFlashBlock && canIgnoreFlash) {
5827
5813
 
5828
5814
  // no custom flash block handling, but SWF has timed out. Will recover if user unblocks / allows SWF load.
5815
+ rebootIntoHTML5();
5829
5816
 
5830
- if (!sm2.useFlashBlock && canIgnoreFlash) {
5831
-
5832
- rebootIntoHTML5();
5833
-
5834
- } else {
5835
-
5836
- _wDS('waitForever');
5817
+ } else {
5837
5818
 
5838
- // fire any regular registered ontimeout() listeners.
5839
- processOnEvents({
5840
- type: 'ontimeout',
5841
- ignoreInit: true,
5842
- error: {
5843
- type: 'INIT_FLASHBLOCK'
5844
- }
5845
- });
5819
+ _wDS('waitForever');
5846
5820
 
5847
- }
5821
+ // fire any regular registered ontimeout() listeners.
5822
+ processOnEvents({
5823
+ type: 'ontimeout',
5824
+ ignoreInit: true,
5825
+ error: {
5826
+ type: 'INIT_FLASHBLOCK'
5827
+ }
5828
+ });
5848
5829
 
5849
5830
  }
5850
5831
 
5851
- } else {
5832
+ } else if (sm2.flashLoadTimeout === 0) {
5852
5833
 
5853
5834
  // SWF loaded? Shouldn't be a blocking issue, then.
5854
5835
 
5855
- if (sm2.flashLoadTimeout === 0) {
5836
+ _wDS('waitForever');
5856
5837
 
5857
- _wDS('waitForever');
5858
-
5859
- } else {
5838
+ } else if (!sm2.useFlashBlock && canIgnoreFlash) {
5860
5839
 
5861
- if (!sm2.useFlashBlock && canIgnoreFlash) {
5840
+ rebootIntoHTML5();
5862
5841
 
5863
- rebootIntoHTML5();
5864
-
5865
- } else {
5866
-
5867
- failSafely(true);
5868
-
5869
- }
5842
+ } else {
5870
5843
 
5871
- }
5844
+ failSafely(true);
5872
5845
 
5873
5846
  }
5874
5847
 
@@ -5942,9 +5915,7 @@ featureCheck = function() {
5942
5915
 
5943
5916
  initComplete = function(bNoDisable) {
5944
5917
 
5945
- if (didInit) {
5946
- return false;
5947
- }
5918
+ if (didInit) return false;
5948
5919
 
5949
5920
  if (sm2.html5Only) {
5950
5921
  // all good.
@@ -5967,7 +5938,7 @@ featureCheck = function() {
5967
5938
  type: (!hasFlash && needsFlash ? 'NO_FLASH' : 'INIT_TIMEOUT')
5968
5939
  };
5969
5940
 
5970
- sm2._wD('SoundManager 2 ' + (disabled ? 'failed to load' : 'loaded') + ' (' + (disabled ? 'Flash security/load error' : 'OK') + ') ' + String.fromCharCode(disabled ? 10006 : 10003), disabled ? 2: 1);
5941
+ sm2._wD('SoundManager 2 ' + (disabled ? 'failed to load' : 'loaded') + ' (' + (disabled ? 'Flash security/load error' : 'OK') + ') ' + String.fromCharCode(disabled ? 10006 : 10003), disabled ? 2 : 1);
5971
5942
 
5972
5943
  if (disabled || bNoDisable) {
5973
5944
 
@@ -6136,9 +6107,7 @@ featureCheck = function() {
6136
6107
 
6137
6108
  domContentLoaded = function() {
6138
6109
 
6139
- if (didDCLoaded) {
6140
- return false;
6141
- }
6110
+ if (didDCLoaded) return false;
6142
6111
 
6143
6112
  didDCLoaded = true;
6144
6113
 
@@ -6152,10 +6121,10 @@ featureCheck = function() {
6152
6121
  sm2._wD('SoundManager 2: No Flash detected' + (!sm2.useHTML5Audio ? ', enabling HTML5.' : '. Trying HTML5-only mode.'), 1);
6153
6122
 
6154
6123
  sm2.setup({
6155
- 'useHTML5Audio': true,
6124
+ useHTML5Audio: true,
6156
6125
  // make sure we aren't preferring flash, either
6157
6126
  // TODO: preferFlash should not matter if flash is not installed. Currently, stuff breaks without the below tweak.
6158
- 'preferFlash': false
6127
+ preferFlash: false
6159
6128
  });
6160
6129
 
6161
6130
  }
@@ -6169,7 +6138,7 @@ featureCheck = function() {
6169
6138
  // TODO: Fatal here vs. timeout approach, etc.
6170
6139
  // hack: fail sooner.
6171
6140
  sm2.setup({
6172
- 'flashLoadTimeout': 1
6141
+ flashLoadTimeout: 1
6173
6142
  });
6174
6143
 
6175
6144
  }
@@ -6281,7 +6250,7 @@ if (typeof module === 'object' && module && typeof module.exports === 'object')
6281
6250
  * soundManager.beginDelayedInit();
6282
6251
  * return soundManager;
6283
6252
  * })
6284
- * });
6253
+ * });
6285
6254
  */
6286
6255
 
6287
6256
  define(function() {
@@ -6304,7 +6273,7 @@ if (typeof module === 'object' && module && typeof module.exports === 'object')
6304
6273
  return {
6305
6274
  constructor: SoundManager,
6306
6275
  getInstance: getInstance
6307
- }
6276
+ };
6308
6277
  });
6309
6278
 
6310
6279
  }