diff --git a/README.md b/README.md index 42785d8..0bf835f 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ Follow the instructions above for your operating system to install a virtual aud - Choose the **virtual output device** (e.g., "VB Cable Input" or "Virtual Audio Cable") from the dropdown - This is the playback device that's wired to your virtual microphone - Do NOT select your regular speakers or headphones + - On Linux change channel count to "Mono" when you select PipeWire or PulseAudio 3. **Choose connection method** diff --git a/RustApp/Cargo.lock b/RustApp/Cargo.lock index 80cee66..6d94139 100644 --- a/RustApp/Cargo.lock +++ b/RustApp/Cargo.lock @@ -278,6 +278,16 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "annotate-snippets" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" +dependencies = [ + "anstyle", + "unicode-width 0.2.2", +] + [[package]] name = "anstream" version = "1.0.0" @@ -661,7 +671,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 6.2.2", ] [[package]] @@ -830,6 +840,7 @@ version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ + "annotate-snippets", "bitflags 2.11.1", "cexpr", "clang-sys", @@ -1046,7 +1057,7 @@ checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" dependencies = [ "glib-sys", "libc", - "system-deps", + "system-deps 6.2.2", ] [[package]] @@ -1151,7 +1162,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom", + "nom 7.1.3", ] [[package]] @@ -1161,7 +1172,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" dependencies = [ "smallvec", - "target-lexicon", + "target-lexicon 0.12.16", +] + +[[package]] +name = "cfg-expr" +version = "0.20.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c6b04e07d8080154ed4ac03546d9a2b303cc2fe1901ba0b35b301516e289368" +dependencies = [ + "smallvec", + "target-lexicon 0.13.3", ] [[package]] @@ -1456,6 +1477,21 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "136d3e02915a2cea4d74caa8681e2d44b1c3254bdbf17d11d41d587ff858832c" +[[package]] +name = "convert_case" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "cookie-factory" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9885fa71e26b8ab7855e2ec7cae6e9b380edff76cd052e07c683a0319d51b3a2" + [[package]] name = "core-foundation" version = "0.9.4" @@ -1517,9 +1553,9 @@ dependencies = [ [[package]] name = "coreaudio-rs" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16dd574a72a021b90c7656c474ea31d11a2f0366a8eff574186e761e0b9e3586" +checksum = "7d5d7dca3ebcf65a035582c9ad4385371a9d9ee6537474d2a278f4e1e475bb58" dependencies = [ "bitflags 2.11.1", "libc", @@ -1649,18 +1685,19 @@ dependencies = [ [[package]] name = "cpal" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8942da362c0f0d895d7cac616263f2f9424edc5687364dfd1d25ef7eba506d7" +version = "0.18.0" +source = "git+https://github.com/RustAudio/cpal.git?rev=3e73d824295c18373e794ef7bb8f53c58bd8af67#3e73d824295c18373e794ef7bb8f53c58bd8af67" dependencies = [ "alsa", + "block2 0.6.2", "coreaudio-rs", "dasp_sample", + "futures", "jack", "jni 0.21.1", "js-sys", "libc", - "mach2", + "mach2 0.6.0", "ndk", "ndk-context", "num-derive", @@ -1672,10 +1709,11 @@ dependencies = [ "objc2-core-audio-types", "objc2-core-foundation", "objc2-foundation 0.3.2", - "wasm-bindgen", - "wasm-bindgen-futures", + "pipewire", + "pulseaudio", "web-sys", - "windows 0.62.2", + "windows 0.61.3", + "windows-core 0.61.2", ] [[package]] @@ -2365,6 +2403,17 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" +[[package]] +name = "enum-primitive-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba7795da175654fe16979af73f81f26a8ea27638d8d9823d317016888a63dc4c" +dependencies = [ + "num-traits", + "quote", + "syn 2.0.117", +] + [[package]] name = "enum_dispatch" version = "0.3.13" @@ -2943,7 +2992,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 6.2.2", ] [[package]] @@ -2960,7 +3009,7 @@ dependencies = [ "libc", "pango-sys", "pkg-config", - "system-deps", + "system-deps 6.2.2", ] [[package]] @@ -3105,7 +3154,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 6.2.2", "winapi", ] @@ -3170,7 +3219,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" dependencies = [ "libc", - "system-deps", + "system-deps 6.2.2", ] [[package]] @@ -3208,7 +3257,7 @@ checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" dependencies = [ "glib-sys", "libc", - "system-deps", + "system-deps 6.2.2", ] [[package]] @@ -3305,7 +3354,7 @@ dependencies = [ "gobject-sys", "libc", "pango-sys", - "system-deps", + "system-deps 6.2.2", ] [[package]] @@ -4042,7 +4091,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06d3a048d09fbb6597dbf7c69f40d14df4a49487db1487191618c893fc3b1c26" dependencies = [ "core-foundation-sys", - "mach2", + "mach2 0.5.0", ] [[package]] @@ -4502,6 +4551,34 @@ dependencies = [ "redox_syscall 0.7.4", ] +[[package]] +name = "libspa" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b8cfa2a7656627b4c92c6b9ef929433acd673d5ab3708cda1b18478ac00df4" +dependencies = [ + "bitflags 2.11.1", + "cc", + "convert_case", + "cookie-factory", + "libc", + "libspa-sys", + "nix 0.30.1", + "nom 8.0.0", + "system-deps 7.0.8", +] + +[[package]] +name = "libspa-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901049455d2eb6decf9058235d745237952f4804bc584c5fcb41412e6adcc6e0" +dependencies = [ + "bindgen", + "cc", + "system-deps 7.0.8", +] + [[package]] name = "libxdo" version = "0.6.0" @@ -4678,6 +4755,12 @@ dependencies = [ "libc", ] +[[package]] +name = "mach2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b" + [[package]] name = "malloc_buf" version = "0.0.6" @@ -4926,6 +5009,18 @@ dependencies = [ "memoffset 0.7.1", ] +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags 2.11.1", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", +] + [[package]] name = "nnnoiseless" version = "0.5.2" @@ -4952,6 +5047,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + [[package]] name = "notify" version = "8.2.0" @@ -5187,6 +5291,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13a380031deed8e99db00065c45937da434ca987c034e13b87e4441f9e4090be" dependencies = [ + "bitflags 2.11.1", "objc2 0.6.4", "objc2-foundation 0.3.2", ] @@ -5580,7 +5685,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps", + "system-deps 6.2.2", ] [[package]] @@ -5802,6 +5907,34 @@ dependencies = [ "futures-io", ] +[[package]] +name = "pipewire" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9688b89abf11d756499f7c6190711d6dbe5a3acdb30c8fbf001d6596d06a8d44" +dependencies = [ + "anyhow", + "bitflags 2.11.1", + "libc", + "libspa", + "libspa-sys", + "nix 0.30.1", + "once_cell", + "pipewire-sys", + "thiserror 2.0.18", +] + +[[package]] +name = "pipewire-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb028afee0d6ca17020b090e3b8fa2d7de23305aef975c7e5192a5050246ea36" +dependencies = [ + "bindgen", + "libspa-sys", + "system-deps 7.0.8", +] + [[package]] name = "pkg-config" version = "0.3.33" @@ -5948,7 +6081,7 @@ dependencies = [ "inferno", "libc", "log", - "nix", + "nix 0.26.4", "once_cell", "smallvec", "spin", @@ -6164,6 +6297,22 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" +[[package]] +name = "pulseaudio" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d70623bd7967a9ca4c2ae0e807fc380b291f98480fc037042305ec643a4d3373" +dependencies = [ + "bitflags 2.11.1", + "byteorder", + "enum-primitive-derive", + "futures", + "log", + "mio", + "num-traits", + "thiserror 1.0.69", +] + [[package]] name = "pxfm" version = "0.1.29" @@ -6873,6 +7022,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_with" version = "3.18.0" @@ -7369,13 +7527,26 @@ version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" dependencies = [ - "cfg-expr", + "cfg-expr 0.15.8", "heck 0.5.0", "pkg-config", "toml 0.8.2", "version-compare", ] +[[package]] +name = "system-deps" +version = "7.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396a35feb67335377e0251fcbc1092fc85c484bd4e3a7a54319399da127796e7" +dependencies = [ + "cfg-expr 0.20.7", + "heck 0.5.0", + "pkg-config", + "toml 1.1.2+spec-1.1.0", + "version-compare", +] + [[package]] name = "taffy" version = "0.9.2" @@ -7394,6 +7565,12 @@ version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" +[[package]] +name = "target-lexicon" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c" + [[package]] name = "tauri-winrt-notification" version = "0.7.2" @@ -7675,11 +7852,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" dependencies = [ "serde", - "serde_spanned", + "serde_spanned 0.6.9", "toml_datetime 0.6.3", "toml_edit 0.20.2", ] +[[package]] +name = "toml" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +dependencies = [ + "indexmap 2.14.0", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.2", +] + [[package]] name = "toml_datetime" version = "0.6.3" @@ -7717,7 +7909,7 @@ checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" dependencies = [ "indexmap 2.14.0", "serde", - "serde_spanned", + "serde_spanned 0.6.9", "toml_datetime 0.6.3", "winnow 0.5.40", ] @@ -7743,6 +7935,12 @@ dependencies = [ "winnow 1.0.2", ] +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + [[package]] name = "tracing" version = "0.1.44" @@ -8615,23 +8813,11 @@ version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ - "windows-collections 0.2.0", + "windows-collections", "windows-core 0.61.2", - "windows-future 0.2.1", + "windows-future", "windows-link 0.1.3", - "windows-numerics 0.2.0", -] - -[[package]] -name = "windows" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" -dependencies = [ - "windows-collections 0.3.2", - "windows-core 0.62.2", - "windows-future 0.3.2", - "windows-numerics 0.3.1", + "windows-numerics", ] [[package]] @@ -8643,15 +8829,6 @@ dependencies = [ "windows-core 0.61.2", ] -[[package]] -name = "windows-collections" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" -dependencies = [ - "windows-core 0.62.2", -] - [[package]] name = "windows-core" version = "0.52.0" @@ -8705,18 +8882,7 @@ checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ "windows-core 0.61.2", "windows-link 0.1.3", - "windows-threading 0.1.0", -] - -[[package]] -name = "windows-future" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" -dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", - "windows-threading 0.2.1", + "windows-threading", ] [[package]] @@ -8785,16 +8951,6 @@ dependencies = [ "windows-link 0.1.3", ] -[[package]] -name = "windows-numerics" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" -dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", -] - [[package]] name = "windows-result" version = "0.1.2" @@ -8966,15 +9122,6 @@ dependencies = [ "windows-link 0.1.3", ] -[[package]] -name = "windows-threading" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" -dependencies = [ - "windows-link 0.2.1", -] - [[package]] name = "windows-version" version = "0.1.7" @@ -9515,7 +9662,7 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix", + "nix 0.26.4", "once_cell", "ordered-stream", "rand 0.8.6", diff --git a/RustApp/Cargo.toml b/RustApp/Cargo.toml index 636b397..7071f59 100644 --- a/RustApp/Cargo.toml +++ b/RustApp/Cargo.toml @@ -46,7 +46,7 @@ adb = [] [dependencies] clap = { version = "4", features = ["derive"] } # linux: alsa will probably be included as a fallback ? -cpal = { version = "0.17", features = ["jack"] } +cpal = { git = "https://github.com/RustAudio/cpal.git", rev="3e73d824295c18373e794ef7bb8f53c58bd8af67", features = ["jack", "pipewire", "pulseaudio"] } rtrb = "0.3" local-ip-address = "0.6" log = "0.4" diff --git a/RustApp/src/audio/player.rs b/RustApp/src/audio/player.rs index bb57aa7..5b49831 100644 --- a/RustApp/src/audio/player.rs +++ b/RustApp/src/audio/player.rs @@ -126,7 +126,7 @@ fn build_output_stream( device: &cpal::Device, config: cpal::StreamConfig, mut consumer: Consumer, -) -> anyhow::Result +) -> anyhow::Result where F: cpal::SizedSample + AudioBytes + 'static, { @@ -135,7 +135,7 @@ where let frame_bytes = frame_size * channels; device.build_output_stream( - &config, + config, move |data: &mut [F], _| { process_audio(data, &mut consumer, frame_bytes); }, diff --git a/RustApp/src/ui/app.rs b/RustApp/src/ui/app.rs index a68d728..a61c337 100644 --- a/RustApp/src/ui/app.rs +++ b/RustApp/src/ui/app.rs @@ -4,8 +4,7 @@ use std::{ }; use cpal::{ - Device, Host, - traits::{DeviceTrait, HostTrait, StreamTrait}, + Device, Host, HostId, traits::{DeviceTrait, HostTrait, StreamTrait} }; use local_ip_address::list_afinet_netifas; use notify_rust::Notification; @@ -87,10 +86,10 @@ impl AudioDevice { Ok(Self { name: desc .extended() - .first() - .cloned() + .next() + .map(String::from) .unwrap_or(desc.name().to_owned()), - id: id.1, + id: id.to_string(), device, }) } @@ -124,6 +123,8 @@ pub struct AppState { core: Core, pub streamer: Option>, pub config: ConfigManager, + #[cfg(target_os = "linux")] + pub available_hosts: Vec, pub audio_host: Host, pub audio_devices: Vec, pub audio_device: Option, @@ -328,7 +329,9 @@ impl Application for AppState { flags: Self::Flags, ) -> (Self, cosmic::app::Task) { // initialize audio device + let available_hosts = cpal::available_hosts(); let audio_host = cpal::default_host(); + let audio_devices = get_audio_devices(&audio_host); let audio_device = match &flags.config.data().device_id { Some(id) => { @@ -389,6 +392,8 @@ impl Application for AppState { streamer: None, config: flags.config, audio_device, + #[cfg(target_os = "linux")] + available_hosts, audio_host, audio_devices, audio_wave: AudioWave::new(), @@ -459,7 +464,12 @@ impl Application for AppState { }); } AppMsg::RefreshAudioDevices => { + #[cfg(not(target_os = "linux"))] let audio_host = cpal::default_host(); + + #[cfg(target_os = "linux")] + let audio_host = cpal::host_from_id(self.audio_host.id()).unwrap_or(cpal::default_host()); + self.audio_devices = get_audio_devices(&audio_host); } AppMsg::RefreshNetworkAdapters => { @@ -548,6 +558,11 @@ impl Application for AppState { .update(|c| c.device_id = Some(audio_device.id.clone())); return self.update_audio_stream(); } + #[cfg(target_os = "linux")] + AppMsg::SelectedHost(selected_host) => { + self.audio_host = cpal::host_from_id(selected_host).unwrap_or(cpal::default_host()); + self.audio_devices = get_audio_devices(&self.audio_host); + } AppMsg::Adapter(adapter) => { self.config.update(|c| c.ip = Some(adapter.ip)); self.network_adapter = Some(adapter.clone()); diff --git a/RustApp/src/ui/message.rs b/RustApp/src/ui/message.rs index 5431285..7a47879 100644 --- a/RustApp/src/ui/message.rs +++ b/RustApp/src/ui/message.rs @@ -14,6 +14,8 @@ pub enum AppMsg { ChangeConnectionMode(ConnectionMode), Streamer(StreamerMsg), Device(AudioDevice), + #[cfg(target_os = "linux")] + SelectedHost(HostId), Adapter(NetworkAdapter), Connect, Stop, @@ -64,6 +66,8 @@ pub enum MenuMsg { } use cosmic::widget::menu::action::MenuAction; +#[cfg(target_os = "linux")] +use cpal::HostId; impl MenuAction for MenuMsg { type Message = AppMsg; diff --git a/RustApp/src/ui/view.rs b/RustApp/src/ui/view.rs index 8364996..a184165 100644 --- a/RustApp/src/ui/view.rs +++ b/RustApp/src/ui/view.rs @@ -48,7 +48,7 @@ pub fn main_window(app: &AppState) -> Element<'_, AppMsg> { column() .width(Length::FillPortion(1)) .height(Length::Fill) - .spacing(35) + .spacing(20) .align_x(Horizontal::Center) .push_maybe( (connection_mode == ConnectionMode::Tcp @@ -104,25 +104,45 @@ fn wave(app: &AppState) -> Element<'_, AppMsg> { } fn audio(app: &AppState) -> Element<'_, AppMsg> { - let selected = app + #[cfg(target_os = "linux")] + let selected_host = app.available_hosts.iter().find(|d| **d == app.audio_host.id()); + + let selected_device = app .audio_device .as_ref() .and_then(|d| d.id().ok()) - .and_then(|id| app.audio_devices.iter().find(|d| d.id == id.1)); + .and_then(|id| app.audio_devices.iter().find(|d| d.id == id.to_string())); column() .spacing(20) .align_x(Horizontal::Center) .push(text::title4(fl!("audio_device"))) + .push_maybe( + { + #[cfg(target_os = "linux")]{ + Some(tooltip( + pick_list(app.available_hosts.clone(), selected_host, AppMsg::SelectedHost) + .width(Length::Fill), + selected_host.as_ref().map_or("None", |host| &host.name()), + tooltip::Position::Top, + ) + .class(cosmic::theme::Container::Tooltip)) + } + #[cfg(not(target_os = "linux"))] + { + Option::>::None + } + } + ) .push( row() .width(Length::Fill) .spacing(5) .push( tooltip( - pick_list(app.audio_devices.clone(), selected, AppMsg::Device) + pick_list(app.audio_devices.clone(), selected_device, AppMsg::Device) .width(Length::Fill), - selected.as_ref().map_or("None", |device| &device.name), + selected_device.as_ref().map_or("None", |device| &device.name), tooltip::Position::Top, ) .class(cosmic::theme::Container::Tooltip),