Skip to content
This repository was archived by the owner on Jan 10, 2026. It is now read-only.

Commit bafb290

Browse files
committed
Add support for Beyond audio strap devices (sink and source)
1 parent adf3194 commit bafb290

File tree

1 file changed

+82
-22
lines changed

1 file changed

+82
-22
lines changed

src/views/popup_volume.tsx

Lines changed: 82 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ function doesStringMentionHMDSink(input: string) {
283283
|| name.includes("index") // Valve Index
284284
|| name.includes("oculus") // Oculus
285285
|| name.includes("rift") // Also Oculus
286+
|| name.includes("beyond") // Bigscreen Beyond
286287
);
287288
}
288289

@@ -292,6 +293,7 @@ function doesStringMentionHMDSource(input: string) {
292293
name.includes("hmd") // generic hmd name detected
293294
|| name.includes("valve") // Valve Index
294295
|| name.includes("oculus") // Oculus
296+
|| name.includes("beyond") // Beyond
295297
);
296298
}
297299

@@ -478,6 +480,11 @@ enum Mode {
478480
cards
479481
}
480482

483+
enum SearchType {
484+
sink,
485+
source,
486+
}
487+
481488
async function switch_source(globals: Globals, source: ipc.AudioSource) {
482489
try {
483490
await ipc.audio_set_default_source({
@@ -493,7 +500,7 @@ async function switch_source(globals: Globals, source: ipc.AudioSource) {
493500
}
494501
}
495502

496-
async function switch_card(globals: Globals, card: ipc.AudioCard, profile_name: string, name: ProfileDisplayName) {
503+
async function switch_sink_card(globals: Globals, card: ipc.AudioCard, profile_name: string, name: ProfileDisplayName) {
497504
try {
498505
await ipc.audio_set_card_profile({
499506
cardIndex: card.index,
@@ -502,6 +509,7 @@ async function switch_card(globals: Globals, card: ipc.AudioCard, profile_name:
502509

503510
const sinks = await ipc.audio_list_sinks();
504511
let sink_set = false;
512+
505513
// find sink by card name
506514
for (const sink of sinks) {
507515
const sink_dev_name = ipc.mapGet(sink.properties, "device.name");
@@ -545,32 +553,85 @@ async function switchToVRMicrophone(globals: Globals) {
545553
}
546554
}
547555

556+
557+
interface CardPriorityResult {
558+
priority: number;
559+
name: string;
560+
profile: ipc.CardProfile | undefined;
561+
card: ipc.AudioCard,
562+
}
563+
564+
function getCardBestProfile(card: ipc.AudioCard, search_type: SearchType): CardPriorityResult {
565+
// Get the profile with the largest priority value
566+
let best_priority = 0;
567+
let best_profile_name = "";
568+
let best_profile: ipc.CardProfile | undefined = undefined;
569+
570+
ipc.mapIter(card.profiles, (profile_name, profile) => {
571+
if (search_type == SearchType.sink && profile.sinks == 0) {
572+
return; // skip
573+
}
574+
575+
if (search_type == SearchType.source && profile.sources == 0) {
576+
return; // skip
577+
}
578+
579+
if (profile.priority > best_priority) {
580+
best_priority = profile.priority;
581+
best_profile = profile;
582+
best_profile_name = profile_name;
583+
}
584+
});
585+
586+
return {
587+
priority: best_priority,
588+
profile: best_profile,
589+
name: best_profile_name,
590+
card
591+
};
592+
}
593+
594+
function getBestProfileFromArray(arr: Array<CardPriorityResult>): CardPriorityResult | undefined {
595+
let res: CardPriorityResult | undefined = undefined;
596+
597+
let best_priority = 0;
598+
599+
for (const cell of arr) {
600+
if (cell.priority > best_priority) {
601+
best_priority = cell.priority;
602+
res = cell;
603+
}
604+
}
605+
606+
return res;
607+
}
608+
548609
async function switchToVRSpeakers(globals: Globals) {
549610
let switched = false;
550611

551612
const cards = await ipc.audio_list_cards();
552-
for (const card of cards) {
553-
if (isCardMentioningHMD(card)) {
554-
// Get the profile with the largest priority value
555-
let best_priority = 0;
556-
let best_profile_name = "";
557-
let best_profile = undefined;
558-
ipc.mapIter(card.profiles, (profile_name, profile) => {
559-
if (profile.priority > best_priority) {
560-
best_priority = profile.priority;
561-
best_profile = profile;
562-
best_profile_name = profile_name;
563-
}
564-
});
565613

566-
if (best_profile) {
567-
const name = getProfileDisplayName(best_profile_name, card);
568-
switched = true;
569-
switch_card(globals, card, best_profile_name, name);
570-
}
571-
return;
614+
// list of cards with matching VR profiles
615+
let best_profiles = new Array<CardPriorityResult>();
616+
617+
for (const card of cards) {
618+
if (!isCardMentioningHMD(card)) {
619+
continue;
572620
}
573621

622+
best_profiles.push(getCardBestProfile(card, SearchType.sink));
623+
}
624+
625+
if (best_profiles.length > 0) {
626+
const best_profile = getBestProfileFromArray(best_profiles)!;
627+
const name = getProfileDisplayName(best_profile.name, best_profile.card);
628+
switched = true;
629+
switch_sink_card(globals, best_profile.card, best_profile.name, name);
630+
return;
631+
}
632+
633+
// There aren't any cards which mention VR explicitly. Time for plan B.
634+
for (const card of cards) {
574635
ipc.mapIter(card.profiles, (profile_name, _profile) => {
575636
if (switched) {
576637
return;
@@ -581,9 +642,8 @@ async function switchToVRSpeakers(globals: Globals) {
581642
return;
582643
}
583644

645+
switch_sink_card(globals, card, profile_name, name);
584646
switched = true;
585-
586-
switch_card(globals, card, profile_name, name);
587647
});
588648

589649
if (switched) {

0 commit comments

Comments
 (0)