feat(casting): implement casting functionality with auto-mute and UI controls
This commit is contained in:
65
k-tv-frontend/hooks/use-cast.ts
Normal file
65
k-tv-frontend/hooks/use-cast.ts
Normal 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 };
|
||||
}
|
||||
Reference in New Issue
Block a user