diff --git a/src/main/features/core/index.ts b/src/main/features/core/index.ts index fad608283..c53c43a24 100644 --- a/src/main/features/core/index.ts +++ b/src/main/features/core/index.ts @@ -4,3 +4,4 @@ import './player'; import './remote'; import './settings'; import './discord-rpc'; +import './visualizer'; diff --git a/src/main/features/core/visualizer/index.ts b/src/main/features/core/visualizer/index.ts new file mode 100644 index 000000000..534c61af3 --- /dev/null +++ b/src/main/features/core/visualizer/index.ts @@ -0,0 +1,30 @@ +import { ipcMain } from 'electron'; + +import { getMpvInstance } from '../player'; +import { store } from '../settings'; + +import { PlayerType } from '/@/shared/types/types'; + +let isLocalVisualizerSurfaceVisible = false; + +export const setLocalVisualizerSurfaceVisible = (visible: boolean) => { + isLocalVisualizerSurfaceVisible = visible; +}; + +export const canHandleVisualizerDisplayMedia = (): boolean => { + const playbackType = store.get('playbackType', PlayerType.WEB) as PlayerType; + + if (playbackType !== PlayerType.LOCAL) { + return false; + } + + if (!isLocalVisualizerSurfaceVisible) { + return false; + } + + return Boolean(getMpvInstance()?.isRunning()); +}; + +ipcMain.on('visualizer-set-local-surface-visible', (_event, visible: boolean) => { + setLocalVisualizerSurfaceVisible(Boolean(visible)); +}); diff --git a/src/main/index.ts b/src/main/index.ts index 350cbfabf..d16d066c9 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -30,7 +30,9 @@ import packageJson from '../../package.json'; import { disableMediaKeys, enableMediaKeys } from './features/core/player/media-keys'; import { shutdownServer } from './features/core/remote'; import { store } from './features/core/settings'; +import { canHandleVisualizerDisplayMedia } from './features/core/visualizer'; import MenuBuilder, { MenuPlaybackState } from './menu'; +import './features'; import { autoUpdaterLogInterface, createLog, @@ -40,7 +42,6 @@ import { isMacOS, isWindows, } from './utils'; -import './features'; import { PlayerRepeat, PlayerStatus, PlayerType, TitleTheme } from '/@/shared/types/types'; @@ -734,6 +735,11 @@ async function createWindow(first = true): Promise { }); mainWindow.webContents.session.setDisplayMediaRequestHandler((_request, callback) => { + if (!canHandleVisualizerDisplayMedia()) { + callback({}); + return; + } + if (!isMacOS()) { callback({ audio: 'loopback' }); return; diff --git a/src/preload/index.ts b/src/preload/index.ts index 1f87f4083..112b23eb5 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -11,6 +11,7 @@ import { mpris } from './mpris'; import { mpvPlayer, mpvPlayerListener } from './mpv-player'; import { remote } from './remote'; import { utils } from './utils'; +import { visualizer } from './visualizer'; // Custom APIs for renderer const api = { @@ -25,6 +26,7 @@ const api = { mpvPlayerListener, remote, utils, + visualizer, }; export type PreloadApi = typeof api; diff --git a/src/preload/visualizer.ts b/src/preload/visualizer.ts new file mode 100644 index 000000000..c76aa686a --- /dev/null +++ b/src/preload/visualizer.ts @@ -0,0 +1,11 @@ +import { ipcRenderer } from 'electron'; + +const setLocalSurfaceVisible = (visible: boolean) => { + ipcRenderer.send('visualizer-set-local-surface-visible', visible); +}; + +export const visualizer = { + setLocalSurfaceVisible, +}; + +export type VisualizerApi = typeof visualizer; diff --git a/src/renderer/features/visualizer/components/visualizer-system-audio-bridge.tsx b/src/renderer/features/visualizer/components/visualizer-system-audio-bridge.tsx index dc4407a1e..0dd2374c9 100644 --- a/src/renderer/features/visualizer/components/visualizer-system-audio-bridge.tsx +++ b/src/renderer/features/visualizer/components/visualizer-system-audio-bridge.tsx @@ -21,6 +21,21 @@ type PromptState = 'loading' | { consent: boolean }; export function VisualizerSystemAudioBridgeHook() { const playbackType = usePlaybackType(); + const isVisualizerSurfaceVisible = useIsLocalVisualizerSurfaceVisible(); + + useEffect(() => { + if (!isElectron()) { + return; + } + + const shouldReportVisible = playbackType === PlayerType.LOCAL && isVisualizerSurfaceVisible; + + window.api.visualizer.setLocalSurfaceVisible(shouldReportVisible); + + return () => { + window.api.visualizer.setLocalSurfaceVisible(false); + }; + }, [playbackType, isVisualizerSurfaceVisible]); if (!isElectron() || playbackType !== PlayerType.LOCAL) { return null;