mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-17 14:10:14 +02:00
add mediasession
This commit is contained in:
@@ -5,6 +5,7 @@ import { UserFavoriteEventPayload, UserRatingEventPayload } from '/@/renderer/ev
|
|||||||
import { useDiscordRpc } from '/@/renderer/features/discord-rpc/use-discord-rpc';
|
import { useDiscordRpc } from '/@/renderer/features/discord-rpc/use-discord-rpc';
|
||||||
import { MpvPlayer } from '/@/renderer/features/player/audio-player/mpv-player';
|
import { MpvPlayer } from '/@/renderer/features/player/audio-player/mpv-player';
|
||||||
import { WebPlayer } from '/@/renderer/features/player/audio-player/web-player';
|
import { WebPlayer } from '/@/renderer/features/player/audio-player/web-player';
|
||||||
|
import { useMediaSession } from '/@/renderer/features/player/hooks/use-media-session';
|
||||||
import { useMPRIS } from '/@/renderer/features/player/hooks/use-mpris';
|
import { useMPRIS } from '/@/renderer/features/player/hooks/use-mpris';
|
||||||
import { usePowerSaveBlocker } from '/@/renderer/features/player/hooks/use-power-save-blocker';
|
import { usePowerSaveBlocker } from '/@/renderer/features/player/hooks/use-power-save-blocker';
|
||||||
import { useScrobble } from '/@/renderer/features/player/hooks/use-scrobble';
|
import { useScrobble } from '/@/renderer/features/player/hooks/use-scrobble';
|
||||||
@@ -25,6 +26,7 @@ export const AudioPlayers = () => {
|
|||||||
usePowerSaveBlocker();
|
usePowerSaveBlocker();
|
||||||
useDiscordRpc();
|
useDiscordRpc();
|
||||||
useMPRIS();
|
useMPRIS();
|
||||||
|
useMediaSession();
|
||||||
|
|
||||||
// Listen to favorite and rating events to update queue songs
|
// Listen to favorite and rating events to update queue songs
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,73 +1,66 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect, useMemo } from 'react';
|
||||||
|
|
||||||
import {
|
import { usePlayerEvents } from '/@/renderer/features/player/audio-player/hooks/use-player-events';
|
||||||
usePlaybackSettings,
|
import { usePlayer } from '/@/renderer/features/player/context/player-context';
|
||||||
usePlayerSong,
|
import { usePlaybackSettings, useSettingsStore, useTimestampStoreBase } from '/@/renderer/store';
|
||||||
usePlayerStatus,
|
|
||||||
useSettingsStore,
|
|
||||||
} from '/@/renderer/store';
|
|
||||||
import { PlayerStatus } from '/@/shared/types/types';
|
import { PlayerStatus } from '/@/shared/types/types';
|
||||||
|
|
||||||
export const useMediaSession = ({
|
export const useMediaSession = () => {
|
||||||
handleNextTrack,
|
|
||||||
handlePause,
|
|
||||||
handlePlay,
|
|
||||||
handlePrevTrack,
|
|
||||||
handleSeekSlider,
|
|
||||||
handleSkipBackward,
|
|
||||||
handleSkipForward,
|
|
||||||
handleStop,
|
|
||||||
}: {
|
|
||||||
handleNextTrack: () => void;
|
|
||||||
handlePause: () => void;
|
|
||||||
handlePlay: () => void;
|
|
||||||
handlePrevTrack: () => void;
|
|
||||||
handleSeekSlider: (e: any | number) => void;
|
|
||||||
handleSkipBackward: (seconds: number) => void;
|
|
||||||
handleSkipForward: (seconds: number) => void;
|
|
||||||
handleStop: () => void;
|
|
||||||
}) => {
|
|
||||||
const { mediaSession: mediaSessionEnabled } = usePlaybackSettings();
|
const { mediaSession: mediaSessionEnabled } = usePlaybackSettings();
|
||||||
const playerStatus = usePlayerStatus();
|
const player = usePlayer();
|
||||||
const currentSong = usePlayerSong();
|
|
||||||
const mediaSession = navigator.mediaSession;
|
const mediaSession = navigator.mediaSession;
|
||||||
const skip = useSettingsStore((state) => state.general.skipButtons);
|
const skip = useSettingsStore((state) => state.general.skipButtons);
|
||||||
|
|
||||||
|
const isMediaSessionEnabled = useMemo(() => {
|
||||||
|
return mediaSessionEnabled && mediaSession;
|
||||||
|
}, [mediaSessionEnabled, mediaSession]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!mediaSessionEnabled || !mediaSession) {
|
if (!isMediaSessionEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaSession.setActionHandler('nexttrack', () => {
|
mediaSession.setActionHandler('nexttrack', () => {
|
||||||
handleNextTrack();
|
player.mediaNext();
|
||||||
});
|
});
|
||||||
|
|
||||||
mediaSession.setActionHandler('pause', () => {
|
mediaSession.setActionHandler('pause', () => {
|
||||||
handlePause();
|
player.mediaPause();
|
||||||
});
|
});
|
||||||
|
|
||||||
mediaSession.setActionHandler('play', () => {
|
mediaSession.setActionHandler('play', () => {
|
||||||
handlePlay();
|
player.mediaPlay();
|
||||||
});
|
});
|
||||||
|
|
||||||
mediaSession.setActionHandler('previoustrack', () => {
|
mediaSession.setActionHandler('previoustrack', () => {
|
||||||
handlePrevTrack();
|
player.mediaPrevious();
|
||||||
});
|
});
|
||||||
|
|
||||||
mediaSession.setActionHandler('seekto', (e) => {
|
mediaSession.setActionHandler('seekto', (e) => {
|
||||||
handleSeekSlider(e.seekTime);
|
if (e.seekTime) {
|
||||||
|
player.mediaSeekToTimestamp(e.seekTime);
|
||||||
|
} else if (e.seekOffset) {
|
||||||
|
const currentTimestamp = useTimestampStoreBase.getState().timestamp;
|
||||||
|
player.mediaSeekToTimestamp(currentTimestamp + e.seekOffset);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
mediaSession.setActionHandler('stop', () => {
|
mediaSession.setActionHandler('stop', () => {
|
||||||
handleStop();
|
player.mediaStop();
|
||||||
});
|
});
|
||||||
|
|
||||||
mediaSession.setActionHandler('seekbackward', (e) => {
|
mediaSession.setActionHandler('seekbackward', (e) => {
|
||||||
handleSkipBackward(e.seekOffset || skip?.skipBackwardSeconds || 5);
|
const currentTimestamp = useTimestampStoreBase.getState().timestamp;
|
||||||
|
player.mediaSeekToTimestamp(
|
||||||
|
currentTimestamp - (e.seekOffset || skip?.skipBackwardSeconds || 5),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
mediaSession.setActionHandler('seekforward', (e) => {
|
mediaSession.setActionHandler('seekforward', (e) => {
|
||||||
handleSkipForward(e.seekOffset || skip?.skipForwardSeconds || 5);
|
const currentTimestamp = useTimestampStoreBase.getState().timestamp;
|
||||||
|
player.mediaSeekToTimestamp(
|
||||||
|
currentTimestamp + (e.seekOffset || skip?.skipForwardSeconds || 5),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@@ -81,55 +74,37 @@ export const useMediaSession = ({
|
|||||||
mediaSession.setActionHandler('seekforward', null);
|
mediaSession.setActionHandler('seekforward', null);
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
handleNextTrack,
|
player,
|
||||||
handlePause,
|
|
||||||
handlePlay,
|
|
||||||
handlePrevTrack,
|
|
||||||
handleSeekSlider,
|
|
||||||
handleSkipBackward,
|
|
||||||
handleSkipForward,
|
|
||||||
handleStop,
|
|
||||||
mediaSession,
|
|
||||||
mediaSessionEnabled,
|
|
||||||
skip?.skipBackwardSeconds,
|
skip?.skipBackwardSeconds,
|
||||||
skip?.skipForwardSeconds,
|
skip?.skipForwardSeconds,
|
||||||
|
isMediaSessionEnabled,
|
||||||
|
mediaSession,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
usePlayerEvents(
|
||||||
if (!mediaSessionEnabled || !mediaSession) {
|
{
|
||||||
return;
|
onCurrentSongChange: (properties) => {
|
||||||
}
|
if (!isMediaSessionEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const updateMetadata = () => {
|
const song = properties.song;
|
||||||
mediaSession.metadata = new MediaMetadata({
|
mediaSession.metadata = new MediaMetadata({
|
||||||
album: currentSong?.album ?? '',
|
album: song?.album ?? '',
|
||||||
artist: currentSong?.artistName ?? '',
|
artist: song?.artistName ?? '',
|
||||||
artwork: currentSong?.imageUrl
|
artwork: song?.imageUrl ? [{ src: song.imageUrl, type: 'image/png' }] : [],
|
||||||
? [{ src: currentSong.imageUrl, type: 'image/png' }]
|
title: song?.name ?? '',
|
||||||
: [],
|
});
|
||||||
title: currentSong?.name ?? '',
|
},
|
||||||
});
|
onPlayerStatus: (properties) => {
|
||||||
};
|
if (!isMediaSessionEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
updateMetadata();
|
const status = properties.status;
|
||||||
|
mediaSession.playbackState = status === PlayerStatus.PLAYING ? 'playing' : 'paused';
|
||||||
return () => {
|
},
|
||||||
mediaSession.metadata = null;
|
},
|
||||||
};
|
[isMediaSessionEnabled, mediaSession],
|
||||||
}, [currentSong, mediaSession, mediaSessionEnabled]);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!mediaSessionEnabled || !mediaSession) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mediaSession) {
|
|
||||||
const status = playerStatus === PlayerStatus.PLAYING ? 'playing' : 'paused';
|
|
||||||
mediaSession.playbackState = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
mediaSession.playbackState = 'none';
|
|
||||||
};
|
|
||||||
}, [playerStatus, mediaSession, mediaSessionEnabled]);
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user