added some clear states (and bugs)
This commit is contained in:
parent
386e632efb
commit
66acd4698f
9 changed files with 111 additions and 63 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1153,7 +1153,7 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "joystick-controller-client"
|
name = "joystick-controller-client"
|
||||||
version = "1.1.0"
|
version = "2.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-channel",
|
"async-channel",
|
||||||
"config",
|
"config",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "joystick-controller-client"
|
name = "joystick-controller-client"
|
||||||
version = "1.1.0"
|
version = "2.0.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
|
@ -36,7 +36,7 @@ impl TrackerMetrics {
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
self.tracker_times.pop_front();
|
self.tracker_times.pop_front();
|
||||||
}
|
}
|
||||||
self.insert_time(Duration::new(0, 0));
|
// self.insert_time(Duration::new(0, 0));
|
||||||
if let Ok(mut writer) = self.header_text.write() {
|
if let Ok(mut writer) = self.header_text.write() {
|
||||||
writer.clear();
|
writer.clear();
|
||||||
writer.push_str("Status: Disconnected");
|
writer.push_str("Status: Disconnected");
|
||||||
|
|
|
@ -146,6 +146,24 @@ pub async fn remote_video_loop(
|
||||||
let mut tm = tracker_metrics.lock().await;
|
let mut tm = tracker_metrics.lock().await;
|
||||||
tm.clear_times();
|
tm.clear_times();
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
if let Ok(mut ts) = tracker_state.lock() {
|
||||||
|
ts.clear();
|
||||||
|
}
|
||||||
|
// This message forces a redraw after clearing the queue
|
||||||
|
if let Err(e) = to_mec
|
||||||
|
.send(ApplicationEvent::MoveEvent(
|
||||||
|
crate::coordinator::MoveEvent { x: 0, y: 0 },
|
||||||
|
crate::coordinator::ConnectionType::Automated,
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
error!(
|
||||||
|
"Error sending message to MEC during shutdown of tracker thread: {}",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
socket_state.is_connected.store(false, Ordering::SeqCst);
|
socket_state.is_connected.store(false, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ const APP_ID: &str = "net.nickiel.joystick-controller-client";
|
||||||
fn main() -> glib::ExitCode {
|
fn main() -> glib::ExitCode {
|
||||||
// set the environment var to make gtk use window's default action bar
|
// set the environment var to make gtk use window's default action bar
|
||||||
env::set_var("gtk_csd", "0");
|
env::set_var("gtk_csd", "0");
|
||||||
|
|
||||||
// #[cfg(not(debug_assertions))]
|
// #[cfg(not(debug_assertions))]
|
||||||
let file_appender = tracing_appender::rolling::daily(".\\logs", "camera-controller");
|
let file_appender = tracing_appender::rolling::daily(".\\logs", "camera-controller");
|
||||||
let (non_blocking, _gaurd) = tracing_appender::non_blocking(file_appender);
|
let (non_blocking, _gaurd) = tracing_appender::non_blocking(file_appender);
|
||||||
|
|
|
@ -37,6 +37,17 @@ pub struct TrackerState {
|
||||||
pub identity_boxes: Vec<NormalizedBoxCoords>,
|
pub identity_boxes: Vec<NormalizedBoxCoords>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TrackerState {
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.tracking_id = 0;
|
||||||
|
self.highlighted_id = None;
|
||||||
|
self.last_detect = Instant::now();
|
||||||
|
self.enabled = false;
|
||||||
|
self.update_ids = false;
|
||||||
|
self.identity_boxes.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(skip(rt, mec))]
|
#[instrument(skip(rt, mec))]
|
||||||
pub async fn start_socketserver(
|
pub async fn start_socketserver(
|
||||||
rt: Handle,
|
rt: Handle,
|
||||||
|
|
|
@ -24,6 +24,7 @@ pub struct ControlPanel {
|
||||||
pub current_id: Label,
|
pub current_id: Label,
|
||||||
|
|
||||||
pub items: StringList,
|
pub items: StringList,
|
||||||
|
pub list_view: ListView,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -51,7 +52,7 @@ impl ControlPanel {
|
||||||
.bind(&label, "label", Widget::NONE);
|
.bind(&label, "label", Widget::NONE);
|
||||||
});
|
});
|
||||||
|
|
||||||
let items = StringList::new(&["item1", "item2", "item3"]);
|
let items = StringList::new(&["Please connect automatic source"]);
|
||||||
|
|
||||||
let model = SingleSelection::builder()
|
let model = SingleSelection::builder()
|
||||||
.model(&items)
|
.model(&items)
|
||||||
|
@ -114,6 +115,7 @@ impl ControlPanel {
|
||||||
current_id,
|
current_id,
|
||||||
|
|
||||||
items,
|
items,
|
||||||
|
list_view,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -183,11 +183,12 @@ fn calc_box_under_mouse(
|
||||||
|
|
||||||
let overlap_area =
|
let overlap_area =
|
||||||
(median_two_x[1] - median_two_x[0]) * (median_two_y[1] - median_two_y[0]);
|
(median_two_x[1] - median_two_x[0]) * (median_two_y[1] - median_two_y[0]);
|
||||||
|
|
||||||
// We want the one with the largest percentage of it's area as overlap
|
// We want the one with the largest percentage of it's area as overlap
|
||||||
// to be the highlighted one
|
// to be the highlighted one
|
||||||
mouse_over.sort_by(|a, b| {
|
mouse_over.sort_by(|a, b| {
|
||||||
let result = ((a.area() - overlap_area) / a.area()) - ((b.area() - overlap_area) / b.area());
|
let result =
|
||||||
|
((a.area() - overlap_area) / a.area()) - ((b.area() - overlap_area) / b.area());
|
||||||
if 0.0001 > result && result > -0.0001 {
|
if 0.0001 > result && result > -0.0001 {
|
||||||
Ordering::Equal
|
Ordering::Equal
|
||||||
} else if result > 0.0 {
|
} else if result > 0.0 {
|
||||||
|
@ -195,7 +196,7 @@ fn calc_box_under_mouse(
|
||||||
} else {
|
} else {
|
||||||
Ordering::Less
|
Ordering::Less
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
mouse_over
|
mouse_over
|
||||||
|
|
126
src/ui/mod.rs
126
src/ui/mod.rs
|
@ -1,6 +1,6 @@
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Instant;
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use gtk::cairo::Context;
|
use gtk::cairo::Context;
|
||||||
use gtk::gdk::Paintable;
|
use gtk::gdk::Paintable;
|
||||||
|
@ -191,61 +191,73 @@ pub fn build_ui(app: &Application, config: Arc<RwLock<AppConfig>>, runtime: Hand
|
||||||
|
|
||||||
let items = control_panel.items.clone();
|
let items = control_panel.items.clone();
|
||||||
let id_label = control_panel.current_id.clone();
|
let id_label = control_panel.current_id.clone();
|
||||||
|
let model = control_panel
|
||||||
|
.list_view
|
||||||
|
.model()
|
||||||
|
.expect("The list view should have a model!");
|
||||||
|
|
||||||
glib::timeout_add_seconds_local(
|
glib::timeout_add_local(Duration::from_millis(500), move || {
|
||||||
1,
|
#[cfg(feature = "tracker-state-debug")]
|
||||||
glib::clone!(@strong items, @strong id_label => move || {
|
debug!("Getting lock on tracker state for checking identity boxes");
|
||||||
#[cfg(feature = "tracker-state-debug")]
|
|
||||||
debug!("Getting lock on tracker state for checking identity boxes");
|
|
||||||
|
|
||||||
// don't update the stringlist until after letting go of the tracker state
|
// don't update the stringlist until after letting go of the tracker state
|
||||||
// due to async interweaving causing a mutex deadlock
|
// due to async interweaving causing a mutex deadlock
|
||||||
let mut ids: Option<Vec<String>> = None;
|
let mut ids: Option<Vec<String>> = None;
|
||||||
let mut current_id: Option<u32> = None;
|
let mut current_id: u32 = 0;
|
||||||
if let Ok(ts) = tracker_state.lock() {
|
if let Ok(ts) = tracker_state.lock() {
|
||||||
current_id = Some(ts.tracking_id);
|
current_id = ts.tracking_id;
|
||||||
if ts.update_ids {
|
if ts.update_ids {
|
||||||
ids = Some(ts.identity_boxes
|
ids = Some(ts.identity_boxes.iter().map(|t| t.id.to_string()).collect());
|
||||||
.iter()
|
}
|
||||||
.map(|t| t.id.to_string())
|
}
|
||||||
.collect());
|
|
||||||
|
if current_id > 0 {
|
||||||
|
id_label.set_text(current_id.to_string().as_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
let current_id: String = current_id.to_string();
|
||||||
|
|
||||||
|
if let Some(mut ids) = ids {
|
||||||
|
let mut active_index = 0;
|
||||||
|
let mut to_delete_indexes: Vec<u32> = vec![];
|
||||||
|
|
||||||
|
// find all indexes where matching item does not exist in
|
||||||
|
// the ids, list, and remove all items in the ids list
|
||||||
|
// that already exists in the stringList
|
||||||
|
for i in 0..items.n_items() {
|
||||||
|
let item = items.string(i).unwrap_or("Empty".into()).to_string();
|
||||||
|
if item == current_id {
|
||||||
|
active_index = i;
|
||||||
}
|
}
|
||||||
}
|
if !ids.contains(&item) {
|
||||||
|
to_delete_indexes.push(i);
|
||||||
if let Some(id) = current_id {
|
} else {
|
||||||
id_label.set_text(id.to_string().as_str());
|
if let Some(pos) = ids.iter().position(|x| **x == item) {
|
||||||
}
|
ids.remove(pos);
|
||||||
|
|
||||||
if let Some(mut ids) = ids {
|
|
||||||
let mut to_delete_indexes: Vec<u32> = vec![];
|
|
||||||
|
|
||||||
// find all indexes where matching item does not exist in
|
|
||||||
// the ids, list, and remove all items in the ids list
|
|
||||||
// that already exists in the stringList
|
|
||||||
for i in 0..items.n_items() {
|
|
||||||
let item = items.string(i).unwrap_or("Empty".into()).to_string();
|
|
||||||
if !ids.contains(&item) {
|
|
||||||
to_delete_indexes.push(i);
|
|
||||||
} else {
|
|
||||||
if let Some(pos) = ids.iter().position(|x| **x == item) {
|
|
||||||
ids.remove(pos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// invert the order so we don't have to adjust after each deletion
|
|
||||||
to_delete_indexes.sort();
|
|
||||||
to_delete_indexes.reverse();
|
|
||||||
|
|
||||||
to_delete_indexes.iter().for_each(|x| {
|
|
||||||
items.remove(*x);
|
|
||||||
});
|
|
||||||
items.splice(items.n_items(), 0, &ids.iter().map(|x| x.as_str()).collect::<Vec<&str>>()[0..])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glib::ControlFlow::Continue
|
if active_index > 0 {
|
||||||
}),
|
model.select_item(active_index, true);
|
||||||
);
|
}
|
||||||
|
|
||||||
|
// invert the order so we don't have to adjust after each deletion
|
||||||
|
to_delete_indexes.sort();
|
||||||
|
to_delete_indexes.reverse();
|
||||||
|
|
||||||
|
to_delete_indexes.iter().for_each(|x| {
|
||||||
|
items.remove(*x);
|
||||||
|
});
|
||||||
|
items.splice(
|
||||||
|
items.n_items(),
|
||||||
|
0,
|
||||||
|
&ids.iter().map(|x| x.as_str()).collect::<Vec<&str>>()[0..],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
glib::ControlFlow::Continue
|
||||||
|
});
|
||||||
|
|
||||||
let tracker_status_label = liveview_panel.tracker_status_label.clone();
|
let tracker_status_label = liveview_panel.tracker_status_label.clone();
|
||||||
let tracker_enable_toggle = control_panel
|
let tracker_enable_toggle = control_panel
|
||||||
|
@ -259,18 +271,21 @@ pub fn build_ui(app: &Application, config: Arc<RwLock<AppConfig>>, runtime: Hand
|
||||||
if reader.contains("Failed") || reader.contains("Disconnected") {
|
if reader.contains("Failed") || reader.contains("Disconnected") {
|
||||||
tracker_status_label.set_css_classes(&["NoConnection"]);
|
tracker_status_label.set_css_classes(&["NoConnection"]);
|
||||||
|
|
||||||
tracker_enable_toggle.set_label("Press to Connect Tracker");
|
tracker_enable_toggle.set_label("Connect to Tracker Computer");
|
||||||
tracker_enable_toggle.set_active(false);
|
tracker_enable_toggle.set_active(false);
|
||||||
|
tracker_enable_toggle.set_sensitive(true);
|
||||||
} else if reader.contains("Degraded") || reader.contains("Connecting") {
|
} else if reader.contains("Degraded") || reader.contains("Connecting") {
|
||||||
tracker_status_label.set_css_classes(&["LoadingConnection"]);
|
tracker_status_label.set_css_classes(&["LoadingConnection"]);
|
||||||
|
|
||||||
tracker_enable_toggle.set_label("Press to Connect");
|
tracker_enable_toggle.set_label("Please Wait");
|
||||||
tracker_enable_toggle.set_active(false);
|
tracker_enable_toggle.set_active(false);
|
||||||
|
tracker_enable_toggle.set_sensitive(false);
|
||||||
} else if reader.contains("Nominal") {
|
} else if reader.contains("Nominal") {
|
||||||
tracker_status_label.set_css_classes(&["YesConnection"]);
|
tracker_status_label.set_css_classes(&["YesConnection"]);
|
||||||
|
|
||||||
tracker_enable_toggle.set_label("Press to Disconnect");
|
tracker_enable_toggle.set_label("Disconnect Tracker Computer");
|
||||||
tracker_enable_toggle.set_active(true);
|
tracker_enable_toggle.set_active(true);
|
||||||
|
tracker_enable_toggle.set_sensitive(true);
|
||||||
}
|
}
|
||||||
glib::ControlFlow::Continue
|
glib::ControlFlow::Continue
|
||||||
} else {
|
} else {
|
||||||
|
@ -290,7 +305,7 @@ pub fn build_ui(app: &Application, config: Arc<RwLock<AppConfig>>, runtime: Hand
|
||||||
}
|
}
|
||||||
GuiUpdate::SocketConnected => {
|
GuiUpdate::SocketConnected => {
|
||||||
control_panel.connection_buttons.camera_connection.set_sensitive(true);
|
control_panel.connection_buttons.camera_connection.set_sensitive(true);
|
||||||
control_panel.connection_buttons.camera_connection.set_label("Press to Disconnect");
|
control_panel.connection_buttons.camera_connection.set_label("Disconnect Camera");
|
||||||
liveview_panel.cam_status_label.set_label("Connected");
|
liveview_panel.cam_status_label.set_label("Connected");
|
||||||
|
|
||||||
liveview_panel.cam_status_label.set_css_classes(&["YesConnection"]);
|
liveview_panel.cam_status_label.set_css_classes(&["YesConnection"]);
|
||||||
|
@ -306,7 +321,7 @@ pub fn build_ui(app: &Application, config: Arc<RwLock<AppConfig>>, runtime: Hand
|
||||||
},
|
},
|
||||||
GuiUpdate::SocketDisconnected => {
|
GuiUpdate::SocketDisconnected => {
|
||||||
control_panel.connection_buttons.camera_connection.set_sensitive(true);
|
control_panel.connection_buttons.camera_connection.set_sensitive(true);
|
||||||
control_panel.connection_buttons.camera_connection.set_label("Press to Connect to Camera");
|
control_panel.connection_buttons.camera_connection.set_label("Connect to Camera");
|
||||||
liveview_panel.cam_status_label.set_label("Not Connected to Camera");
|
liveview_panel.cam_status_label.set_label("Not Connected to Camera");
|
||||||
|
|
||||||
liveview_panel.cam_status_label.set_css_classes(&["NoConnection"]);
|
liveview_panel.cam_status_label.set_css_classes(&["NoConnection"]);
|
||||||
|
@ -339,6 +354,7 @@ fn draw_boxes(width: i32, height: i32, ctx: &Context, tracker_state: &Arc<Mutex<
|
||||||
#[cfg(feature = "tracker-state-debug")]
|
#[cfg(feature = "tracker-state-debug")]
|
||||||
debug!("Getting tracker state for drawing boxes");
|
debug!("Getting tracker state for drawing boxes");
|
||||||
if let Ok(ts) = tracker_state.lock() {
|
if let Ok(ts) = tracker_state.lock() {
|
||||||
|
println!("ts currently tracking: {}", ts.tracking_id);
|
||||||
let active = ts.tracking_id;
|
let active = ts.tracking_id;
|
||||||
let highlighted_id = ts.highlighted_id.unwrap_or(0);
|
let highlighted_id = ts.highlighted_id.unwrap_or(0);
|
||||||
for nb in ts.identity_boxes.iter() {
|
for nb in ts.identity_boxes.iter() {
|
||||||
|
@ -349,7 +365,7 @@ fn draw_boxes(width: i32, height: i32, ctx: &Context, tracker_state: &Arc<Mutex<
|
||||||
} else {
|
} else {
|
||||||
ctx.set_source_rgb(0.0, 0.0, 1.0);
|
ctx.set_source_rgb(0.0, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if nb.id == active && nb.id == highlighted_id {
|
if nb.id == active && nb.id == highlighted_id {
|
||||||
ctx.set_source_rgb(1.0, 1.0, 0.0);
|
ctx.set_source_rgb(1.0, 1.0, 0.0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue