diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Cargo.lock | 494 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | dmvop.toml | 81 | ||||
| -rw-r--r-- | src/args.rs | 3 | ||||
| -rw-r--r-- | src/device_selector.rs | 78 | ||||
| -rw-r--r-- | src/main.rs | 22 |
7 files changed, 649 insertions, 31 deletions
@@ -1 +1,2 @@ /target +/models @@ -41,6 +41,28 @@ dependencies = [ ] [[package]] +name = "alsa" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812947049edcd670a82cd5c73c3661d2e58468577ba8489de58e1a73c04cbd5d" +dependencies = [ + "alsa-sys", + "bitflags 2.13.0", + "cfg-if", + "libc", +] + +[[package]] +name = "alsa-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad7569085a265dd3f607ebecce7458eaab2132a84393534c95b18dcbc3f31e04" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] name = "android_system_properties" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -214,7 +236,16 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" dependencies = [ - "objc2", + "objc2 0.5.2", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2 0.6.4", ] [[package]] @@ -372,6 +403,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] name = "constant_time_eq" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -433,6 +474,20 @@ dependencies = [ ] [[package]] +name = "coreaudio-rs" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5d7dca3ebcf65a035582c9ad4385371a9d9ee6537474d2a278f4e1e475bb58" +dependencies = [ + "bitflags 2.13.0", + "libc", + "objc2-audio-toolbox", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", +] + +[[package]] name = "coreaudio-sys" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -442,6 +497,36 @@ dependencies = [ ] [[package]] +name = "cpal" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f77b11176c37874be37e8d691c946e31b2b8c357abce9526f6a99eb469e1028" +dependencies = [ + "alsa", + "block2 0.6.2", + "coreaudio-rs 0.14.2", + "dasp_sample", + "jni", + "js-sys", + "libc", + "mach2", + "ndk", + "ndk-context", + "num-derive", + "num-traits", + "objc2 0.6.4", + "objc2-audio-toolbox", + "objc2-avf-audio", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "web-sys", + "windows 0.62.2", + "windows-core 0.62.2", +] + +[[package]] name = "cpufeatures" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -500,6 +585,12 @@ dependencies = [ ] [[package]] +name = "dasp_sample" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" + +[[package]] name = "deflate64" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -561,6 +652,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.13.0", + "objc2 0.6.4", +] + +[[package]] name = "displaydoc" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -576,6 +677,7 @@ name = "dumb-voice-protocol" version = "0.1.0" dependencies = [ "clap", + "cpal", "pinyin", "serde", "tokio", @@ -1152,6 +1254,64 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys 0.4.1", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn", +] + +[[package]] +name = "jni-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn", +] + +[[package]] name = "jobserver" version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1286,6 +1446,12 @@ dependencies = [ ] [[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" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1360,6 +1526,35 @@ dependencies = [ ] [[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.13.0", + "jni-sys 0.3.1", + "log", + "ndk-sys", + "num_enum", + "thiserror 1.0.69", +] + +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + +[[package]] +name = "ndk-sys" +version = "0.6.0+11769913" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" +dependencies = [ + "jni-sys 0.3.1", +] + +[[package]] name = "nix" version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1405,6 +1600,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "num-integer" version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1423,6 +1629,28 @@ dependencies = [ ] [[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "objc" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1460,6 +1688,77 @@ dependencies = [ ] [[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-audio-toolbox" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6948501a91121d6399b79abaa33a8aa4ea7857fe019f341b8c23ad6e81b79b08" +dependencies = [ + "bitflags 2.13.0", + "libc", + "objc2 0.6.4", + "objc2-core-audio", + "objc2-core-audio-types", + "objc2-core-foundation", + "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 = [ + "bitflags 2.13.0", + "objc2 0.6.4", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-audio" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1eebcea8b0dbff5f7c8504f3107c68fc061a3eb44932051c8cf8a68d969c3b2" +dependencies = [ + "dispatch2", + "objc2 0.6.4", + "objc2-core-audio-types", + "objc2-core-foundation", + "objc2-foundation 0.3.2", +] + +[[package]] +name = "objc2-core-audio-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c" +dependencies = [ + "bitflags 2.13.0", + "objc2 0.6.4", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.13.0", + "block2 0.6.2", + "dispatch2", + "libc", + "objc2 0.6.4", +] + +[[package]] name = "objc2-encode" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1472,10 +1771,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ "bitflags 2.13.0", - "block2", + "block2 0.5.1", "dispatch", "libc", - "objc2", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags 2.13.0", + "block2 0.6.2", + "libc", + "objc2 0.6.4", + "objc2-core-foundation", ] [[package]] @@ -1667,6 +1979,15 @@ dependencies = [ ] [[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.12+spec-1.1.0", +] + +[[package]] name = "proc-macro2" version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1816,6 +2137,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] name = "rustfft" version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1888,6 +2218,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] name = "schannel" version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1940,6 +2279,12 @@ dependencies = [ ] [[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] name = "serde" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2052,6 +2397,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] name = "slab" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2328,8 +2689,8 @@ checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", - "toml_datetime", - "toml_edit", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", ] [[package]] @@ -2342,6 +2703,15 @@ dependencies = [ ] [[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] name = "toml_edit" version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2350,9 +2720,30 @@ dependencies = [ "indexmap", "serde", "serde_spanned", - "toml_datetime", + "toml_datetime 0.6.11", "toml_write", - "winnow", + "winnow 0.7.15", +] + +[[package]] +name = "toml_edit" +version = "0.25.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" +dependencies = [ + "indexmap", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.3", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.3", ] [[package]] @@ -2578,18 +2969,18 @@ version = "0.3.1" source = "git+https://github.com/Weicao-CatilGrass/vtx-engine?rev=35b954ad50ec6211e6a25ca4777d1685311f696e#35b954ad50ec6211e6a25ca4777d1685311f696e" dependencies = [ "aec3", - "block2", + "block2 0.5.1", "chrono", "core-foundation 0.10.1", - "coreaudio-rs", + "coreaudio-rs 0.11.3", "directories", "dispatch", "futures", "hound", "libc", "libloading", - "objc2", - "objc2-foundation", + "objc2 0.5.2", + "objc2-foundation 0.2.2", "pipewire", "reqwest", "rustfft", @@ -2600,11 +2991,21 @@ dependencies = [ "toml", "tracing", "uuid", - "windows", + "windows 0.58.0", "zip", ] [[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] name = "want" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2723,6 +3124,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2739,6 +3149,27 @@ dependencies = [ ] [[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core 0.62.2", + "windows-future", + "windows-numerics", +] + +[[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.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2765,6 +3196,17 @@ dependencies = [ ] [[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", + "windows-threading", +] + +[[package]] name = "windows-implement" version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2815,6 +3257,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[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", +] + +[[package]] name = "windows-registry" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2921,6 +3373,15 @@ dependencies = [ ] [[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + +[[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3020,6 +3481,15 @@ dependencies = [ ] [[package]] +name = "winnow" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" +dependencies = [ + "memchr", +] + +[[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -15,6 +15,7 @@ toml = "0.8" tokio = { version = "1.52.3", features = ["net", "rt", "rt-multi-thread", "macros"] } tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } pinyin = { version = "0.11.0", features = ["with_tone", "with_tone_num", "with_tone_num_end"] } +cpal = "0.18.1" [dependencies.vtx-engine] git = "https://github.com/Weicao-CatilGrass/vtx-engine" diff --git a/dmvop.toml b/dmvop.toml new file mode 100644 index 0000000..c80bacb --- /dev/null +++ b/dmvop.toml @@ -0,0 +1,81 @@ +## DMVOP Config File +## Name this file `dmvop.toml` and place it in the working dir to be auto-detected! +## +## DMVOP will auto-load this config file to avoid repeated CLI args + +## Your audio input device, you can query with `dmvop --list-devices` +## Use `auto` to automatically get the device in use +device = "auto" + +## Output format +## Sets the text format after transcription +## Supported parameters: +## - %{vol} Volume +## - %{word} Content +## - %{confid} Confidence score +format = "%{word} (%%{vol})" # Hello. (%50) + +## Whisper model selection +## Use `dmvop --list-models` to view available models +## Use `dmvop --download-model=<NAME>` to download available models +## (Model download and reading directory is configured in `models_dir`, relative to the current configuration directory) +model = "base.en" + +## Expected language for Whisper to recognize +## This makes it more inclined to recognize the specified language +lang = "en" + +## Expected output mode +output = [ + ## Directly use stdout to output to terminal + "stdout", + + ## Directly use stderr to output to terminal + # "stderr", + + ## TCP service mode + ## After the client connects to the current port (port configured in `port`) + ## DMVOP will automatically broadcast output to all connected clients + # "tcp", + + ## UDP service mode + ## The client sends a message packet to the current port to complete the handshake (port configured in `port`) + ## After that, DMVOP will automatically send content to the first client that handshook + # "udp", + + ## UDP broadcast mode + ## When enabled, DMVOP will directly broadcast messages to all devices on the LAN listening to the specified port + ## (port configured in `port`, subnet mask configured in `subnet_mask`) + # "udp-broadcast", + + ## IPC socket mode + ## Sends messages to the specified Unix socket file + ## (use `socket_file` to specify the socket file) + ## Note: This mode is only supported on UNIX + # "ipc" +] + +## Port used in UDP / TCP / UDP_BROADCAST mode +port = 5117 + +## Instant mode +## Shorter detection time, closer to real-time +instant = false + +## Model file storage directory +## Used to specify the directory for downloading and reading Whisper model files +## (Relative to the current configuration directory) +models_dir = "./models" + +## Subnet mask +## Used in UDP broadcast mode to specify the subnet mask for broadcasting +subnet_mask = "255.255.255.0" + +## IPC socket file path +## Used in IPC socket mode to specify the Unix socket file +## Note: This mode is only supported on UNIX systems +socket_file = "./dmvop.sock" + +## Post-processor +## After text parsing, a post-processor can be used to process the text content +# post = "+pinyin(tone)" diff --git a/src/args.rs b/src/args.rs index 9a4bd0d..1f0b7df 100644 --- a/src/args.rs +++ b/src/args.rs @@ -69,7 +69,8 @@ pub struct DMVOPArguments { long = "device", alias = "dev", allow_hyphen_values = true, - require_equals = true + require_equals = true, + default_value = "auto" )] pub device_name: Option<String>, diff --git a/src/device_selector.rs b/src/device_selector.rs new file mode 100644 index 0000000..12f8a79 --- /dev/null +++ b/src/device_selector.rs @@ -0,0 +1,78 @@ +use cpal::traits::{DeviceTrait, HostTrait}; + +/// Pick the best input device from the available list. +/// +/// - `"auto"` → query OS default input device via cpal, match against list +/// - `"<name>"` → match by device ID or name; exits if not found +/// - `None` → exits with error +pub fn pick_device<'a>( + name: &Option<String>, + devices: &'a [vtx_engine::AudioDevice], +) -> Option<&'a vtx_engine::AudioDevice> { + let name = match name { + Some(n) if n == "auto" || n.is_empty() => return pick_auto(devices), + Some(n) => n.as_str(), + None => { + eprintln!( + "[dmvop] No device specified. Use --device=<name> or --list-devices to see available devices." + ); + std::process::exit(1); + } + }; + + // Try exact match by id or name + if let Some(d) = devices.iter().find(|d| d.id == name || d.name == name) { + return Some(d); + } + + eprintln!( + "[dmvop] Device '{}' not found. Use --list-devices to see available devices.", + name + ); + std::process::exit(1); +} + +/// Use cpal to find the system's default input device, then match it +/// against the vtx-engine device list by WASAPI ID. +fn pick_auto<'a>(devices: &'a [vtx_engine::AudioDevice]) -> Option<&'a vtx_engine::AudioDevice> { + let host = cpal::default_host(); + let device = match host.default_input_device() { + Some(d) => d, + None => { + eprintln!("[dmvop] No default input device found."); + return devices.first(); + } + }; + + // Get the WASAPI device ID from cpal + let cpal_device_id = match device.id() { + Ok(id) => id, + Err(_) => return devices.first(), + }; + let cpal_raw_id = cpal_device_id.id().to_string(); + + // Match against vtx-engine devices by ID (substring — cpal might omit braces) + for dev in devices { + let dev_id_clean = dev.id.trim_matches('{').trim_matches('}'); + let cpal_id_clean = cpal_raw_id.trim_matches('{').trim_matches('}'); + if dev_id_clean.contains(cpal_id_clean) || cpal_id_clean.contains(dev_id_clean) { + return Some(dev); + } + } + + // Fallback: match by name (cpal DeviceId Display includes host:raw_id) + let cpal_display = cpal_device_id.to_string().to_lowercase(); + for dev in devices { + if cpal_display.contains(&dev.name.to_lowercase()) + || dev.name.to_lowercase().contains(&cpal_display) + { + return Some(dev); + } + } + + eprintln!( + "[dmvop] Default device ({}) not matched, using first available.", + cpal_raw_id + ); + devices.first() +} diff --git a/src/main.rs b/src/main.rs index 2aa68ac..87f7657 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,9 @@ pub mod post_proc; mod args; pub use args::*; +mod device_selector; mod output_protocol; + use clap::Parser; use output_protocol::OutputProtocol; use std::path::PathBuf; @@ -220,30 +222,14 @@ async fn main() { // --------------------------------------------------------------- // Find the requested device and start capture // --------------------------------------------------------------- - let device_name = match &args.device_name { - Some(n) => n.as_str(), - None => { - eprintln!( - "[dmvop] No device specified. Use --device=<name> or --list-devices to see available devices." - ); - std::process::exit(1); - } - }; - - let device = devices - .iter() - .find(|d| d.id == device_name || d.name == device_name) - .or_else(|| devices.first()); + let device = device_selector::pick_device(&args.device_name, &devices); match &device { Some(d) => { debug_log!("[dmvop] Using input device: {} (id: {})", d.name, d.id); } None => { - eprintln!( - "[dmvop] Device '{}' not found and no fallback available.", - device_name - ); + eprintln!("[dmvop] No input devices found. Make sure a microphone is connected."); std::process::exit(1); } } |
