soundmanager2-rails 2.97.20150601 → 2.97.20170601

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,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
  }