diff --git a/docs/uncompiled/artplayer-plugin-chromecast/index.js b/docs/uncompiled/artplayer-plugin-chromecast/index.js index f8a5464a9..ebedbcb29 100644 --- a/docs/uncompiled/artplayer-plugin-chromecast/index.js +++ b/docs/uncompiled/artplayer-plugin-chromecast/index.js @@ -176,6 +176,7 @@ function artplayerPluginChromecast(option) { const DEFAULT_SDK = "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"; let isCastInitialized = false; let castSession = null; + let castState = null; const initializeCastApi = ()=>{ return new Promise((resolve, reject)=>{ window["__onGCastApiAvailable"] = (isAvailable)=>{ @@ -185,9 +186,49 @@ function artplayerPluginChromecast(option) { receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, autoJoinPolicy: window.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED }); + // Listen for session state changes context.addEventListener(window.cast.framework.CastContextEventType.SESSION_STATE_CHANGED, (event)=>{ + const SessionState = window.cast.framework.SessionState; + castState = event.sessionState; castSession = event.session; - updateCastButton(); + switch(event.sessionState){ + case SessionState.NO_SESSION: + option.onStateChange?.("disconnected"); + updateCastButton("disconnected"); + break; + case SessionState.SESSION_STARTING: + option.onStateChange?.("connecting"); + updateCastButton("connecting"); + break; + case SessionState.SESSION_STARTED: + option.onStateChange?.("connected"); + updateCastButton("connected"); + break; + case SessionState.SESSION_ENDING: + option.onStateChange?.("disconnecting"); + updateCastButton("disconnecting"); + break; + case SessionState.SESSION_RESUMED: + option.onStateChange?.("connected"); + updateCastButton("connected"); + break; + } + }); + // Listen for cast state changes + context.addEventListener(window.cast.framework.CastContextEventType.CAST_STATE_CHANGED, (event)=>{ + const CastState = window.cast.framework.CastState; + switch(event.castState){ + case CastState.NO_DEVICES_AVAILABLE: + option.onCastAvailable?.(false); + break; + case CastState.NOT_CONNECTED: + option.onCastAvailable?.(true); + break; + case CastState.CONNECTING: + case CastState.CONNECTED: + option.onCastAvailable?.(true); + break; + } }); isCastInitialized = true; resolve(); @@ -200,14 +241,30 @@ function artplayerPluginChromecast(option) { const url = option.url || art.option.url; const mediaInfo = new window.chrome.cast.media.MediaInfo(url, option.mimeType || getMimeType(url)); const request = new window.chrome.cast.media.LoadRequest(mediaInfo); - session.loadMedia(request).then(()=>art.notice.show = "Casting started").catch((error)=>{ + session.loadMedia(request).then(()=>{ + art.notice.show = "Casting started"; + option.onCastStart?.(); + }).catch((error)=>{ art.notice.show = "Error casting media"; + option.onError?.(error); throw error; }); }; - const updateCastButton = ()=>{ + const updateCastButton = (state)=>{ const button = document.querySelector(".art-icon-cast"); - if (button) button.style.color = castSession ? "red" : "white"; + if (button) switch(state){ + case "connected": + button.style.color = "red"; + break; + case "connecting": + case "disconnecting": + button.style.color = "orange"; + break; + case "disconnected": + default: + button.style.color = "white"; + break; + } }; return async (art)=>{ art.controls.add({ @@ -220,6 +277,7 @@ function artplayerPluginChromecast(option) { await initializeCastApi(); } catch (error) { art.notice.show = "Failed to initialize Cast API"; + option.onError?.(error); throw error; } const context = window.cast.framework.CastContext.getInstance(); @@ -229,12 +287,15 @@ function artplayerPluginChromecast(option) { castVideo(art, session); } catch (error) { art.notice.show = "Error connecting to cast session"; + option.onError?.(error); throw error; } } }); return { - name: "artplayerPluginChromecast" + name: "artplayerPluginChromecast", + getCastState: ()=>castState, + isCasting: ()=>castSession !== null }; }; } diff --git a/docs/uncompiled/artplayer-plugin-chromecast/index.js.map b/docs/uncompiled/artplayer-plugin-chromecast/index.js.map index ea97b0d09..58a0a4698 100644 --- a/docs/uncompiled/artplayer-plugin-chromecast/index.js.map +++ b/docs/uncompiled/artplayer-plugin-chromecast/index.js.map @@ -1 +1 @@ -{"mappings":"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","sources":["packages/artplayer-plugin-chromecast/src/index.js","node_modules/@parcel/transformer-js/src/esmodule-helpers.js"],"sourcesContent":["const loadScript = (src) =>\n new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = src;\n script.onload = resolve;\n script.onerror = reject;\n document.body.appendChild(script);\n });\n\nconst getMimeType = (url) => {\n const extension = url.split('?')[0].split('#')[0].split('.').pop().toLowerCase();\n const mimeTypes = {\n mp4: 'video/mp4',\n webm: 'video/webm',\n ogg: 'video/ogg',\n ogv: 'video/ogg',\n mp3: 'audio/mp3',\n wav: 'audio/wav',\n flv: 'video/x-flv',\n mov: 'video/quicktime',\n avi: 'video/x-msvideo',\n wmv: 'video/x-ms-wmv',\n mpd: 'application/dash+xml',\n m3u8: 'application/x-mpegURL',\n };\n return mimeTypes[extension] || 'application/octet-stream';\n};\n\nexport default function artplayerPluginChromecast(option) {\n const DEFAULT_ICON = ``;\n const DEFAULT_SDK = 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1';\n\n let isCastInitialized = false;\n let castSession = null;\n\n const initializeCastApi = () => {\n return new Promise((resolve, reject) => {\n window['__onGCastApiAvailable'] = (isAvailable) => {\n if (isAvailable) {\n const context = window.cast.framework.CastContext.getInstance();\n context.setOptions({\n receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID,\n autoJoinPolicy: window.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED,\n });\n context.addEventListener(\n window.cast.framework.CastContextEventType.SESSION_STATE_CHANGED,\n (event) => {\n castSession = event.session;\n updateCastButton();\n },\n );\n isCastInitialized = true;\n resolve();\n } else {\n reject(new Error('Cast API is not available'));\n }\n };\n if (!window.chrome || !window.chrome.cast) {\n loadScript(option.sdk || DEFAULT_SDK).catch(reject);\n }\n });\n };\n\n const castVideo = (art, session) => {\n const url = option.url || art.option.url;\n const mediaInfo = new window.chrome.cast.media.MediaInfo(url, option.mimeType || getMimeType(url));\n const request = new window.chrome.cast.media.LoadRequest(mediaInfo);\n session\n .loadMedia(request)\n .then(() => (art.notice.show = 'Casting started'))\n .catch((error) => {\n art.notice.show = 'Error casting media';\n throw error;\n });\n };\n\n const updateCastButton = () => {\n const button = document.querySelector('.art-icon-cast');\n if (button) {\n button.style.color = castSession ? 'red' : 'white';\n }\n };\n\n return async (art) => {\n art.controls.add({\n name: 'chromecast',\n position: 'right',\n tooltip: 'Chromecast',\n html: `${option.icon || DEFAULT_ICON}`,\n click: async () => {\n if (!isCastInitialized) {\n try {\n await initializeCastApi();\n } catch (error) {\n art.notice.show = 'Failed to initialize Cast API';\n throw error;\n }\n }\n\n const context = window.cast.framework.CastContext.getInstance();\n if (castSession) {\n castVideo(art, castSession);\n } else {\n try {\n const session = await context.requestSession();\n castVideo(art, session);\n } catch (error) {\n art.notice.show = 'Error connecting to cast session';\n throw error;\n }\n }\n },\n });\n\n return { name: 'artplayerPluginChromecast' };\n };\n}\n\nif (typeof window !== 'undefined') {\n window['artplayerPluginChromecast'] = artplayerPluginChromecast;\n}\n","exports.interopDefault = function (a) {\n return a && a.__esModule ? a : {default: a};\n};\n\nexports.defineInteropFlag = function (a) {\n Object.defineProperty(a, '__esModule', {value: true});\n};\n\nexports.exportAll = function (source, dest) {\n Object.keys(source).forEach(function (key) {\n if (\n key === 'default' ||\n key === '__esModule' ||\n Object.prototype.hasOwnProperty.call(dest, key)\n ) {\n return;\n }\n\n Object.defineProperty(dest, key, {\n enumerable: true,\n get: function () {\n return source[key];\n },\n });\n });\n\n return dest;\n};\n\nexports.export = function (dest, destName, get) {\n Object.defineProperty(dest, destName, {\n enumerable: true,\n get: get,\n });\n};\n"],"names":[],"version":3,"file":"index.js.map","sourceRoot":"../../../"} \ No newline at end of file +{"mappings":"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","sources":["packages/artplayer-plugin-chromecast/src/index.js","node_modules/@parcel/transformer-js/src/esmodule-helpers.js"],"sourcesContent":["const loadScript = (src) =>\n new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = src;\n script.onload = resolve;\n script.onerror = reject;\n document.body.appendChild(script);\n });\n\nconst getMimeType = (url) => {\n const extension = url.split('?')[0].split('#')[0].split('.').pop().toLowerCase();\n const mimeTypes = {\n mp4: 'video/mp4',\n webm: 'video/webm',\n ogg: 'video/ogg',\n ogv: 'video/ogg',\n mp3: 'audio/mp3',\n wav: 'audio/wav',\n flv: 'video/x-flv',\n mov: 'video/quicktime',\n avi: 'video/x-msvideo',\n wmv: 'video/x-ms-wmv',\n mpd: 'application/dash+xml',\n m3u8: 'application/x-mpegURL',\n };\n return mimeTypes[extension] || 'application/octet-stream';\n};\n\nexport default function artplayerPluginChromecast(option) {\n const DEFAULT_ICON = ``;\n const DEFAULT_SDK = 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1';\n\n let isCastInitialized = false;\n let castSession = null;\n let castState = null;\n\n const initializeCastApi = () => {\n return new Promise((resolve, reject) => {\n window['__onGCastApiAvailable'] = (isAvailable) => {\n if (isAvailable) {\n const context = window.cast.framework.CastContext.getInstance();\n context.setOptions({\n receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID,\n autoJoinPolicy: window.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED,\n });\n\n // Listen for session state changes\n context.addEventListener(\n window.cast.framework.CastContextEventType.SESSION_STATE_CHANGED,\n (event) => {\n const SessionState = window.cast.framework.SessionState;\n castState = event.sessionState;\n castSession = event.session;\n\n switch (event.sessionState) {\n case SessionState.NO_SESSION:\n option.onStateChange?.('disconnected');\n updateCastButton('disconnected');\n break;\n case SessionState.SESSION_STARTING:\n option.onStateChange?.('connecting');\n updateCastButton('connecting');\n break;\n case SessionState.SESSION_STARTED:\n option.onStateChange?.('connected');\n updateCastButton('connected');\n break;\n case SessionState.SESSION_ENDING:\n option.onStateChange?.('disconnecting');\n updateCastButton('disconnecting');\n break;\n case SessionState.SESSION_RESUMED:\n option.onStateChange?.('connected');\n updateCastButton('connected');\n break;\n }\n },\n );\n\n // Listen for cast state changes\n context.addEventListener(window.cast.framework.CastContextEventType.CAST_STATE_CHANGED, (event) => {\n const CastState = window.cast.framework.CastState;\n switch (event.castState) {\n case CastState.NO_DEVICES_AVAILABLE:\n option.onCastAvailable?.(false);\n break;\n case CastState.NOT_CONNECTED:\n option.onCastAvailable?.(true);\n break;\n case CastState.CONNECTING:\n case CastState.CONNECTED:\n option.onCastAvailable?.(true);\n break;\n }\n });\n\n isCastInitialized = true;\n resolve();\n } else {\n reject(new Error('Cast API is not available'));\n }\n };\n if (!window.chrome || !window.chrome.cast) {\n loadScript(option.sdk || DEFAULT_SDK).catch(reject);\n }\n });\n };\n\n const castVideo = (art, session) => {\n const url = option.url || art.option.url;\n const mediaInfo = new window.chrome.cast.media.MediaInfo(url, option.mimeType || getMimeType(url));\n const request = new window.chrome.cast.media.LoadRequest(mediaInfo);\n session\n .loadMedia(request)\n .then(() => {\n art.notice.show = 'Casting started';\n option.onCastStart?.();\n })\n .catch((error) => {\n art.notice.show = 'Error casting media';\n option.onError?.(error);\n throw error;\n });\n };\n\n const updateCastButton = (state) => {\n const button = document.querySelector('.art-icon-cast');\n if (button) {\n switch (state) {\n case 'connected':\n button.style.color = 'red';\n break;\n case 'connecting':\n case 'disconnecting':\n button.style.color = 'orange';\n break;\n case 'disconnected':\n default:\n button.style.color = 'white';\n break;\n }\n }\n };\n\n return async (art) => {\n art.controls.add({\n name: 'chromecast',\n position: 'right',\n tooltip: 'Chromecast',\n html: `${option.icon || DEFAULT_ICON}`,\n click: async () => {\n if (!isCastInitialized) {\n try {\n await initializeCastApi();\n } catch (error) {\n art.notice.show = 'Failed to initialize Cast API';\n option.onError?.(error);\n throw error;\n }\n }\n\n const context = window.cast.framework.CastContext.getInstance();\n if (castSession) {\n castVideo(art, castSession);\n } else {\n try {\n const session = await context.requestSession();\n castVideo(art, session);\n } catch (error) {\n art.notice.show = 'Error connecting to cast session';\n option.onError?.(error);\n throw error;\n }\n }\n },\n });\n\n return {\n name: 'artplayerPluginChromecast',\n getCastState: () => castState,\n isCasting: () => castSession !== null,\n };\n };\n}\n\nif (typeof window !== 'undefined') {\n window['artplayerPluginChromecast'] = artplayerPluginChromecast;\n}\n","exports.interopDefault = function (a) {\n return a && a.__esModule ? a : {default: a};\n};\n\nexports.defineInteropFlag = function (a) {\n Object.defineProperty(a, '__esModule', {value: true});\n};\n\nexports.exportAll = function (source, dest) {\n Object.keys(source).forEach(function (key) {\n if (\n key === 'default' ||\n key === '__esModule' ||\n Object.prototype.hasOwnProperty.call(dest, key)\n ) {\n return;\n }\n\n Object.defineProperty(dest, key, {\n enumerable: true,\n get: function () {\n return source[key];\n },\n });\n });\n\n return dest;\n};\n\nexports.export = function (dest, destName, get) {\n Object.defineProperty(dest, destName, {\n enumerable: true,\n get: get,\n });\n};\n"],"names":[],"version":3,"file":"index.js.map","sourceRoot":"../../../"} \ No newline at end of file diff --git a/packages/artplayer-plugin-chromecast/src/index.js b/packages/artplayer-plugin-chromecast/src/index.js index f67a0a9ab..61eaddf4f 100644 --- a/packages/artplayer-plugin-chromecast/src/index.js +++ b/packages/artplayer-plugin-chromecast/src/index.js @@ -32,6 +32,7 @@ export default function artplayerPluginChromecast(option) { let isCastInitialized = false; let castSession = null; + let castState = null; const initializeCastApi = () => { return new Promise((resolve, reject) => { @@ -42,13 +43,57 @@ export default function artplayerPluginChromecast(option) { receiverApplicationId: window.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, autoJoinPolicy: window.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED, }); + + // Listen for session state changes context.addEventListener( window.cast.framework.CastContextEventType.SESSION_STATE_CHANGED, (event) => { + const SessionState = window.cast.framework.SessionState; + castState = event.sessionState; castSession = event.session; - updateCastButton(); + + switch (event.sessionState) { + case SessionState.NO_SESSION: + option.onStateChange?.('disconnected'); + updateCastButton('disconnected'); + break; + case SessionState.SESSION_STARTING: + option.onStateChange?.('connecting'); + updateCastButton('connecting'); + break; + case SessionState.SESSION_STARTED: + option.onStateChange?.('connected'); + updateCastButton('connected'); + break; + case SessionState.SESSION_ENDING: + option.onStateChange?.('disconnecting'); + updateCastButton('disconnecting'); + break; + case SessionState.SESSION_RESUMED: + option.onStateChange?.('connected'); + updateCastButton('connected'); + break; + } }, ); + + // Listen for cast state changes + context.addEventListener(window.cast.framework.CastContextEventType.CAST_STATE_CHANGED, (event) => { + const CastState = window.cast.framework.CastState; + switch (event.castState) { + case CastState.NO_DEVICES_AVAILABLE: + option.onCastAvailable?.(false); + break; + case CastState.NOT_CONNECTED: + option.onCastAvailable?.(true); + break; + case CastState.CONNECTING: + case CastState.CONNECTED: + option.onCastAvailable?.(true); + break; + } + }); + isCastInitialized = true; resolve(); } else { @@ -67,17 +112,33 @@ export default function artplayerPluginChromecast(option) { const request = new window.chrome.cast.media.LoadRequest(mediaInfo); session .loadMedia(request) - .then(() => (art.notice.show = 'Casting started')) + .then(() => { + art.notice.show = 'Casting started'; + option.onCastStart?.(); + }) .catch((error) => { art.notice.show = 'Error casting media'; + option.onError?.(error); throw error; }); }; - const updateCastButton = () => { + const updateCastButton = (state) => { const button = document.querySelector('.art-icon-cast'); if (button) { - button.style.color = castSession ? 'red' : 'white'; + switch (state) { + case 'connected': + button.style.color = 'red'; + break; + case 'connecting': + case 'disconnecting': + button.style.color = 'orange'; + break; + case 'disconnected': + default: + button.style.color = 'white'; + break; + } } }; @@ -93,6 +154,7 @@ export default function artplayerPluginChromecast(option) { await initializeCastApi(); } catch (error) { art.notice.show = 'Failed to initialize Cast API'; + option.onError?.(error); throw error; } } @@ -106,13 +168,18 @@ export default function artplayerPluginChromecast(option) { castVideo(art, session); } catch (error) { art.notice.show = 'Error connecting to cast session'; + option.onError?.(error); throw error; } } }, }); - return { name: 'artplayerPluginChromecast' }; + return { + name: 'artplayerPluginChromecast', + getCastState: () => castState, + isCasting: () => castSession !== null, + }; }; }