From ea2fa978cad190ddf941f669da832ace42b267cd Mon Sep 17 00:00:00 2001 From: csd4ni3l Date: Thu, 22 Jan 2026 20:06:33 +0100 Subject: [PATCH] use rodio's cpal, use microphone device instead of default, only show supported files in the list, and Linux works now when ran with the included script and Discord set to use the virtual_mic source. --- Cargo.lock | 77 ++++------------------------------------------------ Cargo.toml | 1 - run_linux.sh | 8 ++++++ src/main.rs | 13 +++++++-- 4 files changed, 23 insertions(+), 76 deletions(-) create mode 100644 run_linux.sh diff --git a/Cargo.lock b/Cargo.lock index b5f9dcb..a58143b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -115,18 +115,6 @@ dependencies = [ "libc", ] -[[package]] -name = "alsa" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c88dbbce13b232b26250e1e2e6ac18b6a891a646b8148285036ebce260ac5c3" -dependencies = [ - "alsa-sys", - "bitflags 2.10.0", - "cfg-if", - "libc", -] - [[package]] name = "alsa-sys" version = "0.3.1" @@ -2137,14 +2125,14 @@ version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" dependencies = [ - "alsa 0.9.1", + "alsa", "core-foundation-sys", "coreaudio-rs 0.11.3", "dasp_sample", "jni", "js-sys", "libc", - "mach2 0.4.3", + "mach2", "ndk 0.8.0", "ndk-context", "oboe", @@ -2160,13 +2148,13 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbd307f43cc2a697e2d1f8bc7a1d824b5269e052209e28883e5bc04d095aaa3f" dependencies = [ - "alsa 0.9.1", + "alsa", "coreaudio-rs 0.13.0", "dasp_sample", "jni", "js-sys", "libc", - "mach2 0.4.3", + "mach2", "ndk 0.9.0", "ndk-context", "num-derive", @@ -2180,36 +2168,6 @@ dependencies = [ "windows 0.54.0", ] -[[package]] -name = "cpal" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ceb96745bc9bbcf1f7eb1267ee03045275fa0cc82a4b34d8534ffdcaf657c3" -dependencies = [ - "alsa 0.10.0", - "coreaudio-rs 0.13.0", - "dasp_sample", - "jni", - "js-sys", - "libc", - "mach2 0.5.0", - "ndk 0.9.0", - "ndk-context", - "num-derive", - "num-traits", - "objc2 0.6.3", - "objc2-audio-toolbox", - "objc2-avf-audio", - "objc2-core-audio", - "objc2-core-audio-types", - "objc2-core-foundation", - "objc2-foundation 0.3.2", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows 0.62.2", -] - [[package]] name = "crc32fast" version = "1.5.0" @@ -3253,7 +3211,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617ee6cf8e3f66f3b4ea67a4058564628cde41901316e19f559e14c7c72c5e7b" dependencies = [ "core-foundation-sys", - "mach2 0.4.3", + "mach2", ] [[package]] @@ -3456,15 +3414,6 @@ dependencies = [ "libc", ] -[[package]] -name = "mach2" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1b95cd5421ec55b445b5ae102f5ea0e768de1f82bd3001e11f426c269c3aea" -dependencies = [ - "libc", -] - [[package]] name = "malloc_buf" version = "0.0.6" @@ -3849,16 +3798,6 @@ dependencies = [ "objc2-foundation 0.3.2", ] -[[package]] -name = "objc2-avf-audio" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13a380031deed8e99db00065c45937da434ca987c034e13b87e4441f9e4090be" -dependencies = [ - "objc2 0.6.3", - "objc2-foundation 0.3.2", -] - [[package]] name = "objc2-cloud-kit" version = "0.2.2" @@ -3893,7 +3832,6 @@ dependencies = [ "objc2 0.6.3", "objc2-core-audio-types", "objc2-core-foundation", - "objc2-foundation 0.3.2", ] [[package]] @@ -3925,9 +3863,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.10.0", - "block2 0.6.2", "dispatch2", - "libc", "objc2 0.6.3", ] @@ -3994,8 +3930,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.10.0", - "block2 0.6.2", - "libc", "objc2 0.6.3", "objc2-core-foundation", ] @@ -4943,7 +4877,6 @@ version = "0.1.0" dependencies = [ "bevy", "bevy_egui", - "cpal 0.17.0", "rand", "rfd", "rodio 0.21.1", diff --git a/Cargo.toml b/Cargo.toml index 50a069d..b29ef12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ edition = "2024" [dependencies] bevy_egui = "0.38.1" -cpal = "0.17.0" rand = "0.9.2" rfd = "0.16.0" rodio = { version = "0.21.1", features = ["mp3", "wav", "flac", "vorbis"] } diff --git a/run_linux.sh b/run_linux.sh new file mode 100644 index 0000000..0b2daf7 --- /dev/null +++ b/run_linux.sh @@ -0,0 +1,8 @@ +#!/bin/bash +pactl load-module module-null-sink sink_name=VirtualMic sink_properties=device.description="Virtual_Microphone" +pactl load-module module-remap-source master=VirtualMic.monitor source_name=VirtualMicSource source_properties=device.description="Virtual_Mic_Source" + +PULSE_SINK=VirtualMic cargo run + +pactl list modules short | grep "Virtual_Microphone" | cut -f1 | xargs -L1 pactl unload-module +pactl list modules short | grep "Virtual_Mic_Source" | cut -f1 | xargs -L1 pactl unload-module \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 67e54b5..5b446c1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ use bevy_egui::{ EguiContextSettings, EguiContexts, EguiPlugin, EguiPrimaryContextPass, EguiStartupSet, egui, }; -use rodio::{Decoder, OutputStream, OutputStreamBuilder, Sink, mixer::Mixer}; +use rodio::{Decoder, OutputStream, OutputStreamBuilder, Sink, mixer::Mixer, cpal, cpal::traits::{HostTrait, DeviceTrait}}; #[derive(Serialize, Deserialize)] struct JSONData { @@ -39,8 +39,15 @@ struct AppState { use std::time::{SystemTime, UNIX_EPOCH}; +const ALLOWED_FILE_EXTENSIONS: [&str; 4] = ["mp3", "wav", "flac", "ogg"]; + fn main() { - let stream_handle = OutputStreamBuilder::open_default_stream().expect("Unable to open default audio device"); + let host = cpal::default_host(); + let virtual_mic = host.default_output_device().expect("Could not get default output device"); + + println!("Using device: {}", virtual_mic.name().unwrap_or_default()); + + let stream_handle = OutputStreamBuilder::from_device(virtual_mic).expect("Unable to open default audio device").open_stream().expect("Failed to open stream"); let mixer = stream_handle.mixer(); let sink = Sink::connect_new(&mixer); @@ -111,7 +118,7 @@ fn load_data(app_state: &mut AppState) { .filter_map(|entry| { entry.ok().and_then(|e| { let path = e.path(); - if path.is_file() { + if path.is_file() && ALLOWED_FILE_EXTENSIONS.contains(&path.extension().expect("Could not find extension").to_str().expect("Could not convert extension to string")) { path.to_str().map(|s| s.to_string()) } else { None