@ktt45678/vidstack
Version:
UI component library for building high-quality, accessible video and audio experiences on the web.
143 lines (139 loc) • 4.37 kB
JavaScript
import { IS_CHROME } from './vidstack-Dv-j8Hw0.js';
import { loadScript } from './vidstack-DPeH8lGJ.js';
import '@floating-ui/dom';
import { peek } from './vidstack-41uXLVgN.js';
import './vidstack-BI9udY6A.js';
import 'media-captions';
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 {
constructor() {
this.name = "google-cast";
}
/**
* @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.delegate._notify("remote-playback-change", detail, trigger);
}
_createError(code, message) {
const error = Error(message);
error.code = code;
return error;
}
}
export { GoogleCastLoader };