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) {
|
if (shuffle) {
|
||||||
mprisPlayer.shuffle = shuffle;
|
mprisPlayer.shuffle = shuffle !== 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!song) return;
|
if (!song) return;
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { AudioPlayer } from '/@/renderer/components';
|
||||||
import {
|
import {
|
||||||
useCurrentPlayer,
|
useCurrentPlayer,
|
||||||
useCurrentStatus,
|
useCurrentStatus,
|
||||||
|
useMuted,
|
||||||
usePlayer1Data,
|
usePlayer1Data,
|
||||||
usePlayer2Data,
|
usePlayer2Data,
|
||||||
usePlayerControls,
|
usePlayerControls,
|
||||||
|
@ -62,6 +63,7 @@ export const Playerbar = () => {
|
||||||
const player2 = usePlayer2Data();
|
const player2 = usePlayer2Data();
|
||||||
const status = useCurrentStatus();
|
const status = useCurrentStatus();
|
||||||
const player = useCurrentPlayer();
|
const player = useCurrentPlayer();
|
||||||
|
const muted = useMuted();
|
||||||
const { autoNext } = usePlayerControls();
|
const { autoNext } = usePlayerControls();
|
||||||
|
|
||||||
const autoNextFn = useCallback(() => {
|
const autoNextFn = useCallback(() => {
|
||||||
|
@ -92,7 +94,7 @@ export const Playerbar = () => {
|
||||||
crossfadeDuration={settings.crossfadeDuration}
|
crossfadeDuration={settings.crossfadeDuration}
|
||||||
crossfadeStyle={settings.crossfadeStyle}
|
crossfadeStyle={settings.crossfadeStyle}
|
||||||
currentPlayer={player}
|
currentPlayer={player}
|
||||||
muted={settings.muted}
|
muted={muted}
|
||||||
playbackStyle={settings.style}
|
playbackStyle={settings.style}
|
||||||
player1={player1}
|
player1={player1}
|
||||||
player2={player2}
|
player2={player2}
|
||||||
|
|
|
@ -24,6 +24,7 @@ const mpvPlayerListener = isElectron() ? window.electron.mpvPlayerListener : nul
|
||||||
const ipc = isElectron() ? window.electron.ipc : null;
|
const ipc = isElectron() ? window.electron.ipc : null;
|
||||||
const utils = isElectron() ? window.electron.utils : null;
|
const utils = isElectron() ? window.electron.utils : null;
|
||||||
const mpris = isElectron() && utils?.isLinux() ? window.electron.mpris : null;
|
const mpris = isElectron() && utils?.isLinux() ? window.electron.mpris : null;
|
||||||
|
const mediaSession = !isElectron() ? navigator.mediaSession : null;
|
||||||
|
|
||||||
export const useCenterControls = (args: { playersRef: any }) => {
|
export const useCenterControls = (args: { playersRef: any }) => {
|
||||||
const { playersRef } = args;
|
const { playersRef } = args;
|
||||||
|
@ -77,16 +78,50 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
||||||
status?: PlayerStatus;
|
status?: PlayerStatus;
|
||||||
}) => {
|
}) => {
|
||||||
const { song, currentTime, status } = args || {};
|
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({
|
mpris?.updateSong({
|
||||||
currentTime: currentTime || usePlayerStore.getState().current.time,
|
currentTime: time,
|
||||||
repeat: usePlayerStore.getState().repeat,
|
repeat: usePlayerStore.getState().repeat,
|
||||||
shuffle: usePlayerStore.getState().shuffle,
|
shuffle: usePlayerStore.getState().shuffle,
|
||||||
song: song || usePlayerStore.getState().current.song,
|
song: track,
|
||||||
status:
|
status: playStatus === PlayerStatus.PLAYING ? 'Playing' : 'Paused',
|
||||||
(status || usePlayerStore.getState().current.status) === 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(() => {
|
const handlePlay = useCallback(() => {
|
||||||
|
@ -626,6 +661,57 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
||||||
setCurrentTime,
|
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(() => {
|
useEffect(() => {
|
||||||
if (utils?.isLinux()) {
|
if (utils?.isLinux()) {
|
||||||
const unsubCurrentTime = usePlayerStore.subscribe(
|
const unsubCurrentTime = usePlayerStore.subscribe(
|
||||||
|
@ -668,10 +754,8 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
mpris.requestVolume((_e: any, data: { volume: number }) => {
|
mpris.requestVolume((_e: any, data: { volume: number }) => {
|
||||||
const currentVolume = usePlayerStore.getState().volume;
|
let newVolume = data.volume * 100;
|
||||||
const resultingVolume = data.volume + currentVolume;
|
|
||||||
|
|
||||||
let newVolume = resultingVolume;
|
|
||||||
if (newVolume > 100) {
|
if (newVolume > 100) {
|
||||||
newVolume = 100;
|
newVolume = 100;
|
||||||
} else if (newVolume < 0) {
|
} else if (newVolume < 0) {
|
||||||
|
|
|
@ -6,6 +6,8 @@ import { useGeneralSettings } from '/@/renderer/store/settings.store';
|
||||||
const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null;
|
const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null;
|
||||||
const mpvPlayerListener = isElectron() ? window.electron.mpvPlayerListener : null;
|
const mpvPlayerListener = isElectron() ? window.electron.mpvPlayerListener : null;
|
||||||
const ipc = isElectron() ? window.electron.ipc : 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) => {
|
const calculateVolumeUp = (volume: number, volumeWheelStep: number) => {
|
||||||
let volumeToSet;
|
let volumeToSet;
|
||||||
|
@ -41,6 +43,7 @@ export const useRightControls = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isElectron()) {
|
if (isElectron()) {
|
||||||
mpvPlayer.volume(volume);
|
mpvPlayer.volume(volume);
|
||||||
|
mpris?.updateVolume(volume / 100);
|
||||||
|
|
||||||
if (muted) {
|
if (muted) {
|
||||||
mpvPlayer.mute();
|
mpvPlayer.mute();
|
||||||
|
@ -52,22 +55,26 @@ export const useRightControls = () => {
|
||||||
|
|
||||||
const handleVolumeSlider = (e: number) => {
|
const handleVolumeSlider = (e: number) => {
|
||||||
mpvPlayer?.volume(e);
|
mpvPlayer?.volume(e);
|
||||||
|
mpris?.updateVolume(e / 100);
|
||||||
setVolume(e);
|
setVolume(e);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleVolumeSliderState = (e: number) => {
|
const handleVolumeSliderState = (e: number) => {
|
||||||
|
mpris?.updateVolume(e / 100);
|
||||||
setVolume(e);
|
setVolume(e);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleVolumeDown = useCallback(() => {
|
const handleVolumeDown = useCallback(() => {
|
||||||
const volumeToSet = calculateVolumeDown(volume, volumeWheelStep);
|
const volumeToSet = calculateVolumeDown(volume, volumeWheelStep);
|
||||||
mpvPlayer?.volume(volumeToSet);
|
mpvPlayer?.volume(volumeToSet);
|
||||||
|
mpris?.updateVolume(volumeToSet / 100);
|
||||||
setVolume(volumeToSet);
|
setVolume(volumeToSet);
|
||||||
}, [setVolume, volume, volumeWheelStep]);
|
}, [setVolume, volume, volumeWheelStep]);
|
||||||
|
|
||||||
const handleVolumeUp = useCallback(() => {
|
const handleVolumeUp = useCallback(() => {
|
||||||
const volumeToSet = calculateVolumeUp(volume, volumeWheelStep);
|
const volumeToSet = calculateVolumeUp(volume, volumeWheelStep);
|
||||||
mpvPlayer?.volume(volumeToSet);
|
mpvPlayer?.volume(volumeToSet);
|
||||||
|
mpris?.updateVolume(volumeToSet / 100);
|
||||||
setVolume(volumeToSet);
|
setVolume(volumeToSet);
|
||||||
}, [setVolume, volume, volumeWheelStep]);
|
}, [setVolume, volume, volumeWheelStep]);
|
||||||
|
|
||||||
|
@ -81,6 +88,7 @@ export const useRightControls = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
mpvPlayer?.volume(volumeToSet);
|
mpvPlayer?.volume(volumeToSet);
|
||||||
|
mpris?.updateVolume(volumeToSet / 100);
|
||||||
setVolume(volumeToSet);
|
setVolume(volumeToSet);
|
||||||
},
|
},
|
||||||
[setVolume, volume, volumeWheelStep],
|
[setVolume, volume, volumeWheelStep],
|
||||||
|
|
Reference in a new issue