10 changed files with 168 additions and 46 deletions
@ -1,3 +1,17 @@ |
|||||||
|
import { usePlayerStore } from "@/stores/player/store"; |
||||||
|
|
||||||
export function Pause() { |
export function Pause() { |
||||||
return <button type="button" />; |
const display = usePlayerStore((s) => s.display); |
||||||
|
const { isPaused } = usePlayerStore((s) => s.mediaPlaying); |
||||||
|
|
||||||
|
const toggle = () => { |
||||||
|
if (isPaused) display?.play(); |
||||||
|
else display?.pause(); |
||||||
|
}; |
||||||
|
|
||||||
|
return ( |
||||||
|
<button type="button" onClick={toggle}> |
||||||
|
play/pause |
||||||
|
</button> |
||||||
|
); |
||||||
} |
} |
||||||
|
@ -1 +1,45 @@ |
|||||||
export {}; |
import { |
||||||
|
DisplayInterface, |
||||||
|
DisplayInterfaceEvents, |
||||||
|
} from "@/components/player/display/displayInterface"; |
||||||
|
import { Source } from "@/components/player/hooks/usePlayer"; |
||||||
|
import { makeEmitter } from "@/utils/events"; |
||||||
|
|
||||||
|
export function makeVideoElementDisplayInterface(): DisplayInterface { |
||||||
|
const { emit, on, off } = makeEmitter<DisplayInterfaceEvents>(); |
||||||
|
let source: Source | null = null; |
||||||
|
let videoElement: HTMLVideoElement | null = null; |
||||||
|
|
||||||
|
function setSource() { |
||||||
|
if (!videoElement || !source) return; |
||||||
|
videoElement.src = source.url; |
||||||
|
videoElement.addEventListener("play", () => emit("play", undefined)); |
||||||
|
videoElement.addEventListener("pause", () => emit("pause", undefined)); |
||||||
|
} |
||||||
|
|
||||||
|
return { |
||||||
|
on, |
||||||
|
off, |
||||||
|
|
||||||
|
// no need to destroy anything
|
||||||
|
destroy: () => {}, |
||||||
|
|
||||||
|
load(newSource) { |
||||||
|
source = newSource; |
||||||
|
setSource(); |
||||||
|
}, |
||||||
|
|
||||||
|
processVideoElement(video) { |
||||||
|
videoElement = video; |
||||||
|
setSource(); |
||||||
|
}, |
||||||
|
|
||||||
|
pause() { |
||||||
|
videoElement?.pause(); |
||||||
|
}, |
||||||
|
|
||||||
|
play() { |
||||||
|
videoElement?.play(); |
||||||
|
}, |
||||||
|
}; |
||||||
|
} |
||||||
|
@ -1,36 +1,46 @@ |
|||||||
import { RefObject, useEffect, useRef } from "react"; |
import { useEffect, useRef } from "react"; |
||||||
|
|
||||||
import { MWStreamType } from "@/backend/helpers/streams"; |
import { makeVideoElementDisplayInterface } from "@/components/player/display/base"; |
||||||
import { SourceSliceSource } from "@/stores/player/slices/source"; |
import { playerStatus } from "@/stores/player/slices/source"; |
||||||
import { AllSlices } from "@/stores/player/slices/types"; |
|
||||||
import { usePlayerStore } from "@/stores/player/store"; |
import { usePlayerStore } from "@/stores/player/store"; |
||||||
|
|
||||||
// should this video container show right now?
|
// initialize display interface
|
||||||
function useShouldShow(source: SourceSliceSource | null): boolean { |
function useDisplayInterface() { |
||||||
if (!source) return false; |
const display = usePlayerStore((s) => s.display); |
||||||
if (source.type !== MWStreamType.MP4) return false; |
const setDisplay = usePlayerStore((s) => s.setDisplay); |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
if (!display) { |
||||||
|
setDisplay(makeVideoElementDisplayInterface()); |
||||||
|
} |
||||||
|
}, [display, setDisplay]); |
||||||
|
} |
||||||
|
|
||||||
|
function useShouldShowVideoElement() { |
||||||
|
const status = usePlayerStore((s) => s.status); |
||||||
|
|
||||||
|
if (status !== playerStatus.PLAYING) return false; |
||||||
return true; |
return true; |
||||||
} |
} |
||||||
|
|
||||||
// make video element up to par with the state
|
function VideoElement() { |
||||||
function useRestoreVideo( |
const videoEl = useRef<HTMLVideoElement>(null); |
||||||
videoRef: RefObject<HTMLVideoElement>, |
const display = usePlayerStore((s) => s.display); |
||||||
player: AllSlices |
|
||||||
) { |
// report video element to display interface
|
||||||
useEffect(() => { |
useEffect(() => { |
||||||
const el = videoRef.current; |
if (display && videoEl.current) { |
||||||
const src = player.source?.url ?? ""; |
display.processVideoElement(videoEl.current); |
||||||
if (!el) return; |
} |
||||||
if (el.src !== src) el.src = src; |
}, [display, videoEl]); |
||||||
}, [player.source?.url, videoRef]); |
|
||||||
|
return <video autoPlay ref={videoEl} />; |
||||||
} |
} |
||||||
|
|
||||||
export function VideoContainer() { |
export function VideoContainer() { |
||||||
const videoEl = useRef<HTMLVideoElement>(null); |
const show = useShouldShowVideoElement(); |
||||||
const player = usePlayerStore(); |
useDisplayInterface(); |
||||||
useRestoreVideo(videoEl, player); |
|
||||||
const show = useShouldShow(player.source); |
|
||||||
|
|
||||||
if (!show) return null; |
if (!show) return null; |
||||||
return <video autoPlay ref={videoEl} />; |
return <VideoElement />; |
||||||
} |
} |
||||||
|
@ -1,9 +1,30 @@ |
|||||||
|
import { MWStreamType } from "@/backend/helpers/streams"; |
||||||
import { Player } from "@/components/player"; |
import { Player } from "@/components/player"; |
||||||
|
import { usePlayer } from "@/components/player/hooks/usePlayer"; |
||||||
|
import { playerStatus } from "@/stores/player/slices/source"; |
||||||
|
|
||||||
export function PlayerView() { |
export function PlayerView() { |
||||||
|
const { status, playMedia } = usePlayer(); |
||||||
|
|
||||||
|
function scrape() { |
||||||
|
playMedia({ |
||||||
|
type: MWStreamType.MP4, |
||||||
|
url: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4", |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
return ( |
return ( |
||||||
<Player.Container> |
<Player.Container> |
||||||
<Player.Pause /> |
<Player.Pause /> |
||||||
|
|
||||||
|
{status === playerStatus.IDLE ? ( |
||||||
|
<div> |
||||||
|
<p>Its now scraping</p> |
||||||
|
<button type="button" onClick={scrape}> |
||||||
|
Finish scraping |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
) : null} |
||||||
</Player.Container> |
</Player.Container> |
||||||
); |
); |
||||||
} |
} |
||||||
|
@ -1,18 +1,5 @@ |
|||||||
import { useEffect } from "react"; |
|
||||||
|
|
||||||
import { MWStreamType } from "@/backend/helpers/streams"; |
|
||||||
import { usePlayer } from "@/components/player/hooks/usePlayer"; |
|
||||||
import { PlayerView } from "@/pages/PlayerView"; |
import { PlayerView } from "@/pages/PlayerView"; |
||||||
|
|
||||||
export default function VideoTesterView() { |
export default function VideoTesterView() { |
||||||
const player = usePlayer(); |
|
||||||
|
|
||||||
useEffect(() => { |
|
||||||
player.playMedia({ |
|
||||||
type: MWStreamType.MP4, |
|
||||||
url: "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4", |
|
||||||
}); |
|
||||||
}); |
|
||||||
|
|
||||||
return <PlayerView />; |
return <PlayerView />; |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue