mirror of
https://github.com/jeffvli/feishin.git
synced 2026-06-10 22:32:17 +02:00
re-implement mpv with new player
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
import { t } from 'i18next';
|
||||
import isElectron from 'is-electron';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
import { usePlayerActions } from '/@/renderer/store';
|
||||
import { toast } from '/@/shared/components/toast/toast';
|
||||
|
||||
const mpvPlayer = isElectron() ? window.api.mpvPlayer : null;
|
||||
const mpvPlayerListener = isElectron() ? window.api.mpvPlayerListener : null;
|
||||
const ipc = isElectron() ? window.api.ipc : null;
|
||||
|
||||
export const useMainPlayerListener = () => {
|
||||
const {
|
||||
decreaseVolume,
|
||||
increaseVolume,
|
||||
mediaAutoNext,
|
||||
mediaNext,
|
||||
mediaPause,
|
||||
mediaPlay,
|
||||
mediaPrevious,
|
||||
mediaSkipBackward,
|
||||
mediaSkipForward,
|
||||
mediaStop,
|
||||
mediaToggleMute,
|
||||
mediaTogglePlayPause,
|
||||
toggleRepeat,
|
||||
toggleShuffle,
|
||||
} = usePlayerActions();
|
||||
|
||||
const handleMpvError = useCallback(
|
||||
(message: string) => {
|
||||
toast.error({
|
||||
id: 'mpv-error',
|
||||
message,
|
||||
title: t('error.playbackError', { postProcess: 'sentenceCase' }) as string,
|
||||
});
|
||||
mediaPause();
|
||||
mpvPlayer!.pause();
|
||||
},
|
||||
[mediaPause],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!mpvPlayerListener) {
|
||||
return;
|
||||
}
|
||||
|
||||
mpvPlayerListener.rendererPlayPause(() => {
|
||||
mediaTogglePlayPause();
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererNext(() => {
|
||||
mediaNext();
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererPrevious(() => {
|
||||
mediaPrevious();
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererPlayPause(() => {
|
||||
mediaTogglePlayPause();
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererPlay(() => {
|
||||
mediaPlay();
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererPause(() => {
|
||||
mediaPause();
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererStop(() => {
|
||||
mediaStop();
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererSkipForward(() => {
|
||||
mediaSkipForward();
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererSkipBackward(() => {
|
||||
mediaSkipBackward();
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererAutoNext(() => {
|
||||
mediaAutoNext();
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererToggleShuffle(() => {
|
||||
toggleShuffle();
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererToggleRepeat(() => {
|
||||
toggleRepeat();
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererVolumeMute(() => {
|
||||
mediaToggleMute();
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererVolumeUp(() => {
|
||||
increaseVolume(1);
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererVolumeDown(() => {
|
||||
decreaseVolume(1);
|
||||
});
|
||||
|
||||
mpvPlayerListener.rendererError((_event: any, message: string) => {
|
||||
handleMpvError(message);
|
||||
});
|
||||
|
||||
return () => {
|
||||
ipc?.removeAllListeners('renderer-player-play-pause');
|
||||
ipc?.removeAllListeners('renderer-player-next');
|
||||
ipc?.removeAllListeners('renderer-player-previous');
|
||||
ipc?.removeAllListeners('renderer-player-play-pause');
|
||||
ipc?.removeAllListeners('renderer-player-play');
|
||||
ipc?.removeAllListeners('renderer-player-pause');
|
||||
ipc?.removeAllListeners('renderer-player-stop');
|
||||
ipc?.removeAllListeners('renderer-player-skip-forward');
|
||||
ipc?.removeAllListeners('renderer-player-skip-backward');
|
||||
ipc?.removeAllListeners('renderer-player-auto-next');
|
||||
ipc?.removeAllListeners('renderer-player-toggle-shuffle');
|
||||
ipc?.removeAllListeners('renderer-player-toggle-repeat');
|
||||
ipc?.removeAllListeners('renderer-player-volume-mute');
|
||||
ipc?.removeAllListeners('renderer-player-volume-up');
|
||||
ipc?.removeAllListeners('renderer-player-volume-down');
|
||||
ipc?.removeAllListeners('renderer-player-error');
|
||||
};
|
||||
}, [
|
||||
decreaseVolume,
|
||||
handleMpvError,
|
||||
increaseVolume,
|
||||
mediaAutoNext,
|
||||
mediaNext,
|
||||
mediaPause,
|
||||
mediaPlay,
|
||||
mediaPrevious,
|
||||
mediaSkipForward,
|
||||
mediaSkipBackward,
|
||||
mediaStop,
|
||||
mediaToggleMute,
|
||||
mediaTogglePlayPause,
|
||||
toggleRepeat,
|
||||
toggleShuffle,
|
||||
]);
|
||||
};
|
||||
@@ -0,0 +1,105 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import {
|
||||
subscribeCurrentTrack,
|
||||
subscribePlayerMute,
|
||||
subscribePlayerProgress,
|
||||
subscribePlayerQueue,
|
||||
subscribePlayerSeekToTimestamp,
|
||||
subscribePlayerSpeed,
|
||||
subscribePlayerStatus,
|
||||
subscribePlayerVolume,
|
||||
} from '/@/renderer/store';
|
||||
import { QueueData, QueueSong } from '/@/shared/types/domain-types';
|
||||
import { PlayerStatus } from '/@/shared/types/types';
|
||||
|
||||
interface PlayerEvents {
|
||||
cleanup: () => void;
|
||||
}
|
||||
|
||||
interface PlayerEventsCallbacks {
|
||||
onCurrentSongChange?: (
|
||||
properties: { index: number; song: QueueSong | undefined },
|
||||
prev: { index: number; song: QueueSong | undefined },
|
||||
) => void;
|
||||
onPlayerMute?: (properties: { muted: boolean }, prev: { muted: boolean }) => void;
|
||||
onPlayerProgress?: (properties: { timestamp: number }, prev: { timestamp: number }) => void;
|
||||
onPlayerQueueChange?: (queue: QueueData, prev: QueueData) => void;
|
||||
onPlayerSeek?: (properties: { seconds: number }, prev: { seconds: number }) => void;
|
||||
onPlayerSeekToTimestamp?: (
|
||||
properties: { timestamp: number },
|
||||
prev: { timestamp: number },
|
||||
) => void;
|
||||
onPlayerSpeed?: (properties: { speed: number }, prev: { speed: number }) => void;
|
||||
onPlayerStatus?: (properties: { status: PlayerStatus }, prev: { status: PlayerStatus }) => void;
|
||||
onPlayerVolume?: (properties: { volume: number }, prev: { volume: number }) => void;
|
||||
}
|
||||
|
||||
export function usePlayerEvents(callbacks: PlayerEventsCallbacks, deps: React.DependencyList) {
|
||||
useEffect(() => {
|
||||
const engine = createPlayerEvents(callbacks);
|
||||
|
||||
return () => {
|
||||
engine.cleanup();
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [...deps]);
|
||||
}
|
||||
|
||||
function createPlayerEvents(callbacks: PlayerEventsCallbacks): PlayerEvents {
|
||||
const unsubscribers: (() => void)[] = [];
|
||||
|
||||
// Subscribe to current track changes
|
||||
if (callbacks.onCurrentSongChange) {
|
||||
const unsubscribe = subscribeCurrentTrack(callbacks.onCurrentSongChange);
|
||||
unsubscribers.push(unsubscribe);
|
||||
}
|
||||
|
||||
// Subscribe to player progress
|
||||
if (callbacks.onPlayerProgress) {
|
||||
const unsubscribe = subscribePlayerProgress(callbacks.onPlayerProgress);
|
||||
unsubscribers.push(unsubscribe);
|
||||
}
|
||||
|
||||
// Subscribe to queue changes
|
||||
if (callbacks.onPlayerQueueChange) {
|
||||
const unsubscribe = subscribePlayerQueue(callbacks.onPlayerQueueChange);
|
||||
unsubscribers.push(unsubscribe);
|
||||
}
|
||||
|
||||
// Subscribe to seek events
|
||||
if (callbacks.onPlayerSeekToTimestamp) {
|
||||
const unsubscribe = subscribePlayerSeekToTimestamp(callbacks.onPlayerSeekToTimestamp);
|
||||
unsubscribers.push(unsubscribe);
|
||||
}
|
||||
|
||||
// Subscribe to player status changes
|
||||
if (callbacks.onPlayerStatus) {
|
||||
const unsubscribe = subscribePlayerStatus(callbacks.onPlayerStatus);
|
||||
unsubscribers.push(unsubscribe);
|
||||
}
|
||||
|
||||
// Subscribe to volume changes
|
||||
if (callbacks.onPlayerVolume) {
|
||||
const unsubscribe = subscribePlayerVolume(callbacks.onPlayerVolume);
|
||||
unsubscribers.push(unsubscribe);
|
||||
}
|
||||
|
||||
// Subscribe to mute changes
|
||||
if (callbacks.onPlayerMute) {
|
||||
const unsubscribe = subscribePlayerMute(callbacks.onPlayerMute);
|
||||
unsubscribers.push(unsubscribe);
|
||||
}
|
||||
|
||||
// Subscribe to speed changes
|
||||
if (callbacks.onPlayerSpeed) {
|
||||
const unsubscribe = subscribePlayerSpeed(callbacks.onPlayerSpeed);
|
||||
unsubscribers.push(unsubscribe);
|
||||
}
|
||||
|
||||
return {
|
||||
cleanup: () => {
|
||||
unsubscribers.forEach((unsubscribe) => unsubscribe());
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user