291 lines
12 KiB
Rust
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(
|
|
µphone_combo,
|
|
&catalog.microphones,
|
|
state.devices.microphone.as_deref(),
|
|
);
|
|
let microphone_test_button = gtk::Button::with_label("Monitor Mic");
|
|
stabilize_button(µphone_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(µphone_combo);
|
|
microphone_selectors.append(&mic_gain_scale);
|
|
attach_device_control_row(
|
|
&media_grid,
|
|
2,
|
|
µphone_channel_toggle,
|
|
µphone_selectors,
|
|
µphone_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(µphone_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(µphone_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,
|
|
}
|
|
}
|