mirror of
https://github.com/jeffvli/feishin.git
synced 2026-06-11 06:42:38 +02:00
fix mpv player queue behavior to handle gapless playback
This commit is contained in:
@@ -5,6 +5,7 @@ import { immer } from 'zustand/middleware/immer';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { createWithEqualityFn } from 'zustand/traditional';
|
||||
|
||||
import { eventEmitter } from '/@/renderer/events/event-emitter';
|
||||
import { createSelectors } from '/@/renderer/lib/zustand';
|
||||
import { useSettingsStore } from '/@/renderer/store/settings.store';
|
||||
import {
|
||||
@@ -40,6 +41,7 @@ interface Actions {
|
||||
clearSelected: (items: QueueSong[]) => void;
|
||||
decreaseVolume: (value: number) => void;
|
||||
getCurrentSong: () => QueueSong | undefined;
|
||||
getPlayerData: () => PlayerData;
|
||||
getQueue: (groupBy?: QueueGroupingProperty) => GroupedQueue;
|
||||
getQueueOrder: () => {
|
||||
groups: { count: number; name: string }[];
|
||||
@@ -1130,6 +1132,74 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
|
||||
|
||||
return queue.items[index];
|
||||
},
|
||||
getPlayerData: () => {
|
||||
const state = get();
|
||||
const queue = state.getQueue();
|
||||
const index = state.player.index;
|
||||
|
||||
// If shuffle is enabled and not in priority mode, map shuffled position to actual queue position for display
|
||||
let queueIndex = index;
|
||||
if (isShuffleEnabled(state)) {
|
||||
queueIndex = mapShuffledToQueueIndex(index, state.queue.shuffled);
|
||||
}
|
||||
|
||||
const currentSong = queue.items[queueIndex];
|
||||
const repeat = state.player.repeat;
|
||||
|
||||
// For previousSong calculation, we need to consider the shuffled order (only if not in priority mode)
|
||||
let previousSong: QueueSong | undefined;
|
||||
if (isShuffleEnabled(state)) {
|
||||
// Calculate previous in shuffled order
|
||||
const previousShuffledIndex = index - 1;
|
||||
if (previousShuffledIndex >= 0) {
|
||||
const previousQueueIndex = state.queue.shuffled[previousShuffledIndex];
|
||||
previousSong = queue.items[previousQueueIndex];
|
||||
} else if (repeat === PlayerRepeat.ALL) {
|
||||
// Wrap to last in shuffled order
|
||||
const lastShuffledIndex = state.queue.shuffled.length - 1;
|
||||
const lastQueueIndex = state.queue.shuffled[lastShuffledIndex];
|
||||
previousSong = queue.items[lastQueueIndex];
|
||||
}
|
||||
} else {
|
||||
previousSong = queueIndex > 0 ? queue.items[queueIndex - 1] : undefined;
|
||||
}
|
||||
|
||||
// For nextSong calculation, we need to consider the shuffled order (only if not in priority mode)
|
||||
let nextSong: QueueSong | undefined;
|
||||
if (isShuffleEnabled(state)) {
|
||||
// Calculate next in shuffled order
|
||||
const nextShuffledIndex = 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);
|
||||
}
|
||||
|
||||
return {
|
||||
currentSong,
|
||||
index: queueIndex, // Return the actual queue position for display
|
||||
muted: state.player.muted,
|
||||
nextSong,
|
||||
num: state.player.playerNum,
|
||||
player1: state.player.playerNum === 1 ? currentSong : nextSong,
|
||||
player2: state.player.playerNum === 2 ? currentSong : nextSong,
|
||||
previousSong,
|
||||
queue: state.queue,
|
||||
queueLength: state.queue.default.length + state.queue.priority.length,
|
||||
repeat: state.player.repeat,
|
||||
shuffle: state.player.shuffle,
|
||||
speed: state.player.speed,
|
||||
status: state.player.status,
|
||||
transitionType: state.player.transitionType,
|
||||
volume: state.player.volume,
|
||||
};
|
||||
},
|
||||
getQueue: (groupBy?: QueueGroupingProperty) => {
|
||||
const queue = get().getQueueOrder();
|
||||
const queueType = getQueueType();
|
||||
@@ -1301,6 +1371,11 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
|
||||
state.player.playerNum = 1;
|
||||
setTimestampStore(0);
|
||||
});
|
||||
|
||||
eventEmitter.emit('MEDIA_NEXT', {
|
||||
currentIndex,
|
||||
nextIndex,
|
||||
});
|
||||
},
|
||||
mediaPause: () => {
|
||||
set((state) => {
|
||||
@@ -1308,6 +1383,8 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
|
||||
});
|
||||
},
|
||||
mediaPlay: (id?: string) => {
|
||||
let playIndex: number | undefined;
|
||||
|
||||
set((state) => {
|
||||
if (id) {
|
||||
const queue = state.getQueue();
|
||||
@@ -1328,11 +1405,14 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
|
||||
);
|
||||
if (shuffledPosition !== -1) {
|
||||
state.player.index = shuffledPosition;
|
||||
playIndex = shuffledPosition;
|
||||
} else {
|
||||
state.player.index = queueIndex;
|
||||
playIndex = queueIndex;
|
||||
}
|
||||
} else {
|
||||
state.player.index = queueIndex;
|
||||
playIndex = queueIndex;
|
||||
}
|
||||
setTimestampStore(0);
|
||||
}
|
||||
@@ -1340,8 +1420,18 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
|
||||
|
||||
state.player.status = PlayerStatus.PLAYING;
|
||||
});
|
||||
|
||||
if (id && playIndex !== undefined) {
|
||||
eventEmitter.emit('PLAYER_PLAY', {
|
||||
id,
|
||||
index: playIndex,
|
||||
});
|
||||
}
|
||||
},
|
||||
mediaPlayByIndex: (index: number) => {
|
||||
let playIndex: number | undefined;
|
||||
let songId: string | undefined;
|
||||
|
||||
set((state) => {
|
||||
const queue = state.getQueue();
|
||||
|
||||
@@ -1350,6 +1440,12 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the song's unique ID from the queue
|
||||
const song = queue.items[index];
|
||||
if (song) {
|
||||
songId = song._uniqueId;
|
||||
}
|
||||
|
||||
// index is the position in the original queue
|
||||
if (isShuffleEnabled(state)) {
|
||||
// Find the shuffled position for this queue index
|
||||
@@ -1357,15 +1453,23 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
|
||||
index,
|
||||
state.queue.shuffled,
|
||||
);
|
||||
state.player.index =
|
||||
shuffledPosition !== undefined ? shuffledPosition : index;
|
||||
playIndex = shuffledPosition !== undefined ? shuffledPosition : index;
|
||||
state.player.index = playIndex;
|
||||
} else {
|
||||
playIndex = index;
|
||||
state.player.index = index;
|
||||
}
|
||||
setTimestampStore(0);
|
||||
|
||||
state.player.status = PlayerStatus.PLAYING;
|
||||
});
|
||||
|
||||
if (songId && playIndex !== undefined) {
|
||||
eventEmitter.emit('PLAYER_PLAY', {
|
||||
id: songId,
|
||||
index: playIndex,
|
||||
});
|
||||
}
|
||||
},
|
||||
mediaPrevious: () => {
|
||||
const currentIndex = get().player.index;
|
||||
@@ -1400,6 +1504,11 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
|
||||
state.player.playerNum = 1;
|
||||
setTimestampStore(0);
|
||||
});
|
||||
|
||||
eventEmitter.emit('MEDIA_PREV', {
|
||||
currentIndex,
|
||||
prevIndex: previousIndex,
|
||||
});
|
||||
},
|
||||
mediaSeekToTimestamp: (timestamp: number) => {
|
||||
set((state) => {
|
||||
|
||||
Reference in New Issue
Block a user