mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-09 20:29:36 +02:00
make visualizer idle kill consistent for both
This commit is contained in:
@@ -11,8 +11,10 @@ import {
|
|||||||
useFullScreenPlayerStore,
|
useFullScreenPlayerStore,
|
||||||
useFullScreenPlayerStoreActions,
|
useFullScreenPlayerStoreActions,
|
||||||
} from '/@/renderer/store/full-screen-player.store';
|
} from '/@/renderer/store/full-screen-player.store';
|
||||||
|
import { usePlayerStatus } from '/@/renderer/store/player.store';
|
||||||
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
||||||
import { Group } from '/@/shared/components/group/group';
|
import { Group } from '/@/shared/components/group/group';
|
||||||
|
import { PlayerStatus, PlayerType } from '/@/shared/types/types';
|
||||||
|
|
||||||
const VisualizerInner = () => {
|
const VisualizerInner = () => {
|
||||||
const { webAudio } = useWebAudio();
|
const { webAudio } = useWebAudio();
|
||||||
@@ -24,6 +26,9 @@ const VisualizerInner = () => {
|
|||||||
const [motion, setMotion] = useState<any>();
|
const [motion, setMotion] = useState<any>();
|
||||||
const [libraryLoaded, setLibraryLoaded] = useState(false);
|
const [libraryLoaded, setLibraryLoaded] = useState(false);
|
||||||
const AudioMotionAnalyzerRef = useRef<any>(null);
|
const AudioMotionAnalyzerRef = useRef<any>(null);
|
||||||
|
const pauseTimerRef = useRef<NodeJS.Timeout | undefined>(undefined);
|
||||||
|
const playerStatus = usePlayerStatus();
|
||||||
|
const isPlaying = playerStatus === PlayerStatus.PLAYING;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let isMounted = true;
|
let isMounted = true;
|
||||||
@@ -218,8 +223,19 @@ const VisualizerInner = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const { context } = webAudio || {};
|
const { context } = webAudio || {};
|
||||||
const inputNodes = getVisualizerAudioNodes(webAudio, playbackType);
|
const inputNodes = getVisualizerAudioNodes(webAudio, playbackType);
|
||||||
|
const shouldRunForWebPlayback = playbackType === PlayerType.WEB && isPlaying;
|
||||||
|
const shouldRunForMpvLoopback =
|
||||||
|
playbackType === PlayerType.LOCAL && isPlaying && inputNodes.length > 0;
|
||||||
|
|
||||||
let audioMotion: any | undefined;
|
let audioMotion: any | undefined;
|
||||||
if (inputNodes.length > 0 && context && canvasRef.current && !motion && libraryLoaded) {
|
if (
|
||||||
|
inputNodes.length > 0 &&
|
||||||
|
context &&
|
||||||
|
canvasRef.current &&
|
||||||
|
!motion &&
|
||||||
|
libraryLoaded &&
|
||||||
|
(shouldRunForWebPlayback || shouldRunForMpvLoopback)
|
||||||
|
) {
|
||||||
const AudioMotionAnalyzer = AudioMotionAnalyzerRef.current;
|
const AudioMotionAnalyzer = AudioMotionAnalyzerRef.current;
|
||||||
if (!AudioMotionAnalyzer) return;
|
if (!AudioMotionAnalyzer) return;
|
||||||
|
|
||||||
@@ -257,7 +273,11 @@ const VisualizerInner = () => {
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (motion) {
|
if (motion) {
|
||||||
motion.destroy();
|
try {
|
||||||
|
motion.destroy();
|
||||||
|
} catch {
|
||||||
|
// ignore (e.g. already destroyed by idle timer)
|
||||||
|
}
|
||||||
setMotion(undefined);
|
setMotion(undefined);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -272,8 +292,43 @@ const VisualizerInner = () => {
|
|||||||
isCustomGradient,
|
isCustomGradient,
|
||||||
motion,
|
motion,
|
||||||
libraryLoaded,
|
libraryLoaded,
|
||||||
|
isPlaying,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Kill visualizer after 5 seconds of pause
|
||||||
|
useEffect(() => {
|
||||||
|
if (isPlaying) {
|
||||||
|
if (pauseTimerRef.current) {
|
||||||
|
clearTimeout(pauseTimerRef.current);
|
||||||
|
pauseTimerRef.current = undefined;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!motion) return;
|
||||||
|
|
||||||
|
pauseTimerRef.current = setTimeout(() => {
|
||||||
|
setMotion((current) => {
|
||||||
|
if (current) {
|
||||||
|
try {
|
||||||
|
current.destroy();
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
pauseTimerRef.current = undefined;
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (pauseTimerRef.current) {
|
||||||
|
clearTimeout(pauseTimerRef.current);
|
||||||
|
pauseTimerRef.current = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [isPlaying, motion]);
|
||||||
|
|
||||||
// Re-register custom gradients when they change
|
// Re-register custom gradients when they change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (motion && visualizer.type === 'audiomotionanalyzer') {
|
if (motion && visualizer.type === 'audiomotionanalyzer') {
|
||||||
|
|||||||
@@ -62,9 +62,9 @@ const VisualizerInner = () => {
|
|||||||
const { setSettings } = useSettingsStoreActions();
|
const { setSettings } = useSettingsStoreActions();
|
||||||
const playerStatus = usePlayerStatus();
|
const playerStatus = usePlayerStatus();
|
||||||
const isPlaying = playerStatus === PlayerStatus.PLAYING;
|
const isPlaying = playerStatus === PlayerStatus.PLAYING;
|
||||||
const [webInitGeneration, setWebInitGeneration] = useState(0);
|
const [resumeInitGeneration, setResumeInitGeneration] = useState(0);
|
||||||
const wasPlayingRef = useRef(false);
|
const wasPlayingRef = useRef(false);
|
||||||
const isFirstWebMountRef = useRef(true);
|
const isFirstMountRef = useRef(true);
|
||||||
const prevPlaybackTypeRef = useRef(playbackType);
|
const prevPlaybackTypeRef = useRef(playbackType);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -99,14 +99,8 @@ const VisualizerInner = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const prevType = prevPlaybackTypeRef.current;
|
const prevType = prevPlaybackTypeRef.current;
|
||||||
|
|
||||||
if (playbackType !== PlayerType.WEB) {
|
if (isFirstMountRef.current) {
|
||||||
prevPlaybackTypeRef.current = playbackType;
|
isFirstMountRef.current = false;
|
||||||
wasPlayingRef.current = isPlaying;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isFirstWebMountRef.current) {
|
|
||||||
isFirstWebMountRef.current = false;
|
|
||||||
wasPlayingRef.current = isPlaying;
|
wasPlayingRef.current = isPlaying;
|
||||||
prevPlaybackTypeRef.current = playbackType;
|
prevPlaybackTypeRef.current = playbackType;
|
||||||
return;
|
return;
|
||||||
@@ -115,8 +109,8 @@ const VisualizerInner = () => {
|
|||||||
const wasPlaying = wasPlayingRef.current;
|
const wasPlaying = wasPlayingRef.current;
|
||||||
wasPlayingRef.current = isPlaying;
|
wasPlayingRef.current = isPlaying;
|
||||||
|
|
||||||
if (isPlaying && (!wasPlaying || prevType !== PlayerType.WEB)) {
|
if (isPlaying && (!wasPlaying || prevType !== playbackType)) {
|
||||||
setWebInitGeneration((g) => g + 1);
|
setResumeInitGeneration((g) => g + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
prevPlaybackTypeRef.current = playbackType;
|
prevPlaybackTypeRef.current = playbackType;
|
||||||
@@ -157,7 +151,8 @@ const VisualizerInner = () => {
|
|||||||
const container = containerRef.current;
|
const container = containerRef.current;
|
||||||
|
|
||||||
const shouldRunForWebPlayback = playbackType === PlayerType.WEB && isPlaying;
|
const shouldRunForWebPlayback = playbackType === PlayerType.WEB && isPlaying;
|
||||||
const shouldRunForMpvLoopback = playbackType === PlayerType.LOCAL && inputNodes.length > 0;
|
const shouldRunForMpvLoopback =
|
||||||
|
playbackType === PlayerType.LOCAL && isPlaying && inputNodes.length > 0;
|
||||||
|
|
||||||
const needsInitialization =
|
const needsInitialization =
|
||||||
context &&
|
context &&
|
||||||
@@ -229,18 +224,10 @@ const VisualizerInner = () => {
|
|||||||
cleanupVisualizer();
|
cleanupVisualizer();
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [webAudio, playbackType, librariesLoaded, webInitGeneration]);
|
}, [webAudio, playbackType, librariesLoaded, resumeInitGeneration]);
|
||||||
|
|
||||||
// Kill visualizer after 5 seconds of pause
|
// Kill visualizer after 5 seconds of pause
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (playbackType === PlayerType.LOCAL) {
|
|
||||||
if (pauseTimerRef.current) {
|
|
||||||
clearTimeout(pauseTimerRef.current);
|
|
||||||
pauseTimerRef.current = undefined;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isPlaying) {
|
if (isPlaying) {
|
||||||
// Clear pause timer if player resumes
|
// Clear pause timer if player resumes
|
||||||
if (pauseTimerRef.current) {
|
if (pauseTimerRef.current) {
|
||||||
|
|||||||
Reference in New Issue
Block a user