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