Split Linux screensharing audio tracks, Rework screensharing functionality and layout This will need some refactoring soon
133 lines
5.5 KiB
TypeScript
133 lines
5.5 KiB
TypeScript
import { contextBridge, ipcRenderer } from 'electron';
|
|
import { Command, Query } from './cqrs/types';
|
|
|
|
const LINUX_SCREEN_SHARE_MONITOR_AUDIO_CHUNK_CHANNEL = 'linux-screen-share-monitor-audio-chunk';
|
|
const LINUX_SCREEN_SHARE_MONITOR_AUDIO_ENDED_CHANNEL = 'linux-screen-share-monitor-audio-ended';
|
|
|
|
export interface LinuxScreenShareAudioRoutingInfo {
|
|
available: boolean;
|
|
active: boolean;
|
|
monitorCaptureSupported: boolean;
|
|
screenShareSinkName: string;
|
|
screenShareMonitorSourceName: string;
|
|
voiceSinkName: string;
|
|
reason?: string;
|
|
}
|
|
|
|
export interface LinuxScreenShareMonitorCaptureInfo {
|
|
bitsPerSample: number;
|
|
captureId: string;
|
|
channelCount: number;
|
|
sampleRate: number;
|
|
sourceName: string;
|
|
}
|
|
|
|
export interface LinuxScreenShareMonitorAudioChunkPayload {
|
|
captureId: string;
|
|
chunk: Uint8Array;
|
|
}
|
|
|
|
export interface LinuxScreenShareMonitorAudioEndedPayload {
|
|
captureId: string;
|
|
reason?: string;
|
|
}
|
|
|
|
export interface ElectronAPI {
|
|
minimizeWindow: () => void;
|
|
maximizeWindow: () => void;
|
|
closeWindow: () => void;
|
|
|
|
openExternal: (url: string) => Promise<boolean>;
|
|
getSources: () => Promise<{ id: string; name: string; thumbnail: string }[]>;
|
|
prepareLinuxScreenShareAudioRouting: () => Promise<LinuxScreenShareAudioRoutingInfo>;
|
|
activateLinuxScreenShareAudioRouting: () => Promise<LinuxScreenShareAudioRoutingInfo>;
|
|
deactivateLinuxScreenShareAudioRouting: () => Promise<boolean>;
|
|
startLinuxScreenShareMonitorCapture: () => Promise<LinuxScreenShareMonitorCaptureInfo>;
|
|
stopLinuxScreenShareMonitorCapture: (captureId?: string) => Promise<boolean>;
|
|
onLinuxScreenShareMonitorAudioChunk: (listener: (payload: LinuxScreenShareMonitorAudioChunkPayload) => void) => () => void;
|
|
onLinuxScreenShareMonitorAudioEnded: (listener: (payload: LinuxScreenShareMonitorAudioEndedPayload) => void) => () => void;
|
|
getAppDataPath: () => Promise<string>;
|
|
getDesktopSettings: () => Promise<{
|
|
hardwareAcceleration: boolean;
|
|
runtimeHardwareAcceleration: boolean;
|
|
restartRequired: boolean;
|
|
}>;
|
|
setDesktopSettings: (patch: { hardwareAcceleration?: boolean }) => Promise<{
|
|
hardwareAcceleration: boolean;
|
|
runtimeHardwareAcceleration: boolean;
|
|
restartRequired: boolean;
|
|
}>;
|
|
relaunchApp: () => Promise<boolean>;
|
|
readFile: (filePath: string) => Promise<string>;
|
|
writeFile: (filePath: string, data: string) => Promise<boolean>;
|
|
saveFileAs: (defaultFileName: string, data: string) => Promise<{ saved: boolean; cancelled: boolean }>;
|
|
fileExists: (filePath: string) => Promise<boolean>;
|
|
ensureDir: (dirPath: string) => Promise<boolean>;
|
|
|
|
command: <T = unknown>(command: Command) => Promise<T>;
|
|
query: <T = unknown>(query: Query) => Promise<T>;
|
|
}
|
|
|
|
const electronAPI: ElectronAPI = {
|
|
minimizeWindow: () => ipcRenderer.send('window-minimize'),
|
|
maximizeWindow: () => ipcRenderer.send('window-maximize'),
|
|
closeWindow: () => ipcRenderer.send('window-close'),
|
|
|
|
openExternal: (url) => ipcRenderer.invoke('open-external', url),
|
|
getSources: () => ipcRenderer.invoke('get-sources'),
|
|
prepareLinuxScreenShareAudioRouting: () => ipcRenderer.invoke('prepare-linux-screen-share-audio-routing'),
|
|
activateLinuxScreenShareAudioRouting: () => ipcRenderer.invoke('activate-linux-screen-share-audio-routing'),
|
|
deactivateLinuxScreenShareAudioRouting: () => ipcRenderer.invoke('deactivate-linux-screen-share-audio-routing'),
|
|
startLinuxScreenShareMonitorCapture: () => ipcRenderer.invoke('start-linux-screen-share-monitor-capture'),
|
|
stopLinuxScreenShareMonitorCapture: (captureId) => ipcRenderer.invoke('stop-linux-screen-share-monitor-capture', captureId),
|
|
onLinuxScreenShareMonitorAudioChunk: (listener) => {
|
|
const wrappedListener = (_event: Electron.IpcRendererEvent, payload: LinuxScreenShareMonitorAudioChunkPayload) => {
|
|
const chunk = payload.chunk instanceof Uint8Array
|
|
? payload.chunk
|
|
: Uint8Array.from((payload as { chunk?: Iterable<number> }).chunk || []);
|
|
|
|
listener({
|
|
...payload,
|
|
chunk
|
|
});
|
|
};
|
|
|
|
ipcRenderer.on(LINUX_SCREEN_SHARE_MONITOR_AUDIO_CHUNK_CHANNEL, wrappedListener);
|
|
|
|
return () => {
|
|
ipcRenderer.removeListener(LINUX_SCREEN_SHARE_MONITOR_AUDIO_CHUNK_CHANNEL, wrappedListener);
|
|
};
|
|
},
|
|
onLinuxScreenShareMonitorAudioEnded: (listener) => {
|
|
const wrappedListener = (_event: Electron.IpcRendererEvent, payload: LinuxScreenShareMonitorAudioEndedPayload) => {
|
|
listener(payload);
|
|
};
|
|
|
|
ipcRenderer.on(LINUX_SCREEN_SHARE_MONITOR_AUDIO_ENDED_CHANNEL, wrappedListener);
|
|
|
|
return () => {
|
|
ipcRenderer.removeListener(LINUX_SCREEN_SHARE_MONITOR_AUDIO_ENDED_CHANNEL, wrappedListener);
|
|
};
|
|
},
|
|
getAppDataPath: () => ipcRenderer.invoke('get-app-data-path'),
|
|
getDesktopSettings: () => ipcRenderer.invoke('get-desktop-settings'),
|
|
setDesktopSettings: (patch) => ipcRenderer.invoke('set-desktop-settings', patch),
|
|
relaunchApp: () => ipcRenderer.invoke('relaunch-app'),
|
|
readFile: (filePath) => ipcRenderer.invoke('read-file', filePath),
|
|
writeFile: (filePath, data) => ipcRenderer.invoke('write-file', filePath, data),
|
|
saveFileAs: (defaultFileName, data) => ipcRenderer.invoke('save-file-as', defaultFileName, data),
|
|
fileExists: (filePath) => ipcRenderer.invoke('file-exists', filePath),
|
|
ensureDir: (dirPath) => ipcRenderer.invoke('ensure-dir', dirPath),
|
|
|
|
command: (command) => ipcRenderer.invoke('cqrs:command', command),
|
|
query: (query) => ipcRenderer.invoke('cqrs:query', query)
|
|
};
|
|
|
|
contextBridge.exposeInMainWorld('electronAPI', electronAPI);
|
|
|
|
declare global {
|
|
interface Window {
|
|
electronAPI: ElectronAPI;
|
|
}
|
|
}
|