185 lines
7.3 KiB
Rust
185 lines
7.3 KiB
Rust
use anyhow::Result;
|
|
|
|
#[cfg(not(coverage))]
|
|
use {
|
|
super::clipboard::send_clipboard_text_to_remote,
|
|
super::device_test::{DeviceTestController, DeviceTestKind},
|
|
super::devices::{CameraMode, DeviceCatalog},
|
|
super::diagnostics::{PerformanceSample, quality_probe_command},
|
|
super::launcher_clipboard_control_path,
|
|
super::launcher_focus_signal_path,
|
|
super::power::{fetch_capture_power, reset_usb_gadget, set_capture_power_mode},
|
|
super::state::{
|
|
BreakoutSizePreset, CapturePowerStatus, CaptureSizePreset, DisplaySurface,
|
|
FeedSourcePreset, InputRouting, LauncherState, MAX_AUDIO_GAIN_PERCENT,
|
|
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,
|
|
input_control_path, input_state_path, input_toggle_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, write_audio_gain_request, write_input_routing_request,
|
|
write_input_toggle_key_request, write_mic_gain_request,
|
|
},
|
|
crate::handshake::{HandshakeProbe, probe},
|
|
crate::output::display::enumerate_monitors,
|
|
gtk::glib,
|
|
gtk::prelude::*,
|
|
lesavka_common::lesavka::CapturePowerCommand,
|
|
lesavka_common::process_metrics::ProcessCpuSampler,
|
|
std::cell::{Cell, RefCell},
|
|
std::collections::VecDeque,
|
|
std::process::Command,
|
|
std::rc::Rc,
|
|
std::time::{Duration, Instant},
|
|
};
|
|
|
|
include!("ui/message_and_network_state.rs");
|
|
#[cfg(not(coverage))]
|
|
include!("ui/control_requests.rs");
|
|
#[cfg(not(coverage))]
|
|
include!("ui/diagnostic_sampling.rs");
|
|
#[cfg(not(coverage))]
|
|
include!("ui/preview_profiles.rs");
|
|
#[cfg(not(coverage))]
|
|
include!("ui/activation_context.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,
|
|
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,
|
|
relay_tx,
|
|
relay_rx,
|
|
relay_request_in_flight,
|
|
caps_tx,
|
|
caps_rx,
|
|
caps_request_in_flight,
|
|
diagnostics_network,
|
|
diagnostics_process,
|
|
next_power_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");
|
|
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();
|
|
});
|
|
}
|
|
|
|
let _ = app.run_with_args::<&str>(&[]);
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(coverage)]
|
|
pub fn run_gui_launcher(_server_addr: String) -> Result<()> {
|
|
Ok(())
|
|
}
|
|
|
|
/// Keep the coverage stub aligned with the real preview activation rule.
|
|
#[cfg(coverage)]
|
|
fn session_preview_active(
|
|
state: &crate::launcher::state::LauncherState,
|
|
child_running: bool,
|
|
) -> bool {
|
|
(child_running || state.remote_active) && state.capture_power.mode != "forced-off"
|
|
}
|
|
|
|
#[cfg(all(test, not(coverage)))]
|
|
#[path = "tests/ui_preview_profiles.rs"]
|
|
mod tests;
|
|
|
|
#[cfg(all(test, coverage))]
|
|
#[path = "tests/ui_coverage.rs"]
|
|
mod tests;
|