198 lines
7.9 KiB
Rust
Raw Normal View History

use anyhow::Result;
#[cfg(not(coverage))]
use {
2026-04-30 08:16:57 -03:00
super::calibration::{
blind_calibration_estimate, fetch_calibration, nudge_audio_calibration,
restore_default_calibration, restore_factory_calibration,
},
super::clipboard::send_clipboard_text_to_remote,
super::device_test::{DeviceTestController, DeviceTestKind},
super::devices::{CameraMode, DeviceCatalog},
super::diagnostics::PerformanceSample,
super::launcher_clipboard_control_path,
super::launcher_focus_signal_path,
super::power::{
fetch_capture_power, recover_uac_soft, recover_usb_soft, recover_uvc_soft,
set_capture_power_mode,
},
2026-04-30 08:16:57 -03:00
super::preview::{LauncherPreview, PreviewSurface},
super::state::{
2026-04-30 08:16:57 -03:00
BreakoutSizePreset, CalibrationStatus, CapturePowerStatus, CaptureSizePreset,
DisplaySurface, FeedSourcePreset, InputRouting, LauncherState, MAX_AUDIO_GAIN_PERCENT,
2026-04-22 00:56:03 -03:00
MAX_MIC_GAIN_PERCENT,
},
super::ui_components::{
ConsoleLogLevel, build_launcher_view, sync_camera_quality_combo, sync_input_device_combo,
sync_stage_device_combo,
},
super::ui_runtime::{
RelayChild, append_session_log_for_level, apply_popout_window_size,
attach_child_log_streams, audio_gain_control_path, capture_swap_key, copy_plain_text,
copy_session_log, dock_all_displays_to_preview, dock_display_to_preview,
2026-04-30 15:04:00 -03:00
input_control_path, input_state_path, input_toggle_control_path, media_control_path,
mic_gain_control_path, next_input_routing, open_diagnostics_popout, open_popout_window,
open_session_log_popout, path_marker, present_popout_windows, read_input_routing_state,
reap_exited_child, refresh_launcher_ui, refresh_test_buttons, routing_name,
selected_combo_value, selected_server_addr, shutdown_launcher_runtime,
spawn_client_process, stop_child_process, toggle_key_label, update_test_action_result,
uplink_camera_preview_path, uplink_mic_level_path, uplink_telemetry_path,
write_audio_gain_request, write_input_routing_request, write_input_toggle_key_request,
write_media_control_request, write_mic_gain_request,
},
2026-04-16 21:18:34 -03:00
crate::handshake::{HandshakeProbe, probe},
crate::output::display::enumerate_monitors,
gtk::glib,
gtk::prelude::*,
lesavka_common::lesavka::CapturePowerCommand,
lesavka_common::process_metrics::ProcessCpuSampler,
serde_json::json,
std::cell::{Cell, RefCell},
2026-04-16 21:18:34 -03:00
std::collections::VecDeque,
2026-04-30 08:16:57 -03:00
std::path::{Path, PathBuf},
std::process::Command,
std::rc::Rc,
std::time::{Duration, Instant, SystemTime, UNIX_EPOCH},
};
include!("ui/message_and_network_state.rs");
#[cfg(not(coverage))]
include!("ui/control_requests.rs");
#[cfg(not(coverage))]
include!("ui/diagnostic_sampling.rs");
2026-04-21 22:15:47 -03:00
#[cfg(not(coverage))]
include!("ui/preview_profiles.rs");
2026-04-22 00:56:03 -03:00
#[cfg(not(coverage))]
include!("ui/activation_context.rs");
#[cfg(not(coverage))]
include!("ui/startup_window_guard.rs");
#[cfg(coverage)]
include!("ui/session_preview_coverage.rs");
#[cfg(not(coverage))]
pub fn run_gui_launcher(server_addr: String) -> Result<()> {
let app = gtk::Application::builder()
.application_id("dev.lesavka.launcher")
.build();
let catalog = Rc::new(RefCell::new(DeviceCatalog::discover()));
let state = Rc::new(RefCell::new(LauncherState::new()));
state.borrow_mut().apply_catalog_defaults(&catalog.borrow());
let child_proc = Rc::new(RefCell::new(None::<RelayChild>));
let tests = Rc::new(RefCell::new(DeviceTestController::new()));
let server_addr = Rc::new(server_addr);
let focus_signal_path = Rc::new(launcher_focus_signal_path());
let clipboard_control_path = Rc::new(launcher_clipboard_control_path());
let input_control_path = Rc::new(input_control_path());
let input_state_path = Rc::new(input_state_path());
let input_toggle_control_path = Rc::new(input_toggle_control_path());
let _ = std::fs::remove_file(focus_signal_path.as_path());
let _ = std::fs::remove_file(clipboard_control_path.as_path());
let _ = std::fs::remove_file(input_control_path.as_path());
let _ = std::fs::remove_file(input_state_path.as_path());
let _ = std::fs::remove_file(input_toggle_control_path.as_path());
{
let child_proc = Rc::clone(&child_proc);
let focus_signal_path = Rc::clone(&focus_signal_path);
let clipboard_control_path = Rc::clone(&clipboard_control_path);
let input_control_path = Rc::clone(&input_control_path);
let input_state_path = Rc::clone(&input_state_path);
let input_toggle_control_path = Rc::clone(&input_toggle_control_path);
let tests = Rc::clone(&tests);
app.connect_shutdown(move |_| {
stop_child_process(&child_proc);
tests.borrow_mut().stop_all();
let _ = std::fs::remove_file(focus_signal_path.as_path());
let _ = std::fs::remove_file(clipboard_control_path.as_path());
let _ = std::fs::remove_file(input_control_path.as_path());
let _ = std::fs::remove_file(input_state_path.as_path());
let _ = std::fs::remove_file(input_toggle_control_path.as_path());
});
}
{
let catalog = Rc::clone(&catalog);
let state = Rc::clone(&state);
let child_proc = Rc::clone(&child_proc);
let tests = Rc::clone(&tests);
let server_addr = Rc::clone(&server_addr);
let focus_signal_path = Rc::clone(&focus_signal_path);
let input_control_path = Rc::clone(&input_control_path);
let input_state_path = Rc::clone(&input_state_path);
let input_toggle_control_path = Rc::clone(&input_toggle_control_path);
app.connect_activate(move |app| {
let ActivationContext {
window,
launcher_size,
server_entry,
camera_combo,
camera_quality_combo,
microphone_combo,
speaker_combo,
keyboard_combo,
mouse_combo,
widgets,
preview,
popouts,
diagnostics_popout,
log_popout,
camera_quality_syncing,
power_tx,
power_rx,
power_request_in_flight,
2026-04-30 08:16:57 -03:00
calibration_tx,
calibration_rx,
calibration_request_in_flight,
relay_tx,
relay_rx,
relay_request_in_flight,
caps_tx,
caps_rx,
caps_request_in_flight,
diagnostics_network,
diagnostics_process,
next_power_probe,
2026-04-30 08:16:57 -03:00
next_calibration_probe,
next_diagnostics_probe,
next_diagnostics_sample,
preview_session_active,
clipboard_tx,
clipboard_rx,
log_tx,
log_rx,
} = include!("ui/activation_setup.rs");
include!("ui/stage_device_bindings.rs");
include!("ui/eye_display_bindings.rs");
include!("ui/media_device_bindings.rs");
let _: () = include!("ui/device_refresh_binding.rs");
include!("ui/relay_input_bindings.rs");
2026-04-30 08:16:57 -03:00
include!("ui/eye_capture_bindings.rs");
include!("ui/utility_button_bindings.rs");
include!("ui/local_test_bindings.rs");
include!("ui/power_display_key_bindings.rs");
let _: () = include!("ui/runtime_poll.rs");
window.present();
schedule_launcher_window_guard(app, &window, launcher_size);
});
}
let _ = app.run_with_args::<&str>(&[]);
Ok(())
}
#[cfg(coverage)]
pub fn run_gui_launcher(_server_addr: String) -> Result<()> {
Ok(())
}
#[cfg(all(test, not(coverage)))]
#[path = "tests/ui_preview_profiles.rs"]
mod tests;
#[cfg(all(test, coverage))]
#[path = "tests/ui_coverage.rs"]
mod tests;