probe for https
This commit is contained in:
parent
56b5cbedf9
commit
c93801441a
1 changed files with 101 additions and 40 deletions
141
legacy/legacy.js
141
legacy/legacy.js
|
|
@ -23,10 +23,67 @@ $(document).ready(function () {
|
||||||
createjs.Sound.registerPlugins([createjs.HTMLAudioPlugin, createjs.WebAudioPlugin, createjs.FlashPlugin]);
|
createjs.Sound.registerPlugins([createjs.HTMLAudioPlugin, createjs.WebAudioPlugin, createjs.FlashPlugin]);
|
||||||
|
|
||||||
// Initial Load
|
// Initial Load
|
||||||
fetchInstances(function () {
|
// Run HTTPS probe first
|
||||||
loadRecentTracks();
|
checkHttpsSupport(function() {
|
||||||
|
fetchInstances(function () {
|
||||||
|
loadRecentTracks();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function checkHttpsSupport(callback) {
|
||||||
|
if (window.location.protocol === "http:") {
|
||||||
|
// If we are already on HTTP, we might want to check if HTTPS is possible?
|
||||||
|
// Or just assume if user loaded via HTTP, we might need HTTP for APIs too.
|
||||||
|
// But user might be on HTTP because they typed it, but API supports HTTPS.
|
||||||
|
// Let's Probe.
|
||||||
|
// However, if we are on HTTPS, mixed content blocking might prevent HTTP fallback checking?
|
||||||
|
// Actually, we want to know if Client supports HTTPS.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Probe a known HTTPS endpoint (one of our instances)
|
||||||
|
// Use a known stable one, or just try the first instance later?
|
||||||
|
// Better to fail fast now.
|
||||||
|
var probeUrl = "https://tidal.kinoplus.online/";
|
||||||
|
|
||||||
|
console.log("Probing HTTPS support...");
|
||||||
|
|
||||||
|
var probeSuccess = false;
|
||||||
|
var probeFinished = false;
|
||||||
|
|
||||||
|
function finishProbe(success) {
|
||||||
|
if (probeFinished) return;
|
||||||
|
probeFinished = true;
|
||||||
|
if (success) {
|
||||||
|
console.log("HTTPS Probe Successful.");
|
||||||
|
isHttpFallback = false;
|
||||||
|
} else {
|
||||||
|
console.log("HTTPS Probe Failed. Defaulting to HTTP fallback.");
|
||||||
|
isHttpFallback = true;
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
var timeout = setTimeout(function() {
|
||||||
|
finishProbe(false);
|
||||||
|
}, 5000); // 3s timeout for HTTPS check
|
||||||
|
|
||||||
|
try {
|
||||||
|
$.ajax({
|
||||||
|
url: probeUrl,
|
||||||
|
dataType: "json",
|
||||||
|
timeout: 2500, // jQuery timeout
|
||||||
|
success: function() {
|
||||||
|
finishProbe(true);
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
finishProbe(false); // XHR Error or Timeout
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
finishProbe(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Event Bindings
|
// Event Bindings
|
||||||
$("#btn-home").click(function (e) {
|
$("#btn-home").click(function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
@ -92,6 +149,7 @@ $(document).ready(function () {
|
||||||
|
|
||||||
function playNativeFirst(url, id, quality, isRetry) {
|
function playNativeFirst(url, id, quality, isRetry) {
|
||||||
var domPlayer = $("#audio-player")[0];
|
var domPlayer = $("#audio-player")[0];
|
||||||
|
var playbackTimer = null;
|
||||||
|
|
||||||
// Quality Label
|
// Quality Label
|
||||||
var qLabel = (quality === "LOSSLESS") ? " (FLAC)" : " (AAC)";
|
var qLabel = (quality === "LOSSLESS") ? " (FLAC)" : " (AAC)";
|
||||||
|
|
@ -110,7 +168,6 @@ $(document).ready(function () {
|
||||||
|
|
||||||
if (canPlay === "" || canPlay === "no") {
|
if (canPlay === "" || canPlay === "no") {
|
||||||
console.log("Browser reports no FLAC support. Fallback to AAC.");
|
console.log("Browser reports no FLAC support. Fallback to AAC.");
|
||||||
// Directly fallback to AAC
|
|
||||||
if (!attemptFallback) {
|
if (!attemptFallback) {
|
||||||
window.playTrack(id, true);
|
window.playTrack(id, true);
|
||||||
return;
|
return;
|
||||||
|
|
@ -120,69 +177,73 @@ $(document).ready(function () {
|
||||||
|
|
||||||
updateStatus("Starting Native Playback" + qLabel + ((isRetry) ? " (HTTP)..." : "..."));
|
updateStatus("Starting Native Playback" + qLabel + ((isRetry) ? " (HTTP)..." : "..."));
|
||||||
|
|
||||||
// Set error handler for THIS attempt
|
// Helper to handle retry vs legacy fallback
|
||||||
domPlayer.onerror = function() {
|
function triggerRetryOrLegacy(msg) {
|
||||||
var errCode = domPlayer.error ? domPlayer.error.code : 0;
|
if (playbackTimer) {
|
||||||
console.log("Native Error Code: " + errCode);
|
clearTimeout(playbackTimer);
|
||||||
|
playbackTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
// Try HTTP fallback if SSL failed
|
// Try HTTP fallback if SSL failed
|
||||||
if (!isRetry && url.indexOf("https://") === 0) {
|
if (!isRetry && url.indexOf("https://") === 0) {
|
||||||
console.log("HTTPS failed, retrying with HTTP...");
|
console.log("HTTPS failed/timeout (" + msg + "), retrying with HTTP...");
|
||||||
var httpUrl = "http://" + url.substring(8);
|
var httpUrl = "http://" + url.substring(8);
|
||||||
playNativeFirst(httpUrl, id, quality, true);
|
playNativeFirst(httpUrl, id, quality, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to legacy
|
|
||||||
// We pass the ORIGINAL url (let SoundJS try HTTPS first too)
|
|
||||||
// Or maybe we pass the current one?
|
|
||||||
// Let's pass the Original HTTPS one to start the cycle fresh.
|
|
||||||
// Assuming 'streamUrl' from closure is the original.
|
|
||||||
// But we don't have access to it easily if we are deep in recursion?
|
|
||||||
// Actually 'url' arg might be HTTP now.
|
|
||||||
// Let's just pass 'url' - if it worked for HTTP, SoundJS might like HTTP.
|
|
||||||
// But better to reset protocol for SoundJS?
|
|
||||||
// Let's use the valid streamUrl from outer scope?
|
|
||||||
// Variable 'streamUrl' is available in closure!
|
|
||||||
playLegacySoundJS(streamUrl, id, quality);
|
playLegacySoundJS(streamUrl, id, quality);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set error handler for THIS attempt
|
||||||
|
domPlayer.onerror = function() {
|
||||||
|
var errCode = domPlayer.error ? domPlayer.error.code : 0;
|
||||||
|
console.log("Native Error Code: " + errCode);
|
||||||
|
triggerRetryOrLegacy("onerror: " + errCode);
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
domPlayer.src = url;
|
domPlayer.src = url;
|
||||||
var playPromise = domPlayer.play();
|
var playPromise = domPlayer.play();
|
||||||
|
|
||||||
|
// Set a safety timeout for "forever pending" requests (common in Chrome 15 with SSL issues)
|
||||||
|
playbackTimer = setTimeout(function() {
|
||||||
|
console.log("Playback timeout - stalling detected.");
|
||||||
|
triggerRetryOrLegacy("timeout");
|
||||||
|
}, 5000); // 5 seconds to start playing
|
||||||
|
|
||||||
|
// If playback starts, clear timeout
|
||||||
|
domPlayer.onplaying = function() {
|
||||||
|
if (playbackTimer) {
|
||||||
|
clearTimeout(playbackTimer);
|
||||||
|
playbackTimer = null;
|
||||||
|
}
|
||||||
|
updateStatus("Now Playing..." + qLabel);
|
||||||
|
};
|
||||||
|
|
||||||
if (playPromise !== undefined) {
|
if (playPromise !== undefined) {
|
||||||
playPromise
|
playPromise
|
||||||
.then(function() {
|
.then(function() {
|
||||||
updateStatus("Now Playing..." + qLabel);
|
// Promise resolved doesn't always mean playing started (buffering)
|
||||||
|
// But usually it means intent is accepted.
|
||||||
|
// We keep timer running until 'onplaying' checks in?
|
||||||
|
// Actually promise resolve just means "accepted".
|
||||||
|
// Chrome 15 won't have promise.
|
||||||
|
// Modern browsers: resolve -> wait for data -> playing.
|
||||||
|
// If data hangs, promise resolved but playing never fires.
|
||||||
|
// So we keep timer.
|
||||||
})
|
})
|
||||||
.catch(function(e) {
|
.catch(function(e) {
|
||||||
console.log("Native Play Promise Rejected: " + e.name);
|
console.log("Native Play Promise Rejected: " + e.name);
|
||||||
// Retry HTTP logic here too?
|
triggerRetryOrLegacy("promise rejection: " + e.name);
|
||||||
// Promise rejection is usually Autoplay or Format, not Network (Network is onerror).
|
|
||||||
// But maybe SSL error causes rejection?
|
|
||||||
// Let's allow retry here too just in case.
|
|
||||||
if (!isRetry && url.indexOf("https://") === 0) {
|
|
||||||
console.log("HTTPS promise rejected, retrying HTTP...");
|
|
||||||
var httpUrl = "http://" + url.substring(8);
|
|
||||||
playNativeFirst(httpUrl, id, quality, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
playLegacySoundJS(streamUrl, id, quality);
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Legacy browser (no promise), assume success unless onError fires
|
// Legacy browser (no promise)
|
||||||
updateStatus("Now Playing..." + qLabel);
|
// Wait for onplaying or timeout
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Native Exception: " + e.message);
|
console.log("Native Exception: " + e.message);
|
||||||
if (!isRetry && url.indexOf("https://") === 0) {
|
triggerRetryOrLegacy("exception: " + e.message);
|
||||||
var httpUrl = "http://" + url.substring(8);
|
|
||||||
playNativeFirst(httpUrl, id, quality, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
playLegacySoundJS(streamUrl, id, quality);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue