Hide simulator devices in release builds and fix AI tracking mode transition handling
This commit is contained in:
3 files changed
+42
-14
No files matched your search
@@ -8,7 +8,7 @@ Exec=insta360-link-gui
|
|||||||
TryExec=insta360-link-gui
|
TryExec=insta360-link-gui
|
||||||
Icon=insta360-link-controller
|
Icon=insta360-link-controller
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Categories=AudioVideo;Video;Settings;HardwareSettings;
|
Categories=AudioVideo;Video;
|
||||||
Keywords=insta360;link;webcam;camera;ptz;gimbal;uvc;video;tracking;
|
Keywords=insta360;link;webcam;camera;ptz;gimbal;uvc;video;tracking;
|
||||||
StartupNotify=true
|
StartupNotify=true
|
||||||
StartupWMClass=insta360-link-controller
|
StartupWMClass=insta360-link-controller
|
||||||
@@ -255,16 +255,14 @@ impl Insta360App {
|
|||||||
if mode_to_set == VideoMode::AutoTracking {
|
if mode_to_set == VideoMode::AutoTracking {
|
||||||
// `Webcam::CameraInsta::autoTrackClicked` (`0x10006c400`) ->
|
// `Webcam::CameraInsta::autoTrackClicked` (`0x10006c400`) ->
|
||||||
// `onHandleVideoModeChangeEvent` (`0x10005a4cc`) -> `readyAutoTrack` (`0x10006c8c8`):
|
// `onHandleVideoModeChangeEvent` (`0x10005a4cc`) -> `readyAutoTrack` (`0x10006c8c8`):
|
||||||
// 1. Ensure the camera is in `VideoMode::Normal` (`0`) so the firmware's person
|
// 1. Always ensure the camera is in `VideoMode::Normal` (`0`) so the firmware's person
|
||||||
// detector (`GetTrackObjLists`, `XU1 0x14`) runs on the live video stream.
|
// detector (`GetTrackObjLists`, `XU1 0x14`) runs on the live video stream.
|
||||||
// 2. Do NOT send `SetTrackObj(0.5, 0.5)` or `SetVideoMode(AutoTracking)` before
|
// 2. Do NOT send `SetTrackObj(0.5, 0.5)` or `SetVideoMode(AutoTracking)` before
|
||||||
// `GetTrackObjLists` detects a person — doing so aborts firmware person detection!
|
// `GetTrackObjLists` detects a person — doing so aborts firmware person detection!
|
||||||
// 3. Start the 200ms `ready_auto_track` polling loop (`SetCheckTrack(true)`).
|
// 3. Start the 200ms `ready_auto_track` polling loop (`SetCheckTrack(true)`).
|
||||||
if prev_mode != VideoMode::Normal {
|
|
||||||
let _ = self
|
let _ = self
|
||||||
.controller
|
.controller
|
||||||
.set_video_mode_raw(VideoMode::Normal, &VideoModeAuxData::default());
|
.set_video_mode_raw(VideoMode::Normal, &VideoModeAuxData::default());
|
||||||
}
|
|
||||||
self.state.video_mode = VideoMode::AutoTracking;
|
self.state.video_mode = VideoMode::AutoTracking;
|
||||||
self.state.ready_auto_track = true;
|
self.state.ready_auto_track = true;
|
||||||
self.state.last_track_poll = None;
|
self.state.last_track_poll = None;
|
||||||
@@ -328,10 +326,27 @@ impl Insta360App {
|
|||||||
ui.add_space(24.0_f32);
|
ui.add_space(24.0_f32);
|
||||||
|
|
||||||
// Center: Camera Controller Selector
|
// Center: Camera Controller Selector
|
||||||
let current_dev_label = self.selected_device.label();
|
let show_simulators = cfg!(debug_assertions)
|
||||||
|
|| std::env::var("INSTA360_SIMULATOR")
|
||||||
|
.map(|v| v == "1" || v.eq_ignore_ascii_case("true"))
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
let current_dev_label = match &self.selected_device {
|
||||||
|
DeviceSelection::Usb(_) => self.selected_device.label(),
|
||||||
|
DeviceSelection::Simulate(_) if show_simulators => {
|
||||||
|
self.selected_device.label()
|
||||||
|
}
|
||||||
|
DeviceSelection::Simulate(_) => "No Camera Connected".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
egui::ComboBox::from_id_salt("top_camera_selector")
|
egui::ComboBox::from_id_salt("top_camera_selector")
|
||||||
.selected_text(¤t_dev_label)
|
.selected_text(¤t_dev_label)
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
|
if self.connected_cameras.is_empty() && !show_simulators {
|
||||||
|
ui.label(
|
||||||
|
RichText::new("No Camera Connected").color(theme.text03),
|
||||||
|
);
|
||||||
|
}
|
||||||
for cam in self.connected_cameras.clone() {
|
for cam in self.connected_cameras.clone() {
|
||||||
let dev = DeviceSelection::Usb(cam);
|
let dev = DeviceSelection::Usb(cam);
|
||||||
let label = dev.label();
|
let label = dev.label();
|
||||||
@@ -339,6 +354,7 @@ impl Insta360App {
|
|||||||
self.switch_camera(dev);
|
self.switch_camera(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if show_simulators {
|
||||||
if !self.connected_cameras.is_empty() {
|
if !self.connected_cameras.is_empty() {
|
||||||
ui.separator();
|
ui.separator();
|
||||||
}
|
}
|
||||||
@@ -353,18 +369,25 @@ impl Insta360App {
|
|||||||
self.switch_camera(dev);
|
self.switch_camera(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let refresh_btn = ui.button("↻");
|
let refresh_btn = ui.button("↻");
|
||||||
if refresh_btn.on_hover_text("Refresh USB camera devices").clicked() {
|
if refresh_btn.on_hover_text("Refresh USB camera devices").clicked() {
|
||||||
self.connected_cameras = list_connected_cameras().unwrap_or_default();
|
self.connected_cameras = list_connected_cameras().unwrap_or_default();
|
||||||
self.video_engine.refresh_capture_devices();
|
self.video_engine.refresh_capture_devices();
|
||||||
|
if !matches!(self.selected_device, DeviceSelection::Usb(_)) {
|
||||||
|
if let Some(first) = self.connected_cameras.first().cloned() {
|
||||||
|
self.switch_camera(DeviceSelection::Usb(first));
|
||||||
|
}
|
||||||
|
}
|
||||||
self.state.show_toast("Refreshed USB devices", false);
|
self.state.show_toast("Refreshed USB devices", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if show_simulators {
|
||||||
ui.add_space(10.0_f32);
|
ui.add_space(10.0_f32);
|
||||||
|
|
||||||
// Video Feed Source Selector
|
// Video Feed Source Selector (debug / simulator mode only)
|
||||||
let active_feed_label = if self.video_engine.is_using_physical_capture() {
|
let active_feed_label = if self.video_engine.is_using_physical_capture() {
|
||||||
self.video_engine
|
self.video_engine
|
||||||
.active_capture_device()
|
.active_capture_device()
|
||||||
@@ -399,6 +422,7 @@ impl Insta360App {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Right group
|
// Right group
|
||||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||||
@@ -766,7 +790,12 @@ impl Insta360App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Interactive click-and-drag pan/tilt (`DefCamera.qml` `dragMovePanTilt` + `dragDropTransition`)
|
// Interactive click-and-drag pan/tilt (`DefCamera.qml` `dragMovePanTilt` + `dragDropTransition`)
|
||||||
if video_response.dragged() && self.controller.capabilities().support_ptz_drag {
|
// Only active in Normal mode (`!ready_auto_track`) so clicking on the video during AI Tracking
|
||||||
|
// does not send a manual PTZ velocity/stop command that aborts tracking.
|
||||||
|
let manual_ptz_drag_allowed = self.controller.capabilities().support_ptz_drag
|
||||||
|
&& self.state.video_mode == VideoMode::Normal
|
||||||
|
&& !self.state.ready_auto_track;
|
||||||
|
if video_response.dragged() && manual_ptz_drag_allowed {
|
||||||
let drag_delta = video_response.drag_delta();
|
let drag_delta = video_response.drag_delta();
|
||||||
if drag_delta.length_sq() > 0.25_f32 {
|
if drag_delta.length_sq() > 0.25_f32 {
|
||||||
self.state.pan_deg =
|
self.state.pan_deg =
|
||||||
@@ -801,7 +830,7 @@ impl Insta360App {
|
|||||||
self.state.last_ptz_send_time = Some(Instant::now());
|
self.state.last_ptz_send_time = Some(Instant::now());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if video_response.drag_stopped() && self.controller.capabilities().support_ptz_drag {
|
} else if video_response.drag_stopped() && manual_ptz_drag_allowed {
|
||||||
let _ = self.controller.stop_pantilt_relative();
|
let _ = self.controller.stop_pantilt_relative();
|
||||||
self.state.last_ptz_cmd = (0, 0, 0, 0);
|
self.state.last_ptz_cmd = (0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
@@ -1987,12 +2016,6 @@ impl eframe::App for Insta360App {
|
|||||||
.set_video_mode_raw(VideoMode::Normal, &VideoModeAuxData::default());
|
.set_video_mode_raw(VideoMode::Normal, &VideoModeAuxData::default());
|
||||||
self.state.video_mode = VideoMode::Normal;
|
self.state.video_mode = VideoMode::Normal;
|
||||||
}
|
}
|
||||||
// If the camera was pointed straight down into its black neck/base, reset to (0, 0)
|
|
||||||
if self.state.tilt_deg < -65.0_f32 && self.state.pan_deg.abs() < 15.0_f32 {
|
|
||||||
let _ = self.controller.set_pantilt_absolute(0, 0);
|
|
||||||
self.state.pan_deg = 0.0_f32;
|
|
||||||
self.state.tilt_deg = 0.0_f32;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Auto-stop short PTZ directional nudges (`CameraInsta::addPanTilt` 100-120ms timer)
|
// 2. Auto-stop short PTZ directional nudges (`CameraInsta::addPanTilt` 100-120ms timer)
|
||||||
|
|||||||
@@ -111,6 +111,11 @@ pub fn decode_get_video_mode(data: &[u8]) -> Result<(VideoMode, VideoModeAuxData
|
|||||||
actual: data.len(),
|
actual: data.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if data[0] == 0xff {
|
||||||
|
return Err(CodecError::InvalidArgument(
|
||||||
|
"camera video mode is transitioning (0xff)",
|
||||||
|
));
|
||||||
|
}
|
||||||
let mode = VideoMode::from_u8(data[0]);
|
let mode = VideoMode::from_u8(data[0]);
|
||||||
let mut aux = VideoModeAuxData {
|
let mut aux = VideoModeAuxData {
|
||||||
flags: data[1],
|
flags: data[1],
|
||||||
|
|||||||
Reference in new issue
Block a user