@7sage/vidstack
Version:
UI component library for building high-quality, accessible video and audio experiences on the web.
139 lines (135 loc) • 4.23 kB
JavaScript
import { IS_CHROME, loadScript } from './vidstack-CshLUi9f.js';
import { peek } from './vidstack-BUJn1if6.js';
function getCastFrameworkURL() {
return "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1";
}
function hasLoadedCastFramework() {
return !!window.cast?.framework;
}
function isCastAvailable() {
return !!window.chrome?.cast?.isAvailable;
}
function isCastConnected() {
return getCastContext().getCastState() === cast.framework.CastState.CONNECTED;
}
function getCastContext() {
return window.cast.framework.CastContext.getInstance();
}
function getCastSession() {
return getCastContext().getCurrentSession();
}
function getDefaultCastOptions() {
return {
language: "en-US",
autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED,
receiverApplicationId: chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID,
resumeSavedSession: true,
androidReceiverCompatible: true
};
}
function getCastErrorMessage(code) {
const defaultMessage = `Google Cast Error Code: ${code}`;
return defaultMessage;
}
class GoogleCastLoader {
name = "google-cast";
target;
#player;
/**
* @see {@link https://developers.google.com/cast/docs/reference/web_sender/cast.framework.CastContext}
*/
get cast() {
return getCastContext();
}
mediaType() {
return "video";
}
canPlay(src) {
return IS_CHROME;
}
async prompt(ctx) {
let loadEvent, openEvent, errorEvent;
try {
loadEvent = await this.#loadCastFramework(ctx);
if (!this.#player) {
this.#player = new cast.framework.RemotePlayer();
new cast.framework.RemotePlayerController(this.#player);
}
openEvent = ctx.player.createEvent("google-cast-prompt-open", {
trigger: loadEvent
});
ctx.player.dispatchEvent(openEvent);
this.#notifyRemoteStateChange(ctx, "connecting", openEvent);
await this.#showPrompt(peek(ctx.$props.googleCast));
ctx.$state.remotePlaybackInfo.set({
deviceName: getCastSession()?.getCastDevice().friendlyName
});
if (isCastConnected()) this.#notifyRemoteStateChange(ctx, "connected", openEvent);
} catch (code) {
const error = code instanceof Error ? code : this.#createError(
(code + "").toUpperCase(),
"Prompt failed."
);
errorEvent = ctx.player.createEvent("google-cast-prompt-error", {
detail: error,
trigger: openEvent ?? loadEvent,
cancelable: true
});
ctx.player.dispatch(errorEvent);
this.#notifyRemoteStateChange(
ctx,
isCastConnected() ? "connected" : "disconnected",
errorEvent
);
throw error;
} finally {
ctx.player.dispatch("google-cast-prompt-close", {
trigger: errorEvent ?? openEvent ?? loadEvent
});
}
}
async load(ctx) {
{
throw Error("[vidstack] can not load google cast provider server-side");
}
}
async #loadCastFramework(ctx) {
if (hasLoadedCastFramework()) return;
const loadStartEvent = ctx.player.createEvent("google-cast-load-start");
ctx.player.dispatch(loadStartEvent);
await loadScript(getCastFrameworkURL());
await customElements.whenDefined("google-cast-launcher");
const loadedEvent = ctx.player.createEvent("google-cast-loaded", { trigger: loadStartEvent });
ctx.player.dispatch(loadedEvent);
if (!isCastAvailable()) {
throw this.#createError("CAST_NOT_AVAILABLE", "Google Cast not available on this platform.");
}
return loadedEvent;
}
async #showPrompt(options) {
this.#setOptions(options);
const errorCode = await this.cast.requestSession();
if (errorCode) {
throw this.#createError(
errorCode.toUpperCase(),
getCastErrorMessage(errorCode)
);
}
}
#setOptions(options) {
this.cast?.setOptions({
...getDefaultCastOptions(),
...options
});
}
#notifyRemoteStateChange(ctx, state, trigger) {
const detail = { type: "google-cast", state };
ctx.notify("remote-playback-change", detail, trigger);
}
#createError(code, message) {
const error = Error(message);
error.code = code;
return error;
}
}
export { GoogleCastLoader };