diff --git a/src/main/features/linux/mpris.ts b/src/main/features/linux/mpris.ts index 97b439c7..d027c8b9 100644 --- a/src/main/features/linux/mpris.ts +++ b/src/main/features/linux/mpris.ts @@ -130,7 +130,7 @@ ipcMain.on( } if (shuffle) { - mprisPlayer.shuffle = shuffle; + mprisPlayer.shuffle = shuffle !== 'none'; } if (!song) return; diff --git a/src/renderer/features/player/components/playerbar.tsx b/src/renderer/features/player/components/playerbar.tsx index 458f0c2e..8994de3c 100644 --- a/src/renderer/features/player/components/playerbar.tsx +++ b/src/renderer/features/player/components/playerbar.tsx @@ -7,6 +7,7 @@ import { AudioPlayer } from '/@/renderer/components'; import { useCurrentPlayer, useCurrentStatus, + useMuted, usePlayer1Data, usePlayer2Data, usePlayerControls, @@ -62,6 +63,7 @@ export const Playerbar = () => { const player2 = usePlayer2Data(); const status = useCurrentStatus(); const player = useCurrentPlayer(); + const muted = useMuted(); const { autoNext } = usePlayerControls(); const autoNextFn = useCallback(() => { @@ -92,7 +94,7 @@ export const Playerbar = () => { crossfadeDuration={settings.crossfadeDuration} crossfadeStyle={settings.crossfadeStyle} currentPlayer={player} - muted={settings.muted} + muted={muted} playbackStyle={settings.style} player1={player1} player2={player2} diff --git a/src/renderer/features/player/hooks/use-center-controls.ts b/src/renderer/features/player/hooks/use-center-controls.ts index 14aab3eb..4129b6ba 100644 --- a/src/renderer/features/player/hooks/use-center-controls.ts +++ b/src/renderer/features/player/hooks/use-center-controls.ts @@ -24,6 +24,7 @@ const mpvPlayerListener = isElectron() ? window.electron.mpvPlayerListener : nul const ipc = isElectron() ? window.electron.ipc : null; const utils = isElectron() ? window.electron.utils : null; const mpris = isElectron() && utils?.isLinux() ? window.electron.mpris : null; +const mediaSession = !isElectron() ? navigator.mediaSession : null; export const useCenterControls = (args: { playersRef: any }) => { const { playersRef } = args; @@ -77,16 +78,50 @@ export const useCenterControls = (args: { playersRef: any }) => { status?: PlayerStatus; }) => { const { song, currentTime, status } = args || {}; + + const time = currentTime || usePlayerStore.getState().current.time; + const playStatus = status || usePlayerStore.getState().current.status; + const track = song || usePlayerStore.getState().current.song; + mpris?.updateSong({ - currentTime: currentTime || usePlayerStore.getState().current.time, + currentTime: time, repeat: usePlayerStore.getState().repeat, shuffle: usePlayerStore.getState().shuffle, - song: song || usePlayerStore.getState().current.song, - status: - (status || usePlayerStore.getState().current.status) === PlayerStatus.PLAYING - ? 'Playing' - : 'Paused', + song: track, + status: playStatus === PlayerStatus.PLAYING ? 'Playing' : 'Paused', }); + + if (mediaSession) { + mediaSession.playbackState = playStatus === PlayerStatus.PLAYING ? 'playing' : 'paused'; + + let metadata: MediaMetadata; + + if (track) { + let artwork: MediaImage[]; + + if (track.imageUrl) { + const image300 = track.imageUrl + ?.replace(/&size=\d+/, '&size=300') + .replace(/\?width=\d+/, '?width=300') + .replace(/&height=\d+/, '&height=300'); + + artwork = [{ sizes: '300x300', src: image300, type: 'image/png' }]; + } else { + artwork = []; + } + + metadata = new MediaMetadata({ + album: track.album ?? '', + artist: track.artistName, + artwork, + title: track.name, + }); + } else { + metadata = new MediaMetadata(); + } + + mediaSession.metadata = metadata; + } }; const handlePlay = useCallback(() => { @@ -626,6 +661,57 @@ export const useCenterControls = (args: { playersRef: any }) => { setCurrentTime, ]); + useEffect(() => { + if (!isElectron() && mediaSession) { + mediaSession.setActionHandler('nexttrack', () => { + handleNextTrack(); + }); + + mediaSession.setActionHandler('pause', () => { + handlePause(); + }); + + mediaSession.setActionHandler('play', () => { + handlePlay(); + }); + + mediaSession.setActionHandler('previoustrack', () => { + handlePrevTrack(); + }); + + mediaSession.setActionHandler('seekto', (evt) => { + const time = evt.seekTime; + + if (time !== undefined) { + handleSeekSlider(time); + } + }); + + mediaSession.setActionHandler('stop', () => { + handleStop(); + }); + + return () => { + mediaSession.setActionHandler('nexttrack', null); + mediaSession.setActionHandler('pause', null); + mediaSession.setActionHandler('play', null); + mediaSession.setActionHandler('previoustrack', null); + mediaSession.setActionHandler('seekto', null); + mediaSession.setActionHandler('stop', null); + }; + } + + return () => {}; + }, [ + handleNextTrack, + handlePause, + handlePlay, + handlePrevTrack, + handleSeekSlider, + handleStop, + setCurrentTime, + ]); + useEffect(() => { if (utils?.isLinux()) { const unsubCurrentTime = usePlayerStore.subscribe( @@ -668,10 +754,8 @@ export const useCenterControls = (args: { playersRef: any }) => { }); mpris.requestVolume((_e: any, data: { volume: number }) => { - const currentVolume = usePlayerStore.getState().volume; - const resultingVolume = data.volume + currentVolume; + let newVolume = data.volume * 100; - let newVolume = resultingVolume; if (newVolume > 100) { newVolume = 100; } else if (newVolume < 0) { diff --git a/src/renderer/features/player/hooks/use-right-controls.ts b/src/renderer/features/player/hooks/use-right-controls.ts index a307e1a1..ceb1c142 100644 --- a/src/renderer/features/player/hooks/use-right-controls.ts +++ b/src/renderer/features/player/hooks/use-right-controls.ts @@ -6,6 +6,8 @@ import { useGeneralSettings } from '/@/renderer/store/settings.store'; const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null; const mpvPlayerListener = isElectron() ? window.electron.mpvPlayerListener : null; const ipc = isElectron() ? window.electron.ipc : null; +const utils = isElectron() ? window.electron.utils : null; +const mpris = isElectron() && utils?.isLinux() ? window.electron.mpris : null; const calculateVolumeUp = (volume: number, volumeWheelStep: number) => { let volumeToSet; @@ -41,6 +43,7 @@ export const useRightControls = () => { useEffect(() => { if (isElectron()) { mpvPlayer.volume(volume); + mpris?.updateVolume(volume / 100); if (muted) { mpvPlayer.mute(); @@ -52,22 +55,26 @@ export const useRightControls = () => { const handleVolumeSlider = (e: number) => { mpvPlayer?.volume(e); + mpris?.updateVolume(e / 100); setVolume(e); }; const handleVolumeSliderState = (e: number) => { + mpris?.updateVolume(e / 100); setVolume(e); }; const handleVolumeDown = useCallback(() => { const volumeToSet = calculateVolumeDown(volume, volumeWheelStep); mpvPlayer?.volume(volumeToSet); + mpris?.updateVolume(volumeToSet / 100); setVolume(volumeToSet); }, [setVolume, volume, volumeWheelStep]); const handleVolumeUp = useCallback(() => { const volumeToSet = calculateVolumeUp(volume, volumeWheelStep); mpvPlayer?.volume(volumeToSet); + mpris?.updateVolume(volumeToSet / 100); setVolume(volumeToSet); }, [setVolume, volume, volumeWheelStep]); @@ -81,6 +88,7 @@ export const useRightControls = () => { } mpvPlayer?.volume(volumeToSet); + mpris?.updateVolume(volumeToSet / 100); setVolume(volumeToSet); }, [setVolume, volume, volumeWheelStep],