simplify remote/media session (#632)

This commit is contained in:
Kendall Garner 2024-07-03 08:47:26 +00:00 committed by GitHub
parent d57b4b4b68
commit 110a1a63f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 236 additions and 230 deletions

View file

@ -1,5 +1,4 @@
import { useCallback } from 'react';
import isElectron from 'is-electron';
import styled from 'styled-components';
import { usePlaybackType, useSettingsStore } from '/@/renderer/store/settings.store';
import { PlaybackType } from '/@/renderer/types';
@ -17,6 +16,7 @@ import { CenterControls } from './center-controls';
import { LeftControls } from './left-controls';
import { RightControls } from './right-controls';
import { PlayersRef } from '/@/renderer/features/player/ref/players-ref';
import { updateSong } from '/@/renderer/features/player/update-remote-song';
const PlayerbarContainer = styled.div`
width: 100vw;
@ -59,8 +59,6 @@ const CenterGridItem = styled.div`
overflow: hidden;
`;
const remote = isElectron() ? window.electron.remote : null;
export const Playerbar = () => {
const playersRef = PlayersRef;
const settings = useSettingsStore((state) => state.playback);
@ -75,13 +73,7 @@ export const Playerbar = () => {
const autoNextFn = useCallback(() => {
const playerData = autoNext();
if (remote) {
remote.updateSong({
currentTime: 0,
song: playerData.current.song,
});
}
updateSong(playerData.current.song);
}, [autoNext]);
return (

View file

@ -14,9 +14,9 @@ import {
import { usePlaybackType } from '/@/renderer/store/settings.store';
import { useScrobble } from '/@/renderer/features/player/hooks/use-scrobble';
import debounce from 'lodash/debounce';
import { QueueSong } from '/@/renderer/api/types';
import { toast } from '/@/renderer/components';
import { useTranslation } from 'react-i18next';
import { updateSong } from '/@/renderer/features/player/update-remote-song';
const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null;
const mpvPlayerListener = isElectron() ? window.electron.mpvPlayerListener : null;
@ -24,7 +24,7 @@ const ipc = isElectron() ? window.electron.ipc : null;
const utils = isElectron() ? window.electron.utils : null;
const mpris = isElectron() && utils?.isLinux() ? window.electron.mpris : null;
const remote = isElectron() ? window.electron.remote : null;
const mediaSession = !isElectron() || !utils?.isLinux() ? navigator.mediaSession : null;
const mediaSession = navigator.mediaSession;
export const useCenterControls = (args: { playersRef: any }) => {
const { t } = useTranslation();
@ -46,6 +46,23 @@ export const useCenterControls = (args: { playersRef: any }) => {
const { handleScrobbleFromSongRestart, handleScrobbleFromSeek } = useScrobble();
useEffect(() => {
if (mediaSession) {
mediaSession.playbackState =
playerStatus === PlayerStatus.PLAYING ? 'playing' : 'paused';
}
remote?.updatePlayback(playerStatus);
}, [playerStatus]);
useEffect(() => {
remote?.updateRepeat(repeatStatus);
}, [repeatStatus]);
useEffect(() => {
remote?.updateShuffle(shuffleStatus !== PlayerShuffle.NONE);
}, [shuffleStatus]);
const resetPlayers = useCallback(() => {
if (player1Ref.getInternalPlayer()) {
player1Ref.getInternalPlayer().currentTime = 0;
@ -76,61 +93,7 @@ export const useCenterControls = (args: { playersRef: any }) => {
const isMpvPlayer = isElectron() && playbackType === PlaybackType.LOCAL;
const mprisUpdateSong = (args?: {
currentTime?: number;
song?: QueueSong;
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;
remote?.updateSong({
currentTime: time,
repeat: usePlayerStore.getState().repeat,
shuffle: usePlayerStore.getState().shuffle !== PlayerShuffle.NONE,
song: track,
status: playStatus,
});
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(() => {
mprisUpdateSong({ status: PlayerStatus.PLAYING });
if (isMpvPlayer) {
mpvPlayer?.volume(usePlayerStore.getState().volume);
mpvPlayer!.play();
@ -145,8 +108,6 @@ export const useCenterControls = (args: { playersRef: any }) => {
}, [currentPlayerRef, isMpvPlayer, play]);
const handlePause = useCallback(() => {
mprisUpdateSong({ status: PlayerStatus.PAUSED });
if (isMpvPlayer) {
mpvPlayer!.pause();
}
@ -155,8 +116,6 @@ export const useCenterControls = (args: { playersRef: any }) => {
}, [isMpvPlayer, pause]);
const handleStop = useCallback(() => {
mprisUpdateSong({ status: PlayerStatus.PAUSED });
if (isMpvPlayer) {
mpvPlayer!.pause();
mpvPlayer!.seekTo(0);
@ -212,13 +171,13 @@ export const useCenterControls = (args: { playersRef: any }) => {
const handleRepeatAll = {
local: () => {
const playerData = autoNext();
mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING });
updateSong(playerData.current.song);
mpvPlayer!.autoNext(playerData);
play();
},
web: () => {
const playerData = autoNext();
mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING });
updateSong(playerData.current.song);
},
};
@ -226,15 +185,12 @@ export const useCenterControls = (args: { playersRef: any }) => {
local: () => {
if (isLastTrack) {
const playerData = setCurrentIndex(0);
mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PAUSED });
updateSong(playerData.current.song);
mpvPlayer!.setQueue(playerData, true);
pause();
} else {
const playerData = autoNext();
mprisUpdateSong({
song: playerData.current.song,
status: PlayerStatus.PLAYING,
});
updateSong(playerData.current.song);
mpvPlayer!.autoNext(playerData);
play();
}
@ -242,14 +198,10 @@ export const useCenterControls = (args: { playersRef: any }) => {
web: () => {
if (isLastTrack) {
resetPlayers();
mprisUpdateSong({ status: PlayerStatus.PAUSED });
pause();
} else {
const playerData = autoNext();
mprisUpdateSong({
song: playerData.current.song,
status: PlayerStatus.PLAYING,
});
updateSong(playerData.current.song);
resetPlayers();
}
},
@ -258,20 +210,15 @@ export const useCenterControls = (args: { playersRef: any }) => {
const handleRepeatOne = {
local: () => {
const playerData = autoNext();
mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING });
updateSong(playerData.current.song);
mpvPlayer!.autoNext(playerData);
play();
},
web: () => {
if (isLastTrack) {
mprisUpdateSong({ status: PlayerStatus.PAUSED });
resetPlayers();
} else {
const playerData = autoNext();
mprisUpdateSong({
song: playerData.current.song,
status: PlayerStatus.PLAYING,
});
autoNext();
resetPlayers();
}
},
@ -309,12 +256,12 @@ export const useCenterControls = (args: { playersRef: any }) => {
const handleRepeatAll = {
local: () => {
const playerData = next();
mprisUpdateSong({ song: playerData.current.song });
updateSong(playerData.current.song);
mpvPlayer!.setQueue(playerData);
},
web: () => {
const playerData = next();
mprisUpdateSong({ song: playerData.current.song });
updateSong(playerData.current.song);
},
};
@ -322,27 +269,24 @@ export const useCenterControls = (args: { playersRef: any }) => {
local: () => {
if (isLastTrack) {
const playerData = setCurrentIndex(0);
mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PAUSED });
updateSong(playerData.current.song);
mpvPlayer!.setQueue(playerData, true);
pause();
} else {
const playerData = next();
mprisUpdateSong({ song: playerData.current.song });
updateSong(playerData.current.song);
mpvPlayer!.setQueue(playerData);
}
},
web: () => {
if (isLastTrack) {
const playerData = setCurrentIndex(0);
mprisUpdateSong({
song: playerData.current.song,
status: PlayerStatus.PAUSED,
});
updateSong(playerData.current.song);
resetPlayers();
pause();
} else {
const playerData = next();
mprisUpdateSong({ song: playerData.current.song });
updateSong(playerData.current.song);
resetPlayers();
}
},
@ -352,14 +296,14 @@ export const useCenterControls = (args: { playersRef: any }) => {
local: () => {
if (!isLastTrack) {
const playerData = next();
mprisUpdateSong({ song: playerData.current.song });
updateSong(playerData.current.song);
mpvPlayer!.setQueue(playerData);
}
},
web: () => {
if (!isLastTrack) {
const playerData = next();
mprisUpdateSong({ song: playerData.current.song });
updateSong(playerData.current.song);
}
},
};
@ -413,22 +357,22 @@ export const useCenterControls = (args: { playersRef: any }) => {
local: () => {
if (!isFirstTrack) {
const playerData = previous();
mprisUpdateSong({ song: playerData.current.song });
updateSong(playerData.current.song);
mpvPlayer!.setQueue(playerData);
} else {
const playerData = setCurrentIndex(queue.length - 1);
mprisUpdateSong({ song: playerData.current.song });
updateSong(playerData.current.song);
mpvPlayer!.setQueue(playerData);
}
},
web: () => {
if (isFirstTrack) {
const playerData = setCurrentIndex(queue.length - 1);
mprisUpdateSong({ song: playerData.current.song });
updateSong(playerData.current.song);
resetPlayers();
} else {
const playerData = previous();
mprisUpdateSong({ song: playerData.current.song });
updateSong(playerData.current.song);
resetPlayers();
}
},
@ -438,26 +382,22 @@ export const useCenterControls = (args: { playersRef: any }) => {
local: () => {
if (isFirstTrack) {
const playerData = setCurrentIndex(0);
mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PAUSED });
updateSong(playerData.current.song);
mpvPlayer!.setQueue(playerData, true);
pause();
} else {
const playerData = previous();
mprisUpdateSong({
currentTime: usePlayerStore.getState().current.time,
song: playerData.current.song,
});
updateSong(playerData.current.song);
mpvPlayer!.setQueue(playerData);
}
},
web: () => {
if (isFirstTrack) {
resetPlayers();
mprisUpdateSong({ status: PlayerStatus.PAUSED });
pause();
} else {
const playerData = previous();
mprisUpdateSong({ song: playerData.current.song });
updateSong(playerData.current.song);
resetPlayers();
}
},
@ -466,12 +406,12 @@ export const useCenterControls = (args: { playersRef: any }) => {
const handleRepeatOne = {
local: () => {
const playerData = previous();
mprisUpdateSong({ song: playerData.current.song });
updateSong(playerData.current.song);
mpvPlayer!.setQueue(playerData);
},
web: () => {
const playerData = previous();
mprisUpdateSong({ song: playerData.current.song });
updateSong(playerData.current.song);
resetPlayers();
},
};

View file

@ -2,13 +2,7 @@ import { useCallback, useRef } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { useCurrentServer, usePlayerControls, usePlayerStore } from '/@/renderer/store';
import { usePlaybackType } from '/@/renderer/store/settings.store';
import {
PlayQueueAddOptions,
Play,
PlaybackType,
PlayerStatus,
PlayerShuffle,
} from '/@/renderer/types';
import { PlayQueueAddOptions, Play, PlaybackType } from '/@/renderer/types';
import { toast } from '/@/renderer/components/toast/index';
import isElectron from 'is-electron';
import { nanoid } from 'nanoid/non-secure';
@ -30,6 +24,7 @@ import {
import { queryKeys } from '/@/renderer/api/query-keys';
import { useTranslation } from 'react-i18next';
import { PlayersRef } from '/@/renderer/features/player/ref/players-ref';
import { updateSong } from '/@/renderer/features/player/update-remote-song';
const getRootQueryKey = (itemType: LibraryItem, serverId: string) => {
let queryKey;
@ -59,7 +54,6 @@ const getRootQueryKey = (itemType: LibraryItem, serverId: string) => {
};
const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null;
const remote = isElectron() ? window.electron.remote : null;
const addToQueue = usePlayerStore.getState().actions.addToQueue;
@ -171,6 +165,8 @@ export const useHandlePlayQueueAdd = () => {
const hadSong = usePlayerStore.getState().queue.default.length > 0;
const playerData = addToQueue({ initialIndex: initialSongIndex, playType, songs });
updateSong(playerData.current.song);
if (playbackType === PlaybackType.LOCAL) {
mpvPlayer!.volume(usePlayerStore.getState().volume);
@ -197,14 +193,6 @@ export const useHandlePlayQueueAdd = () => {
play();
}
remote?.updateSong({
currentTime: usePlayerStore.getState().current.time,
repeat: usePlayerStore.getState().repeat,
shuffle: usePlayerStore.getState().shuffle !== PlayerShuffle.NONE,
song: playerData.current.song,
status: PlayerStatus.PLAYING,
});
return null;
},
[play, playbackType, queryClient, server, t],

View file

@ -0,0 +1,39 @@
import isElectron from 'is-electron';
import { QueueSong } from '/@/renderer/api/types';
const remote = isElectron() ? window.electron.remote : null;
const mediaSession = navigator.mediaSession;
export const updateSong = (song: QueueSong | undefined) => {
if (mediaSession) {
let metadata: MediaMetadata;
if (song?.id) {
let artwork: MediaImage[];
if (song.imageUrl) {
const image300 = song.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: song.album ?? '',
artist: song.artistName,
artwork,
title: song.name,
});
} else {
metadata = new MediaMetadata();
}
mediaSession.metadata = metadata;
}
remote?.updateSong(song);
};