add linux audio picker

This commit is contained in:
Vendicated 2023-09-28 01:55:31 +02:00
parent e93b07001a
commit 7447fe3b70
No known key found for this signature in database
GPG key ID: D66986BAF75ECF18
3 changed files with 55 additions and 5 deletions

View file

@ -55,7 +55,10 @@ export function registerScreenShareHandler() {
const choice = await request.frame const choice = await request.frame
.executeJavaScript(`Vesktop.Components.ScreenShare.openScreenSharePicker(${JSON.stringify(data)})`) .executeJavaScript(`Vesktop.Components.ScreenShare.openScreenSharePicker(${JSON.stringify(data)})`)
.then(e => e as StreamPick) .then(e => e as StreamPick)
.catch(() => null); .catch(e => {
console.error("Error during screenshare picker", e);
return null;
});
if (!choice) return callback({}); if (!choice) return callback({});

View file

@ -8,10 +8,10 @@ import "./screenSharePicker.css";
import { closeModal, Modals, openModal, useAwaiter } from "@vencord/types/utils"; import { closeModal, Modals, openModal, useAwaiter } from "@vencord/types/utils";
import { findStoreLazy } from "@vencord/types/webpack"; import { findStoreLazy } from "@vencord/types/webpack";
import { Button, Card, Forms, Switch, Text, useState } from "@vencord/types/webpack/common"; import { Button, Card, Forms, Select, Switch, Text, useState } from "@vencord/types/webpack/common";
import type { Dispatch, SetStateAction } from "react"; import type { Dispatch, SetStateAction } from "react";
import { addPatch } from "renderer/patches/shared"; import { addPatch } from "renderer/patches/shared";
import { isWindows } from "renderer/utils"; import { isLinux, isWindows } from "renderer/utils";
const StreamResolutions = ["480", "720", "1080", "1440"] as const; const StreamResolutions = ["480", "720", "1080", "1440"] as const;
const StreamFps = ["15", "30", "60"] as const; const StreamFps = ["15", "30", "60"] as const;
@ -25,6 +25,7 @@ interface StreamSettings {
resolution: StreamResolution; resolution: StreamResolution;
fps: StreamFps; fps: StreamFps;
audio: boolean; audio: boolean;
audioSource?: string;
} }
export interface StreamPick extends StreamSettings { export interface StreamPick extends StreamSettings {
@ -71,16 +72,21 @@ addPatch({
}); });
export function openScreenSharePicker(screens: Source[], skipPicker = false) { export function openScreenSharePicker(screens: Source[], skipPicker = false) {
let didSubmit = false;
return new Promise<StreamPick>((resolve, reject) => { return new Promise<StreamPick>((resolve, reject) => {
const key = openModal( const key = openModal(
props => ( props => (
<ModalComponent <ModalComponent
screens={screens} screens={screens}
modalProps={props} modalProps={props}
submit={resolve} submit={async v => {
didSubmit = true;
if (v.audioSource && v.audioSource !== "None") await VesktopNative.virtmic.start(v.audioSource);
resolve(v);
}}
close={() => { close={() => {
props.onClose(); props.onClose();
reject("Aborted"); if (!didSubmit) reject("Aborted");
}} }}
skipPicker={skipPicker} skipPicker={skipPicker}
/> />
@ -183,11 +189,51 @@ function StreamSettings({
Stream With Audio Stream With Audio
</Switch> </Switch>
)} )}
{isLinux && (
<AudioSourcePickerLinux
audioSource={settings.audioSource}
setAudioSource={source => setSettings(s => ({ ...s, audioSource: source }))}
/>
)}
</Card> </Card>
</div> </div>
); );
} }
function AudioSourcePickerLinux({
audioSource,
setAudioSource
}: {
audioSource?: string;
setAudioSource(s: string): void;
}) {
const [sources, _, loading] = useAwaiter(() => VesktopNative.virtmic.list(), { fallbackValue: [] });
const sourcesWithNone = sources ? ["None", ...sources] : null;
return (
<section>
<Forms.FormTitle>Audio</Forms.FormTitle>
{loading && <Forms.FormTitle>Loading Audio sources...</Forms.FormTitle>}
{sourcesWithNone === null && (
<Forms.FormTitle>
Failed to retrieve Audio Sources. If you would like to stream with Audio, make sure you're using
Pipewire, not Pulseaudio
</Forms.FormTitle>
)}
{sourcesWithNone && (
<Select
options={sourcesWithNone.map(s => ({ label: s, value: s, default: s === "None" }))}
isSelected={s => s === audioSource}
select={setAudioSource}
serialize={String}
/>
)}
</section>
);
}
function ModalComponent({ function ModalComponent({
screens, screens,
modalProps, modalProps,

View file

@ -17,3 +17,4 @@ const { platform } = navigator;
export const isWindows = platform.startsWith("Win"); export const isWindows = platform.startsWith("Win");
export const isMac = platform.startsWith("Mac"); export const isMac = platform.startsWith("Mac");
export const isLinux = platform.startsWith("Linux");