diff --git a/Cargo.lock b/Cargo.lock index d29b120..d595b15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -254,6 +254,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys 0.8.4", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.6.2" @@ -266,6 +276,30 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +[[package]] +name = "core-graphics" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "970a29baf4110c26fedbc7f82107d42c23f7e88e404c4577ed73fe99ff85a212" +dependencies = [ + "bitflags", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" +dependencies = [ + "bitflags", + "core-foundation", + "libc", +] + [[package]] name = "coreaudio-rs" version = "0.11.2" @@ -308,7 +342,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "windows", + "windows 0.46.0", ] [[package]] @@ -332,6 +366,19 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enigo" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "802e4b2ae123615659085369b453cba87c5562e46ed8050a909fee18a9bc3157" +dependencies = [ + "core-graphics", + "libc", + "objc", + "pkg-config", + "windows 0.51.1", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -344,6 +391,33 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.26", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + [[package]] name = "form_urlencoded" version = "1.2.0" @@ -614,6 +688,15 @@ dependencies = [ "libc", ] +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "matchit" version = "0.7.0" @@ -805,6 +888,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + [[package]] name = "object" version = "0.31.1" @@ -872,7 +964,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -1158,6 +1250,7 @@ dependencies = [ "axum-template", "cpal", "dotenvy", + "enigo", "log", "minijinja", "minimp3", @@ -1532,13 +1625,32 @@ dependencies = [ "windows-targets 0.42.2", ] +[[package]] +name = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -1558,17 +1670,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -1579,9 +1691,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -1591,9 +1703,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -1603,9 +1715,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -1615,9 +1727,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -1627,9 +1739,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" @@ -1639,9 +1751,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -1651,9 +1763,9 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" diff --git a/Cargo.toml b/Cargo.toml index 6fd2ed8..53fec25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ axum = "0.6.18" axum-template = { version = "0.19.0", features = ["minijinja"] } cpal = "0.15.2" dotenvy = "0.15.7" +enigo = "0.1.3" log = "0.4.20" minijinja = { version = "1.0.3", features = ["loader"] } minimp3 = "0.5.1" diff --git a/src/main.rs b/src/main.rs index 8c69ee1..2b26262 100644 --- a/src/main.rs +++ b/src/main.rs @@ -88,7 +88,10 @@ async fn play_handler( player .lock() .unwrap() - .send(vbplay::Command::Play(full_file_name.into())) + .send(vbplay::Command::PlayWhilePressing( + full_file_name.into(), + "".to_owned(), // placeholder. + )) .unwrap(); } "".to_owned() diff --git a/src/vbplay.rs b/src/vbplay.rs index a6c26c9..5d153db 100644 --- a/src/vbplay.rs +++ b/src/vbplay.rs @@ -1,5 +1,6 @@ use cpal::traits::{DeviceTrait, HostTrait}; use cpal::{Device, Host}; +use enigo::*; use log::{debug, error, info}; use minimp3::{Decoder, Error}; use regex::Regex; @@ -7,6 +8,11 @@ use std::fs::File; use std::io::Read; use std::io::{BufReader, Cursor}; use std::sync::mpsc::{self, Sender}; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, Mutex, +}; + use std::thread; #[derive(Clone)] @@ -18,6 +24,7 @@ pub enum SoundDecoder { pub enum Command { Play(String), + PlayWhilePressing(String, String), Stop, } @@ -78,15 +85,50 @@ pub fn audio_thread(select_device: DeviceSelection, select_decoder: SoundDecoder // Create a rodio Sink connected to our device let (_stream, stream_handle) = rodio::OutputStream::try_from_device(&device).unwrap(); - let sink = rodio::Sink::try_new(&stream_handle).unwrap(); + let new_sink = rodio::Sink::try_new(&stream_handle).unwrap(); + + let sink_mutex = Arc::new(Mutex::new(new_sink)); + let is_button_thread_active = Arc::new(AtomicBool::new(false)); for command in rx { match command { Command::Play(file_name) => { - play_file(&sink, file_name, &select_decoder); + if let Ok(sink) = sink_mutex.lock() { + play_file(&sink, file_name, &select_decoder); + } else { + error!("Mutex Lock Failure while trying to play sound.") + } + } + Command::PlayWhilePressing(file_name, press_button) => { + if let Ok(sink) = sink_mutex.lock() { + play_file(&sink, file_name, &select_decoder); + } else { + error!("Mutex Lock Failure while trying to play sound with callbacks."); + } + + if !is_button_thread_active.load(Ordering::SeqCst) { + let sink_mutex_clone = sink_mutex.clone(); + let is_active_clone = is_button_thread_active.clone(); + thread::spawn(move || { + let mut enigo = Enigo::new(); + enigo.mouse_down(MouseButton::Forward); + is_active_clone.store(true, Ordering::SeqCst); + + while sink_mutex_clone.lock().map_or(false, |sink| !sink.empty()) { + thread::sleep(std::time::Duration::from_millis(100)); + } + + enigo.mouse_up(MouseButton::Forward); + is_active_clone.store(false, Ordering::SeqCst); + }); + } } Command::Stop => { - sink.stop(); + if let Ok(sink) = sink_mutex.lock() { + sink.stop(); + } else { + error!("Mutex Lock Failure while trying to stop sound."); + } } } } @@ -99,7 +141,7 @@ fn detect_decoder(file_name: &str, sound_decoder: &SoundDecoder) -> SoundDecoder // TODO: File detection via ending or whitelisting? // This function MUST NOT return SoundDecoder::Detect match sound_decoder { - SoundDecoder::Detect => SoundDecoder::Rodio, + SoundDecoder::Detect => SoundDecoder::Mp3Mini, other => other.clone(), } }