mod audio; mod config; mod correlation; mod goniometer; mod model; mod ppm; mod routes; mod rta; mod state; mod true_peak; mod vu; use std::net::SocketAddr; use anyhow::Context; use axum::{ routing::{get, post}, Router, }; use config::PhoenixConfig; use state::AppState; use tower_http::{cors::CorsLayer, trace::TraceLayer}; use tracing::info; #[tokio::main] async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt() .with_env_filter( std::env::var("PHOENIX_LOG") .unwrap_or_else(|_| "phoenix=info,tower_http=info".to_string()), ) .init(); let config = PhoenixConfig::from_env(); let state = AppState::new(config.clone()); state.spawn_audio_capture(); let app = Router::new() .route("/health", get(routes::health)) .route("/api/v1/status", get(routes::status)) .route( "/api/v1/global-config", get(routes::get_global_config).post(routes::set_global_config), ) .route( "/api/v1/frontend-presets", get(routes::get_frontend_presets).post(routes::set_frontend_preset), ) .route( "/api/v1/frontend-layouts", get(routes::get_frontend_layouts).post(routes::set_frontend_layout), ) .route( "/api/v1/update/download", post(routes::download_online_update), ) .route("/api/v1/update/log", get(routes::get_online_update_log)) .route( "/api/v1/update/restart", post(routes::restart_after_online_update), ) .route( "/api/v1/rta-config", get(routes::get_rta_config).post(routes::set_rta_config), ) .route( "/api/v1/recordings/wav/start/:session_id", post(routes::start_wav_recording), ) .route( "/api/v1/recordings/wav/stop/:session_id", post(routes::stop_wav_recording), ) .route( "/api/v1/recordings/stop/:session_id/:format", post(routes::stop_recording_with_format), ) .route( "/api/v1/recordings/save/:target/:filename", post(routes::save_recording_file), ) .route("/api/v1/metrics/ws", get(routes::metrics_ws)) .route("/api/v1/spectro/ws", get(routes::spectro_ws)) .route("/api/v1/visuals/ws", get(routes::visuals_ws)) .layer(CorsLayer::permissive()) .layer(TraceLayer::new_for_http()) .with_state(state); let addr: SocketAddr = config .listen_addr .parse() .with_context(|| format!("invalid listen address: {}", config.listen_addr))?; info!("Phoenix listening on http://{}", addr); let listener = tokio::net::TcpListener::bind(addr).await?; axum::serve(listener, app).await?; Ok(()) }