From 0b70ed158b2ea30264d9fbe53887787a25178489 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sat, 29 Nov 2025 21:35:09 -0800 Subject: [PATCH] fix mpris --- src/main/features/linux/mpris.ts | 2 +- src/preload/mpris.ts | 44 ++++++++++--- .../player/audio-player/mpv-player.tsx | 2 - .../player/audio-player/wavesurfer-player.tsx | 2 - .../player/audio-player/web-player.tsx | 3 - .../player/components/audio-players.tsx | 2 + .../features/player/hooks/use-mpris.ts | 61 +++++++++++++++++-- 7 files changed, 94 insertions(+), 22 deletions(-) diff --git a/src/main/features/linux/mpris.ts b/src/main/features/linux/mpris.ts index 48d0816d5..85a0fd4ea 100644 --- a/src/main/features/linux/mpris.ts +++ b/src/main/features/linux/mpris.ts @@ -115,7 +115,7 @@ ipcMain.on('update-position', (_event, arg: number) => { mprisPlayer.getPosition = () => arg * 1e6; }); -ipcMain.on('mpris-update-seek', (_event, arg) => { +ipcMain.on('update-seek', (_event, arg) => { mprisPlayer.seeked(arg * 1e6); }); diff --git a/src/preload/mpris.ts b/src/preload/mpris.ts index 4d8602207..9cb98e040 100644 --- a/src/preload/mpris.ts +++ b/src/preload/mpris.ts @@ -1,21 +1,42 @@ import { ipcRenderer, IpcRendererEvent } from 'electron'; -import { PlayerRepeat } from '/@/shared/types/types'; +import { QueueSong } from '/@/shared/types/domain-types'; +import { PlayerRepeat, PlayerStatus } from '/@/shared/types/types'; const updatePosition = (timeSec: number) => { - ipcRenderer.send('mpris-update-position', timeSec); + ipcRenderer.send('update-position', timeSec); }; const updateSeek = (timeSec: number) => { - ipcRenderer.send('mpris-update-seek', timeSec); + ipcRenderer.send('update-seek', timeSec); }; -const toggleRepeat = () => { - ipcRenderer.send('mpris-toggle-repeat'); +const updateVolume = (volume: number) => { + ipcRenderer.send('update-volume', volume); }; -const toggleShuffle = () => { - ipcRenderer.send('mpris-toggle-shuffle'); +const updateStatus = (status: PlayerStatus) => { + ipcRenderer.send('update-playback', status); +}; + +const updateRepeat = (repeat: PlayerRepeat) => { + ipcRenderer.send('update-repeat', repeat); +}; + +const updateShuffle = (shuffle: boolean) => { + ipcRenderer.send('update-shuffle', shuffle); +}; + +const updateSong = (song: QueueSong | undefined) => { + ipcRenderer.send('update-song', song); +}; + +const requestSeek = (cb: (event: IpcRendererEvent, data: { offset: number }) => void) => { + ipcRenderer.on('request-seek', cb); +}; + +const requestPosition = (cb: (event: IpcRendererEvent, data: { position: number }) => void) => { + ipcRenderer.on('request-position', cb); }; const requestToggleRepeat = ( @@ -31,12 +52,17 @@ const requestToggleShuffle = ( }; export const mpris = { + requestPosition, + requestSeek, requestToggleRepeat, requestToggleShuffle, - toggleRepeat, - toggleShuffle, updatePosition, + updateRepeat, updateSeek, + updateShuffle, + updateSong, + updateStatus, + updateVolume, }; export type Mpris = typeof mpris; diff --git a/src/renderer/features/player/audio-player/mpv-player.tsx b/src/renderer/features/player/audio-player/mpv-player.tsx index 438fa70f4..d4a5a0772 100644 --- a/src/renderer/features/player/audio-player/mpv-player.tsx +++ b/src/renderer/features/player/audio-player/mpv-player.tsx @@ -133,8 +133,6 @@ export function MpvPlayer() { return () => clearInterval(interval); }, [localPlayerStatus, setTimestamp]); - useMainPlayerListener(); - const currentUrl = useSongUrl(currentSong, true, transcode); const nextUrl = useSongUrl(nextSong, false, transcode); diff --git a/src/renderer/features/player/audio-player/wavesurfer-player.tsx b/src/renderer/features/player/audio-player/wavesurfer-player.tsx index 1d2e686dd..5ed9f7b35 100644 --- a/src/renderer/features/player/audio-player/wavesurfer-player.tsx +++ b/src/renderer/features/player/audio-player/wavesurfer-player.tsx @@ -230,8 +230,6 @@ export function WaveSurferPlayer() { return () => clearInterval(interval); }, [localPlayerStatus, num, setTimestamp, transitionType]); - useMainPlayerListener(); - const player1Url = useSongUrl(player1, num === 1, transcode); const player2Url = useSongUrl(player2, num === 2, transcode); diff --git a/src/renderer/features/player/audio-player/web-player.tsx b/src/renderer/features/player/audio-player/web-player.tsx index 38108b13a..0ab70fdbd 100644 --- a/src/renderer/features/player/audio-player/web-player.tsx +++ b/src/renderer/features/player/audio-player/web-player.tsx @@ -7,7 +7,6 @@ import { WebPlayerEngine, WebPlayerEngineHandle, } from '/@/renderer/features/player/audio-player/engine/web-player-engine'; -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 { useSongUrl } from '/@/renderer/features/player/audio-player/hooks/use-stream-url'; import { PlayerOnProgressProps } from '/@/renderer/features/player/audio-player/types'; @@ -262,8 +261,6 @@ export function WebPlayer() { return () => clearInterval(interval); }, [localPlayerStatus, num, setTimestamp, transitionType]); - useMainPlayerListener(); - const player1Url = useSongUrl(player1, num === 1, transcode); const player2Url = useSongUrl(player2, num === 2, transcode); diff --git a/src/renderer/features/player/components/audio-players.tsx b/src/renderer/features/player/components/audio-players.tsx index 5934c03e8..2a1f7a080 100644 --- a/src/renderer/features/player/components/audio-players.tsx +++ b/src/renderer/features/player/components/audio-players.tsx @@ -3,6 +3,7 @@ import { useEffect } from 'react'; import { eventEmitter } from '/@/renderer/events/event-emitter'; import { UserFavoriteEventPayload, UserRatingEventPayload } from '/@/renderer/events/events'; import { useDiscordRpc } from '/@/renderer/features/discord-rpc/use-discord-rpc'; +import { useMainPlayerListener } from '/@/renderer/features/player/audio-player/hooks/use-main-player-listener'; import { MpvPlayer } from '/@/renderer/features/player/audio-player/mpv-player'; import { WebPlayer } from '/@/renderer/features/player/audio-player/web-player'; import { useMediaSession } from '/@/renderer/features/player/hooks/use-media-session'; @@ -26,6 +27,7 @@ export const AudioPlayers = () => { usePowerSaveBlocker(); useDiscordRpc(); useMPRIS(); + useMainPlayerListener(); useMediaSession(); // Listen to favorite and rating events to update queue songs diff --git a/src/renderer/features/player/hooks/use-mpris.ts b/src/renderer/features/player/hooks/use-mpris.ts index 43d61e868..11b2f6f97 100644 --- a/src/renderer/features/player/hooks/use-mpris.ts +++ b/src/renderer/features/player/hooks/use-mpris.ts @@ -1,8 +1,9 @@ import isElectron from 'is-electron'; -import { useEffect } from 'react'; +import { useEffect, useRef } from 'react'; import { usePlayerEvents } from '/@/renderer/features/player/audio-player/hooks/use-player-events'; import { usePlayerStore } from '/@/renderer/store'; +import { PlayerShuffle } from '/@/shared/types/types'; const ipc = isElectron() ? window.api.ipc : null; const utils = isElectron() ? window.api.utils : null; @@ -16,6 +17,14 @@ export const useMPRIS = () => { return; } + mpris?.requestPosition((_e: unknown, data: { position: number }) => { + player.mediaSeekToTimestamp(data.position); + }); + + mpris?.requestSeek((_e: unknown, data: { offset: number }) => { + player.mediaSkipForward(data.offset); + }); + mpris?.requestToggleRepeat(() => { player.toggleRepeat(); }); @@ -27,11 +36,38 @@ export const useMPRIS = () => { return () => { ipc?.removeAllListeners('mpris-request-toggle-repeat'); ipc?.removeAllListeners('mpris-request-toggle-shuffle'); + ipc?.removeAllListeners('request-position'); + ipc?.removeAllListeners('request-seek'); }; }, [player]); + const isInitializedRef = useRef(false); + + useEffect(() => { + if (isInitializedRef.current) { + return; + } + + isInitializedRef.current = true; + + const currentSong = player.getCurrentSong(); + + if (!currentSong) { + return; + } + + mpris?.updateSong(currentSong); + }, [player]); + usePlayerEvents( { + onCurrentSongChange: (properties) => { + if (!mpris) { + return; + } + + mpris?.updateSong(properties.song); + }, onPlayerProgress: (properties) => { if (!mpris) { return; @@ -40,12 +76,12 @@ export const useMPRIS = () => { const timestamp = properties.timestamp; mpris?.updatePosition(timestamp); }, - onPlayerRepeat: () => { + onPlayerRepeat: (properties) => { if (!mpris) { return; } - mpris?.toggleRepeat(); + mpris?.updateRepeat(properties.repeat); }, onPlayerSeek: (properties) => { if (!mpris) { @@ -55,12 +91,27 @@ export const useMPRIS = () => { const seconds = properties.seconds; mpris?.updateSeek(seconds); }, - onPlayerShuffle: () => { + onPlayerShuffle: (properties) => { if (!mpris) { return; } - mpris?.toggleShuffle(); + const isShuffleEnabled = properties.shuffle !== PlayerShuffle.NONE; + mpris?.updateShuffle(isShuffleEnabled); + }, + onPlayerStatus: (properties) => { + if (!mpris) { + return; + } + + mpris?.updateStatus(properties.status); + }, + onPlayerVolume: (properties) => { + if (!mpris) { + return; + } + + mpris?.updateVolume(properties.volume); }, }, [],