69 lines
1.9 kB
1
import type { BrowserWindow } from "electron";
2
import { app, desktopCapturer } from "electron";
3
import path from "node:path";
4
import { type PatchBay } from "./types";
5
6
const logger = moonlightHost.getLogger("rocketship");
7
8
function getPatchbay() {
9
try {
10
const venmic = require(path.join(path.dirname(moonlightHost.asarPath), "..", "venmic.node")) as {
11
PatchBay: new () => PatchBay;
12
};
13
const patchbay = new venmic.PatchBay();
14
return patchbay;
15
} catch (error) {
16
logger.error("Failed to load venmic.node:", error);
17
return null;
18
}
19
}
20
21
const patchbay = getPatchbay();
22
23
// TODO: figure out how to map source to window with venmic
24
function linkVenmic() {
25
if (patchbay == null) return false;
26
27
try {
28
const pid =
29
app
30
.getAppMetrics()
31
.find((proc) => proc.name === "Audio Service")
32
?.pid?.toString() ?? "";
33
34
logger.info("Audio Service PID:", pid);
35
36
patchbay.unlink();
37
return patchbay.link({
38
exclude: [{ "application.process.id": pid }, { "media.class": "Stream/Input/Audio" }],
39
ignore_devices: true,
40
only_speakers: true,
41
only_default_speakers: true
42
});
43
} catch (error) {
44
logger.error("Failed to link venmic:", error);
45
return false;
46
}
47
}
48
49
moonlightHost.events.on("window-created", (window: BrowserWindow, isMainWindow: boolean) => {
50
if (!isMainWindow) return;
51
const windowSession = window.webContents.session;
52
53
// @ts-expect-error these types ancient
54
windowSession.setDisplayMediaRequestHandler(
55
(request: any, callback: any) => {
56
const linked = linkVenmic();
57
desktopCapturer.getSources({ types: ["screen", "window"] }).then((sources) => {
58
//logger.debug("desktopCapturer.getSources", sources);
59
logger.debug("Linked to venmic:", linked);
60
61
callback({
62
video: sources[0],
63
audio: "loopback"
64
});
65
});
66
},
67
{ useSystemPicker: true }
68
);
69
});
70