lesavka/client/src/launcher/ui_components/build_device_controls.rs

291 lines
12 KiB
Rust

{
let device_refresh_button = gtk::Button::with_label("Refresh Devices");
stabilize_button(&device_refresh_button, 132);
device_refresh_button.set_tooltip_text(Some("Re-scan connected devices."));
let (devices_panel, devices_body) =
build_panel_with_action("Device Staging", Some(device_refresh_button.upcast_ref()));
devices_panel.set_hexpand(true);
devices_panel.set_vexpand(false);
devices_panel.set_valign(gtk::Align::Fill);
devices_body.set_spacing(8);
let control_group = build_subgroup("Control Inputs");
let control_stack = gtk::Box::new(gtk::Orientation::Vertical, 10);
control_group.append(&control_stack);
let camera_combo = gtk::ComboBoxText::new();
sync_stage_device_combo(
&camera_combo,
&catalog.cameras,
state.devices.camera.as_deref(),
);
let camera_quality_combo = gtk::ComboBoxText::new();
sync_camera_quality_combo(
&camera_quality_combo,
&state.camera_quality_options(catalog),
state.selected_camera_quality(catalog),
);
camera_quality_combo.set_size_request(88, -1);
camera_quality_combo.set_tooltip_text(Some("Webcam uplink quality."));
let camera_test_button = gtk::Button::with_label("Start Preview");
stabilize_button(&camera_test_button, 118);
camera_test_button.set_tooltip_text(Some("Preview selected webcam locally."));
let speaker_combo = gtk::ComboBoxText::new();
sync_stage_device_combo(
&speaker_combo,
&catalog.speakers,
state.devices.speaker.as_deref(),
);
let speaker_test_button = gtk::Button::with_label("Play Tone");
stabilize_button(&speaker_test_button, 118);
speaker_test_button.set_tooltip_text(Some("Play a local test tone."));
let keyboard_combo = gtk::ComboBoxText::new();
keyboard_combo.append(Some("all"), "all keyboards");
for keyboard in &catalog.keyboards {
append_input_choice(&keyboard_combo, keyboard);
}
super::ui_runtime::set_combo_active_text(&keyboard_combo, state.devices.keyboard.as_deref());
keyboard_combo.set_tooltip_text(Some("Keyboard source for relay input."));
let keyboard_row = build_inline_selector_row("Keyboard", &keyboard_combo);
control_stack.append(&keyboard_row);
let mouse_combo = gtk::ComboBoxText::new();
mouse_combo.append(Some("all"), "all mice");
for mouse in &catalog.mice {
append_input_choice(&mouse_combo, mouse);
}
super::ui_runtime::set_combo_active_text(&mouse_combo, state.devices.mouse.as_deref());
mouse_combo.set_tooltip_text(Some("Pointer source for relay input."));
let mouse_row = build_inline_selector_row("Mouse", &mouse_combo);
control_stack.append(&mouse_row);
devices_body.append(&control_group);
let media_group = build_subgroup("Media Controls");
let media_grid = gtk::Grid::new();
media_grid.set_row_spacing(10);
media_grid.set_column_spacing(8);
media_group.append(&media_grid);
let camera_channel_toggle = gtk::CheckButton::with_label("Camera");
camera_channel_toggle.set_active(state.channels.camera);
camera_channel_toggle.set_tooltip_text(Some("Send webcam during relay."));
let audio_channel_toggle = gtk::CheckButton::with_label("Speaker");
audio_channel_toggle.set_active(state.channels.audio);
audio_channel_toggle.set_tooltip_text(Some("Play remote audio here."));
let microphone_channel_toggle = gtk::CheckButton::with_label("Mic");
microphone_channel_toggle.set_active(state.channels.microphone);
microphone_channel_toggle.set_tooltip_text(Some("Send mic during relay."));
let audio_gain_adjustment = gtk::Adjustment::new(
f64::from(state.audio_gain_percent),
0.0,
f64::from(super::state::MAX_AUDIO_GAIN_PERCENT),
25.0,
100.0,
0.0,
);
let audio_gain_scale =
gtk::Scale::new(gtk::Orientation::Horizontal, Some(&audio_gain_adjustment));
audio_gain_scale.set_draw_value(false);
audio_gain_scale.set_hexpand(false);
audio_gain_scale.set_size_request(96, -1);
audio_gain_scale.set_tooltip_text(Some("Speaker volume. Double-click resets to 200%."));
attach_scale_reset_gesture(
&audio_gain_scale,
f64::from(super::state::DEFAULT_AUDIO_GAIN_PERCENT),
);
let audio_gain_value = gtk::Label::new(Some(&state.audio_gain_label()));
audio_gain_value.set_visible(false);
let mic_gain_adjustment = gtk::Adjustment::new(
f64::from(state.mic_gain_percent),
0.0,
f64::from(super::state::MAX_MIC_GAIN_PERCENT),
25.0,
100.0,
0.0,
);
let mic_gain_scale = gtk::Scale::new(gtk::Orientation::Horizontal, Some(&mic_gain_adjustment));
mic_gain_scale.set_draw_value(false);
mic_gain_scale.set_hexpand(false);
mic_gain_scale.set_size_request(96, -1);
mic_gain_scale.set_tooltip_text(Some("Mic gain. Double-click resets to 100%."));
attach_scale_reset_gesture(
&mic_gain_scale,
f64::from(super::state::DEFAULT_MIC_GAIN_PERCENT),
);
let mic_gain_value = gtk::Label::new(Some(&state.mic_gain_label()));
mic_gain_value.set_visible(false);
camera_combo.set_size_request(0, -1);
let camera_selectors = gtk::Box::new(gtk::Orientation::Horizontal, 6);
camera_combo.set_hexpand(true);
camera_quality_combo.set_hexpand(false);
camera_selectors.append(&camera_combo);
camera_selectors.append(&camera_quality_combo);
speaker_combo.set_size_request(0, -1);
attach_device_control_row(
&media_grid,
0,
&camera_channel_toggle,
&camera_selectors,
&camera_test_button,
);
let speaker_selectors = gtk::Box::new(gtk::Orientation::Horizontal, 6);
speaker_combo.set_hexpand(true);
speaker_selectors.append(&speaker_combo);
speaker_selectors.append(&audio_gain_scale);
attach_device_control_row(
&media_grid,
1,
&audio_channel_toggle,
&speaker_selectors,
&speaker_test_button,
);
let microphone_combo = gtk::ComboBoxText::new();
sync_stage_device_combo(
&microphone_combo,
&catalog.microphones,
state.devices.microphone.as_deref(),
);
let microphone_test_button = gtk::Button::with_label("Monitor Mic");
stabilize_button(&microphone_test_button, 118);
microphone_test_button.set_tooltip_text(Some("Monitor mic through speaker."));
microphone_combo.set_size_request(0, -1);
let microphone_selectors = gtk::Box::new(gtk::Orientation::Horizontal, 6);
microphone_combo.set_hexpand(true);
microphone_selectors.append(&microphone_combo);
microphone_selectors.append(&mic_gain_scale);
attach_device_control_row(
&media_grid,
2,
&microphone_channel_toggle,
&microphone_selectors,
&microphone_test_button,
);
let audio_check_detail = gtk::Label::new(Some("Idle"));
audio_check_detail.add_css_class("dim-label");
audio_check_detail.set_wrap(false);
audio_check_detail.set_ellipsize(pango::EllipsizeMode::End);
audio_check_detail.set_xalign(0.0);
audio_check_detail.set_visible(false);
let audio_check_meter = gtk::ProgressBar::new();
audio_check_meter.add_css_class("audio-check-meter");
audio_check_meter.set_show_text(false);
devices_body.append(&media_group);
staging_row.append(&devices_panel);
let (preview_panel, preview_body) = build_panel("Device Testing");
preview_panel.set_hexpand(true);
preview_panel.set_vexpand(false);
preview_panel.set_valign(gtk::Align::Fill);
preview_body.set_vexpand(false);
preview_body.set_spacing(8);
let testing_row = gtk::Box::new(gtk::Orientation::Horizontal, 8);
testing_row.set_hexpand(true);
testing_row.set_vexpand(true);
testing_row.set_valign(gtk::Align::Fill);
let device_body_height_group = gtk::SizeGroup::new(gtk::SizeGroupMode::Vertical);
device_body_height_group.add_widget(&devices_body);
device_body_height_group.add_widget(&testing_row);
let camera_preview = gtk::Picture::new();
camera_preview.set_can_shrink(false);
camera_preview.set_hexpand(true);
camera_preview.set_vexpand(true);
camera_preview.set_halign(gtk::Align::Fill);
camera_preview.set_valign(gtk::Align::Fill);
camera_preview.set_size_request(
CAMERA_PREVIEW_VIEWPORT_WIDTH,
CAMERA_PREVIEW_VIEWPORT_HEIGHT,
);
camera_preview.set_keep_aspect_ratio(true);
camera_preview.add_css_class("camera-preview-frame");
let camera_status = gtk::Label::new(Some("Select a webcam and click Start Preview."));
camera_status.add_css_class("dim-label");
camera_status.set_wrap(false);
camera_status.set_ellipsize(pango::EllipsizeMode::End);
camera_status.set_xalign(0.0);
camera_status.set_visible(false);
let camera_preview_shell = gtk::Box::new(gtk::Orientation::Vertical, 0);
camera_preview_shell.set_hexpand(true);
camera_preview_shell.set_vexpand(true);
camera_preview_shell.set_halign(gtk::Align::Fill);
camera_preview_shell.set_valign(gtk::Align::Fill);
camera_preview_shell.set_size_request(
CAMERA_PREVIEW_VIEWPORT_WIDTH,
CAMERA_PREVIEW_VIEWPORT_HEIGHT,
);
let camera_preview_frame = gtk::AspectFrame::new(0.5, 0.5, 16.0 / 9.0, false);
camera_preview_frame.set_hexpand(true);
camera_preview_frame.set_vexpand(true);
camera_preview_frame.set_halign(gtk::Align::Fill);
camera_preview_frame.set_valign(gtk::Align::Fill);
camera_preview_frame.set_size_request(
CAMERA_PREVIEW_VIEWPORT_WIDTH,
CAMERA_PREVIEW_VIEWPORT_HEIGHT,
);
camera_preview_frame.set_child(Some(&camera_preview));
camera_preview_shell.append(&camera_preview_frame);
let webcam_group = build_subgroup("Webcam Preview");
webcam_group.set_hexpand(true);
webcam_group.set_vexpand(true);
webcam_group.set_valign(gtk::Align::Fill);
webcam_group.append(&camera_preview_shell);
testing_row.append(&webcam_group);
let playback_group = build_subgroup("Mic Playback");
playback_group.set_hexpand(false);
playback_group.set_vexpand(true);
playback_group.set_valign(gtk::Align::Fill);
playback_group.set_size_request(72, -1);
let playback_body = gtk::Box::new(gtk::Orientation::Vertical, 6);
playback_body.set_halign(gtk::Align::Center);
playback_body.set_vexpand(true);
playback_body.set_valign(gtk::Align::Fill);
let microphone_replay_button = gtk::Button::with_label("Replay");
stabilize_button(&microphone_replay_button, 70);
audio_check_meter.set_orientation(gtk::Orientation::Vertical);
audio_check_meter.set_inverted(true);
audio_check_meter.set_hexpand(false);
audio_check_meter.set_vexpand(true);
audio_check_meter.set_halign(gtk::Align::Center);
audio_check_meter.set_size_request(20, 0);
audio_check_meter.set_show_text(false);
audio_check_meter.set_text(Some("Idle"));
playback_body.append(&audio_check_meter);
playback_body.append(&microphone_replay_button);
playback_group.append(&playback_body);
testing_row.append(&playback_group);
preview_body.append(&testing_row);
staging_row.append(&preview_panel);
DeviceControlsContext {
device_refresh_button,
camera_combo,
camera_quality_combo,
microphone_combo,
speaker_combo,
keyboard_combo,
mouse_combo,
camera_channel_toggle,
microphone_channel_toggle,
audio_channel_toggle,
audio_gain_scale,
audio_gain_value,
mic_gain_scale,
mic_gain_value,
audio_check_detail,
audio_check_meter,
device_body_height_group,
camera_preview,
camera_status,
camera_test_button,
microphone_test_button,
microphone_replay_button,
speaker_test_button,
}
}