J.A.R.V.I.S-py/app/src/main.rs

122 lines
3 KiB
Rust
Raw Normal View History

use std::env;
use std::error::Error;
use std::path::PathBuf;
use once_cell::sync::{Lazy, OnceCell};
2025-12-11 23:43:50 +05:00
use platform_dirs::AppDirs;
// expose the config
mod config;
// include log
#[macro_use]
extern crate simple_log;
mod log;
// include app
mod app;
// include db
mod db;
// include tray
// @TODO. macOS currently not supported for tray functionality.
#[cfg(not(target_os = "macos"))]
mod tray;
// include recorder
mod recorder;
// include speech-to-text
mod stt;
// include text-to-speech
// empty
// include commands
mod commands;
use crate::commands::list;
2025-12-11 23:43:50 +05:00
use commands::AssistantCommand;
// include audio
mod audio;
// include listener
mod listener;
// some global data
2025-12-11 23:43:50 +05:00
static APP_DIR: Lazy<PathBuf> = Lazy::new(|| env::current_dir().unwrap());
static SOUND_DIR: Lazy<PathBuf> = Lazy::new(|| APP_DIR.clone().join("sound"));
static APP_DIRS: OnceCell<AppDirs> = OnceCell::new();
static APP_CONFIG_DIR: OnceCell<PathBuf> = OnceCell::new();
static APP_LOG_DIR: OnceCell<PathBuf> = OnceCell::new();
static DB: OnceCell<db::structs::Settings> = OnceCell::new();
static COMMANDS_LIST: OnceCell<Vec<AssistantCommand>> = OnceCell::new();
fn main() -> Result<(), String> {
// initialize directories
config::init_dirs()?;
// initialize logging
log::init_logging()?;
// log some base info
info!("Starting Jarvis v{} ...", config::APP_VERSION.unwrap());
2025-12-11 23:43:50 +05:00
info!(
"Config directory is: {}",
APP_CONFIG_DIR.get().unwrap().display()
);
info!("Log directory is: {}", APP_LOG_DIR.get().unwrap().display());
// initialize database (settings)
DB.set(db::init_settings());
// initialize tray
// @TODO. macOS currently not supported for tray functionality,
// due to the separate thread in which tray processing works,
// but macOS requires it to be processed in the main thread only
// The solution may be to include wake-word detection etc. in the winit event loop. (only for MacOS, though?)
#[cfg(not(target_os = "macos"))]
tray::init();
// init recorder
if recorder::init().is_err() {
app::close(1); // cannot continue without recorder
}
// init stt engine
if stt::init().is_err() {
// @TODO. Allow continuing even without STT, if commands is using keywords or smthng?
app::close(1); // cannot continue without stt
}
// init tts engine
// none for now (Silero-rs coming)
// init commands
info!("Initializing commands.");
let commands = commands::parse_commands().unwrap();
2025-12-11 23:43:50 +05:00
info!(
"Commands initialized.\nOverall commands parsed: {}\nParsed commands: {:?}",
commands.len(),
commands::list(&commands)
);
COMMANDS_LIST.set(commands).unwrap();
// init audio
if audio::init().is_err() {
// @TODO. Allow continuing even without audio?
app::close(1); // cannot continue without audio
}
// init wake-word engine
if listener::init().is_err() {
app::close(1); // cannot continue without wake-word engine
}
// start the app
app::start();
Ok(())
2025-12-11 23:43:50 +05:00
}