diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 6a489fc..4fc0775 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -4,6 +4,8 @@ * Copyright (c) 2023 Vendicated and Vencord contributors */ +if (process.platform === "linux") import("./virtmic"); + import { execFile } from "child_process"; import { app, dialog, RelaunchOptions, session, shell } from "electron"; import { mkdirSync, readFileSync, watch } from "fs"; diff --git a/src/main/screenShare.ts b/src/main/screenShare.ts index 8cfe5b5..b5927a1 100644 --- a/src/main/screenShare.ts +++ b/src/main/screenShare.ts @@ -43,6 +43,11 @@ export function registerScreenShareHandler() { if (isWayland) { const video = data[0]; + if (video) + await request.frame.executeJavaScript( + `Vesktop.Components.ScreenShare.openScreenSharePicker(${JSON.stringify([data])}, true)` + ); + callback(video ? { video } : {}); return; } diff --git a/src/main/virtmic.ts b/src/main/virtmic.ts new file mode 100644 index 0000000..8eb98e9 --- /dev/null +++ b/src/main/virtmic.ts @@ -0,0 +1,54 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Vesktop, a desktop app aiming to give you a snappier Discord Experience + * Copyright (c) 2023 Vendicated and Vencord contributors + */ + +import { ChildProcess, execFile } from "child_process"; +import { ipcMain } from "electron"; +import { join } from "path"; +import { IpcEvents } from "shared/IpcEvents"; +import { STATIC_DIR } from "shared/paths"; +import { promisify } from "util"; + +const BIN = join(STATIC_DIR, "vencord-virtmic"); +const execFileP = promisify(execFile); + +ipcMain.handle(IpcEvents.VIRT_MIC_LIST, async () => { + return execFileP(BIN, ["--list-targets"]) + .then(res => + res.stdout + .trim() + .split("\n") + .map(s => s.trim()) + .filter(Boolean) + ) + .catch(e => { + console.error("virt-mic-list failed", e); + return null; + }); +}); + +let virtMicProc: ChildProcess | null = null; + +function kill() { + virtMicProc?.kill(); + virtMicProc = null; +} + +ipcMain.handle(IpcEvents.VIRT_MIC_START, (_, target: string) => { + kill(); + + return new Promise(resolve => { + virtMicProc = execFile(BIN, [target], { encoding: "utf-8" }); + virtMicProc.stdout?.on("data", (chunk: string) => { + if (chunk.includes("vencord-virtmic")) resolve(true); + }); + virtMicProc.on("error", () => resolve(false)); + virtMicProc.on("exit", () => resolve(false)); + + setTimeout(() => resolve(false), 1000); + }); +}); + +ipcMain.handle(IpcEvents.VIRT_MIC_KILL, () => kill()); diff --git a/src/preload/VesktopNative.ts b/src/preload/VesktopNative.ts index 1706bed..36960fb 100644 --- a/src/preload/VesktopNative.ts +++ b/src/preload/VesktopNative.ts @@ -58,5 +58,12 @@ export const VesktopNative = { }, capturer: { getLargeThumbnail: (id: string) => invoke(IpcEvents.CAPTURER_GET_LARGE_THUMBNAIL, id) + }, + + /** only available on Linux. */ + virtmic: { + list: () => invoke(IpcEvents.VIRT_MIC_LIST), + start: (target: string) => invoke(IpcEvents.VIRT_MIC_START, target), + kill: () => invoke(IpcEvents.VIRT_MIC_KILL) } }; diff --git a/src/renderer/components/ScreenSharePicker.tsx b/src/renderer/components/ScreenSharePicker.tsx index bd7083c..1660a88 100644 --- a/src/renderer/components/ScreenSharePicker.tsx +++ b/src/renderer/components/ScreenSharePicker.tsx @@ -70,7 +70,7 @@ addPatch({ } }); -export function openScreenSharePicker(screens: Source[]) { +export function openScreenSharePicker(screens: Source[], skipPicker = false) { return new Promise((resolve, reject) => { const key = openModal( props => ( @@ -82,6 +82,7 @@ export function openScreenSharePicker(screens: Source[]) { props.onClose(); reject("Aborted"); }} + skipPicker={skipPicker} /> ), { @@ -191,14 +192,16 @@ function ModalComponent({ screens, modalProps, submit, - close + close, + skipPicker }: { screens: Source[]; modalProps: any; submit: (data: StreamPick) => void; close: () => void; + skipPicker: boolean; }) { - const [selected, setSelected] = useState(); + const [selected, setSelected] = useState(skipPicker ? screens[0].id : void 0); const [settings, setSettings] = useState({ resolution: "1080", fps: "60", @@ -259,7 +262,7 @@ function ModalComponent({ Go Live - {selected ? ( + {selected && !skipPicker ? ( diff --git a/src/shared/IpcEvents.ts b/src/shared/IpcEvents.ts index 2d453e3..96f86d3 100644 --- a/src/shared/IpcEvents.ts +++ b/src/shared/IpcEvents.ts @@ -40,5 +40,9 @@ export const enum IpcEvents { AUTOSTART_ENABLED = "VCD_AUTOSTART_ENABLED", ENABLE_AUTOSTART = "VCD_ENABLE_AUTOSTART", - DISABLE_AUTOSTART = "VCD_DISABLE_AUTOSTART" + DISABLE_AUTOSTART = "VCD_DISABLE_AUTOSTART", + + VIRT_MIC_LIST = "VCD_VIRT_MIC_LIST", + VIRT_MIC_START = "VCD_VIRT_MIC_START", + VIRT_MIC_KILL = "VCD_VIRT_MIC_STOP" } diff --git a/static/vencord-virtmic b/static/vencord-virtmic new file mode 100755 index 0000000..c1b74a7 Binary files /dev/null and b/static/vencord-virtmic differ