#[cfg(target_os = "macos")]
use cocoa::base::nil;
#[cfg(target_os = "macos")]
use cocoa::appkit::{NSApplication, NSApplicationActivationPolicyAccessory};
#[cfg(target_os = "macos")]
use cocoa::foundation::NSAutoreleasePool;
mod audio;
mod input;
mod ui;
mod config;
use anyhow::Result;
use log::{info, error};
use once_cell::sync::Lazy;
use parking_lot::Mutex;
use std::sync::Arc;
use std::io::Write;
static APP_STATE: Lazy<Arc<Mutex<config::Config>>> = Lazy::new(|| {
Arc::new(Mutex::new(config::Config::load().unwrap_or_default()))
});
fn main() -> Result<()> {
env_logger::Builder::from_env(env_logger::Env::default()
.filter_or("RUST_LOG", "debug"))
.format(|buf, record| {
writeln!(buf, "[{}] {}", record.level(), record.args())
})
.init();
info!("Starting ClickClack...");
#[cfg(target_os = "macos")]
unsafe {
let _pool = NSAutoreleasePool::new(nil);
let app = NSApplication::sharedApplication(nil);
app.setActivationPolicy_(NSApplicationActivationPolicyAccessory);
}
if let Err(e) = ui::tray::ensure_assets_exist() {
error!("Failed to initialize assets: {}", e);
return Err(anyhow::anyhow!("Failed to initialize assets: {}", e));
}
info!("Assets initialized successfully");
let sound_engine = Arc::new(audio::SoundEngine::new()?);
info!("Sound engine initialized");
let keyboard_handler = input::KeyboardHandler::new(sound_engine.clone())?;
keyboard_handler.start()?;
info!("Keyboard handler started");
let _tray = ui::TrayIcon::new()?;
info!("Tray icon created");
#[cfg(target_os = "macos")]
unsafe {
let app = NSApplication::sharedApplication(nil);
app.run();
}
#[cfg(not(target_os = "macos"))]
loop {
std::thread::sleep(std::time::Duration::from_millis(100));
}
Ok(())
}