diff --git a/Cargo.toml b/Cargo.toml index 6346f59..3ec35ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,6 +46,7 @@ features = [ "Win32_UI_Controls", "Win32_Graphics_Dwm", "Win32_UI_Shell", + "Win32_System_Console", # attaching to console ] #[target.'cfg(windows)'.dependencies.windows-sys] diff --git a/src/main.rs b/src/main.rs index afe537a..601a6df 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![cfg_attr(not(test), windows_subsystem = "windows")] // not(debug_assertions) would hide the console only on release builds. + use axum_template::engine::Engine; use minijinja::{path_loader, Environment}; use state::AppState; @@ -19,6 +21,16 @@ mod vbplay; fn main() { dotenv().ok(); + + #[cfg(target_os = "windows")] + { + // if you run this from a windows console, we attach to the parent process. + use windows::Win32::System::Console::{AttachConsole, ATTACH_PARENT_PROCESS}; + unsafe { + AttachConsole(ATTACH_PARENT_PROCESS).unwrap_or_default(); + } + } + let rt = tokio::runtime::Runtime::new().unwrap(); let device_pattern = env::var("DEVICE_PATTERN").expect("Need a device pattern"); @@ -32,6 +44,7 @@ fn main() { DeviceSelection::FindByPattern(device_pattern), SoundDecoder::Detect, ); + let event_handler = Box::new(example_handler::PressMouseForward::new()); audio.on_playback(event_handler); let audio = Arc::new(Mutex::new(audio)); @@ -52,6 +65,7 @@ fn main() { }; let (ui_to_server_tx, ui_to_server_rx) = mpsc::channel(32); + //let (server_to_ui_tx, server_to_ui_rx) = mpsc::channel(32); let server_handle = rt.spawn(async move { server::run_server(app_state, ui_to_server_rx).await; @@ -72,5 +86,5 @@ fn main() { drop(audio); eprintln!("Reached end of program."); - std::process::exit(0); + //std::process::exit(0); } diff --git a/src/ui.rs b/src/ui.rs index 25c7f81..659d544 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,19 +1,26 @@ use eframe::egui; use raw_window_handle::{HasWindowHandle, RawWindowHandle}; -use std::sync::{Arc, Mutex}; +use std::sync::Mutex; +use std::sync::{ + atomic::{AtomicBool, Ordering}, + Arc, +}; use tokio::sync::mpsc; use tray_item::TrayItem; use crate::server::{ServerMessage, ServerSettings}; +pub enum UIMessage { + ServerHasQuit, +} + pub fn run_ui( settings: Arc>, should_run: Arc>, tx: mpsc::Sender, ) { - // Create an atomic bool to track window visibility - static VISIBLE: once_cell::sync::Lazy> = - once_cell::sync::Lazy::new(|| Mutex::new(true)); + // Initialize visibility as AtomicBool + let visible = Arc::new(AtomicBool::new(true)); let icon = crate::icon::load_app_icon("icon-soundboard"); @@ -22,11 +29,12 @@ pub fn run_ui( ..Default::default() }; + let visible_for_tray = Arc::clone(&visible); + eframe::run_native( "App", native_options, Box::new(|cc| { - // Set up the tray icon event handler let window_handle = cc.window_handle().unwrap(); let window_handle = window_handle.as_raw(); let mut tray = TrayItem::new( @@ -34,34 +42,33 @@ pub fn run_ui( tray_item::IconSource::Resource("icon-soundboard"), ) .unwrap(); + if let RawWindowHandle::Win32(handle) = window_handle { #[cfg(windows)] { - // Windows Only. use windows::Win32::Foundation::HWND; use windows::Win32::UI::WindowsAndMessaging::{ - ShowWindow, - SW_HIDE, - SW_RESTORE, // SW_SHOWDEFAULT, SW_SHOWNORMAL, + ShowWindow, SW_HIDE, SW_RESTORE, }; tray.add_label("Server Control").unwrap(); + let window_handle = HWND(handle.hwnd.into()); tray.add_menu_item("Show/Hide", { + //let visible_for_tray = Arc::clone(&visible_for_tray); move || { - let mut visible_lock = VISIBLE.lock().unwrap(); - let window_handle = HWND(handle.hwnd.into()); + let is_visible = visible_for_tray.load(Ordering::SeqCst); - if *visible_lock { + if is_visible { unsafe { _ = ShowWindow(window_handle, SW_HIDE); } - *visible_lock = false; + visible_for_tray.store(false, Ordering::SeqCst); } else { unsafe { _ = ShowWindow(window_handle, SW_RESTORE); } - *visible_lock = true; + visible_for_tray.store(true, Ordering::SeqCst); } } })