fix duplicate PLAYER_PLAY event causing race condition in mpv

This commit is contained in:
jeffvli
2025-12-26 14:49:06 -08:00
parent dff182cbc5
commit e4b5cf36e1
+67 -142
View File
@@ -209,6 +209,68 @@ function calculateNextIndex(
}
}
function emitPlayerPlayEvent(
targetSongUniqueId: string | undefined,
set: (fn: (state: PlayerState) => void) => void,
get: () => PlayerState,
): void {
// If playSongId is provided, find the song and start playback on it
if (targetSongUniqueId) {
let playIndex: number | undefined;
set((state) => {
const queue = state.getQueue();
const queueIndex = queue.items.findIndex(
(item) => item._uniqueId === targetSongUniqueId,
);
if (queueIndex !== -1) {
if (
state.player.shuffle === PlayerShuffle.TRACK &&
state.queue.shuffled.length > 0
) {
// Find the shuffled position for this queue index
const shuffledPosition = state.queue.shuffled.findIndex(
(idx) => idx === queueIndex,
);
if (shuffledPosition !== -1) {
state.player.index = shuffledPosition;
playIndex = shuffledPosition;
} else {
state.player.index = queueIndex;
playIndex = queueIndex;
}
} else {
state.player.index = queueIndex;
playIndex = queueIndex;
}
state.player.status = PlayerStatus.PLAYING;
setTimestampStore(0);
}
});
// Emit PLAYER_PLAY event if playback was started
if (playIndex !== undefined) {
eventEmitter.emit('PLAYER_PLAY', {
id: targetSongUniqueId,
index: playIndex,
});
}
} else {
// Otherwise, emit PLAYER_PLAY event for current song if available
const currentState = get();
const queue = currentState.getQueue();
const currentIndex = currentState.player.index;
const currentSong = queue.items[currentIndex];
if (currentSong && currentIndex !== undefined && currentIndex >= 0) {
eventEmitter.emit('PLAYER_PLAY', {
id: currentSong._uniqueId,
index: currentIndex,
});
}
}
}
// Helper function to find shuffled position for a given queue index
function findShuffledPositionForQueueIndex(
queueIndex: number,
@@ -502,21 +564,7 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
}
});
const currentState = get();
const queue = currentState.getQueue();
const currentIndex = currentState.player.index;
const currentSong = queue.items[currentIndex];
if (
currentSong &&
currentIndex !== undefined &&
currentIndex >= 0
) {
eventEmitter.emit('PLAYER_PLAY', {
id: currentSong._uniqueId,
index: currentIndex,
});
}
emitPlayerPlayEvent(targetSongUniqueId, set, get);
break;
}
case Play.SHUFFLE: {
@@ -543,22 +591,7 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
}
});
// Emit PLAYER_PLAY event after state is updated
const currentState = get();
const queue = currentState.getQueue();
const currentIndex = currentState.player.index;
const currentSong = queue.items[currentIndex];
if (
currentSong &&
currentIndex !== undefined &&
currentIndex >= 0
) {
eventEmitter.emit('PLAYER_PLAY', {
id: currentSong._uniqueId,
index: currentIndex,
});
}
emitPlayerPlayEvent(targetSongUniqueId, set, get);
break;
}
}
@@ -802,21 +835,7 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
}
});
const currentState = get();
const queue = currentState.getQueue();
const currentIndex = currentState.player.index;
const currentSong = queue.items[currentIndex];
if (
currentSong &&
currentIndex !== undefined &&
currentIndex >= 0
) {
eventEmitter.emit('PLAYER_PLAY', {
id: currentSong._uniqueId,
index: currentIndex,
});
}
emitPlayerPlayEvent(targetSongUniqueId, set, get);
break;
}
case Play.SHUFFLE: {
@@ -846,66 +865,13 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
);
});
// Emit PLAYER_PLAY event after state is updated
const currentState = get();
const queue = currentState.getQueue();
const currentIndex = currentState.player.index;
const currentSong = queue.items[currentIndex];
if (currentSong && currentIndex !== undefined) {
eventEmitter.emit('PLAYER_PLAY', {
id: currentSong._uniqueId,
index: currentIndex,
});
}
emitPlayerPlayEvent(targetSongUniqueId, set, get);
break;
}
}
break;
}
}
// If playSongId is provided, find the song and start playback on it
if (targetSongUniqueId) {
let playIndex: number | undefined;
set((state) => {
const queue = state.getQueue();
const queueIndex = queue.items.findIndex(
(item) => item._uniqueId === targetSongUniqueId,
);
if (queueIndex !== -1) {
if (
state.player.shuffle === PlayerShuffle.TRACK &&
state.queue.shuffled.length > 0
) {
// Find the shuffled position for this queue index
const shuffledPosition = state.queue.shuffled.findIndex(
(idx) => idx === queueIndex,
);
if (shuffledPosition !== -1) {
state.player.index = shuffledPosition;
playIndex = shuffledPosition;
} else {
state.player.index = queueIndex;
playIndex = queueIndex;
}
} else {
state.player.index = queueIndex;
playIndex = queueIndex;
}
state.player.status = PlayerStatus.PLAYING;
setTimestampStore(0);
}
});
// Emit PLAYER_PLAY event if playback was started
if (playIndex !== undefined) {
eventEmitter.emit('PLAYER_PLAY', {
id: targetSongUniqueId,
index: playIndex,
});
}
}
},
addToQueueByUniqueId: (items, uniqueId, edge, playSongId) => {
const newItems = items.map(toQueueSong);
@@ -1099,48 +1065,7 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
}
});
// If playSongId is provided, find the song and start playback on it
if (targetSongUniqueId) {
let playIndex: number | undefined;
set((state) => {
const queue = state.getQueue();
const queueIndex = queue.items.findIndex(
(item) => item._uniqueId === targetSongUniqueId,
);
if (queueIndex !== -1) {
if (
state.player.shuffle === PlayerShuffle.TRACK &&
state.queue.shuffled.length > 0
) {
// Find the shuffled position for this queue index
const shuffledPosition = state.queue.shuffled.findIndex(
(idx) => idx === queueIndex,
);
if (shuffledPosition !== -1) {
state.player.index = shuffledPosition;
playIndex = shuffledPosition;
} else {
state.player.index = queueIndex;
playIndex = queueIndex;
}
} else {
state.player.index = queueIndex;
playIndex = queueIndex;
}
state.player.status = PlayerStatus.PLAYING;
setTimestampStore(0);
}
});
// Emit PLAYER_PLAY event if playback was started
if (playIndex !== undefined) {
eventEmitter.emit('PLAYER_PLAY', {
id: targetSongUniqueId,
index: playIndex,
});
}
}
emitPlayerPlayEvent(targetSongUniqueId, set, get);
},
clearQueue: () => {
set((state) => {