mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-10 04:30:25 +02:00
move timestamp update to separate effect
This commit is contained in:
@@ -17,7 +17,7 @@ interface MpvPlayerEngineProps {
|
|||||||
nextSrc: string | undefined;
|
nextSrc: string | undefined;
|
||||||
onEnded: () => void;
|
onEnded: () => void;
|
||||||
onProgress: (e: PlayerOnProgressProps) => void;
|
onProgress: (e: PlayerOnProgressProps) => void;
|
||||||
playerRef: RefObject<MpvPlayerEngineHandle>;
|
playerRef: RefObject<MpvPlayerEngineHandle | null>;
|
||||||
playerStatus: PlayerStatus;
|
playerStatus: PlayerStatus;
|
||||||
speed?: number;
|
speed?: number;
|
||||||
volume: number;
|
volume: number;
|
||||||
@@ -109,7 +109,9 @@ export const MpvPlayerEngine = (props: MpvPlayerEngineProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const vol = volume / 100 || 0;
|
const vol = volume / 100 || 0;
|
||||||
setInternalVolume(vol);
|
queueMicrotask(() => {
|
||||||
|
setInternalVolume(vol);
|
||||||
|
});
|
||||||
mpvPlayer.volume(volume);
|
mpvPlayer.volume(volume);
|
||||||
}, [volume]);
|
}, [volume]);
|
||||||
|
|
||||||
@@ -147,11 +149,15 @@ export const MpvPlayerEngine = (props: MpvPlayerEngineProps) => {
|
|||||||
if (currentSrc) {
|
if (currentSrc) {
|
||||||
// Set current song at position 0 and next song at position 1
|
// Set current song at position 0 and next song at position 1
|
||||||
mpvPlayer.setQueue(currentSrc, nextSrc, playerStatus !== PlayerStatus.PLAYING);
|
mpvPlayer.setQueue(currentSrc, nextSrc, playerStatus !== PlayerStatus.PLAYING);
|
||||||
setPreviousCurrentSrc(currentSrc);
|
setTimeout(() => {
|
||||||
|
setPreviousCurrentSrc(currentSrc);
|
||||||
|
}, 0);
|
||||||
} else {
|
} else {
|
||||||
// Clear queue if no current song
|
// Clear queue if no current song
|
||||||
mpvPlayer.setQueue(undefined, undefined, true);
|
mpvPlayer.setQueue(undefined, undefined, true);
|
||||||
setPreviousCurrentSrc(undefined);
|
setTimeout(() => {
|
||||||
|
setPreviousCurrentSrc(undefined);
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If currentSrc hasn't changed but nextSrc has, update position 1
|
// If currentSrc hasn't changed but nextSrc has, update position 1
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ interface WebPlayerEngineProps {
|
|||||||
onProgressPlayer1: (e: PlayerOnProgressProps) => void;
|
onProgressPlayer1: (e: PlayerOnProgressProps) => void;
|
||||||
onProgressPlayer2: (e: PlayerOnProgressProps) => void;
|
onProgressPlayer2: (e: PlayerOnProgressProps) => void;
|
||||||
playerNum: number;
|
playerNum: number;
|
||||||
playerRef: RefObject<WebPlayerEngineHandle>;
|
playerRef: RefObject<null | WebPlayerEngineHandle>;
|
||||||
playerStatus: PlayerStatus;
|
playerStatus: PlayerStatus;
|
||||||
speed?: number;
|
speed?: number;
|
||||||
src1: string | undefined;
|
src1: string | undefined;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useCallback, useRef, useState } from 'react';
|
import isElectron from 'is-electron';
|
||||||
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
import { MpvPlayerEngine, MpvPlayerEngineHandle } from './engine/mpv-player-engine';
|
import { MpvPlayerEngine, MpvPlayerEngineHandle } from './engine/mpv-player-engine';
|
||||||
|
|
||||||
import { useMainPlayerListener } from '/@/renderer/features/player/audio-player/hooks/use-main-player-listener';
|
import { useMainPlayerListener } from '/@/renderer/features/player/audio-player/hooks/use-main-player-listener';
|
||||||
import { usePlayerEvents } from '/@/renderer/features/player/audio-player/hooks/use-player-events';
|
import { usePlayerEvents } from '/@/renderer/features/player/audio-player/hooks/use-player-events';
|
||||||
import { PlayerOnProgressProps } from '/@/renderer/features/player/audio-player/types';
|
|
||||||
import {
|
import {
|
||||||
usePlayerActions,
|
usePlayerActions,
|
||||||
usePlayerData,
|
usePlayerData,
|
||||||
@@ -17,6 +17,8 @@ import { PlayerStatus } from '/@/shared/types/types';
|
|||||||
const PLAY_PAUSE_FADE_DURATION = 300;
|
const PLAY_PAUSE_FADE_DURATION = 300;
|
||||||
const PLAY_PAUSE_FADE_INTERVAL = 10;
|
const PLAY_PAUSE_FADE_INTERVAL = 10;
|
||||||
|
|
||||||
|
const mpvPlayer = isElectron() ? window.api.mpvPlayer : null;
|
||||||
|
|
||||||
export function MpvPlayer() {
|
export function MpvPlayer() {
|
||||||
const playerRef = useRef<MpvPlayerEngineHandle>(null);
|
const playerRef = useRef<MpvPlayerEngineHandle>(null);
|
||||||
const { currentSong, nextSong, status } = usePlayerData();
|
const { currentSong, nextSong, status } = usePlayerData();
|
||||||
@@ -64,12 +66,10 @@ export function MpvPlayer() {
|
|||||||
[isTransitioning],
|
[isTransitioning],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onProgress = useCallback(
|
const onProgress = useCallback(() => {
|
||||||
(e: PlayerOnProgressProps) => {
|
// Progress callback is now only used for transition logic
|
||||||
setTimestamp(Number(e.playedSeconds.toFixed(0)));
|
// Timestamp updates are handled separately in useEffect
|
||||||
},
|
}, []);
|
||||||
[setTimestamp],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleOnEnded = useCallback(() => {
|
const handleOnEnded = useCallback(() => {
|
||||||
// When mpv auto-advances to the next song (position 1 becomes position 0),
|
// When mpv auto-advances to the next song (position 1 becomes position 0),
|
||||||
@@ -107,6 +107,29 @@ export function MpvPlayer() {
|
|||||||
[volume, isTransitioning, fadeAndSetStatus],
|
[volume, isTransitioning, fadeAndSetStatus],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (localPlayerStatus !== PlayerStatus.PLAYING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const interval = setInterval(async () => {
|
||||||
|
if (!mpvPlayer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const time = await mpvPlayer.getCurrentTime();
|
||||||
|
if (time !== undefined) {
|
||||||
|
setTimestamp(Number(time.toFixed(0)));
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, [localPlayerStatus, setTimestamp]);
|
||||||
|
|
||||||
useMainPlayerListener();
|
useMainPlayerListener();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { Dispatch } from 'react';
|
import type { Dispatch } from 'react';
|
||||||
import type ReactPlayer from 'react-player';
|
import type ReactPlayer from 'react-player';
|
||||||
|
|
||||||
import { useCallback, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
WebPlayerEngine,
|
WebPlayerEngine,
|
||||||
@@ -23,7 +23,7 @@ const PLAY_PAUSE_FADE_DURATION = 300;
|
|||||||
const PLAY_PAUSE_FADE_INTERVAL = 10;
|
const PLAY_PAUSE_FADE_INTERVAL = 10;
|
||||||
|
|
||||||
export function WebPlayer() {
|
export function WebPlayer() {
|
||||||
const playerRef = useRef<WebPlayerEngineHandle>(null);
|
const playerRef = useRef<null | WebPlayerEngineHandle>(null);
|
||||||
const { num, player1, player2, status } = usePlayerData();
|
const { num, player1, player2, status } = usePlayerData();
|
||||||
const { mediaAutoNext, setTimestamp } = usePlayerActions();
|
const { mediaAutoNext, setTimestamp } = usePlayerActions();
|
||||||
const { crossfadeDuration, speed, transitionType } = usePlayerProperties();
|
const { crossfadeDuration, speed, transitionType } = usePlayerProperties();
|
||||||
@@ -71,12 +71,6 @@ export function WebPlayer() {
|
|||||||
|
|
||||||
const onProgressPlayer1 = useCallback(
|
const onProgressPlayer1 = useCallback(
|
||||||
(e: PlayerOnProgressProps) => {
|
(e: PlayerOnProgressProps) => {
|
||||||
if (transitionType === 'crossfade' && num === 1) {
|
|
||||||
setTimestamp(Number(e.playedSeconds.toFixed(0)));
|
|
||||||
} else if (transitionType === 'gapless') {
|
|
||||||
setTimestamp(Number(e.playedSeconds.toFixed(0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!playerRef.current?.player1()) {
|
if (!playerRef.current?.player1()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -108,17 +102,11 @@ export function WebPlayer() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[crossfadeDuration, isTransitioning, num, setTimestamp, transitionType, volume],
|
[crossfadeDuration, isTransitioning, num, transitionType, volume],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onProgressPlayer2 = useCallback(
|
const onProgressPlayer2 = useCallback(
|
||||||
(e: PlayerOnProgressProps) => {
|
(e: PlayerOnProgressProps) => {
|
||||||
if (transitionType === PlayerStyle.CROSSFADE && num === 2) {
|
|
||||||
setTimestamp(Number(e.playedSeconds.toFixed(0)));
|
|
||||||
} else if (transitionType === PlayerStyle.GAPLESS) {
|
|
||||||
setTimestamp(Number(e.playedSeconds.toFixed(0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!playerRef.current?.player2()) {
|
if (!playerRef.current?.player2()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -150,7 +138,7 @@ export function WebPlayer() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[crossfadeDuration, isTransitioning, num, setTimestamp, transitionType, volume],
|
[crossfadeDuration, isTransitioning, num, transitionType, volume],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleOnEndedPlayer1 = useCallback(() => {
|
const handleOnEndedPlayer1 = useCallback(() => {
|
||||||
@@ -205,6 +193,34 @@ export function WebPlayer() {
|
|||||||
[volume, num, isTransitioning],
|
[volume, num, isTransitioning],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (localPlayerStatus !== PlayerStatus.PLAYING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
const activePlayer =
|
||||||
|
num === 1 ? playerRef.current?.player1() : playerRef.current?.player2();
|
||||||
|
const internalPlayer =
|
||||||
|
activePlayer?.ref?.getInternalPlayer() as HTMLAudioElement | null;
|
||||||
|
|
||||||
|
if (!internalPlayer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentTime = internalPlayer.currentTime;
|
||||||
|
|
||||||
|
if (
|
||||||
|
transitionType === PlayerStyle.CROSSFADE ||
|
||||||
|
transitionType === PlayerStyle.GAPLESS
|
||||||
|
) {
|
||||||
|
setTimestamp(Number(currentTime.toFixed(0)));
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, [localPlayerStatus, num, setTimestamp, transitionType]);
|
||||||
|
|
||||||
useMainPlayerListener();
|
useMainPlayerListener();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user