mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-10 04:30:25 +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 = () => {
|
const handleOnAutoNext = () => {
|
||||||
mediaAutoNext();
|
mediaAutoNext();
|
||||||
const playerData = usePlayerStore.getState().getPlayerData();
|
handleMpvAutoNext(transcode);
|
||||||
const nextSongUrl = playerData.nextSong
|
|
||||||
? getSongUrl(playerData.nextSong, transcode)
|
|
||||||
: undefined;
|
|
||||||
mpvPlayer?.setQueueNext(nextSongUrl);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mpvPlayerListener.rendererAutoNext(handleOnAutoNext);
|
mpvPlayerListener.rendererAutoNext(handleOnAutoNext);
|
||||||
@@ -241,37 +237,20 @@ export const MpvPlayerEngine = (props: MpvPlayerEngineProps) => {
|
|||||||
usePlayerEvents(
|
usePlayerEvents(
|
||||||
{
|
{
|
||||||
onMediaNext: () => {
|
onMediaNext: () => {
|
||||||
const playerData = usePlayerStore.getState().getPlayerData();
|
replaceMpvQueue(transcode);
|
||||||
const currentSongUrl = playerData.currentSong
|
|
||||||
? getSongUrl(playerData.currentSong, transcode)
|
|
||||||
: undefined;
|
|
||||||
const nextSongUrl = playerData.nextSong
|
|
||||||
? getSongUrl(playerData.nextSong, transcode)
|
|
||||||
: undefined;
|
|
||||||
mpvPlayer?.setQueue(currentSongUrl, nextSongUrl, false);
|
|
||||||
},
|
},
|
||||||
onMediaPrev: () => {
|
onMediaPrev: () => {
|
||||||
const playerData = usePlayerStore.getState().getPlayerData();
|
replaceMpvQueue(transcode);
|
||||||
const currentSongUrl = playerData.currentSong
|
},
|
||||||
? getSongUrl(playerData.currentSong, transcode)
|
onNextSongInsertion: (song) => {
|
||||||
: undefined;
|
const nextSongUrl = song ? getSongUrl(song, transcode) : undefined;
|
||||||
const nextSongUrl = playerData.nextSong
|
mpvPlayer?.setQueueNext(nextSongUrl);
|
||||||
? getSongUrl(playerData.nextSong, transcode)
|
|
||||||
: undefined;
|
|
||||||
mpvPlayer?.setQueue(currentSongUrl, nextSongUrl, false);
|
|
||||||
},
|
},
|
||||||
onPlayerPlay: () => {
|
onPlayerPlay: () => {
|
||||||
const playerData = usePlayerStore.getState().getPlayerData();
|
replaceMpvQueue(transcode);
|
||||||
const currentSongUrl = playerData.currentSong
|
|
||||||
? getSongUrl(playerData.currentSong, transcode)
|
|
||||||
: undefined;
|
|
||||||
const nextSongUrl = playerData.nextSong
|
|
||||||
? getSongUrl(playerData.nextSong, transcode)
|
|
||||||
: undefined;
|
|
||||||
mpvPlayer?.setQueue(currentSongUrl, nextSongUrl, false);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[mpvPlayer, transcode],
|
[transcode],
|
||||||
);
|
);
|
||||||
|
|
||||||
useImperativeHandle<MpvPlayerEngineHandle, MpvPlayerEngineHandle>(playerRef, () => ({
|
useImperativeHandle<MpvPlayerEngineHandle, MpvPlayerEngineHandle>(playerRef, () => ({
|
||||||
@@ -317,3 +296,30 @@ export const MpvPlayerEngine = (props: MpvPlayerEngineProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
MpvPlayerEngine.displayName = 'MpvPlayerEngine';
|
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 { eventEmitter } from '/@/renderer/events/event-emitter';
|
||||||
import {
|
import {
|
||||||
subscribeCurrentTrack,
|
subscribeCurrentTrack,
|
||||||
|
subscribeNextSongInsertion,
|
||||||
subscribePlayerMute,
|
subscribePlayerMute,
|
||||||
subscribePlayerProgress,
|
subscribePlayerProgress,
|
||||||
subscribePlayerQueue,
|
subscribePlayerQueue,
|
||||||
@@ -27,6 +28,7 @@ interface PlayerEventsCallbacks {
|
|||||||
) => void;
|
) => void;
|
||||||
onMediaNext?: (properties: { currentIndex: number; nextIndex: number }) => void;
|
onMediaNext?: (properties: { currentIndex: number; nextIndex: number }) => void;
|
||||||
onMediaPrev?: (properties: { currentIndex: number; prevIndex: number }) => void;
|
onMediaPrev?: (properties: { currentIndex: number; prevIndex: number }) => void;
|
||||||
|
onNextSongInsertion?: (song: QueueSong | undefined) => void;
|
||||||
onPlayerMute?: (properties: { muted: boolean }, prev: { muted: boolean }) => void;
|
onPlayerMute?: (properties: { muted: boolean }, prev: { muted: boolean }) => void;
|
||||||
onPlayerPlay?: (properties: { id: string; index: number }) => void;
|
onPlayerPlay?: (properties: { id: string; index: number }) => void;
|
||||||
onPlayerProgress?: (properties: { timestamp: number }, prev: { timestamp: number }) => void;
|
onPlayerProgress?: (properties: { timestamp: number }, prev: { timestamp: number }) => void;
|
||||||
@@ -78,6 +80,12 @@ function createPlayerEvents(callbacks: PlayerEventsCallbacks): PlayerEvents {
|
|||||||
unsubscribers.push(unsubscribe);
|
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
|
// Subscribe to player progress
|
||||||
if (callbacks.onPlayerProgress) {
|
if (callbacks.onPlayerProgress) {
|
||||||
const unsubscribe = subscribePlayerProgress(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 = (
|
export const subscribePlayerVolume = (
|
||||||
onChange: (properties: { volume: number }, prev: { volume: number }) => void,
|
onChange: (properties: { volume: number }, prev: { volume: number }) => void,
|
||||||
) => {
|
) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user