feat(casting): implement casting functionality with auto-mute and UI controls

This commit is contained in:
2026-03-14 02:38:54 +01:00
parent 953366ed63
commit 0bdf7104a9
4 changed files with 112 additions and 1 deletions

View File

@@ -0,0 +1,65 @@
"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 };
}