add media session/mpris
This commit is contained in:
parent
76805a0b19
commit
97ccf3bc6d
4 changed files with 105 additions and 11 deletions
|
@ -130,7 +130,7 @@ ipcMain.on(
|
|||
}
|
||||
|
||||
if (shuffle) {
|
||||
mprisPlayer.shuffle = shuffle;
|
||||
mprisPlayer.shuffle = shuffle !== 'none';
|
||||
}
|
||||
|
||||
if (!song) return;
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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],
|
||||
|
|
Reference in a new issue