mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-07 04:20:12 +02:00
fix mpv autoNext and next song replacement behavior
This commit is contained in:
@@ -224,11 +224,7 @@ export const MpvPlayerEngine = (props: MpvPlayerEngineProps) => {
|
||||
|
||||
const handleOnAutoNext = () => {
|
||||
mediaAutoNext();
|
||||
const playerData = usePlayerStore.getState().getPlayerData();
|
||||
const nextSongUrl = playerData.nextSong
|
||||
? getSongUrl(playerData.nextSong, transcode)
|
||||
: undefined;
|
||||
mpvPlayer?.setQueueNext(nextSongUrl);
|
||||
handleMpvAutoNext(transcode);
|
||||
};
|
||||
|
||||
mpvPlayerListener.rendererAutoNext(handleOnAutoNext);
|
||||
@@ -241,37 +237,20 @@ export const MpvPlayerEngine = (props: MpvPlayerEngineProps) => {
|
||||
usePlayerEvents(
|
||||
{
|
||||
onMediaNext: () => {
|
||||
const playerData = usePlayerStore.getState().getPlayerData();
|
||||
const currentSongUrl = playerData.currentSong
|
||||
? getSongUrl(playerData.currentSong, transcode)
|
||||
: undefined;
|
||||
const nextSongUrl = playerData.nextSong
|
||||
? getSongUrl(playerData.nextSong, transcode)
|
||||
: undefined;
|
||||
mpvPlayer?.setQueue(currentSongUrl, nextSongUrl, false);
|
||||
replaceMpvQueue(transcode);
|
||||
},
|
||||
onMediaPrev: () => {
|
||||
const playerData = usePlayerStore.getState().getPlayerData();
|
||||
const currentSongUrl = playerData.currentSong
|
||||
? getSongUrl(playerData.currentSong, transcode)
|
||||
: undefined;
|
||||
const nextSongUrl = playerData.nextSong
|
||||
? getSongUrl(playerData.nextSong, transcode)
|
||||
: undefined;
|
||||
mpvPlayer?.setQueue(currentSongUrl, nextSongUrl, false);
|
||||
replaceMpvQueue(transcode);
|
||||
},
|
||||
onNextSongInsertion: (song) => {
|
||||
const nextSongUrl = song ? getSongUrl(song, transcode) : undefined;
|
||||
mpvPlayer?.setQueueNext(nextSongUrl);
|
||||
},
|
||||
onPlayerPlay: () => {
|
||||
const playerData = usePlayerStore.getState().getPlayerData();
|
||||
const currentSongUrl = playerData.currentSong
|
||||
? getSongUrl(playerData.currentSong, transcode)
|
||||
: undefined;
|
||||
const nextSongUrl = playerData.nextSong
|
||||
? getSongUrl(playerData.nextSong, transcode)
|
||||
: undefined;
|
||||
mpvPlayer?.setQueue(currentSongUrl, nextSongUrl, false);
|
||||
replaceMpvQueue(transcode);
|
||||
},
|
||||
},
|
||||
[mpvPlayer, transcode],
|
||||
[transcode],
|
||||
);
|
||||
|
||||
useImperativeHandle<MpvPlayerEngineHandle, MpvPlayerEngineHandle>(playerRef, () => ({
|
||||
@@ -317,3 +296,30 @@ export const MpvPlayerEngine = (props: MpvPlayerEngineProps) => {
|
||||
};
|
||||
|
||||
MpvPlayerEngine.displayName = 'MpvPlayerEngine';
|
||||
|
||||
function handleMpvAutoNext(transcode: {
|
||||
bitrate?: number | undefined;
|
||||
enabled: boolean;
|
||||
format?: string | undefined;
|
||||
}) {
|
||||
const playerData = usePlayerStore.getState().getPlayerData();
|
||||
const nextSongUrl = playerData.nextSong
|
||||
? getSongUrl(playerData.nextSong, transcode)
|
||||
: undefined;
|
||||
mpvPlayer?.autoNext(nextSongUrl);
|
||||
}
|
||||
|
||||
function replaceMpvQueue(transcode: {
|
||||
bitrate?: number | undefined;
|
||||
enabled: boolean;
|
||||
format?: string | undefined;
|
||||
}) {
|
||||
const playerData = usePlayerStore.getState().getPlayerData();
|
||||
const currentSongUrl = playerData.currentSong
|
||||
? getSongUrl(playerData.currentSong, transcode)
|
||||
: undefined;
|
||||
const nextSongUrl = playerData.nextSong
|
||||
? getSongUrl(playerData.nextSong, transcode)
|
||||
: undefined;
|
||||
mpvPlayer?.setQueue(currentSongUrl, nextSongUrl, false);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useEffect } from 'react';
|
||||
import { eventEmitter } from '/@/renderer/events/event-emitter';
|
||||
import {
|
||||
subscribeCurrentTrack,
|
||||
subscribeNextSongInsertion,
|
||||
subscribePlayerMute,
|
||||
subscribePlayerProgress,
|
||||
subscribePlayerQueue,
|
||||
@@ -27,6 +28,7 @@ interface PlayerEventsCallbacks {
|
||||
) => void;
|
||||
onMediaNext?: (properties: { currentIndex: number; nextIndex: number }) => void;
|
||||
onMediaPrev?: (properties: { currentIndex: number; prevIndex: number }) => void;
|
||||
onNextSongInsertion?: (song: QueueSong | undefined) => void;
|
||||
onPlayerMute?: (properties: { muted: boolean }, prev: { muted: boolean }) => void;
|
||||
onPlayerPlay?: (properties: { id: string; index: number }) => void;
|
||||
onPlayerProgress?: (properties: { timestamp: number }, prev: { timestamp: number }) => void;
|
||||
@@ -78,6 +80,12 @@ function createPlayerEvents(callbacks: PlayerEventsCallbacks): PlayerEvents {
|
||||
unsubscribers.push(unsubscribe);
|
||||
}
|
||||
|
||||
// Subscribe to next song insertions (when a song is added at next position)
|
||||
if (callbacks.onNextSongInsertion) {
|
||||
const unsubscribe = subscribeNextSongInsertion(callbacks.onNextSongInsertion);
|
||||
unsubscribers.push(unsubscribe);
|
||||
}
|
||||
|
||||
// Subscribe to player progress
|
||||
if (callbacks.onPlayerProgress) {
|
||||
const unsubscribe = subscribePlayerProgress(callbacks.onPlayerProgress);
|
||||
|
||||
@@ -2383,6 +2383,59 @@ export const subscribeCurrentTrack = (
|
||||
);
|
||||
};
|
||||
|
||||
export const subscribeNextSong = (
|
||||
onChange: (
|
||||
properties: { index: number; song: QueueSong | undefined },
|
||||
prev: { index: number; song: QueueSong | undefined },
|
||||
) => void,
|
||||
) => {
|
||||
return usePlayerStoreBase.subscribe(
|
||||
(state) => {
|
||||
const queue = state.getQueue();
|
||||
let queueIndex = state.player.index;
|
||||
const repeat = state.player.repeat;
|
||||
|
||||
// If shuffle is enabled and not in priority mode, map shuffled position to actual queue position
|
||||
if (isShuffleEnabled(state)) {
|
||||
queueIndex = mapShuffledToQueueIndex(queueIndex, state.queue.shuffled);
|
||||
}
|
||||
|
||||
// Calculate next song based on shuffle and repeat settings
|
||||
let nextSong: QueueSong | undefined;
|
||||
if (isShuffleEnabled(state)) {
|
||||
// Calculate next in shuffled order
|
||||
const nextShuffledIndex = state.player.index + 1;
|
||||
if (nextShuffledIndex < state.queue.shuffled.length) {
|
||||
const nextQueueIndex = state.queue.shuffled[nextShuffledIndex];
|
||||
nextSong = queue.items[nextQueueIndex];
|
||||
} else if (repeat === PlayerRepeat.ALL) {
|
||||
// Wrap to first in shuffled order
|
||||
const firstQueueIndex = state.queue.shuffled[0];
|
||||
nextSong = queue.items[firstQueueIndex];
|
||||
}
|
||||
} else {
|
||||
nextSong = calculateNextSong(queueIndex, queue.items, repeat);
|
||||
}
|
||||
|
||||
// Calculate the index for the next song
|
||||
let nextIndex: number | undefined;
|
||||
if (nextSong) {
|
||||
nextIndex = queue.items.findIndex((item) => item._uniqueId === nextSong?._uniqueId);
|
||||
}
|
||||
|
||||
return { index: nextIndex ?? -1, song: nextSong };
|
||||
},
|
||||
(nextSong, prevNextSong) => {
|
||||
onChange(nextSong, prevNextSong);
|
||||
},
|
||||
{
|
||||
equalityFn: (a, b) => {
|
||||
return a.song?._uniqueId === b.song?._uniqueId;
|
||||
},
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export const subscribePlayerVolume = (
|
||||
onChange: (properties: { volume: number }, prev: { volume: number }) => void,
|
||||
) => {
|
||||
|
||||
Reference in New Issue
Block a user