From a3cc8e656745d7536d8f9ee0898fd809a8f06859 Mon Sep 17 00:00:00 2001 From: Guru Prasad Srinivasa Date: Fri, 21 Jun 2019 05:04:29 -0400 Subject: [PATCH 1/7] Added cast support --- src/js/config/defaults.js | 13 + src/js/controls.js | 12 +- src/js/listeners.js | 3 + src/js/plugins/google-cast.js | 404 +++++++++++++++++++++++++++++ src/js/plyr.js | 13 +- src/js/source.js | 9 + src/js/support.js | 2 + src/js/ui.js | 4 + src/sass/components/controls.scss | 15 +- src/sprite/plyr-googlecast-off.svg | 40 +++ src/sprite/plyr-googlecast-on.svg | 40 +++ 11 files changed, 551 insertions(+), 4 deletions(-) create mode 100644 src/js/plugins/google-cast.js create mode 100644 src/sprite/plyr-googlecast-off.svg create mode 100644 src/sprite/plyr-googlecast-on.svg diff --git a/src/js/config/defaults.js b/src/js/config/defaults.js index cdac31367..0c817a849 100644 --- a/src/js/config/defaults.js +++ b/src/js/config/defaults.js @@ -136,6 +136,7 @@ const defaults = { 'pip', 'airplay', // 'download', + 'googlecast', 'fullscreen', ], settings: ['captions', 'quality', 'speed'], @@ -161,6 +162,8 @@ const defaults = { download: 'Download', enterFullscreen: 'Enter fullscreen', exitFullscreen: 'Exit fullscreen', + enableGoogleCast: 'Google Cast', + disableGoogleCast: 'Disable Cast', frameTitle: 'Player for {title}', captions: 'Captions', settings: 'Settings', @@ -201,6 +204,9 @@ const defaults = { googleIMA: { sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js', }, + googlecast: { + api: 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1', + }, }, // Custom control listeners @@ -218,6 +224,7 @@ const defaults = { fullscreen: null, pip: null, airplay: null, + googlecast: null, speed: null, quality: null, loop: null, @@ -300,6 +307,7 @@ const defaults = { fullscreen: '[data-plyr="fullscreen"]', pip: '[data-plyr="pip"]', airplay: '[data-plyr="airplay"]', + googlecast: '[data-plyr="googlecast"]', settings: '[data-plyr="settings"]', loop: '[data-plyr="loop"]', }, @@ -320,6 +328,7 @@ const defaults = { progress: '.plyr__progress', captions: '.plyr__captions', caption: '.plyr__caption', + googlecast: '.plyr__googlecast', }, // Class hooks added to the player in different states @@ -373,6 +382,10 @@ const defaults = { active: 'plyr--airplay-active', }, tabFocus: 'plyr__tab-focus', + googlecast: { + enabled: 'plyr--googlecast-enabled', + active: 'plyr--googlecast-active', + }, previewThumbnails: { // Tooltip thumbs thumbContainer: 'plyr__preview-thumb', diff --git a/src/js/controls.js b/src/js/controls.js index 7afcd2c00..a76d2af9d 100644 --- a/src/js/controls.js +++ b/src/js/controls.js @@ -247,7 +247,13 @@ const controls = { props.label = 'play'; props.icon = 'play'; break; - + case 'googlecast': + props.toggle = true; + props.label = 'enableGoogleCast'; + props.labelPressed = 'disableGoogleCast'; + props.icon = 'googlecast-off'; + props.iconPressed = 'googlecast-on'; + break; default: if (is.empty(props.label)) { props.label = type; @@ -1573,6 +1579,10 @@ const controls = { container.appendChild(createButton.call(this, 'airplay', defaultAttributes)); } + // Google cast button + if (control === 'googlecast' && support.googlecast) { + container.appendChild(controls.createButton.call(this, 'googlecast')); + } // Download button if (control === 'download') { const attributes = extend({}, defaultAttributes, { diff --git a/src/js/listeners.js b/src/js/listeners.js index c5076ff31..cbc25ddaf 100644 --- a/src/js/listeners.js +++ b/src/js/listeners.js @@ -579,6 +579,9 @@ class Listeners { 'download', ); + // Google cast + this.bind(elements.buttons.googlecast, 'click', player.googlecast, 'googlecast'); + // Fullscreen toggle this.bind( elements.buttons.fullscreen, diff --git a/src/js/plugins/google-cast.js b/src/js/plugins/google-cast.js new file mode 100644 index 000000000..a06ce7b9b --- /dev/null +++ b/src/js/plugins/google-cast.js @@ -0,0 +1,404 @@ +import Console from "../console"; +import { createElement,getAttributesFromSelector, insertAfter, toggleClass } from '../utils/elements'; +import { triggerEvent } from '../utils/events'; +import is from '../utils/is'; +import loadScript from '../utils/load-script'; +import { extend } from '../utils/objects'; + +const googlecast = { + setup(config) { + if (!window.chrome) { // TODO: Figure out if this is the right check + // We're not on Chrome. Bail since google-cast does not work + // on other browsers + return; + } + googlecast.defaults = {}; + googlecast.config = {}; + + googlecast.events = { + 'ready': googlecast.onReady, + 'play': googlecast.onPlay, + 'pause': googlecast.onPause, + 'seeked': googlecast.onSeek, + 'volumechange': googlecast.onVolumeChange, + 'qualityrequested': googlecast.onQualityChange, + 'loadedmetadata': googlecast.onLoadedMetadata, + }; + + googlecast.debug = new Console(true); + // TODO: Get cast logs under a separate namespace? + + // Inject the container + + debugger + if (!is.element(this.elements.googlecast)) { + this.elements.googlecast = createElement( + 'div', + getAttributesFromSelector(this.config.selectors.googlecast) + ); + insertAfter(this.elements.googlecast, this.elements.wrapper); + } + // Set the class hook + toggleClass(this.elements.container, this.config.classNames.googlecast.enabled, true); + + if (!window.chrome.cast) { + loadScript(this.config.urls.googlecast.api).then(() => { + // FIXME: There __has__ to be a better way to do this + // window.chrome.cast isn't immediately available when this function runs + const interval = setInterval(() => { + if (window.chrome.cast.isAvailable) { + clearInterval(interval); + googlecast.defaults = { + options: { + // receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, + receiverApplicationId: 'C248C800', + autoJoinPolicy: window.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED, + }, + }; + const opts = extend({}, googlecast.defaults, config); + googlecast.initializeCastApi(opts); + } + }, 100); + }); + } + }, + + initializeCastApi(config) { + const { framework } = window.cast; + const { CastContext } = framework; + CastContext.getInstance().setOptions(config.options); + + // Set up event handlers + CastContext + .getInstance() + .addEventListener( + framework.CastContextEventType.CAST_STATE_CHANGED, + googlecast.castStateListener + ); + CastContext + .getInstance() + .addEventListener( + framework.CastContextEventType.SESSION_STATE_CHANGED, + googlecast.sessionStateListener + ); + googlecast.debug.log('Initialized google cast'); + }, + + getCurrentSession() { + return window.cast.framework.CastContext.getInstance().getCurrentSession(); + }, + + getCurrentPlyr() { + return googlecast.currentPlyr; + }, + + onPlay() { + const plyr = googlecast.getCurrentPlyr(); + googlecast.debug.log('Asking remote player to play'); + // Seek before playing? + // googlecast.onSeek(); + plyr.remotePlayerController.playOrPause(); + }, + onPause() { + const plyr = googlecast.getCurrentPlyr(); + googlecast.debug.log('Asking remote player to pause'); + plyr.remotePlayerController.playOrPause(); + // Seek after pause + googlecast.onSeek(); + }, + onSeek() { + const plyr = googlecast.getCurrentPlyr(); + const timestamp = plyr.currentTime; + plyr.remotePlayer.currentTime = timestamp; + plyr.remotePlayerController.seek(); + googlecast.debug.log(`Asking remote player to seek to ${timestamp}`); + }, + onLoadedMetadata() { + googlecast.debug.log('Running googlecast.onReady()'); + const plyr = googlecast.getCurrentPlyr(); + const oldLoadRequest = plyr.googlecastLoadRequest; + const newLoadRequest = googlecast.buildLoadRequest(plyr); + if (oldLoadRequest.media.contentId === newLoadRequest.media.contentId) { + return; + } + googlecast.loadMedia(plyr, newLoadRequest); + }, + onReady() { + googlecast.debug.log('Running googlecast.onReady()'); + const plyr = googlecast.getCurrentPlyr(); + googlecast.loadMedia(plyr); + }, + onVolumeChange() { + const plyr = googlecast.getCurrentPlyr(); + // We need to specially handle the case where plyr is muted + let { volume } = plyr; + if (plyr.muted) { + volume = 0; + } + plyr.remotePlayer.volumeLevel = volume; + plyr.remotePlayerController.setVolumeLevel(); + }, + onQualityChange() { + const plyr = googlecast.getCurrentPlyr(); + googlecast.loadMedia(plyr); + }, + loadMedia(plyr, loadRequest) { + googlecast.debug.log('load media called'); + const session = googlecast.getCurrentSession(); + if (!session) { + return; + } + if (!loadRequest) { + loadRequest = googlecast.buildLoadRequest(plyr); + } + session.loadMedia(loadRequest).then(() => { + googlecast.debug.log('Successfully handled loadMedia'); + googlecast.getCurrentPlyr().googlecastLoadRequest = loadRequest; + googlecast.bindPlyr(plyr); + }).catch((err) => { + googlecast.debug.log(`Error during loadMedia: ${err}`); + }); + }, + buildLoadRequest(plyr) { + // TODO: We need to be able to override the defaults + const defaults = { + mediaInfo: { + source: plyr.source, + contentType: 'video/mp4', + }, + metadata: { + metadataType: window.chrome.cast.media.MetadataType.GENERIC, + title: plyr.config.title || plyr.source, + images: [{ + url: plyr.poster, + }], + }, + loadRequest: { + autoplay: plyr.playing, + currentTime: plyr.currentTime, + customData: { + type: plyr.type, + provider: plyr.provider, + }, + }, + }; + + if (plyr.hls) { + // Plyr has been hijacked by HLS + const { customData } = defaults.loadRequest; + customData.subType = 'hls'; + customData.source = plyr.hls.manifestURL; + } + + const options = extend({}, defaults); + const mediaInfo = new window.chrome.cast.media.MediaInfo(options.mediaInfo.source, options.mediaInfo.contentType); + mediaInfo.streamType = defaults.mediaInfo.streamType; + + mediaInfo.metadata = new window.chrome.cast.media.GenericMediaMetadata(); + Object.assign(mediaInfo.metadata, options.metadata); + + const loadRequest = new window.chrome.cast.media.LoadRequest(mediaInfo); + loadRequest.customData = options.loadRequest.customData; + loadRequest.autoplay = options.loadRequest.autoplay; + loadRequest.currentTime = options.loadRequest.currentTime; + return loadRequest; + }, + setCurrentPlyr(plyr) { + googlecast.currentPlyr = plyr; + }, + bindEvents(plyr) { + // Iterate over events and add all listeners + Object.keys(googlecast.events).forEach((evt) => { + const fn = googlecast.events[evt]; + plyr.on(evt, fn); + }); + }, + bindPlyr(plyr, options) { + if (googlecast.currentPlyr !== plyr) { + googlecast.debug.warn('Warning! Current plyr !== plyr in bindPlyr()'); + googlecast.currentPlyr = plyr; + } + googlecast.currentPlyrOptions = options; + + // TODO: Figure out if we should do plyr.remotePlayer = plyr.remotePlayer || new window.cast.framework.RemotePlayer() + plyr.remotePlayer = new window.cast.framework.RemotePlayer(); + // TODO: Figure out if we should do plyr.remotePlayerController = plyr.remotePlayerController || new window.cast.framework.RemotePlayerController(plyr.remotePlayer); + plyr.remotePlayerController = new window.cast.framework.RemotePlayerController(plyr.remotePlayer); + + googlecast.bindEvents(plyr); + plyr.googlecastEnabled = true; // FIXME: This should probably use state from controls + googlecast.debug.log('Plyr bound'); + }, + + unbindPlyr(plyr) { + const { currentPlyr } = googlecast; + if (currentPlyr === plyr) { + Object.keys(googlecast.events).forEach((evt) => { + const fn = googlecast.events[evt]; + plyr.off(evt, fn); + }); + } + delete currentPlyr.googlecastEnabled; // FIXME: This should probably use state from controls + googlecast.currentPlyr = undefined; + googlecast.currentPlyrOptions = undefined; + }, + + getErrorMessage(error) { + const { chrome } = window; + switch (error.code) { + case chrome.cast.ErrorCode.API_NOT_INITIALIZED: + return `The API is not initialized.${error.description ? ` :${error.description}` : ''}`; + case chrome.cast.ErrorCode.CANCEL: + return `The operation was canceled by the user${error.description ? ` :${error.description}` : ''}`; + case chrome.cast.ErrorCode.CHANNEL_ERROR: + return `A channel to the receiver is not available.${error.description + ? ` :${error.description}` + : ''}`; + case chrome.cast.ErrorCode.EXTENSION_MISSING: + return `The Cast extension is not available.${error.description ? ` :${error.description}` : ''}`; + case chrome.cast.ErrorCode.INVALID_PARAMETER: + return `The parameters to the operation were not valid.${error.description + ? ` :${error.description}` + : ''}`; + case chrome.cast.ErrorCode.RECEIVER_UNAVAILABLE: + return `No receiver was compatible with the session request.${error.description + ? ` :${error.description}` + : ''}`; + case chrome.cast.ErrorCode.SESSION_ERROR: + return `A session could not be created, or a session was invalid.${error.description + ? ` :${error.description}` + : ''}`; + case chrome.cast.ErrorCode.TIMEOUT: + return `The operation timed out.${error.description ? ` :${error.description}` : ''}`; + default: + return `Unknown error: ${JSON.stringify(error)}`; + } + }, + + castStateListener(data) { + googlecast.debug.log(`Cast State Changed: ${JSON.stringify(data)}`); + const plyr = googlecast.getCurrentPlyr(); + const cs = window.cast.framework.CastState; + let castEvent; + switch (data.castState) { + case cs.NO_DEVICES_AVAILABLE: + case cs.NOT_CONNECTED: + googlecast.debug.log('NOT CONNECTED'); + castEvent = 'castdisabled'; + break; + case cs.CONNECTING: + break; + case cs.CONNECTED: + castEvent = 'castenabled'; + break; + default: + // googlecast.debug.log(`Unknown cast state=${JSON.stringify(data.castState)}`); + break; + } + if (plyr && castEvent) { + const castActive = castEvent === 'castenabled'; + // Add class hook + toggleClass(plyr.elements.container, plyr.config.classNames.googlecast.active, castActive); + triggerEvent.call(plyr, plyr.elements.container, castEvent, true); + } + }, + + sessionStateListener(data) { + const plyr = googlecast.getCurrentPlyr(); + if (!plyr) { + return; + } + // console.log("Session State Changed: " + JSON.stringify(data)); + const ss = window.cast.framework.SessionState; + + switch (data.sessionState) { + case ss.NO_SESSION: + break; + case ss.SESSION_STARTING: + break; + case ss.SESSION_STARTED: + case ss.SESSION_RESUMED: + // run on ready + googlecast.onReady(); + break; + case ss.SESSION_START_FAILED: + case ss.SESSION_ENDED: + break; + case ss.SESSION_ENDING: + break; + default: + // plyr.log(`Unknown session state=${JSON.stringify(data.sessionState)}`); + break; + } + googlecast.debug.log(`sessionStateListener: state=${data.sessionState}`); + }, + + requestSession(plyr) { + // Check if a session already exists, if it does, just use it + const session = googlecast.getCurrentSession(); + let wasPlyrAlreadyBound = true; + const existingPlyr = googlecast.getCurrentPlyr(); + if (existingPlyr !== undefined && existingPlyr !== plyr) { + googlecast.unbindPlyr(existingPlyr); + } + if (existingPlyr !== plyr) { + googlecast.setCurrentPlyr(plyr); + wasPlyrAlreadyBound = false; + } + + function onRequestSuccess(e) { + // This only triggers when a new session is created. + // It does not trigger on successfully showing the drop down and + // requesting stop session. + } + + function onError(e) { + googlecast.unbindPlyr(googlecast.getCurrentPlyr()); + } + + // We need to show the cast drop down if: + // 1) There was no session + // 2) There was a session and the current plyr was already bound + // + // (2) is needed since we need a way to disable cast via the current + // plyr instance + if (session === null || wasPlyrAlreadyBound) { + const promise = window.cast.framework.CastContext.getInstance().requestSession(); + promise.then(onRequestSuccess, onError); + } else { + // We have a session and we're just looking to bind plyr which we've + // done already. Just load media and change icon based on session state. + const cs = window.cast.framework.CastContext.getInstance().getCastState(); + const castStateEventData = new window.cast.framework.CastStateEventData(cs); + googlecast.castStateListener(castStateEventData); + + const ss = window.cast.framework.CastContext.getInstance().getSessionState(); + const sessionStateEventData = new window.cast.framework.SessionStateEventData(session, ss, 0); + googlecast.sessionStateListener(sessionStateEventData); + } + }, + + // Display cast container and button (for initialization) + show() { + // If there's no cast toggle, bail + if (!this.elements.buttons.googlecast) { + return; + } + + // Try to load the value from storage + let active = this.storage.googlecast; + + // Otherwise fall back to the default config + if (!is.boolean(active)) { + ({ active } = this.googlecast); + } else { + this.googlecast.active = active; + } + + if (active) { + toggleClass(this.elements.container, this.config.classNames.googlecast.active, true); + toggleState(this.elements.buttons.googlecast, true); + } + }, +}; +export default googlecast; diff --git a/src/js/plyr.js b/src/js/plyr.js index 980f26bcf..fc47b62c1 100644 --- a/src/js/plyr.js +++ b/src/js/plyr.js @@ -15,6 +15,7 @@ import Fullscreen from './fullscreen'; import Listeners from './listeners'; import media from './media'; import Ads from './plugins/ads'; +import googlecast from './plugins/google-cast'; import PreviewThumbnails from './plugins/preview-thumbnails'; import source from './source'; import Storage from './storage'; @@ -58,7 +59,7 @@ class Plyr { // jQuery, NodeList or Array passed, use first element if ((window.jQuery && this.media instanceof jQuery) || is.nodeList(this.media) || is.array(this.media)) { // eslint-disable-next-line - this.media = this.media[0]; + this.media = this.media[0]; } // Set config @@ -1034,6 +1035,16 @@ class Plyr { } } + /** + * Trigger google cast dialog + */ + googlecast() { + if (!support.googlecast) { + return; + } + googlecast.requestSession(this); + } + /** * Toggle the player controls * @param {Boolean} [toggle] - Whether to show the controls diff --git a/src/js/source.js b/src/js/source.js index 0173cc9e2..7209949ff 100644 --- a/src/js/source.js +++ b/src/js/source.js @@ -10,6 +10,7 @@ import ui from './ui'; import { createElement, insertElement, removeElement } from './utils/elements'; import is from './utils/is'; import { getDeep } from './utils/objects'; +import googlecast from './plugins/google-cast'; const source = { // Add elements to HTML5 media (source, tracks, etc) @@ -28,6 +29,7 @@ const source = { // Update source // Sources are not checked for support so be careful change(input) { + debugger if (!getDeep(input, 'sources.length')) { this.debug.warn('Invalid source format'); return; @@ -36,6 +38,10 @@ const source = { // Cancel current network requests html5.cancelRequests.call(this); + if (this.hls) { + this.hls.destroy(); + } + // Destroy instance and re-setup this.destroy.call( this, @@ -47,6 +53,9 @@ const source = { removeElement(this.media); this.media = null; + // Remove hls property if set + delete plyr.hls + // Reset class name if (is.element(this.elements.container)) { this.elements.container.removeAttribute('class'); diff --git a/src/js/support.js b/src/js/support.js index 819658675..1a3f4803c 100644 --- a/src/js/support.js +++ b/src/js/support.js @@ -61,6 +61,8 @@ const support = { // Safari only currently airplay: is.function(window.WebKitPlaybackTargetAvailabilityEvent), + googlecast: !is.nullOrUndefined(window.chrome), + // Inline playback support // https://webkit.org/blog/6784/new-video-policies-for-ios/ playsinline: 'playsInline' in document.createElement('video'), diff --git a/src/js/ui.js b/src/js/ui.js index 953ecba24..0520e97d8 100644 --- a/src/js/ui.js +++ b/src/js/ui.js @@ -4,6 +4,7 @@ import captions from './captions'; import controls from './controls'; +import googlecast from './plugins/google-cast'; import support from './support'; import browser from './utils/browser'; import { getElement, toggleClass } from './utils/elements'; @@ -61,6 +62,9 @@ const ui = { captions.setup.call(this); } + // Google cast + googlecast.setup.call(this); + // Reset volume this.volume = null; diff --git a/src/sass/components/controls.scss b/src/sass/components/controls.scss index f4559bba8..0e8880fde 100644 --- a/src/sass/components/controls.scss +++ b/src/sass/components/controls.scss @@ -91,16 +91,27 @@ transform: translateY(100%); } +.plyr--cast-active .plyr__controls .icon--cast-on { + display: block; + color: #2243f9; + + & + svg { + display: none; + } +} + // Some options are hidden by default .plyr [data-plyr='captions'], .plyr [data-plyr='pip'], .plyr [data-plyr='airplay'], -.plyr [data-plyr='fullscreen'] { +.plyr [data-plyr='fullscreen'], +.plyr [data-plyr='cast'] { display: none; } .plyr--captions-enabled [data-plyr='captions'], .plyr--pip-supported [data-plyr='pip'], .plyr--airplay-supported [data-plyr='airplay'], -.plyr--fullscreen-enabled [data-plyr='fullscreen'] { +.plyr--fullscreen-enabled [data-plyr='fullscreen'], +.plyr--cast-enabled [data-plyr='cast'] { display: inline-block; } diff --git a/src/sprite/plyr-googlecast-off.svg b/src/sprite/plyr-googlecast-off.svg new file mode 100644 index 000000000..7758a1fd8 --- /dev/null +++ b/src/sprite/plyr-googlecast-off.svg @@ -0,0 +1,40 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/src/sprite/plyr-googlecast-on.svg b/src/sprite/plyr-googlecast-on.svg new file mode 100644 index 000000000..50ea04cf5 --- /dev/null +++ b/src/sprite/plyr-googlecast-on.svg @@ -0,0 +1,40 @@ + + + + + + image/svg+xml + + + + + + + + + + From 02c6fb3107490a49d840425e2af929f0fc2a371e Mon Sep 17 00:00:00 2001 From: Cody Barr Date: Tue, 22 Nov 2022 13:27:55 -0800 Subject: [PATCH 2/7] fix: remove debugger --- src/js/plugins/google-cast.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/js/plugins/google-cast.js b/src/js/plugins/google-cast.js index a06ce7b9b..0cf123483 100644 --- a/src/js/plugins/google-cast.js +++ b/src/js/plugins/google-cast.js @@ -29,8 +29,6 @@ const googlecast = { // TODO: Get cast logs under a separate namespace? // Inject the container - - debugger if (!is.element(this.elements.googlecast)) { this.elements.googlecast = createElement( 'div', From 71819c9125d3a53a02f6a437a5eaf149dbe084dc Mon Sep 17 00:00:00 2001 From: Cody Barr Date: Tue, 22 Nov 2022 13:59:48 -0800 Subject: [PATCH 3/7] fix: broke google cast api link --- src/js/config/defaults.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/js/config/defaults.js b/src/js/config/defaults.js index 83cf9dc91..550be9fe8 100644 --- a/src/js/config/defaults.js +++ b/src/js/config/defaults.js @@ -211,9 +211,9 @@ const defaults = { }, googleIMA: { sdk: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js', - googlecast: { - api: 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1', - }, + }, + googlecast: { + api: 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1', }, }, From b905f538d0c97a97e43833d4ddbebd2761cb68b3 Mon Sep 17 00:00:00 2001 From: Cody Barr Date: Tue, 22 Nov 2022 14:02:59 -0800 Subject: [PATCH 4/7] style: lint fixes --- src/js/plugins/google-cast.js | 725 +++++++++++++++++----------------- 1 file changed, 360 insertions(+), 365 deletions(-) diff --git a/src/js/plugins/google-cast.js b/src/js/plugins/google-cast.js index 0cf123483..688c02b52 100644 --- a/src/js/plugins/google-cast.js +++ b/src/js/plugins/google-cast.js @@ -1,402 +1,397 @@ -import Console from "../console"; -import { createElement,getAttributesFromSelector, insertAfter, toggleClass } from '../utils/elements'; +import Console from '../console'; +import { createElement, getAttributesFromSelector, insertAfter, toggleClass } from '../utils/elements'; import { triggerEvent } from '../utils/events'; import is from '../utils/is'; import loadScript from '../utils/load-script'; import { extend } from '../utils/objects'; const googlecast = { - setup(config) { - if (!window.chrome) { // TODO: Figure out if this is the right check - // We're not on Chrome. Bail since google-cast does not work - // on other browsers - return; - } - googlecast.defaults = {}; - googlecast.config = {}; + setup(config) { + if (!window.chrome) { + // TODO: Figure out if this is the right check + // We're not on Chrome. Bail since google-cast does not work + // on other browsers + return; + } + googlecast.defaults = {}; + googlecast.config = {}; - googlecast.events = { - 'ready': googlecast.onReady, - 'play': googlecast.onPlay, - 'pause': googlecast.onPause, - 'seeked': googlecast.onSeek, - 'volumechange': googlecast.onVolumeChange, - 'qualityrequested': googlecast.onQualityChange, - 'loadedmetadata': googlecast.onLoadedMetadata, - }; + googlecast.events = { + ready: googlecast.onReady, + play: googlecast.onPlay, + pause: googlecast.onPause, + seeked: googlecast.onSeek, + volumechange: googlecast.onVolumeChange, + qualityrequested: googlecast.onQualityChange, + loadedmetadata: googlecast.onLoadedMetadata, + }; - googlecast.debug = new Console(true); - // TODO: Get cast logs under a separate namespace? + googlecast.debug = new Console(true); + // TODO: Get cast logs under a separate namespace? - // Inject the container - if (!is.element(this.elements.googlecast)) { - this.elements.googlecast = createElement( - 'div', - getAttributesFromSelector(this.config.selectors.googlecast) - ); - insertAfter(this.elements.googlecast, this.elements.wrapper); - } - // Set the class hook - toggleClass(this.elements.container, this.config.classNames.googlecast.enabled, true); + // Inject the container + if (!is.element(this.elements.googlecast)) { + this.elements.googlecast = createElement('div', getAttributesFromSelector(this.config.selectors.googlecast)); + insertAfter(this.elements.googlecast, this.elements.wrapper); + } + // Set the class hook + toggleClass(this.elements.container, this.config.classNames.googlecast.enabled, true); - if (!window.chrome.cast) { - loadScript(this.config.urls.googlecast.api).then(() => { - // FIXME: There __has__ to be a better way to do this - // window.chrome.cast isn't immediately available when this function runs - const interval = setInterval(() => { - if (window.chrome.cast.isAvailable) { - clearInterval(interval); - googlecast.defaults = { - options: { - // receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, - receiverApplicationId: 'C248C800', - autoJoinPolicy: window.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED, - }, - }; - const opts = extend({}, googlecast.defaults, config); - googlecast.initializeCastApi(opts); - } - }, 100); - }); - } - }, + if (!window.chrome.cast) { + loadScript(this.config.urls.googlecast.api).then(() => { + // FIXME: There __has__ to be a better way to do this + // window.chrome.cast isn't immediately available when this function runs + const interval = setInterval(() => { + if (window.chrome.cast.isAvailable) { + clearInterval(interval); + googlecast.defaults = { + options: { + // receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, + receiverApplicationId: 'C248C800', + autoJoinPolicy: window.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED, + }, + }; + const opts = extend({}, googlecast.defaults, config); + googlecast.initializeCastApi(opts); + } + }, 100); + }); + } + }, - initializeCastApi(config) { - const { framework } = window.cast; - const { CastContext } = framework; - CastContext.getInstance().setOptions(config.options); + initializeCastApi(config) { + const { framework } = window.cast; + const { CastContext } = framework; + CastContext.getInstance().setOptions(config.options); - // Set up event handlers - CastContext - .getInstance() - .addEventListener( - framework.CastContextEventType.CAST_STATE_CHANGED, - googlecast.castStateListener - ); - CastContext - .getInstance() - .addEventListener( - framework.CastContextEventType.SESSION_STATE_CHANGED, - googlecast.sessionStateListener - ); - googlecast.debug.log('Initialized google cast'); - }, + // Set up event handlers + CastContext.getInstance().addEventListener( + framework.CastContextEventType.CAST_STATE_CHANGED, + googlecast.castStateListener, + ); + CastContext.getInstance().addEventListener( + framework.CastContextEventType.SESSION_STATE_CHANGED, + googlecast.sessionStateListener, + ); + googlecast.debug.log('Initialized google cast'); + }, - getCurrentSession() { - return window.cast.framework.CastContext.getInstance().getCurrentSession(); - }, + getCurrentSession() { + return window.cast.framework.CastContext.getInstance().getCurrentSession(); + }, - getCurrentPlyr() { - return googlecast.currentPlyr; - }, + getCurrentPlyr() { + return googlecast.currentPlyr; + }, - onPlay() { - const plyr = googlecast.getCurrentPlyr(); - googlecast.debug.log('Asking remote player to play'); - // Seek before playing? - // googlecast.onSeek(); - plyr.remotePlayerController.playOrPause(); - }, - onPause() { - const plyr = googlecast.getCurrentPlyr(); - googlecast.debug.log('Asking remote player to pause'); - plyr.remotePlayerController.playOrPause(); - // Seek after pause - googlecast.onSeek(); - }, - onSeek() { - const plyr = googlecast.getCurrentPlyr(); - const timestamp = plyr.currentTime; - plyr.remotePlayer.currentTime = timestamp; - plyr.remotePlayerController.seek(); - googlecast.debug.log(`Asking remote player to seek to ${timestamp}`); - }, - onLoadedMetadata() { - googlecast.debug.log('Running googlecast.onReady()'); - const plyr = googlecast.getCurrentPlyr(); - const oldLoadRequest = plyr.googlecastLoadRequest; - const newLoadRequest = googlecast.buildLoadRequest(plyr); - if (oldLoadRequest.media.contentId === newLoadRequest.media.contentId) { - return; - } - googlecast.loadMedia(plyr, newLoadRequest); - }, - onReady() { - googlecast.debug.log('Running googlecast.onReady()'); - const plyr = googlecast.getCurrentPlyr(); - googlecast.loadMedia(plyr); - }, - onVolumeChange() { - const plyr = googlecast.getCurrentPlyr(); - // We need to specially handle the case where plyr is muted - let { volume } = plyr; - if (plyr.muted) { - volume = 0; - } - plyr.remotePlayer.volumeLevel = volume; - plyr.remotePlayerController.setVolumeLevel(); - }, - onQualityChange() { - const plyr = googlecast.getCurrentPlyr(); - googlecast.loadMedia(plyr); - }, - loadMedia(plyr, loadRequest) { - googlecast.debug.log('load media called'); - const session = googlecast.getCurrentSession(); - if (!session) { - return; - } - if (!loadRequest) { - loadRequest = googlecast.buildLoadRequest(plyr); - } - session.loadMedia(loadRequest).then(() => { - googlecast.debug.log('Successfully handled loadMedia'); - googlecast.getCurrentPlyr().googlecastLoadRequest = loadRequest; - googlecast.bindPlyr(plyr); - }).catch((err) => { - googlecast.debug.log(`Error during loadMedia: ${err}`); - }); - }, - buildLoadRequest(plyr) { - // TODO: We need to be able to override the defaults - const defaults = { - mediaInfo: { - source: plyr.source, - contentType: 'video/mp4', - }, - metadata: { - metadataType: window.chrome.cast.media.MetadataType.GENERIC, - title: plyr.config.title || plyr.source, - images: [{ - url: plyr.poster, - }], - }, - loadRequest: { - autoplay: plyr.playing, - currentTime: plyr.currentTime, - customData: { - type: plyr.type, - provider: plyr.provider, - }, - }, - }; + onPlay() { + const plyr = googlecast.getCurrentPlyr(); + googlecast.debug.log('Asking remote player to play'); + // Seek before playing? + // googlecast.onSeek(); + plyr.remotePlayerController.playOrPause(); + }, + onPause() { + const plyr = googlecast.getCurrentPlyr(); + googlecast.debug.log('Asking remote player to pause'); + plyr.remotePlayerController.playOrPause(); + // Seek after pause + googlecast.onSeek(); + }, + onSeek() { + const plyr = googlecast.getCurrentPlyr(); + const timestamp = plyr.currentTime; + plyr.remotePlayer.currentTime = timestamp; + plyr.remotePlayerController.seek(); + googlecast.debug.log(`Asking remote player to seek to ${timestamp}`); + }, + onLoadedMetadata() { + googlecast.debug.log('Running googlecast.onReady()'); + const plyr = googlecast.getCurrentPlyr(); + const oldLoadRequest = plyr.googlecastLoadRequest; + const newLoadRequest = googlecast.buildLoadRequest(plyr); + if (oldLoadRequest.media.contentId === newLoadRequest.media.contentId) { + return; + } + googlecast.loadMedia(plyr, newLoadRequest); + }, + onReady() { + googlecast.debug.log('Running googlecast.onReady()'); + const plyr = googlecast.getCurrentPlyr(); + googlecast.loadMedia(plyr); + }, + onVolumeChange() { + const plyr = googlecast.getCurrentPlyr(); + // We need to specially handle the case where plyr is muted + let { volume } = plyr; + if (plyr.muted) { + volume = 0; + } + plyr.remotePlayer.volumeLevel = volume; + plyr.remotePlayerController.setVolumeLevel(); + }, + onQualityChange() { + const plyr = googlecast.getCurrentPlyr(); + googlecast.loadMedia(plyr); + }, + loadMedia(plyr, loadRequest) { + googlecast.debug.log('load media called'); + const session = googlecast.getCurrentSession(); + if (!session) { + return; + } + if (!loadRequest) { + loadRequest = googlecast.buildLoadRequest(plyr); + } + session + .loadMedia(loadRequest) + .then(() => { + googlecast.debug.log('Successfully handled loadMedia'); + googlecast.getCurrentPlyr().googlecastLoadRequest = loadRequest; + googlecast.bindPlyr(plyr); + }) + .catch((err) => { + googlecast.debug.log(`Error during loadMedia: ${err}`); + }); + }, + buildLoadRequest(plyr) { + // TODO: We need to be able to override the defaults + const defaults = { + mediaInfo: { + source: plyr.source, + contentType: 'video/mp4', + }, + metadata: { + metadataType: window.chrome.cast.media.MetadataType.GENERIC, + title: plyr.config.title || plyr.source, + images: [ + { + url: plyr.poster, + }, + ], + }, + loadRequest: { + autoplay: plyr.playing, + currentTime: plyr.currentTime, + customData: { + type: plyr.type, + provider: plyr.provider, + }, + }, + }; - if (plyr.hls) { - // Plyr has been hijacked by HLS - const { customData } = defaults.loadRequest; - customData.subType = 'hls'; - customData.source = plyr.hls.manifestURL; - } + if (plyr.hls) { + // Plyr has been hijacked by HLS + const { customData } = defaults.loadRequest; + customData.subType = 'hls'; + customData.source = plyr.hls.manifestURL; + } - const options = extend({}, defaults); - const mediaInfo = new window.chrome.cast.media.MediaInfo(options.mediaInfo.source, options.mediaInfo.contentType); - mediaInfo.streamType = defaults.mediaInfo.streamType; + const options = extend({}, defaults); + const mediaInfo = new window.chrome.cast.media.MediaInfo(options.mediaInfo.source, options.mediaInfo.contentType); + mediaInfo.streamType = defaults.mediaInfo.streamType; - mediaInfo.metadata = new window.chrome.cast.media.GenericMediaMetadata(); - Object.assign(mediaInfo.metadata, options.metadata); + mediaInfo.metadata = new window.chrome.cast.media.GenericMediaMetadata(); + Object.assign(mediaInfo.metadata, options.metadata); - const loadRequest = new window.chrome.cast.media.LoadRequest(mediaInfo); - loadRequest.customData = options.loadRequest.customData; - loadRequest.autoplay = options.loadRequest.autoplay; - loadRequest.currentTime = options.loadRequest.currentTime; - return loadRequest; - }, - setCurrentPlyr(plyr) { - googlecast.currentPlyr = plyr; - }, - bindEvents(plyr) { - // Iterate over events and add all listeners - Object.keys(googlecast.events).forEach((evt) => { - const fn = googlecast.events[evt]; - plyr.on(evt, fn); - }); - }, - bindPlyr(plyr, options) { - if (googlecast.currentPlyr !== plyr) { - googlecast.debug.warn('Warning! Current plyr !== plyr in bindPlyr()'); - googlecast.currentPlyr = plyr; - } - googlecast.currentPlyrOptions = options; + const loadRequest = new window.chrome.cast.media.LoadRequest(mediaInfo); + loadRequest.customData = options.loadRequest.customData; + loadRequest.autoplay = options.loadRequest.autoplay; + loadRequest.currentTime = options.loadRequest.currentTime; + return loadRequest; + }, + setCurrentPlyr(plyr) { + googlecast.currentPlyr = plyr; + }, + bindEvents(plyr) { + // Iterate over events and add all listeners + Object.keys(googlecast.events).forEach((evt) => { + const fn = googlecast.events[evt]; + plyr.on(evt, fn); + }); + }, + bindPlyr(plyr, options) { + if (googlecast.currentPlyr !== plyr) { + googlecast.debug.warn('Warning! Current plyr !== plyr in bindPlyr()'); + googlecast.currentPlyr = plyr; + } + googlecast.currentPlyrOptions = options; - // TODO: Figure out if we should do plyr.remotePlayer = plyr.remotePlayer || new window.cast.framework.RemotePlayer() - plyr.remotePlayer = new window.cast.framework.RemotePlayer(); - // TODO: Figure out if we should do plyr.remotePlayerController = plyr.remotePlayerController || new window.cast.framework.RemotePlayerController(plyr.remotePlayer); - plyr.remotePlayerController = new window.cast.framework.RemotePlayerController(plyr.remotePlayer); + // TODO: Figure out if we should do plyr.remotePlayer = plyr.remotePlayer || new window.cast.framework.RemotePlayer() + plyr.remotePlayer = new window.cast.framework.RemotePlayer(); + // TODO: Figure out if we should do plyr.remotePlayerController = plyr.remotePlayerController || new window.cast.framework.RemotePlayerController(plyr.remotePlayer); + plyr.remotePlayerController = new window.cast.framework.RemotePlayerController(plyr.remotePlayer); - googlecast.bindEvents(plyr); - plyr.googlecastEnabled = true; // FIXME: This should probably use state from controls - googlecast.debug.log('Plyr bound'); - }, + googlecast.bindEvents(plyr); + plyr.googlecastEnabled = true; // FIXME: This should probably use state from controls + googlecast.debug.log('Plyr bound'); + }, - unbindPlyr(plyr) { - const { currentPlyr } = googlecast; - if (currentPlyr === plyr) { - Object.keys(googlecast.events).forEach((evt) => { - const fn = googlecast.events[evt]; - plyr.off(evt, fn); - }); - } - delete currentPlyr.googlecastEnabled; // FIXME: This should probably use state from controls - googlecast.currentPlyr = undefined; - googlecast.currentPlyrOptions = undefined; - }, + unbindPlyr(plyr) { + const { currentPlyr } = googlecast; + if (currentPlyr === plyr) { + Object.keys(googlecast.events).forEach((evt) => { + const fn = googlecast.events[evt]; + plyr.off(evt, fn); + }); + } + delete currentPlyr.googlecastEnabled; // FIXME: This should probably use state from controls + googlecast.currentPlyr = undefined; + googlecast.currentPlyrOptions = undefined; + }, - getErrorMessage(error) { - const { chrome } = window; - switch (error.code) { - case chrome.cast.ErrorCode.API_NOT_INITIALIZED: - return `The API is not initialized.${error.description ? ` :${error.description}` : ''}`; - case chrome.cast.ErrorCode.CANCEL: - return `The operation was canceled by the user${error.description ? ` :${error.description}` : ''}`; - case chrome.cast.ErrorCode.CHANNEL_ERROR: - return `A channel to the receiver is not available.${error.description - ? ` :${error.description}` - : ''}`; - case chrome.cast.ErrorCode.EXTENSION_MISSING: - return `The Cast extension is not available.${error.description ? ` :${error.description}` : ''}`; - case chrome.cast.ErrorCode.INVALID_PARAMETER: - return `The parameters to the operation were not valid.${error.description - ? ` :${error.description}` - : ''}`; - case chrome.cast.ErrorCode.RECEIVER_UNAVAILABLE: - return `No receiver was compatible with the session request.${error.description - ? ` :${error.description}` - : ''}`; - case chrome.cast.ErrorCode.SESSION_ERROR: - return `A session could not be created, or a session was invalid.${error.description - ? ` :${error.description}` - : ''}`; - case chrome.cast.ErrorCode.TIMEOUT: - return `The operation timed out.${error.description ? ` :${error.description}` : ''}`; - default: - return `Unknown error: ${JSON.stringify(error)}`; - } - }, + getErrorMessage(error) { + const { chrome } = window; + switch (error.code) { + case chrome.cast.ErrorCode.API_NOT_INITIALIZED: + return `The API is not initialized.${error.description ? ` :${error.description}` : ''}`; + case chrome.cast.ErrorCode.CANCEL: + return `The operation was canceled by the user${error.description ? ` :${error.description}` : ''}`; + case chrome.cast.ErrorCode.CHANNEL_ERROR: + return `A channel to the receiver is not available.${error.description ? ` :${error.description}` : ''}`; + case chrome.cast.ErrorCode.EXTENSION_MISSING: + return `The Cast extension is not available.${error.description ? ` :${error.description}` : ''}`; + case chrome.cast.ErrorCode.INVALID_PARAMETER: + return `The parameters to the operation were not valid.${error.description ? ` :${error.description}` : ''}`; + case chrome.cast.ErrorCode.RECEIVER_UNAVAILABLE: + return `No receiver was compatible with the session request.${ + error.description ? ` :${error.description}` : '' + }`; + case chrome.cast.ErrorCode.SESSION_ERROR: + return `A session could not be created, or a session was invalid.${ + error.description ? ` :${error.description}` : '' + }`; + case chrome.cast.ErrorCode.TIMEOUT: + return `The operation timed out.${error.description ? ` :${error.description}` : ''}`; + default: + return `Unknown error: ${JSON.stringify(error)}`; + } + }, - castStateListener(data) { - googlecast.debug.log(`Cast State Changed: ${JSON.stringify(data)}`); - const plyr = googlecast.getCurrentPlyr(); - const cs = window.cast.framework.CastState; - let castEvent; - switch (data.castState) { - case cs.NO_DEVICES_AVAILABLE: - case cs.NOT_CONNECTED: - googlecast.debug.log('NOT CONNECTED'); - castEvent = 'castdisabled'; - break; - case cs.CONNECTING: - break; - case cs.CONNECTED: - castEvent = 'castenabled'; - break; - default: - // googlecast.debug.log(`Unknown cast state=${JSON.stringify(data.castState)}`); - break; - } - if (plyr && castEvent) { - const castActive = castEvent === 'castenabled'; - // Add class hook - toggleClass(plyr.elements.container, plyr.config.classNames.googlecast.active, castActive); - triggerEvent.call(plyr, plyr.elements.container, castEvent, true); - } - }, + castStateListener(data) { + googlecast.debug.log(`Cast State Changed: ${JSON.stringify(data)}`); + const plyr = googlecast.getCurrentPlyr(); + const cs = window.cast.framework.CastState; + let castEvent; + switch (data.castState) { + case cs.NO_DEVICES_AVAILABLE: + case cs.NOT_CONNECTED: + googlecast.debug.log('NOT CONNECTED'); + castEvent = 'castdisabled'; + break; + case cs.CONNECTING: + break; + case cs.CONNECTED: + castEvent = 'castenabled'; + break; + default: + // googlecast.debug.log(`Unknown cast state=${JSON.stringify(data.castState)}`); + break; + } + if (plyr && castEvent) { + const castActive = castEvent === 'castenabled'; + // Add class hook + toggleClass(plyr.elements.container, plyr.config.classNames.googlecast.active, castActive); + triggerEvent.call(plyr, plyr.elements.container, castEvent, true); + } + }, - sessionStateListener(data) { - const plyr = googlecast.getCurrentPlyr(); - if (!plyr) { - return; - } - // console.log("Session State Changed: " + JSON.stringify(data)); - const ss = window.cast.framework.SessionState; + sessionStateListener(data) { + const plyr = googlecast.getCurrentPlyr(); + if (!plyr) { + return; + } + // console.log("Session State Changed: " + JSON.stringify(data)); + const ss = window.cast.framework.SessionState; - switch (data.sessionState) { - case ss.NO_SESSION: - break; - case ss.SESSION_STARTING: - break; - case ss.SESSION_STARTED: - case ss.SESSION_RESUMED: - // run on ready - googlecast.onReady(); - break; - case ss.SESSION_START_FAILED: - case ss.SESSION_ENDED: - break; - case ss.SESSION_ENDING: - break; - default: - // plyr.log(`Unknown session state=${JSON.stringify(data.sessionState)}`); - break; - } - googlecast.debug.log(`sessionStateListener: state=${data.sessionState}`); - }, + switch (data.sessionState) { + case ss.NO_SESSION: + break; + case ss.SESSION_STARTING: + break; + case ss.SESSION_STARTED: + case ss.SESSION_RESUMED: + // run on ready + googlecast.onReady(); + break; + case ss.SESSION_START_FAILED: + case ss.SESSION_ENDED: + break; + case ss.SESSION_ENDING: + break; + default: + // plyr.log(`Unknown session state=${JSON.stringify(data.sessionState)}`); + break; + } + googlecast.debug.log(`sessionStateListener: state=${data.sessionState}`); + }, - requestSession(plyr) { - // Check if a session already exists, if it does, just use it - const session = googlecast.getCurrentSession(); - let wasPlyrAlreadyBound = true; - const existingPlyr = googlecast.getCurrentPlyr(); - if (existingPlyr !== undefined && existingPlyr !== plyr) { - googlecast.unbindPlyr(existingPlyr); - } - if (existingPlyr !== plyr) { - googlecast.setCurrentPlyr(plyr); - wasPlyrAlreadyBound = false; - } + requestSession(plyr) { + // Check if a session already exists, if it does, just use it + const session = googlecast.getCurrentSession(); + let wasPlyrAlreadyBound = true; + const existingPlyr = googlecast.getCurrentPlyr(); + if (existingPlyr !== undefined && existingPlyr !== plyr) { + googlecast.unbindPlyr(existingPlyr); + } + if (existingPlyr !== plyr) { + googlecast.setCurrentPlyr(plyr); + wasPlyrAlreadyBound = false; + } - function onRequestSuccess(e) { - // This only triggers when a new session is created. - // It does not trigger on successfully showing the drop down and - // requesting stop session. - } + function onRequestSuccess(e) { + // This only triggers when a new session is created. + // It does not trigger on successfully showing the drop down and + // requesting stop session. + } - function onError(e) { - googlecast.unbindPlyr(googlecast.getCurrentPlyr()); - } + function onError(e) { + googlecast.unbindPlyr(googlecast.getCurrentPlyr()); + } - // We need to show the cast drop down if: - // 1) There was no session - // 2) There was a session and the current plyr was already bound - // - // (2) is needed since we need a way to disable cast via the current - // plyr instance - if (session === null || wasPlyrAlreadyBound) { - const promise = window.cast.framework.CastContext.getInstance().requestSession(); - promise.then(onRequestSuccess, onError); - } else { - // We have a session and we're just looking to bind plyr which we've - // done already. Just load media and change icon based on session state. - const cs = window.cast.framework.CastContext.getInstance().getCastState(); - const castStateEventData = new window.cast.framework.CastStateEventData(cs); - googlecast.castStateListener(castStateEventData); + // We need to show the cast drop down if: + // 1) There was no session + // 2) There was a session and the current plyr was already bound + // + // (2) is needed since we need a way to disable cast via the current + // plyr instance + if (session === null || wasPlyrAlreadyBound) { + const promise = window.cast.framework.CastContext.getInstance().requestSession(); + promise.then(onRequestSuccess, onError); + } else { + // We have a session and we're just looking to bind plyr which we've + // done already. Just load media and change icon based on session state. + const cs = window.cast.framework.CastContext.getInstance().getCastState(); + const castStateEventData = new window.cast.framework.CastStateEventData(cs); + googlecast.castStateListener(castStateEventData); - const ss = window.cast.framework.CastContext.getInstance().getSessionState(); - const sessionStateEventData = new window.cast.framework.SessionStateEventData(session, ss, 0); - googlecast.sessionStateListener(sessionStateEventData); - } - }, + const ss = window.cast.framework.CastContext.getInstance().getSessionState(); + const sessionStateEventData = new window.cast.framework.SessionStateEventData(session, ss, 0); + googlecast.sessionStateListener(sessionStateEventData); + } + }, - // Display cast container and button (for initialization) - show() { - // If there's no cast toggle, bail - if (!this.elements.buttons.googlecast) { - return; - } + // Display cast container and button (for initialization) + show() { + // If there's no cast toggle, bail + if (!this.elements.buttons.googlecast) { + return; + } - // Try to load the value from storage - let active = this.storage.googlecast; + // Try to load the value from storage + let active = this.storage.googlecast; - // Otherwise fall back to the default config - if (!is.boolean(active)) { - ({ active } = this.googlecast); - } else { - this.googlecast.active = active; - } + // Otherwise fall back to the default config + if (!is.boolean(active)) { + ({ active } = this.googlecast); + } else { + this.googlecast.active = active; + } - if (active) { - toggleClass(this.elements.container, this.config.classNames.googlecast.active, true); - toggleState(this.elements.buttons.googlecast, true); - } - }, + if (active) { + toggleClass(this.elements.container, this.config.classNames.googlecast.active, true); + toggleState(this.elements.buttons.googlecast, true); + } + }, }; export default googlecast; From 55a31298719d6bb5aeeca055a6ecb4f40a4c4c68 Mon Sep 17 00:00:00 2001 From: Cody Barr Date: Tue, 22 Nov 2022 14:03:59 -0800 Subject: [PATCH 5/7] fix: implement better check for cast api load --- src/js/plugins/google-cast.js | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/js/plugins/google-cast.js b/src/js/plugins/google-cast.js index 688c02b52..db3dcc0e4 100644 --- a/src/js/plugins/google-cast.js +++ b/src/js/plugins/google-cast.js @@ -38,24 +38,23 @@ const googlecast = { toggleClass(this.elements.container, this.config.classNames.googlecast.enabled, true); if (!window.chrome.cast) { - loadScript(this.config.urls.googlecast.api).then(() => { - // FIXME: There __has__ to be a better way to do this - // window.chrome.cast isn't immediately available when this function runs - const interval = setInterval(() => { - if (window.chrome.cast.isAvailable) { - clearInterval(interval); - googlecast.defaults = { - options: { - // receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, - receiverApplicationId: 'C248C800', - autoJoinPolicy: window.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED, - }, - }; - const opts = extend({}, googlecast.defaults, config); - googlecast.initializeCastApi(opts); - } - }, 100); - }); + if (!window.chrome.cast) { + window['__onGCastApiAvailable'] = function (isAvailable) { + if (!isAvailable) return; + + googlecast.defaults = { + options: { + // receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, + receiverApplicationId: 'C248C800', + autoJoinPolicy: window.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED, + }, + }; + const opts = extend({}, googlecast.defaults, config); + googlecast.initializeCastApi(opts); + }; + + loadScript(this.config.urls.googlecast.api); + } } }, From 677980c04e0bfc84f124f7c53d1cd3b464eea072 Mon Sep 17 00:00:00 2001 From: Cody Barr Date: Tue, 22 Nov 2022 14:06:31 -0800 Subject: [PATCH 6/7] fix: swapped receiverApplicationId --- src/js/plugins/google-cast.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/plugins/google-cast.js b/src/js/plugins/google-cast.js index db3dcc0e4..d6e1d8147 100644 --- a/src/js/plugins/google-cast.js +++ b/src/js/plugins/google-cast.js @@ -44,8 +44,8 @@ const googlecast = { googlecast.defaults = { options: { - // receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, - receiverApplicationId: 'C248C800', + receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, + // receiverApplicationId: 'C248C800', autoJoinPolicy: window.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED, }, }; From 4ef8313f008cf570f2ae690c6e184d07eedcd56e Mon Sep 17 00:00:00 2001 From: Cody Barr Date: Tue, 22 Nov 2022 14:31:08 -0800 Subject: [PATCH 7/7] fix: remove extra if block Bad copy paste! --- src/js/plugins/google-cast.js | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/js/plugins/google-cast.js b/src/js/plugins/google-cast.js index d6e1d8147..bbb877cfc 100644 --- a/src/js/plugins/google-cast.js +++ b/src/js/plugins/google-cast.js @@ -38,23 +38,21 @@ const googlecast = { toggleClass(this.elements.container, this.config.classNames.googlecast.enabled, true); if (!window.chrome.cast) { - if (!window.chrome.cast) { - window['__onGCastApiAvailable'] = function (isAvailable) { - if (!isAvailable) return; - - googlecast.defaults = { - options: { - receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, - // receiverApplicationId: 'C248C800', - autoJoinPolicy: window.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED, - }, - }; - const opts = extend({}, googlecast.defaults, config); - googlecast.initializeCastApi(opts); + window['__onGCastApiAvailable'] = function (isAvailable) { + if (!isAvailable) return; + + googlecast.defaults = { + options: { + receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, + // receiverApplicationId: 'C248C800', + autoJoinPolicy: window.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED, + }, }; + const opts = extend({}, googlecast.defaults, config); + googlecast.initializeCastApi(opts); + }; - loadScript(this.config.urls.googlecast.api); - } + loadScript(this.config.urls.googlecast.api); } },