66 lines
2.2 KiB
TypeScript
66 lines
2.2 KiB
TypeScript
"use client";
|
|
import { useEffect, useState, useCallback, useRef } from "react";
|
|
|
|
|
|
export function useCast() {
|
|
const [castAvailable, setCastAvailable] = useState(false);
|
|
const [isCasting, setIsCasting] = useState(false);
|
|
const [castDeviceName, setCastDeviceName] = useState<string | null>(null);
|
|
const initialized = useRef(false);
|
|
|
|
useEffect(() => {
|
|
if (initialized.current) return;
|
|
initialized.current = true;
|
|
|
|
const init = () => {
|
|
const ctx = cast.framework.CastContext.getInstance();
|
|
ctx.setOptions({
|
|
receiverApplicationId: chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID,
|
|
autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED,
|
|
});
|
|
ctx.addEventListener(
|
|
cast.framework.CastContextEventType.CAST_STATE_CHANGED,
|
|
(e) => {
|
|
const casting = e.castState === cast.framework.CastState.CONNECTED;
|
|
setIsCasting(casting);
|
|
setCastDeviceName(
|
|
casting ? (ctx.getCurrentSession()?.getCastDevice().friendlyName ?? null) : null
|
|
);
|
|
setCastAvailable(e.castState !== cast.framework.CastState.NO_DEVICES_AVAILABLE);
|
|
},
|
|
);
|
|
const state = ctx.getCastState();
|
|
setCastAvailable(state !== cast.framework.CastState.NO_DEVICES_AVAILABLE);
|
|
setIsCasting(state === cast.framework.CastState.CONNECTED);
|
|
};
|
|
|
|
if (window.cast?.framework) {
|
|
init();
|
|
} else {
|
|
window.__onGCastApiAvailable = (isAvailable: boolean) => {
|
|
if (isAvailable) init();
|
|
};
|
|
}
|
|
}, []);
|
|
|
|
const requestCast = useCallback(async (streamUrl: string) => {
|
|
if (!window.cast?.framework) return;
|
|
const ctx = cast.framework.CastContext.getInstance();
|
|
let session = ctx.getCurrentSession();
|
|
if (!session) {
|
|
const err = await ctx.requestSession();
|
|
if (err) return;
|
|
session = ctx.getCurrentSession();
|
|
}
|
|
if (!session) return;
|
|
const mediaInfo = new chrome.cast.media.MediaInfo(streamUrl, "application/x-mpegURL");
|
|
await session.loadMedia(new chrome.cast.media.LoadRequest(mediaInfo));
|
|
}, []);
|
|
|
|
const stopCasting = useCallback(() => {
|
|
window.cast?.framework.CastContext.getInstance().endCurrentSession(true);
|
|
}, []);
|
|
|
|
return { castAvailable, isCasting, castDeviceName, requestCast, stopCasting };
|
|
}
|