feat: Use VLC discovery API for chromecast and other devices

Currently, this only works for chromecast. In the future, this implementation will also work for other types like upnp & airplay.
This commit is contained in:
herrrta
2025-02-22 13:28:40 -05:00
parent cf284eb3d8
commit 7ea2d81fb4
17 changed files with 305 additions and 94 deletions

View File

@@ -1,4 +1,4 @@
import { Ionicons } from "@expo/vector-icons";
import {Ionicons, MaterialCommunityIcons} from "@expo/vector-icons";
import { PropsWithChildren, ReactNode } from "react";
import {
TouchableOpacity,
@@ -13,7 +13,7 @@ interface Props extends TouchableOpacityProps, ViewProps {
value?: string | null | undefined;
children?: ReactNode;
iconAfter?: ReactNode;
icon?: keyof typeof Ionicons.glyphMap;
icon?: keyof typeof Ionicons.glyphMap | keyof typeof MaterialCommunityIcons.glyphMap;
showArrow?: boolean;
textColor?: "default" | "blue" | "red";
onPress?: () => void;
@@ -89,7 +89,19 @@ const ListItemContent = ({
<View className="flex flex-row items-center w-full">
{icon && (
<View className="border border-neutral-800 rounded-md h-8 w-8 flex items-center justify-center mr-2">
<Ionicons name="person-circle-outline" size={18} color="white" />
{icon in Ionicons.glyphMap ?
<Ionicons
name={icon as keyof typeof Ionicons.glyphMap}
size={18}
color="white"
/>
:
<MaterialCommunityIcons
name={icon as keyof typeof MaterialCommunityIcons.glyphMap}
size={18}
color="white"
/>
}
</View>
)}
<Text

View File

@@ -80,6 +80,7 @@ interface Props {
mediaSource?: MediaSourceInfo | null;
seek: (ticks: number) => void;
startPictureInPicture: () => Promise<void>;
startDiscovery: () => Promise<void>;
play: (() => Promise<void>) | (() => void);
pause: () => void;
getAudioTracks?: (() => Promise<TrackInfo[] | null>) | (() => TrackInfo[]);
@@ -93,32 +94,33 @@ interface Props {
const CONTROLS_TIMEOUT = 4000;
export const Controls: React.FC<Props> = ({
item,
seek,
startPictureInPicture,
play,
pause,
togglePlay,
isPlaying,
isSeeking,
progress,
isBuffering,
cacheProgress,
showControls,
setShowControls,
ignoreSafeAreas,
setIgnoreSafeAreas,
mediaSource,
isVideoLoaded,
getAudioTracks,
getSubtitleTracks,
setSubtitleURL,
setSubtitleTrack,
setAudioTrack,
offline = false,
enableTrickplay = true,
isVlc = false,
}) => {
item,
seek,
startDiscovery,
startPictureInPicture,
play,
pause,
togglePlay,
isPlaying,
isSeeking,
progress,
isBuffering,
cacheProgress,
showControls,
setShowControls,
ignoreSafeAreas,
setIgnoreSafeAreas,
mediaSource,
isVideoLoaded,
getAudioTracks,
getSubtitleTracks,
setSubtitleURL,
setSubtitleTrack,
setAudioTrack,
offline = false,
enableTrickplay = true,
isVlc = false,
}) => {
const [settings] = useSettings();
const router = useRouter();
const insets = useSafeAreaInsets();
@@ -494,6 +496,17 @@ export const Controls: React.FC<Props> = ({
)}
<View className="flex flex-row items-center space-x-2 ">
<TouchableOpacity
onPress={startDiscovery}
className="aspect-square flex flex-col rounded-xl items-center justify-center p-2"
>
<MaterialIcons
name="cast"
size={24}
color="white"
style={{ opacity: showControls ? 1 : 0 }}
/>
</TouchableOpacity>
{!Platform.isTV && (
<TouchableOpacity
onPress={startPictureInPicture}