crates/veilvoice-audio/src/devices.rs
veilvoice-audio · 257 lines · read the source here · or on GitHub
Enumerating audio devices, and guessing which of them are virtual cables.
What this is for
Live scrambling is only useful if the veiled voice can be routed into something else -- a call, a stream, a recorder. The way that is done on every desktop platform is a virtual audio cable: a driver that presents a playback device on one side and a microphone on the other, so anything that can select a microphone can receive VeilVoice's output.
So the list this module produces is not merely a list. Picking the wrong output device is the single most common way for live mode to appear broken while working perfectly, and the whole reason DeviceInfo::is_virtual_cable exists is to put the right entry in front of the user.
The detection is name matching, and that is a limitation, not an oversight
There is no portable way to ask an audio device whether it is virtual. CPAL does not expose it because the underlying APIs largely do not either. So VIRTUAL_CABLE_HINTS matches on name fragments, which means:
- a cable this list has never heard of is reported as an ordinary device;
- a real device whose name happens to contain "loopback" or "virtual" is flagged when it should not be.
Both are wrong in the harmless direction: the flag reorders and annotates a list, it never restricts what the user may choose. A heuristic that hides options would be a different and worse thing than one that highlights them, and this is deliberately the second.
The alternative -- showing an unsorted list of identically named endpoints and letting the user find the right one -- was tried and is worse.
Enumeration can fail, and does
Device lists come from the OS and are not stable: a device can disappear between being listed and being opened, a host may have no devices at all, and on Linux a machine with no sound server is entirely normal. Every function here returns a crate::Error rather than panicking or quietly returning an empty list, because an empty list and a failed query mean very different things to somebody trying to work out why they cannot be heard.
In plain words
This asks your computer which microphones and speakers it has, and works out which of them are virtual cables.
A virtual cable is a small piece of software that pretends to be a speaker on one side and a microphone on the other. It is how a veiled voice gets into a call: VeilVoice plays into the cable, and the calling program picks the cable as its microphone and never knows the difference.
Working out which device is a cable is done by recognising the names the common ones use, so it is a good guess rather than a certainty. Nothing depends on the guess being right: it decides which device is suggested, never which ones you are allowed to choose.
WHAT THIS FILE CONTAINS
257 lines defining 6 functions (4 public), 2 types and 1 constant. Everything below is read out of the source, so it cannot disagree with the code.
The types it owns.
enum Directionline 64 · Which direction a device carries audio.struct DeviceInfoline 73 · A device the user can choose.
What happens when it runs. These are the ways in: public, and nothing else in this file calls them, so they are what an outside caller reaches first.
find_virtual_cableline 154 · Find the first output device that looks like a virtual audio cable.
reacheslist,looks_virtual,name_of_optname_ofline 164 · The name of an opened device, or a placeholder when the OS will not say.
reachesname_of_optopenline 169 · Look up a device by exact name, or the host default when name is None.
reachesname_of_opt
WHAT CALLS WHAT
The functions this file defines, and the calls between them. An edge means the callee's name appears, called, inside the caller's body. This is a syntactic reading, not a type-resolved one.
The same graph as Mermaid source
%%{init: {"theme":"base","themeVariables":{"background":"#1a1b26","primaryColor":"#1f2335","primaryTextColor":"#c0caf5","primaryBorderColor":"#7aa2f7","secondaryColor":"#16161e","tertiaryColor":"#16161e","lineColor":"#737aa2","textColor":"#c0caf5","mainBkg":"#1f2335","nodeBorder":"#7aa2f7","clusterBkg":"#16161e","clusterBorder":"#2f3549","fontFamily":"ui-monospace, SFMono-Regular, Consolas, monospace","fontSize":"14px"}}}%%
flowchart TD
n_looks_virtual["looks_virtual<br/>line 106"]
n_name_of_opt["name_of_opt<br/>line 116"]
n_list["list<br/>line 121"]
n_find_virtual_cable(["find_virtual_cable<br/>line 154"])
n_name_of(["name_of<br/>line 164"])
n_open(["open<br/>line 169"])
n_find_virtual_cable --> n_list
n_list --> n_looks_virtual
n_list --> n_name_of_opt
n_name_of --> n_name_of_opt
n_open --> n_name_of_opt
click n_looks_virtual href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/devices.rs#L106" "open the source"
click n_name_of_opt href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/devices.rs#L116" "open the source"
click n_list href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/devices.rs#L121" "open the source"
click n_find_virtual_cable href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/devices.rs#L154" "open the source"
click n_name_of href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/devices.rs#L164" "open the source"
click n_open href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-audio/src/devices.rs#L169" "open the source"
classDef entry fill:#1f2335,stroke:#7aa2f7,color:#c0caf5
class n_find_virtual_cable,n_name_of,n_open entry
classDef api fill:#1f2335,stroke:#7dcfff,color:#c0caf5
class n_list api
classDef helper fill:#1f2335,stroke:#bb9af7,color:#c0caf5
class n_looks_virtual,n_name_of_opt helper
This site loads no third-party script, so it cannot run Mermaid; the diagram above is the same nodes and edges drawn by the generator instead. GitHub renders the source below directly.
ITEMS
| Item | Line | Documentation |
|---|---|---|
Direction pub enum | 64 | Which direction a device carries audio. |
DeviceInfo pub struct | 73 | A device the user can choose. |
VIRTUAL_CABLE_HINTS const | 89 | Name fragments used by the common virtual audio cables. |
looks_virtual fn | 106 | Whether a device's name suggests it is a virtual cable rather than real hardware. |
name_of_opt fn | 116 | A device's name as the platform reports it, or None when it will not say. |
list pub fn | 121 | List the devices available in one direction. |
find_virtual_cable pub fn | 154 | Find the first output device that looks like a virtual audio cable. |
name_of pub fn | 164 | The name of an opened device, or a placeholder when the OS will not say. |
open pub fn | 169 | Look up a device by exact name, or the host default when name is None. |