soundmanager-rails 0.1.4 → 0.1.5
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +1 -1
- data/lib/soundmanager-rails/version.rb +1 -1
- data/vendor/assets/images/swf/soundmanager2.swf +0 -0
- data/vendor/assets/images/swf/soundmanager2_debug.swf +0 -0
- data/vendor/assets/images/swf/soundmanager2_flash9.swf +0 -0
- data/vendor/assets/images/swf/soundmanager2_flash9_debug.swf +0 -0
- data/vendor/assets/javascripts/soundmanager2-jsmin.js +98 -94
- data/vendor/assets/javascripts/soundmanager2-nodebug-jsmin.js +70 -67
- data/vendor/assets/javascripts/soundmanager2-nodebug.js +184 -87
- data/vendor/assets/javascripts/soundmanager2.js +383 -131
- metadata +4 -2
@@ -8,11 +8,11 @@
|
|
8
8
|
* Code provided under the BSD License:
|
9
9
|
* http://schillmania.com/projects/soundmanager2/license.txt
|
10
10
|
*
|
11
|
-
* V2.97a.
|
11
|
+
* V2.97a.20130512
|
12
12
|
*/
|
13
13
|
|
14
14
|
/*global window, SM2_DEFER, sm2Debugger, console, document, navigator, setTimeout, setInterval, clearInterval, Audio, opera */
|
15
|
-
/*jslint regexp: true, sloppy: true, white: true, nomen: true, plusplus: true */
|
15
|
+
/*jslint regexp: true, sloppy: true, white: true, nomen: true, plusplus: true, todo: true */
|
16
16
|
|
17
17
|
/**
|
18
18
|
* About this file
|
@@ -74,7 +74,8 @@ function SoundManager(smURL, smID) {
|
|
74
74
|
'useHTML5Audio': true, // use HTML5 Audio() where API is supported (most Safari, Chrome versions), Firefox (no MP3/MP4.) Ideally, transparent vs. Flash API where possible.
|
75
75
|
'html5Test': /^(probably|maybe)$/i, // HTML5 Audio() format support test. Use /^probably$/i; if you want to be more conservative.
|
76
76
|
'preferFlash': true, // overrides useHTML5audio. if true and flash support present, will try to use flash for MP3/MP4 as needed since HTML5 audio support is still quirky in browsers.
|
77
|
-
'noSWFCache': false
|
77
|
+
'noSWFCache': false, // if true, appends ?ts={date} to break aggressive SWF caching.
|
78
|
+
'idPrefix': 'sound' // if an id is not provided to createSound(), this prefix is used for generated IDs - 'sound0', 'sound1' etc.
|
78
79
|
|
79
80
|
};
|
80
81
|
|
@@ -166,6 +167,11 @@ function SoundManager(smURL, smID) {
|
|
166
167
|
'required': false
|
167
168
|
},
|
168
169
|
|
170
|
+
'opus': {
|
171
|
+
'type': ['audio/ogg; codecs=opus', 'audio/opus'],
|
172
|
+
'required': false
|
173
|
+
},
|
174
|
+
|
169
175
|
'wav': {
|
170
176
|
'type': ['audio/wav; codecs="1"', 'audio/wav', 'audio/wave', 'audio/x-wav'],
|
171
177
|
'required': false
|
@@ -183,7 +189,7 @@ function SoundManager(smURL, smID) {
|
|
183
189
|
|
184
190
|
// dynamic attributes
|
185
191
|
|
186
|
-
this.versionNumber = 'V2.97a.
|
192
|
+
this.versionNumber = 'V2.97a.20130512';
|
187
193
|
this.version = null;
|
188
194
|
this.movieURL = null;
|
189
195
|
this.altURL = null;
|
@@ -260,11 +266,11 @@ function SoundManager(smURL, smID) {
|
|
260
266
|
|
261
267
|
var SMSound,
|
262
268
|
sm2 = this, globalHTML5Audio = null, flash = null, sm = 'soundManager', smc = sm + ': ', h5 = 'HTML5::', id, ua = navigator.userAgent, wl = window.location.href.toString(), doc = document, doNothing, setProperties, init, fV, on_queue = [], debugOpen = true, debugTS, didAppend = false, appendSuccess = false, didInit = false, disabled = false, windowLoaded = false, _wDS, wdCount = 0, initComplete, mixin, assign, extraOptions, addOnEvent, processOnEvents, initUserOnload, delayWaitForEI, waitForEI, setVersionInfo, handleFocus, strings, initMovie, preInit, domContentLoaded, winOnLoad, didDCLoaded, getDocument, createMovie, catchError, setPolling, initDebug, debugLevels = ['log', 'info', 'warn', 'error'], defaultFlashVersion = 8, disableObject, failSafely, normalizeMovieURL, oRemoved = null, oRemovedHTML = null, str, flashBlockHandler, getSWFCSS, swfCSS, toggleDebug, loopFix, policyFix, complain, idCheck, waitingForEI = false, initPending = false, startTimer, stopTimer, timerExecute, h5TimerCount = 0, h5IntervalTimer = null, parseURL, messages = [],
|
263
|
-
needsFlash = null, featureCheck, html5OK, html5CanPlay, html5Ext, html5Unload, domContentLoadedIE, testHTML5, event, slice = Array.prototype.slice, useGlobalHTML5Audio = false, lastGlobalHTML5URL, hasFlash, detectFlash, badSafariFix, html5_events, showSupport, flushMessages,
|
264
|
-
is_iDevice = ua.match(/(ipad|iphone|ipod)/i), isAndroid = ua.match(/android/i), isIE = ua.match(/msie/i), isWebkit = ua.match(/webkit/i), isSafari = (ua.match(/safari/i) && !ua.match(/chrome/i)), isOpera = (ua.match(/opera/i)),
|
269
|
+
canIgnoreFlash, needsFlash = null, featureCheck, html5OK, html5CanPlay, html5Ext, html5Unload, domContentLoadedIE, testHTML5, event, slice = Array.prototype.slice, useGlobalHTML5Audio = false, lastGlobalHTML5URL, hasFlash, detectFlash, badSafariFix, html5_events, showSupport, flushMessages, wrapCallback, idCounter = 0,
|
270
|
+
is_iDevice = ua.match(/(ipad|iphone|ipod)/i), isAndroid = ua.match(/android/i), isIE = ua.match(/msie/i), isWebkit = ua.match(/webkit/i), isSafari = (ua.match(/safari/i) && !ua.match(/chrome/i)), isOpera = (ua.match(/opera/i)), isFirefox = (ua.match(/firefox/i)),
|
265
271
|
mobileHTML5 = (ua.match(/(mobile|pre\/|xoom)/i) || is_iDevice || isAndroid),
|
266
272
|
isBadSafari = (!wl.match(/usehtml5audio/i) && !wl.match(/sm2\-ignorebadua/i) && isSafari && !ua.match(/silk/i) && ua.match(/OS X 10_6_([3-7])/i)), // Safari 4 and 5 (excluding Kindle Fire, "Silk") occasionally fail to load/play HTML5 audio on Snow Leopard 10.6.3 through 10.6.7 due to bug(s) in QuickTime X and/or other underlying frameworks. :/ Confirmed bug. https://bugs.webkit.org/show_bug.cgi?id=32159
|
267
|
-
hasConsole = (window.console !== _undefined && console.log !== _undefined), isFocused = (doc.hasFocus !== _undefined?doc.hasFocus():null), tryInitOnFocus = (isSafari && (doc.hasFocus === _undefined || !doc.hasFocus())), okToDisable = !tryInitOnFocus, flashMIME = /(mp3|mp4|mpa|m4a|m4b)/i,
|
273
|
+
hasConsole = (window.console !== _undefined && console.log !== _undefined), isFocused = (doc.hasFocus !== _undefined?doc.hasFocus():null), tryInitOnFocus = (isSafari && (doc.hasFocus === _undefined || !doc.hasFocus())), okToDisable = !tryInitOnFocus, flashMIME = /(mp3|mp4|mpa|m4a|m4b)/i, msecScale = 1000,
|
268
274
|
emptyURL = 'about:blank', // safe URL to unload, or load nothing from (flash 8 + most HTML5 UAs)
|
269
275
|
overHTTP = (doc.location?doc.location.protocol.match(/http/i):null),
|
270
276
|
http = (!overHTTP ? 'http:/'+'/' : ''),
|
@@ -336,14 +342,18 @@ function SoundManager(smURL, smID) {
|
|
336
342
|
|
337
343
|
// special case 1: "Late setup". SM2 loaded normally, but user didn't assign flash URL eg., setup({url:...}) before SM2 init. Treat as delayed init.
|
338
344
|
|
339
|
-
if (
|
340
|
-
sm2.beginDelayedInit();
|
341
|
-
}
|
345
|
+
if (options) {
|
342
346
|
|
343
|
-
|
347
|
+
if (noURL && didDCLoaded && options.url !== _undefined) {
|
348
|
+
sm2.beginDelayedInit();
|
349
|
+
}
|
350
|
+
|
351
|
+
// special case 2: If lazy-loading SM2 (DOMContentLoaded has already happened) and user calls setup() with url: parameter, try to init ASAP.
|
352
|
+
|
353
|
+
if (!didDCLoaded && options.url !== _undefined && doc.readyState === 'complete') {
|
354
|
+
setTimeout(domContentLoaded, 1);
|
355
|
+
}
|
344
356
|
|
345
|
-
if (!didDCLoaded && options.url !== _undefined && doc.readyState === 'complete') {
|
346
|
-
setTimeout(domContentLoaded, 1);
|
347
357
|
}
|
348
358
|
|
349
359
|
return sm2;
|
@@ -352,7 +362,7 @@ function SoundManager(smURL, smID) {
|
|
352
362
|
|
353
363
|
this.ok = function() {
|
354
364
|
|
355
|
-
return (needsFlash?(didInit && !disabled):(sm2.useHTML5Audio && sm2.hasHTML5));
|
365
|
+
return (needsFlash ? (didInit && !disabled) : (sm2.useHTML5Audio && sm2.hasHTML5));
|
356
366
|
|
357
367
|
};
|
358
368
|
|
@@ -387,7 +397,7 @@ function SoundManager(smURL, smID) {
|
|
387
397
|
}
|
388
398
|
|
389
399
|
if (_url !== _undefined) {
|
390
|
-
// function overloading in JS! :) ..assume simple createSound(id,url) use case
|
400
|
+
// function overloading in JS! :) ..assume simple createSound(id, url) use case
|
391
401
|
oOptions = {
|
392
402
|
'id': oOptions,
|
393
403
|
'url': _url
|
@@ -399,12 +409,17 @@ function SoundManager(smURL, smID) {
|
|
399
409
|
|
400
410
|
options.url = parseURL(options.url);
|
401
411
|
|
412
|
+
// generate an id, if needed.
|
413
|
+
if (options.id === undefined) {
|
414
|
+
options.id = sm2.setupOptions.idPrefix + (idCounter++);
|
415
|
+
}
|
416
|
+
|
402
417
|
// <d>
|
403
418
|
if (options.id.toString().charAt(0).match(/^[0-9]$/)) {
|
404
419
|
sm2._wD(cs + str('badID', options.id), 2);
|
405
420
|
}
|
406
421
|
|
407
|
-
sm2._wD(cs + options.id + ' (' + options.url + ')', 1);
|
422
|
+
sm2._wD(cs + options.id + (options.url ? ' (' + options.url + ')' : ''), 1);
|
408
423
|
// </d>
|
409
424
|
|
410
425
|
if (idCheck(options.id, true)) {
|
@@ -429,10 +444,23 @@ function SoundManager(smURL, smID) {
|
|
429
444
|
|
430
445
|
} else {
|
431
446
|
|
447
|
+
if (sm2.html5Only) {
|
448
|
+
sm2._wD(options.id + ': No HTML5 support for this sound, and no Flash. Exiting.');
|
449
|
+
return make();
|
450
|
+
}
|
451
|
+
|
452
|
+
// TODO: Move HTML5/flash checks into generic URL parsing/handling function.
|
453
|
+
|
454
|
+
if (sm2.html5.usingFlash && options.url && options.url.match(/data\:/i)) {
|
455
|
+
// data: URIs not supported by Flash, either.
|
456
|
+
sm2._wD(options.id + ': data: URIs not supported via Flash. Exiting.');
|
457
|
+
return make();
|
458
|
+
}
|
459
|
+
|
432
460
|
if (fV > 8) {
|
433
461
|
if (options.isMovieStar === null) {
|
434
462
|
// attempt to detect MPEG-4 formats
|
435
|
-
options.isMovieStar = !!(options.serverURL || (options.type ? options.type.match(netStreamMimeTypes) : false) || options.url.match(netStreamPattern));
|
463
|
+
options.isMovieStar = !!(options.serverURL || (options.type ? options.type.match(netStreamMimeTypes) : false) || (options.url && options.url.match(netStreamPattern)));
|
436
464
|
}
|
437
465
|
// <d>
|
438
466
|
if (options.isMovieStar) {
|
@@ -598,30 +626,50 @@ function SoundManager(smURL, smID) {
|
|
598
626
|
|
599
627
|
this.play = function(sID, oOptions) {
|
600
628
|
|
601
|
-
var result =
|
629
|
+
var result = null,
|
630
|
+
// legacy function-overloading use case: play('mySound', '/path/to/some.mp3');
|
631
|
+
overloaded = (oOptions && !(oOptions instanceof Object));
|
602
632
|
|
603
633
|
if (!didInit || !sm2.ok()) {
|
604
634
|
complain(sm + '.play(): ' + str(!didInit?'notReady':'notOK'));
|
605
|
-
return
|
635
|
+
return false;
|
606
636
|
}
|
607
637
|
|
608
|
-
if (!idCheck(sID)) {
|
609
|
-
|
610
|
-
|
638
|
+
if (!idCheck(sID, overloaded)) {
|
639
|
+
|
640
|
+
if (!overloaded) {
|
641
|
+
// no sound found for the given ID. Bail.
|
642
|
+
return false;
|
643
|
+
}
|
644
|
+
|
645
|
+
if (overloaded) {
|
611
646
|
oOptions = {
|
612
647
|
url: oOptions
|
613
648
|
};
|
614
649
|
}
|
650
|
+
|
615
651
|
if (oOptions && oOptions.url) {
|
616
|
-
// overloading use case, create+play: .play('someID',{url:'/path/to.mp3'});
|
617
|
-
sm2._wD(sm + '.play():
|
652
|
+
// overloading use case, create+play: .play('someID', {url:'/path/to.mp3'});
|
653
|
+
sm2._wD(sm + '.play(): Attempting to create "' + sID + '"', 1);
|
618
654
|
oOptions.id = sID;
|
619
655
|
result = sm2.createSound(oOptions).play();
|
620
656
|
}
|
621
|
-
|
657
|
+
|
658
|
+
} else if (overloaded) {
|
659
|
+
|
660
|
+
// existing sound object case
|
661
|
+
oOptions = {
|
662
|
+
url: oOptions
|
663
|
+
};
|
664
|
+
|
622
665
|
}
|
623
666
|
|
624
|
-
|
667
|
+
if (result === null) {
|
668
|
+
// default case
|
669
|
+
result = sm2.sounds[sID].play(oOptions);
|
670
|
+
}
|
671
|
+
|
672
|
+
return result;
|
625
673
|
|
626
674
|
};
|
627
675
|
|
@@ -1020,14 +1068,14 @@ function SoundManager(smURL, smID) {
|
|
1020
1068
|
this.getSoundById = function(sID, _suppressDebug) {
|
1021
1069
|
|
1022
1070
|
if (!sID) {
|
1023
|
-
|
1071
|
+
return null;
|
1024
1072
|
}
|
1025
1073
|
|
1026
1074
|
var result = sm2.sounds[sID];
|
1027
1075
|
|
1028
1076
|
// <d>
|
1029
1077
|
if (!result && !_suppressDebug) {
|
1030
|
-
sm2._wD('"' + sID + '"
|
1078
|
+
sm2._wD(sm + '.getSoundById(): Sound "' + sID + '" not found.', 2);
|
1031
1079
|
}
|
1032
1080
|
// </d>
|
1033
1081
|
|
@@ -1118,10 +1166,10 @@ function SoundManager(smURL, smID) {
|
|
1118
1166
|
* Applies when debugMode = true
|
1119
1167
|
*
|
1120
1168
|
* @param {string} sText The console message
|
1121
|
-
* @param {object}
|
1169
|
+
* @param {object} nType Optional log level (number), or object. Number case: Log type/style where 0 = 'info', 1 = 'warn', 2 = 'error'. Object case: Object to be dumped.
|
1122
1170
|
*/
|
1123
1171
|
|
1124
|
-
this._writeDebug = function(sText,
|
1172
|
+
this._writeDebug = function(sText, sTypeOrObject) {
|
1125
1173
|
|
1126
1174
|
// pseudo-private console.log()-style output
|
1127
1175
|
// <d>
|
@@ -1133,11 +1181,11 @@ function SoundManager(smURL, smID) {
|
|
1133
1181
|
}
|
1134
1182
|
|
1135
1183
|
if (hasConsole && sm2.useConsole) {
|
1136
|
-
if (
|
1184
|
+
if (sTypeOrObject && typeof sTypeOrObject === 'object') {
|
1137
1185
|
// object passed; dump to console.
|
1138
|
-
console.log(sText,
|
1139
|
-
} else if (debugLevels[
|
1140
|
-
console[debugLevels[
|
1186
|
+
console.log(sText, sTypeOrObject);
|
1187
|
+
} else if (debugLevels[sTypeOrObject] !== _undefined) {
|
1188
|
+
console[debugLevels[sTypeOrObject]](sText);
|
1141
1189
|
} else {
|
1142
1190
|
console.log(sText);
|
1143
1191
|
}
|
@@ -1158,19 +1206,19 @@ function SoundManager(smURL, smID) {
|
|
1158
1206
|
oItem.className = 'sm2-alt';
|
1159
1207
|
}
|
1160
1208
|
|
1161
|
-
if (
|
1162
|
-
|
1209
|
+
if (sTypeOrObject === _undefined) {
|
1210
|
+
sTypeOrObject = 0;
|
1163
1211
|
} else {
|
1164
|
-
|
1212
|
+
sTypeOrObject = parseInt(sTypeOrObject, 10);
|
1165
1213
|
}
|
1166
1214
|
|
1167
1215
|
oItem.appendChild(doc.createTextNode(sText));
|
1168
1216
|
|
1169
|
-
if (
|
1170
|
-
if (
|
1217
|
+
if (sTypeOrObject) {
|
1218
|
+
if (sTypeOrObject >= 2) {
|
1171
1219
|
oItem.style.fontWeight = 'bold';
|
1172
1220
|
}
|
1173
|
-
if (
|
1221
|
+
if (sTypeOrObject === 3) {
|
1174
1222
|
oItem.style.color = '#ff3333';
|
1175
1223
|
}
|
1176
1224
|
}
|
@@ -1231,7 +1279,7 @@ function SoundManager(smURL, smID) {
|
|
1231
1279
|
|
1232
1280
|
// <d>
|
1233
1281
|
if (sm2.soundIDs.length) {
|
1234
|
-
sm2._wD('Destroying ' + sm2.soundIDs.length + ' SMSound
|
1282
|
+
sm2._wD('Destroying ' + sm2.soundIDs.length + ' SMSound object' + (sm2.soundIDs.length !== 1 ? 's' : '') + '...');
|
1235
1283
|
}
|
1236
1284
|
// </d>
|
1237
1285
|
|
@@ -1241,7 +1289,7 @@ function SoundManager(smURL, smID) {
|
|
1241
1289
|
sm2.sounds[sm2.soundIDs[i]].destruct();
|
1242
1290
|
}
|
1243
1291
|
|
1244
|
-
// trash ze flash
|
1292
|
+
// trash ze flash (remove from the DOM)
|
1245
1293
|
|
1246
1294
|
if (flash) {
|
1247
1295
|
|
@@ -1253,8 +1301,6 @@ function SoundManager(smURL, smID) {
|
|
1253
1301
|
|
1254
1302
|
oRemoved = flash.parentNode.removeChild(flash);
|
1255
1303
|
|
1256
|
-
_wDS('flRemoved');
|
1257
|
-
|
1258
1304
|
} catch(e) {
|
1259
1305
|
|
1260
1306
|
// Remove failed? May be due to flash blockers silently removing the SWF object/embed node from the DOM. Warn and continue.
|
@@ -1274,6 +1320,8 @@ function SoundManager(smURL, smID) {
|
|
1274
1320
|
sm2.soundIDs = [];
|
1275
1321
|
sm2.sounds = {};
|
1276
1322
|
|
1323
|
+
idCounter = 0;
|
1324
|
+
|
1277
1325
|
if (!resetEvents) {
|
1278
1326
|
// reset callbacks for onready, ontimeout etc. so that they will fire again on re-init
|
1279
1327
|
for (i in on_queue) {
|
@@ -1404,7 +1452,7 @@ function SoundManager(smURL, smID) {
|
|
1404
1452
|
|
1405
1453
|
SMSound = function(oOptions) {
|
1406
1454
|
|
1407
|
-
var s = this, resetProperties, add_html5_events, remove_html5_events, stop_html5_timer, start_html5_timer, attachOnPosition, onplay_called = false, onPositionItems = [], onPositionFired = 0, detachOnPosition, applyFromTo, lastURL = null, lastHTML5State;
|
1455
|
+
var s = this, resetProperties, add_html5_events, remove_html5_events, stop_html5_timer, start_html5_timer, attachOnPosition, onplay_called = false, onPositionItems = [], onPositionFired = 0, detachOnPosition, applyFromTo, lastURL = null, lastHTML5State, urlOmitted;
|
1408
1456
|
|
1409
1457
|
lastHTML5State = {
|
1410
1458
|
// tracks duration + position (time)
|
@@ -1436,6 +1484,9 @@ function SoundManager(smURL, smID) {
|
|
1436
1484
|
// internal HTML5 Audio() object reference
|
1437
1485
|
this._a = null;
|
1438
1486
|
|
1487
|
+
// for flash 8 special-case createSound() without url, followed by load/play with url case
|
1488
|
+
urlOmitted = (this.url ? false : true);
|
1489
|
+
|
1439
1490
|
/**
|
1440
1491
|
* SMSound() public methods
|
1441
1492
|
* ------------------------
|
@@ -1492,12 +1543,26 @@ function SoundManager(smURL, smID) {
|
|
1492
1543
|
|
1493
1544
|
sm2._wD(s.id + ': load (' + instanceOptions.url + ')');
|
1494
1545
|
|
1546
|
+
if (!instanceOptions.url && !s.url) {
|
1547
|
+
sm2._wD(s.id + ': load(): url is unassigned. Exiting.', 2);
|
1548
|
+
return s;
|
1549
|
+
}
|
1550
|
+
|
1551
|
+
// <d>
|
1552
|
+
if (!s.isHTML5 && fV === 8 && !s.url && !instanceOptions.autoPlay) {
|
1553
|
+
// flash 8 load() -> play() won't work before onload has fired.
|
1554
|
+
sm2._wD(s.id + ': Flash 8 load() limitation: Wait for onload() before calling play().', 1);
|
1555
|
+
}
|
1556
|
+
// </d>
|
1557
|
+
|
1495
1558
|
if (instanceOptions.url === s.url && s.readyState !== 0 && s.readyState !== 2) {
|
1496
1559
|
_wDS('onURL', 1);
|
1497
1560
|
// if loaded and an onload() exists, fire immediately.
|
1498
1561
|
if (s.readyState === 3 && instanceOptions.onload) {
|
1499
1562
|
// assume success based on truthy duration.
|
1500
|
-
|
1563
|
+
wrapCallback(s, function() {
|
1564
|
+
instanceOptions.onload.apply(s, [(!!s.duration)]);
|
1565
|
+
});
|
1501
1566
|
}
|
1502
1567
|
return s;
|
1503
1568
|
}
|
@@ -1541,7 +1606,8 @@ function SoundManager(smURL, smID) {
|
|
1541
1606
|
// early HTML5 implementation (non-standard)
|
1542
1607
|
s._a.autobuffer = 'auto';
|
1543
1608
|
|
1544
|
-
// standard
|
1609
|
+
// standard property, values: none / metadata / auto
|
1610
|
+
// reference: http://msdn.microsoft.com/en-us/library/ie/ff974759%28v=vs.85%29.aspx
|
1545
1611
|
s._a.preload = 'auto';
|
1546
1612
|
|
1547
1613
|
s._a._called_load = true;
|
@@ -1558,6 +1624,17 @@ function SoundManager(smURL, smID) {
|
|
1558
1624
|
|
1559
1625
|
} else {
|
1560
1626
|
|
1627
|
+
if (sm2.html5Only) {
|
1628
|
+
sm2._wD(s.id + ': No flash support. Exiting.');
|
1629
|
+
return s;
|
1630
|
+
}
|
1631
|
+
|
1632
|
+
if (s._iO.url && s._iO.url.match(/data\:/i)) {
|
1633
|
+
// data: URIs not supported by Flash, either.
|
1634
|
+
sm2._wD(s.id + ': data: URIs not supported via Flash. Exiting.');
|
1635
|
+
return s;
|
1636
|
+
}
|
1637
|
+
|
1561
1638
|
try {
|
1562
1639
|
s.isHTML5 = false;
|
1563
1640
|
s._iO = policyFix(loopFix(instanceOptions));
|
@@ -1614,10 +1691,9 @@ function SoundManager(smURL, smID) {
|
|
1614
1691
|
if (s._a) {
|
1615
1692
|
|
1616
1693
|
s._a.pause();
|
1617
|
-
html5Unload(s._a, emptyURL);
|
1618
1694
|
|
1619
1695
|
// update empty URL, too
|
1620
|
-
lastURL =
|
1696
|
+
lastURL = html5Unload(s._a);
|
1621
1697
|
|
1622
1698
|
}
|
1623
1699
|
|
@@ -1667,7 +1743,6 @@ function SoundManager(smURL, smID) {
|
|
1667
1743
|
if (!_bFromSM) {
|
1668
1744
|
// ensure deletion from controller
|
1669
1745
|
sm2.destroySound(s.id, true);
|
1670
|
-
|
1671
1746
|
}
|
1672
1747
|
|
1673
1748
|
};
|
@@ -1681,7 +1756,9 @@ function SoundManager(smURL, smID) {
|
|
1681
1756
|
|
1682
1757
|
this.play = function(oOptions, _updatePlayState) {
|
1683
1758
|
|
1684
|
-
var fN, allowMulti, a, onready,
|
1759
|
+
var fN, allowMulti, a, onready,
|
1760
|
+
audioClone, onended, oncanplay,
|
1761
|
+
startOK = true,
|
1685
1762
|
exit = null;
|
1686
1763
|
|
1687
1764
|
// <d>
|
@@ -1711,7 +1788,7 @@ function SoundManager(smURL, smID) {
|
|
1711
1788
|
s.instanceOptions = s._iO;
|
1712
1789
|
|
1713
1790
|
// RTMP-only
|
1714
|
-
if (s._iO.serverURL && !s.connected) {
|
1791
|
+
if (!s.isHTML5 && s._iO.serverURL && !s.connected) {
|
1715
1792
|
if (!s.getAutoPlay()) {
|
1716
1793
|
sm2._wD(fN +' Netstream not connected yet - setting autoPlay');
|
1717
1794
|
s.setAutoPlay(true);
|
@@ -1729,6 +1806,10 @@ function SoundManager(smURL, smID) {
|
|
1729
1806
|
allowMulti = s._iO.multiShot;
|
1730
1807
|
if (!allowMulti) {
|
1731
1808
|
sm2._wD(fN + 'Already playing (one-shot)', 1);
|
1809
|
+
if (s.isHTML5) {
|
1810
|
+
// go back to original position.
|
1811
|
+
s.setPosition(s._iO.position);
|
1812
|
+
}
|
1732
1813
|
exit = s;
|
1733
1814
|
} else {
|
1734
1815
|
sm2._wD(fN + 'Already playing (multi-shot)', 1);
|
@@ -1741,8 +1822,19 @@ function SoundManager(smURL, smID) {
|
|
1741
1822
|
|
1742
1823
|
// edge case: play() with explicit URL parameter
|
1743
1824
|
if (oOptions.url && oOptions.url !== s.url) {
|
1744
|
-
|
1745
|
-
|
1825
|
+
|
1826
|
+
// special case for createSound() followed by load() / play() with url; avoid double-load case.
|
1827
|
+
if (!s.readyState && !s.isHTML5 && fV === 8 && urlOmitted) {
|
1828
|
+
|
1829
|
+
urlOmitted = false;
|
1830
|
+
|
1831
|
+
} else {
|
1832
|
+
|
1833
|
+
// load using merged options
|
1834
|
+
s.load(s._iO);
|
1835
|
+
|
1836
|
+
}
|
1837
|
+
|
1746
1838
|
}
|
1747
1839
|
|
1748
1840
|
if (!s.loaded) {
|
@@ -1752,13 +1844,22 @@ function SoundManager(smURL, smID) {
|
|
1752
1844
|
sm2._wD(fN + 'Attempting to load');
|
1753
1845
|
|
1754
1846
|
// try to get this sound playing ASAP
|
1755
|
-
if (!s.isHTML5) {
|
1756
|
-
|
1847
|
+
if (!s.isHTML5 && !sm2.html5Only) {
|
1848
|
+
|
1849
|
+
// flash: assign directly because setAutoPlay() increments the instanceCount
|
1757
1850
|
s._iO.autoPlay = true;
|
1758
1851
|
s.load(s._iO);
|
1759
|
-
|
1852
|
+
|
1853
|
+
} else if (s.isHTML5) {
|
1854
|
+
|
1760
1855
|
// iOS needs this when recycling sounds, loading a new URL on an existing object.
|
1761
1856
|
s.load(s._iO);
|
1857
|
+
|
1858
|
+
} else {
|
1859
|
+
|
1860
|
+
sm2._wD(fN + 'Unsupported type. Exiting.');
|
1861
|
+
exit = s;
|
1862
|
+
|
1762
1863
|
}
|
1763
1864
|
|
1764
1865
|
// HTML5 hack - re-set instanceOptions?
|
@@ -1777,7 +1878,8 @@ function SoundManager(smURL, smID) {
|
|
1777
1878
|
|
1778
1879
|
} else {
|
1779
1880
|
|
1780
|
-
|
1881
|
+
// "play()"
|
1882
|
+
sm2._wD(fN.substr(0, fN.lastIndexOf(':')));
|
1781
1883
|
|
1782
1884
|
}
|
1783
1885
|
|
@@ -1857,9 +1959,10 @@ function SoundManager(smURL, smID) {
|
|
1857
1959
|
|
1858
1960
|
}
|
1859
1961
|
|
1860
|
-
sm2._wD(fN + 'Starting to play');
|
1962
|
+
// sm2._wD(fN + 'Starting to play');
|
1861
1963
|
|
1862
|
-
|
1964
|
+
// increment instance counter, where enabled + supported
|
1965
|
+
if (!s.instanceCount || s._iO.multiShotEvents || (s.isHTML5 && s._iO.multiShot && !useGlobalHTML5Audio) || (!s.isHTML5 && fV > 8 && !s.getAutoPlay())) {
|
1863
1966
|
s.instanceCount++;
|
1864
1967
|
}
|
1865
1968
|
|
@@ -1887,13 +1990,13 @@ function SoundManager(smURL, smID) {
|
|
1887
1990
|
|
1888
1991
|
if (!s.isHTML5) {
|
1889
1992
|
|
1890
|
-
startOK = flash._start(s.id, s._iO.loops || 1, (fV === 9 ? s.
|
1993
|
+
startOK = flash._start(s.id, s._iO.loops || 1, (fV === 9 ? s.position : s.position / msecScale), s._iO.multiShot || false);
|
1891
1994
|
|
1892
1995
|
if (fV === 9 && !startOK) {
|
1893
1996
|
// edge case: no sound hardware, or 32-channel flash ceiling hit.
|
1894
1997
|
// applies only to Flash 9, non-NetStream/MovieStar sounds.
|
1895
1998
|
// http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/media/Sound.html#play%28%29
|
1896
|
-
sm2._wD(fN + 'No sound hardware, or 32-sound ceiling hit');
|
1999
|
+
sm2._wD(fN + 'No sound hardware, or 32-sound ceiling hit', 2);
|
1897
2000
|
if (s._iO.onplayerror) {
|
1898
2001
|
s._iO.onplayerror.apply(s);
|
1899
2002
|
}
|
@@ -1902,13 +2005,56 @@ function SoundManager(smURL, smID) {
|
|
1902
2005
|
|
1903
2006
|
} else {
|
1904
2007
|
|
1905
|
-
|
2008
|
+
if (s.instanceCount < 2) {
|
2009
|
+
|
2010
|
+
// HTML5 single-instance case
|
2011
|
+
|
2012
|
+
start_html5_timer();
|
2013
|
+
|
2014
|
+
a = s._setup_html5();
|
2015
|
+
|
2016
|
+
s.setPosition(s._iO.position);
|
2017
|
+
|
2018
|
+
a.play();
|
2019
|
+
|
2020
|
+
} else {
|
1906
2021
|
|
1907
|
-
|
2022
|
+
// HTML5 multi-shot case
|
1908
2023
|
|
1909
|
-
|
2024
|
+
sm2._wD(s.id + ': Cloning Audio() for instance #' + s.instanceCount + '...');
|
1910
2025
|
|
1911
|
-
|
2026
|
+
audioClone = new Audio(s._iO.url);
|
2027
|
+
|
2028
|
+
onended = function() {
|
2029
|
+
event.remove(audioClone, 'onended', onended);
|
2030
|
+
s._onfinish(s);
|
2031
|
+
// cleanup
|
2032
|
+
html5Unload(audioClone);
|
2033
|
+
audioClone = null;
|
2034
|
+
};
|
2035
|
+
|
2036
|
+
oncanplay = function() {
|
2037
|
+
event.remove(audioClone, 'canplay', oncanplay);
|
2038
|
+
try {
|
2039
|
+
audioClone.currentTime = s._iO.position/msecScale;
|
2040
|
+
} catch(err) {
|
2041
|
+
complain(s.id + ': multiShot play() failed to apply position of ' + (s._iO.position/msecScale));
|
2042
|
+
}
|
2043
|
+
audioClone.play();
|
2044
|
+
};
|
2045
|
+
|
2046
|
+
event.add(audioClone, 'ended', onended);
|
2047
|
+
|
2048
|
+
if (s._iO.position) {
|
2049
|
+
// HTML5 audio can't seek before onplay() event has fired.
|
2050
|
+
// wait for canplay, then seek to position and start playback.
|
2051
|
+
event.add(audioClone, 'canplay', oncanplay);
|
2052
|
+
} else {
|
2053
|
+
// begin playback at currentTime: 0
|
2054
|
+
audioClone.play();
|
2055
|
+
}
|
2056
|
+
|
2057
|
+
}
|
1912
2058
|
|
1913
2059
|
}
|
1914
2060
|
|
@@ -2051,21 +2197,20 @@ function SoundManager(smURL, smID) {
|
|
2051
2197
|
nMsecOffset = 0;
|
2052
2198
|
}
|
2053
2199
|
|
2054
|
-
var
|
2055
|
-
position, position1K,
|
2200
|
+
var position, position1K,
|
2056
2201
|
// Use the duration from the instance options, if we don't have a track duration yet.
|
2057
2202
|
// position >= 0 and <= current available (loaded) duration
|
2058
2203
|
offset = (s.isHTML5 ? Math.max(nMsecOffset, 0) : Math.min(s.duration || s._iO.duration, Math.max(nMsecOffset, 0)));
|
2059
2204
|
|
2060
|
-
original_pos = s.position;
|
2061
2205
|
s.position = offset;
|
2062
|
-
position1K = s.position/
|
2206
|
+
position1K = s.position/msecScale;
|
2063
2207
|
s._resetOnPosition(s.position);
|
2064
2208
|
s._iO.position = offset;
|
2065
2209
|
|
2066
2210
|
if (!s.isHTML5) {
|
2067
2211
|
|
2068
2212
|
position = (fV === 9 ? s.position : position1K);
|
2213
|
+
|
2069
2214
|
if (s.readyState && s.readyState !== 2) {
|
2070
2215
|
// if paused or not playing, will not resume (by playing)
|
2071
2216
|
flash._setPosition(s.id, position, (s.paused || !s.playState), s._iO.multiShot);
|
@@ -2075,13 +2220,16 @@ function SoundManager(smURL, smID) {
|
|
2075
2220
|
|
2076
2221
|
// Set the position in the canplay handler if the sound is not ready yet
|
2077
2222
|
if (s._html5_canplay) {
|
2223
|
+
|
2078
2224
|
if (s._a.currentTime !== position1K) {
|
2225
|
+
|
2079
2226
|
/**
|
2080
2227
|
* DOM/JS errors/exceptions to watch out for:
|
2081
2228
|
* if seek is beyond (loaded?) position, "DOM exception 11"
|
2082
2229
|
* "INDEX_SIZE_ERR": DOM exception 1
|
2083
2230
|
*/
|
2084
2231
|
sm2._wD(s.id + ': setPosition('+position1K+')');
|
2232
|
+
|
2085
2233
|
try {
|
2086
2234
|
s._a.currentTime = position1K;
|
2087
2235
|
if (s.playState === 0 || s.paused) {
|
@@ -2091,19 +2239,25 @@ function SoundManager(smURL, smID) {
|
|
2091
2239
|
} catch(e) {
|
2092
2240
|
sm2._wD(s.id + ': setPosition(' + position1K + ') failed: ' + e.message, 2);
|
2093
2241
|
}
|
2242
|
+
|
2094
2243
|
}
|
2095
|
-
} else {
|
2096
|
-
sm2._wD(s.id + ': setPosition(' + position1K + '): Cannot seek yet, sound not ready');
|
2097
|
-
}
|
2098
2244
|
|
2099
|
-
|
2245
|
+
} else if (position1K) {
|
2246
|
+
|
2247
|
+
// warn on non-zero seek attempts
|
2248
|
+
sm2._wD(s.id + ': setPosition(' + position1K + '): Cannot seek yet, sound not ready', 2);
|
2249
|
+
return s;
|
2250
|
+
|
2251
|
+
}
|
2100
2252
|
|
2101
|
-
if (s.isHTML5) {
|
2102
2253
|
if (s.paused) {
|
2254
|
+
|
2103
2255
|
// if paused, refresh UI right away
|
2104
2256
|
// force update
|
2105
2257
|
s._onTimer(true);
|
2258
|
+
|
2106
2259
|
}
|
2260
|
+
|
2107
2261
|
}
|
2108
2262
|
|
2109
2263
|
return s;
|
@@ -2203,7 +2357,7 @@ function SoundManager(smURL, smID) {
|
|
2203
2357
|
|
2204
2358
|
if (s.playState === 0) {
|
2205
2359
|
s.play({
|
2206
|
-
position: (fV === 9 && !s.isHTML5 ? s.position : s.position /
|
2360
|
+
position: (fV === 9 && !s.isHTML5 ? s.position : s.position / msecScale)
|
2207
2361
|
});
|
2208
2362
|
return s;
|
2209
2363
|
}
|
@@ -2647,7 +2801,7 @@ function SoundManager(smURL, smID) {
|
|
2647
2801
|
// TODO: investigate why this goes wack if not set/re-set each time.
|
2648
2802
|
s.durationEstimate = s.duration;
|
2649
2803
|
|
2650
|
-
time = (s._a.currentTime *
|
2804
|
+
time = (s._a.currentTime * msecScale || 0);
|
2651
2805
|
|
2652
2806
|
if (time !== lastHTML5State.time) {
|
2653
2807
|
|
@@ -2680,7 +2834,7 @@ function SoundManager(smURL, smID) {
|
|
2680
2834
|
|
2681
2835
|
var instanceOptions = s._iO,
|
2682
2836
|
// if audio object exists, use its duration - else, instance option duration (if provided - it's a hack, really, and should be retired) OR null
|
2683
|
-
d = (s._a && s._a.duration ? s._a.duration*
|
2837
|
+
d = (s._a && s._a.duration ? s._a.duration*msecScale : (instanceOptions && instanceOptions.duration ? instanceOptions.duration : null)),
|
2684
2838
|
result = (d && !isNaN(d) && d !== Infinity ? d : null);
|
2685
2839
|
|
2686
2840
|
return result;
|
@@ -2706,9 +2860,9 @@ function SoundManager(smURL, smID) {
|
|
2706
2860
|
|
2707
2861
|
this._setup_html5 = function(oOptions) {
|
2708
2862
|
|
2709
|
-
var instanceOptions = mixin(s._iO, oOptions),
|
2710
|
-
a = useGlobalHTML5Audio ? globalHTML5Audio
|
2711
|
-
dURL =
|
2863
|
+
var instanceOptions = mixin(s._iO, oOptions),
|
2864
|
+
a = useGlobalHTML5Audio ? globalHTML5Audio : s._a,
|
2865
|
+
dURL = decodeURI(instanceOptions.url),
|
2712
2866
|
sameURL;
|
2713
2867
|
|
2714
2868
|
/**
|
@@ -2719,12 +2873,12 @@ function SoundManager(smURL, smID) {
|
|
2719
2873
|
|
2720
2874
|
if (useGlobalHTML5Audio) {
|
2721
2875
|
|
2722
|
-
if (dURL === lastGlobalHTML5URL) {
|
2876
|
+
if (dURL === decodeURI(lastGlobalHTML5URL)) {
|
2723
2877
|
// global HTML5 audio: re-use of URL
|
2724
2878
|
sameURL = true;
|
2725
2879
|
}
|
2726
2880
|
|
2727
|
-
} else if (dURL === lastURL) {
|
2881
|
+
} else if (dURL === decodeURI(lastURL)) {
|
2728
2882
|
|
2729
2883
|
// options URL is the same as the "last" URL, and we used (loaded) it
|
2730
2884
|
sameURL = true;
|
@@ -2744,7 +2898,7 @@ function SoundManager(smURL, smID) {
|
|
2744
2898
|
|
2745
2899
|
}
|
2746
2900
|
|
2747
|
-
} else if (!useGlobalHTML5Audio && dURL ===
|
2901
|
+
} else if (!useGlobalHTML5Audio && dURL === decodeURI(lastURL)) {
|
2748
2902
|
|
2749
2903
|
// non-global HTML5 reuse case: same url, ignore request
|
2750
2904
|
s._apply_loop(a, instanceOptions.loops);
|
@@ -2889,7 +3043,7 @@ function SoundManager(smURL, smID) {
|
|
2889
3043
|
|
2890
3044
|
// <d>
|
2891
3045
|
fN = s.id + ': ';
|
2892
|
-
sm2._wD(fN + (loadOK ? 'onload()' : 'Failed to load? - ' + s.url), (loadOK ? 1 : 2));
|
3046
|
+
sm2._wD(fN + (loadOK ? 'onload()' : 'Failed to load / invalid sound?' + (!s.duration ? ' Zero-length duration reported.' : ' -') + ' (' + s.url + ')'), (loadOK ? 1 : 2));
|
2893
3047
|
if (!loadOK && !s.isHTML5) {
|
2894
3048
|
if (sm2.sandbox.noRemote === true) {
|
2895
3049
|
sm2._wD(fN + str('noNet'), 1);
|
@@ -2905,7 +3059,9 @@ function SoundManager(smURL, smID) {
|
|
2905
3059
|
s._onbufferchange(0);
|
2906
3060
|
|
2907
3061
|
if (s._iO.onload) {
|
2908
|
-
|
3062
|
+
wrapCallback(s, function() {
|
3063
|
+
s._iO.onload.apply(s, [loadOK]);
|
3064
|
+
});
|
2909
3065
|
}
|
2910
3066
|
|
2911
3067
|
return true;
|
@@ -3004,7 +3160,9 @@ function SoundManager(smURL, smID) {
|
|
3004
3160
|
// fire onfinish for last, or every instance
|
3005
3161
|
if (io_onfinish) {
|
3006
3162
|
sm2._wD(s.id + ': onfinish()');
|
3007
|
-
|
3163
|
+
wrapCallback(s, function() {
|
3164
|
+
io_onfinish.apply(s);
|
3165
|
+
});
|
3008
3166
|
}
|
3009
3167
|
}
|
3010
3168
|
|
@@ -3278,6 +3436,23 @@ function SoundManager(smURL, smID) {
|
|
3278
3436
|
|
3279
3437
|
};
|
3280
3438
|
|
3439
|
+
wrapCallback = function(oSound, callback) {
|
3440
|
+
|
3441
|
+
/**
|
3442
|
+
* 03/03/2013: Fix for Flash Player 11.6.602.171 + Flash 8 (flashVersion = 8) SWF issue
|
3443
|
+
* setTimeout() fix for certain SMSound callbacks like onload() and onfinish(), where subsequent calls like play() and load() fail when Flash Player 11.6.602.171 is installed, and using soundManager with flashVersion = 8 (which is the default).
|
3444
|
+
* Not sure of exact cause. Suspect race condition and/or invalid (NaN-style) position argument trickling down to the next JS -> Flash _start() call, in the play() case.
|
3445
|
+
* Fix: setTimeout() to yield, plus safer null / NaN checking on position argument provided to Flash.
|
3446
|
+
* https://getsatisfaction.com/schillmania/topics/recent_chrome_update_seems_to_have_broken_my_sm2_audio_player
|
3447
|
+
*/
|
3448
|
+
if (!oSound.isHTML5 && fV === 8) {
|
3449
|
+
window.setTimeout(callback, 0);
|
3450
|
+
} else {
|
3451
|
+
callback();
|
3452
|
+
}
|
3453
|
+
|
3454
|
+
};
|
3455
|
+
|
3281
3456
|
// additional soundManager properties that soundManager.setup() will accept
|
3282
3457
|
|
3283
3458
|
extraOptions = {
|
@@ -3562,7 +3737,7 @@ function SoundManager(smURL, smID) {
|
|
3562
3737
|
s._onbufferchange(0);
|
3563
3738
|
|
3564
3739
|
// position according to instance options
|
3565
|
-
position1K = (s._iO.position !== _undefined && !isNaN(s._iO.position)?s._iO.position/
|
3740
|
+
position1K = (s._iO.position !== _undefined && !isNaN(s._iO.position)?s._iO.position/msecScale:null);
|
3566
3741
|
|
3567
3742
|
// set the position if position was set before the sound loaded
|
3568
3743
|
if (s.position && this.currentTime !== position1K) {
|
@@ -3615,6 +3790,14 @@ function SoundManager(smURL, smID) {
|
|
3615
3790
|
error: html5_event(function() {
|
3616
3791
|
|
3617
3792
|
sm2._wD(this._s.id + ': HTML5 error, code ' + this.error.code);
|
3793
|
+
/**
|
3794
|
+
* HTML5 error codes, per W3C
|
3795
|
+
* Error 1: Client aborted download at user's request.
|
3796
|
+
* Error 2: Network error after load started.
|
3797
|
+
* Error 3: Decoding issue.
|
3798
|
+
* Error 4: Media (audio file) not supported.
|
3799
|
+
* Reference: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#error-codes
|
3800
|
+
*/
|
3618
3801
|
// call load with error state?
|
3619
3802
|
this._s._onload(false);
|
3620
3803
|
|
@@ -3649,7 +3832,7 @@ function SoundManager(smURL, smID) {
|
|
3649
3832
|
|
3650
3833
|
play: html5_event(function() {
|
3651
3834
|
|
3652
|
-
sm2._wD(this._s.id + ': play()');
|
3835
|
+
// sm2._wD(this._s.id + ': play()');
|
3653
3836
|
// once play starts, no buffering
|
3654
3837
|
this._s._onbufferchange(0);
|
3655
3838
|
|
@@ -3673,9 +3856,7 @@ function SoundManager(smURL, smID) {
|
|
3673
3856
|
ranges = e.target.buffered,
|
3674
3857
|
// firefox 3.6 implements e.loaded/total (bytes)
|
3675
3858
|
loaded = (e.loaded||0),
|
3676
|
-
total = (e.total||1)
|
3677
|
-
// HTML5 returns msec. SM2 API uses seconds for setPosition() etc., whether Flash or HTML5.
|
3678
|
-
scale = 1000;
|
3859
|
+
total = (e.total||1);
|
3679
3860
|
|
3680
3861
|
// reset the "buffered" (loaded byte ranges) array
|
3681
3862
|
s.buffered = [];
|
@@ -3686,25 +3867,26 @@ function SoundManager(smURL, smID) {
|
|
3686
3867
|
// https://developer.mozilla.org/en/DOM/TimeRanges
|
3687
3868
|
|
3688
3869
|
// re-build "buffered" array
|
3870
|
+
// HTML5 returns seconds. SM2 API uses msec for setPosition() etc., whether Flash or HTML5.
|
3689
3871
|
for (i=0, j=ranges.length; i<j; i++) {
|
3690
3872
|
s.buffered.push({
|
3691
|
-
'start': ranges.start(i) *
|
3692
|
-
'end': ranges.end(i) *
|
3873
|
+
'start': ranges.start(i) * msecScale,
|
3874
|
+
'end': ranges.end(i) * msecScale
|
3693
3875
|
});
|
3694
3876
|
}
|
3695
3877
|
|
3696
3878
|
// use the last value locally
|
3697
|
-
buffered = (ranges.end(0) - ranges.start(0)) *
|
3879
|
+
buffered = (ranges.end(0) - ranges.start(0)) * msecScale;
|
3698
3880
|
|
3699
3881
|
// linear case, buffer sum; does not account for seeking and HTTP partials / byte ranges
|
3700
|
-
loaded = buffered/(e.target.duration*
|
3882
|
+
loaded = Math.min(1, buffered/(e.target.duration*msecScale));
|
3701
3883
|
|
3702
3884
|
// <d>
|
3703
3885
|
if (isProgress && ranges.length > 1) {
|
3704
3886
|
str = [];
|
3705
3887
|
j = ranges.length;
|
3706
3888
|
for (i=0; i<j; i++) {
|
3707
|
-
str.push(e.target.buffered.start(i)*
|
3889
|
+
str.push(e.target.buffered.start(i)*msecScale +'-'+ e.target.buffered.end(i)*msecScale);
|
3708
3890
|
}
|
3709
3891
|
sm2._wD(this._s.id + ': progress, timeRanges: ' + str.join(', '));
|
3710
3892
|
}
|
@@ -3780,15 +3962,20 @@ function SoundManager(smURL, smID) {
|
|
3780
3962
|
|
3781
3963
|
var result;
|
3782
3964
|
|
3783
|
-
if (iO
|
3965
|
+
if (!iO || (!iO.type && !iO.url && !iO.serverURL)) {
|
3966
|
+
|
3967
|
+
// nothing to check
|
3968
|
+
result = false;
|
3969
|
+
|
3970
|
+
} else if (iO.serverURL || (iO.type && preferFlashCheck(iO.type))) {
|
3784
3971
|
|
3785
3972
|
// RTMP, or preferring flash
|
3786
3973
|
result = false;
|
3787
3974
|
|
3788
3975
|
} else {
|
3789
3976
|
|
3790
|
-
// Use type, if specified. If HTML5-only mode, no other options, so just give 'er
|
3791
|
-
result = ((iO.type ? html5CanPlay({type:iO.type}) : html5CanPlay({url:iO.url}) || sm2.html5Only));
|
3977
|
+
// Use type, if specified. Pass data: URIs to HTML5. If HTML5-only mode, no other options, so just give 'er
|
3978
|
+
result = ((iO.type ? html5CanPlay({type:iO.type}) : html5CanPlay({url:iO.url}) || sm2.html5Only || iO.url.match(/data\:/i)));
|
3792
3979
|
|
3793
3980
|
}
|
3794
3981
|
|
@@ -3796,7 +3983,7 @@ function SoundManager(smURL, smID) {
|
|
3796
3983
|
|
3797
3984
|
};
|
3798
3985
|
|
3799
|
-
html5Unload = function(oAudio
|
3986
|
+
html5Unload = function(oAudio) {
|
3800
3987
|
|
3801
3988
|
/**
|
3802
3989
|
* Internal method: Unload media, and cancel any current/pending network requests.
|
@@ -3806,13 +3993,19 @@ function SoundManager(smURL, smID) {
|
|
3806
3993
|
* Other UA behaviour is unclear, so everyone else gets an about:blank-style URL.
|
3807
3994
|
*/
|
3808
3995
|
|
3996
|
+
var url;
|
3997
|
+
|
3809
3998
|
if (oAudio) {
|
3810
3999
|
|
3811
|
-
// Firefox likes '' for unload (used to work?) - however, may request hosting page URL (bad.) Most other UAs dislike '' and fail to unload.
|
4000
|
+
// Firefox likes '' for unload (used to work, but no longer?) - however, may request hosting page URL (bad.) Most other UAs dislike '' and fail to unload.
|
4001
|
+
url = (isSafari && !is_iDevice ? null : (isFirefox ? emptyURL : null));
|
4002
|
+
|
3812
4003
|
oAudio.src = url;
|
3813
4004
|
|
3814
4005
|
// reset some state, too
|
3815
|
-
oAudio.
|
4006
|
+
if (oAudio._called_unload !== undefined) {
|
4007
|
+
oAudio._called_load = false;
|
4008
|
+
}
|
3816
4009
|
|
3817
4010
|
}
|
3818
4011
|
|
@@ -3823,6 +4016,8 @@ function SoundManager(smURL, smID) {
|
|
3823
4016
|
|
3824
4017
|
}
|
3825
4018
|
|
4019
|
+
return url;
|
4020
|
+
|
3826
4021
|
};
|
3827
4022
|
|
3828
4023
|
html5CanPlay = function(o) {
|
@@ -3906,6 +4101,9 @@ function SoundManager(smURL, smID) {
|
|
3906
4101
|
*/
|
3907
4102
|
|
3908
4103
|
if (!sm2.useHTML5Audio || !sm2.hasHTML5) {
|
4104
|
+
// without HTML5, we need Flash.
|
4105
|
+
sm2.html5.usingFlash = true;
|
4106
|
+
needsFlash = true;
|
3909
4107
|
return false;
|
3910
4108
|
}
|
3911
4109
|
|
@@ -3993,6 +4191,9 @@ function SoundManager(smURL, smID) {
|
|
3993
4191
|
support.canPlayType = (a?cp:null);
|
3994
4192
|
sm2.html5 = mixin(sm2.html5, support);
|
3995
4193
|
|
4194
|
+
sm2.html5.usingFlash = featureCheck();
|
4195
|
+
needsFlash = sm2.html5.usingFlash;
|
4196
|
+
|
3996
4197
|
return true;
|
3997
4198
|
|
3998
4199
|
};
|
@@ -4012,7 +4213,7 @@ function SoundManager(smURL, smID) {
|
|
4012
4213
|
waitForever: smc + 'Waiting indefinitely for Flash (will recover if unblocked)...',
|
4013
4214
|
waitSWF: smc + 'Waiting for 100% SWF load...',
|
4014
4215
|
needFunction: smc + 'Function object expected for %s',
|
4015
|
-
badID: '
|
4216
|
+
badID: 'Sound ID "%s" should be a string, starting with a non-numeric character',
|
4016
4217
|
currentObj: smc + '_debug(): Current sound objects',
|
4017
4218
|
waitOnload: smc + 'Waiting for window.onload()',
|
4018
4219
|
docLoaded: smc + 'Document already loaded',
|
@@ -4026,7 +4227,6 @@ function SoundManager(smURL, smID) {
|
|
4026
4227
|
smError: 'SMSound.load(): Exception: JS-Flash communication failed, or JS error.',
|
4027
4228
|
fbTimeout: 'No flash response, applying .'+swfCSS.swfTimedout+' CSS...',
|
4028
4229
|
fbLoaded: 'Flash loaded',
|
4029
|
-
flRemoved: smc + 'Flash movie removed.',
|
4030
4230
|
fbHandler: smc + 'flashBlockHandler()',
|
4031
4231
|
manURL: 'SMSound.load(): Using manually-assigned URL',
|
4032
4232
|
onURL: sm + '.load(): current URL already assigned.',
|
@@ -4101,7 +4301,7 @@ function SoundManager(smURL, smID) {
|
|
4101
4301
|
complain = function(sMsg) {
|
4102
4302
|
|
4103
4303
|
// <d>
|
4104
|
-
if (
|
4304
|
+
if (hasConsole && console.warn !== _undefined) {
|
4105
4305
|
console.warn(sMsg);
|
4106
4306
|
} else {
|
4107
4307
|
sm2._wD(sMsg);
|
@@ -4231,11 +4431,11 @@ function SoundManager(smURL, smID) {
|
|
4231
4431
|
// starts debug mode, creating output <div> for UAs without console object
|
4232
4432
|
|
4233
4433
|
// allow force of debug mode via URL
|
4434
|
+
// <d>
|
4234
4435
|
if (sm2.debugURLParam.test(wl)) {
|
4235
4436
|
sm2.debugMode = true;
|
4236
4437
|
}
|
4237
4438
|
|
4238
|
-
// <d>
|
4239
4439
|
if (id(sm2.debugID)) {
|
4240
4440
|
return false;
|
4241
4441
|
}
|
@@ -4339,6 +4539,7 @@ function SoundManager(smURL, smID) {
|
|
4339
4539
|
sm2Debugger.handleEvent(sEventType, bSuccess, sMessage);
|
4340
4540
|
} catch(e) {
|
4341
4541
|
// oh well
|
4542
|
+
return false;
|
4342
4543
|
}
|
4343
4544
|
}
|
4344
4545
|
|
@@ -4377,6 +4578,7 @@ function SoundManager(smURL, smID) {
|
|
4377
4578
|
error = {type:'FLASHBLOCK'};
|
4378
4579
|
|
4379
4580
|
if (sm2.html5Only) {
|
4581
|
+
// no flash, or unused
|
4380
4582
|
return false;
|
4381
4583
|
}
|
4382
4584
|
|
@@ -4535,6 +4737,7 @@ function SoundManager(smURL, smID) {
|
|
4535
4737
|
obj = new AX('ShockwaveFlash.ShockwaveFlash');
|
4536
4738
|
} catch(e) {
|
4537
4739
|
// oh well
|
4740
|
+
obj = null;
|
4538
4741
|
}
|
4539
4742
|
hasPlugin = (!!obj);
|
4540
4743
|
// cleanup, because it is ActiveX after all
|
@@ -4549,9 +4752,8 @@ function SoundManager(smURL, smID) {
|
|
4549
4752
|
|
4550
4753
|
featureCheck = function() {
|
4551
4754
|
|
4552
|
-
var
|
4755
|
+
var flashNeeded,
|
4553
4756
|
item,
|
4554
|
-
result = true,
|
4555
4757
|
formats = sm2.audioFormats,
|
4556
4758
|
// iPhone <= 3.1 has broken HTML5 audio(), but firmware 3.2 (original iPad) + iOS4 works.
|
4557
4759
|
isSpecial = (is_iDevice && !!(ua.match(/os (1|2|3_0|3_1)/i)));
|
@@ -4564,12 +4766,11 @@ function SoundManager(smURL, smID) {
|
|
4564
4766
|
// ignore flash case, however
|
4565
4767
|
sm2.html5Only = true;
|
4566
4768
|
|
4769
|
+
// hide the SWF, if present
|
4567
4770
|
if (sm2.oMC) {
|
4568
4771
|
sm2.oMC.style.display = 'none';
|
4569
4772
|
}
|
4570
4773
|
|
4571
|
-
result = false;
|
4572
|
-
|
4573
4774
|
} else {
|
4574
4775
|
|
4575
4776
|
if (sm2.useHTML5Audio) {
|
@@ -4591,11 +4792,22 @@ function SoundManager(smURL, smID) {
|
|
4591
4792
|
|
4592
4793
|
if (sm2.useHTML5Audio && sm2.hasHTML5) {
|
4593
4794
|
|
4795
|
+
// sort out whether flash is optional, required or can be ignored.
|
4796
|
+
|
4797
|
+
// innocent until proven guilty.
|
4798
|
+
canIgnoreFlash = true;
|
4799
|
+
|
4594
4800
|
for (item in formats) {
|
4595
4801
|
if (formats.hasOwnProperty(item)) {
|
4596
|
-
if (
|
4597
|
-
|
4598
|
-
|
4802
|
+
if (formats[item].required) {
|
4803
|
+
if (!sm2.html5.canPlayType(formats[item].type)) {
|
4804
|
+
// 100% HTML5 mode is not possible.
|
4805
|
+
canIgnoreFlash = false;
|
4806
|
+
flashNeeded = true;
|
4807
|
+
} else if (sm2.preferFlash && (sm2.flash[item] || sm2.flash[formats[item].type])) {
|
4808
|
+
// flash may be required, or preferred for this format.
|
4809
|
+
flashNeeded = true;
|
4810
|
+
}
|
4599
4811
|
}
|
4600
4812
|
}
|
4601
4813
|
}
|
@@ -4604,10 +4816,11 @@ function SoundManager(smURL, smID) {
|
|
4604
4816
|
|
4605
4817
|
// sanity check...
|
4606
4818
|
if (sm2.ignoreFlash) {
|
4607
|
-
|
4819
|
+
flashNeeded = false;
|
4820
|
+
canIgnoreFlash = true;
|
4608
4821
|
}
|
4609
4822
|
|
4610
|
-
sm2.html5Only = (sm2.hasHTML5 && sm2.useHTML5Audio && !
|
4823
|
+
sm2.html5Only = (sm2.hasHTML5 && sm2.useHTML5Audio && !flashNeeded);
|
4611
4824
|
|
4612
4825
|
return (!sm2.html5Only);
|
4613
4826
|
|
@@ -4675,7 +4888,7 @@ function SoundManager(smURL, smID) {
|
|
4675
4888
|
|
4676
4889
|
if (h5IntervalTimer === null && h5TimerCount === 0) {
|
4677
4890
|
|
4678
|
-
h5IntervalTimer =
|
4891
|
+
h5IntervalTimer = setInterval(timerExecute, sm2.html5PollingInterval);
|
4679
4892
|
|
4680
4893
|
}
|
4681
4894
|
|
@@ -4721,7 +4934,7 @@ function SoundManager(smURL, smID) {
|
|
4721
4934
|
|
4722
4935
|
// no active timers, stop polling interval.
|
4723
4936
|
|
4724
|
-
|
4937
|
+
clearInterval(h5IntervalTimer);
|
4725
4938
|
|
4726
4939
|
h5IntervalTimer = null;
|
4727
4940
|
|
@@ -4818,10 +5031,9 @@ function SoundManager(smURL, smID) {
|
|
4818
5031
|
|
4819
5032
|
};
|
4820
5033
|
|
4821
|
-
this._externalInterfaceOK = function(
|
5034
|
+
this._externalInterfaceOK = function(swfVersion) {
|
4822
5035
|
|
4823
5036
|
// flash callback confirming flash loaded, EI working etc.
|
4824
|
-
// flashDate = approx. timing/delay info for JS/flash bridge
|
4825
5037
|
// swfVersion: SWF build string
|
4826
5038
|
|
4827
5039
|
if (sm2.swfLoaded) {
|
@@ -4856,7 +5068,7 @@ function SoundManager(smURL, smID) {
|
|
4856
5068
|
}
|
4857
5069
|
// </d>
|
4858
5070
|
|
4859
|
-
//
|
5071
|
+
// IE needs a larger timeout
|
4860
5072
|
setTimeout(init, isIE ? 100 : 1);
|
4861
5073
|
|
4862
5074
|
};
|
@@ -5254,26 +5466,69 @@ function SoundManager(smURL, smID) {
|
|
5254
5466
|
// give up / time-out, depending
|
5255
5467
|
|
5256
5468
|
if (!didInit && okToDisable) {
|
5469
|
+
|
5257
5470
|
if (p === null) {
|
5471
|
+
|
5258
5472
|
// SWF failed. Maybe blocked.
|
5473
|
+
|
5259
5474
|
if (sm2.useFlashBlock || sm2.flashLoadTimeout === 0) {
|
5475
|
+
|
5260
5476
|
if (sm2.useFlashBlock) {
|
5477
|
+
|
5261
5478
|
flashBlockHandler();
|
5479
|
+
|
5262
5480
|
}
|
5481
|
+
|
5263
5482
|
_wDS('waitForever');
|
5483
|
+
|
5264
5484
|
} else {
|
5485
|
+
|
5265
5486
|
// no custom flash block handling, but SWF has timed out. Will recover if user unblocks / allows SWF load.
|
5266
|
-
|
5267
|
-
|
5268
|
-
|
5487
|
+
|
5488
|
+
if (!sm2.useFlashBlock && canIgnoreFlash) {
|
5489
|
+
|
5490
|
+
// special case: try for a reboot with preferFlash: false, if 100% HTML5 mode is possible and useFlashBlock is not enabled.
|
5491
|
+
|
5492
|
+
window.setTimeout(function() {
|
5493
|
+
|
5494
|
+
complain(smc + 'useFlashBlock is false, 100% HTML5 mode is possible. Rebooting with preferFlash: false...');
|
5495
|
+
|
5496
|
+
sm2.setup({
|
5497
|
+
preferFlash: false
|
5498
|
+
}).reboot();
|
5499
|
+
|
5500
|
+
// if for some reason you want to detect this case, use an ontimeout() callback and look for html5Only and didFlashBlock == true.
|
5501
|
+
sm2.didFlashBlock = true;
|
5502
|
+
|
5503
|
+
sm2.beginDelayedInit();
|
5504
|
+
|
5505
|
+
}, 1);
|
5506
|
+
|
5507
|
+
} else {
|
5508
|
+
|
5509
|
+
_wDS('waitForever');
|
5510
|
+
|
5511
|
+
// fire any regular registered ontimeout() listeners.
|
5512
|
+
processOnEvents({type:'ontimeout', ignoreInit: true});
|
5513
|
+
|
5514
|
+
}
|
5515
|
+
|
5269
5516
|
}
|
5517
|
+
|
5270
5518
|
} else {
|
5519
|
+
|
5271
5520
|
// flash loaded? Shouldn't be a blocking issue, then.
|
5521
|
+
|
5272
5522
|
if (sm2.flashLoadTimeout === 0) {
|
5273
|
-
|
5523
|
+
|
5524
|
+
_wDS('waitForever');
|
5525
|
+
|
5274
5526
|
} else {
|
5527
|
+
|
5275
5528
|
failSafely(true);
|
5529
|
+
|
5276
5530
|
}
|
5531
|
+
|
5277
5532
|
}
|
5278
5533
|
}
|
5279
5534
|
|
@@ -5333,7 +5588,7 @@ function SoundManager(smURL, smID) {
|
|
5333
5588
|
if (sm2.useHTML5Audio && sm2.hasHTML5) {
|
5334
5589
|
for (item in sm2.audioFormats) {
|
5335
5590
|
if (sm2.audioFormats.hasOwnProperty(item)) {
|
5336
|
-
tests.push(item + ' = ' + sm2.html5[item] + (!sm2.html5[item] &&
|
5591
|
+
tests.push(item + ' = ' + sm2.html5[item] + (!sm2.html5[item] && needsFlash && sm2.flash[item] ? ' (using flash)' : (sm2.preferFlash && sm2.flash[item] && needsFlash ? ' (preferring flash)': (!sm2.html5[item] ? ' (' + (sm2.audioFormats[item].required ? 'required, ':'') + 'and no flash support)' : ''))));
|
5337
5592
|
}
|
5338
5593
|
}
|
5339
5594
|
sm2._wD('SoundManager 2 HTML5 support: ' + tests.join(', '), 1);
|
@@ -5530,12 +5785,11 @@ function SoundManager(smURL, smID) {
|
|
5530
5785
|
a2 = 'sm2-preferflash=',
|
5531
5786
|
b = null,
|
5532
5787
|
b2 = null,
|
5533
|
-
hasCon = (window.console !== _undefined && typeof console.log === 'function'),
|
5534
5788
|
l = wl.toLowerCase();
|
5535
5789
|
|
5536
5790
|
if (l.indexOf(a) !== -1) {
|
5537
5791
|
b = (l.charAt(l.indexOf(a)+a.length) === '1');
|
5538
|
-
if (
|
5792
|
+
if (hasConsole) {
|
5539
5793
|
console.log((b?'Enabling ':'Disabling ')+'useHTML5Audio via URL parameter');
|
5540
5794
|
}
|
5541
5795
|
sm2.setup({
|
@@ -5545,7 +5799,7 @@ function SoundManager(smURL, smID) {
|
|
5545
5799
|
|
5546
5800
|
if (l.indexOf(a2) !== -1) {
|
5547
5801
|
b2 = (l.charAt(l.indexOf(a2)+a2.length) === '1');
|
5548
|
-
if (
|
5802
|
+
if (hasConsole) {
|
5549
5803
|
console.log((b2?'Enabling ':'Disabling ')+'preferFlash via URL parameter');
|
5550
5804
|
}
|
5551
5805
|
sm2.setup({
|
@@ -5567,8 +5821,6 @@ function SoundManager(smURL, smID) {
|
|
5567
5821
|
}
|
5568
5822
|
|
5569
5823
|
testHTML5();
|
5570
|
-
sm2.html5.usingFlash = featureCheck();
|
5571
|
-
needsFlash = sm2.html5.usingFlash;
|
5572
5824
|
|
5573
5825
|
if (!hasFlash && needsFlash) {
|
5574
5826
|
messages.push(strings.needFlash);
|