Compare commits
3 commits
f6b9c50e7e
...
386e632efb
Author | SHA1 | Date | |
---|---|---|---|
|
386e632efb | ||
|
6aa1c8789d | ||
|
a2d303fdfe |
10 changed files with 91 additions and 80 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
/target
|
/target
|
||||||
settings.toml
|
settings.toml
|
||||||
.direnv/*
|
.direnv/*
|
||||||
|
logs/*
|
|
@ -1,4 +1,4 @@
|
||||||
camera_ip = "10.0.0.33"
|
camera_ip = "localhost"
|
||||||
camera_port = 8765
|
camera_port = 8765
|
||||||
tracker_ip = "localhost"
|
tracker_ip = "localhost"
|
||||||
tracker_port = 6543
|
tracker_port = 6543
|
||||||
|
|
|
@ -95,7 +95,7 @@ impl<'a> CoordState<'a> {
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument]
|
#[instrument(skip(self))]
|
||||||
pub async fn socket_send(&mut self, message: Message) {
|
pub async fn socket_send(&mut self, message: Message) {
|
||||||
if let Some(mut socket) = self.sck_outbound.take() {
|
if let Some(mut socket) = self.sck_outbound.take() {
|
||||||
if let Err(e) = socket.send(message).await {
|
if let Err(e) = socket.send(message).await {
|
||||||
|
|
|
@ -48,7 +48,7 @@ pub enum ApplicationEvent {
|
||||||
EnableAutomatic(bool),
|
EnableAutomatic(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument]
|
#[instrument(skip_all)]
|
||||||
pub async fn start_coordinator(
|
pub async fn start_coordinator(
|
||||||
// Main_Event_Channel
|
// Main_Event_Channel
|
||||||
mec: Receiver<ApplicationEvent>,
|
mec: Receiver<ApplicationEvent>,
|
||||||
|
|
|
@ -23,7 +23,7 @@ use super::{
|
||||||
SocketState,
|
SocketState,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[instrument]
|
#[instrument(skip_all)]
|
||||||
pub async fn remote_video_loop(
|
pub async fn remote_video_loop(
|
||||||
conn_string: String,
|
conn_string: String,
|
||||||
appsink: Arc<Mutex<AppSink>>,
|
appsink: Arc<Mutex<AppSink>>,
|
||||||
|
|
|
@ -35,7 +35,7 @@ impl FilterFn for UnknownSlayer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument(skip(tx))]
|
||||||
pub async fn joystick_loop(tx: Sender<ApplicationEvent>, is_alive: Arc<AtomicBool>) {
|
pub async fn joystick_loop(tx: Sender<ApplicationEvent>, is_alive: Arc<AtomicBool>) {
|
||||||
let mut gilrs = GilrsBuilder::new().set_update_state(false).build().unwrap();
|
let mut gilrs = GilrsBuilder::new().set_update_state(false).build().unwrap();
|
||||||
|
|
||||||
|
|
17
src/main.rs
17
src/main.rs
|
@ -3,8 +3,6 @@ use gtk::{glib, Application};
|
||||||
use std::{env, sync::Arc};
|
use std::{env, sync::Arc};
|
||||||
use tokio::{runtime, sync::RwLock};
|
use tokio::{runtime, sync::RwLock};
|
||||||
use tracing::{self, info, Level};
|
use tracing::{self, info, Level};
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
use tracing_appender;
|
|
||||||
use tracing_subscriber;
|
use tracing_subscriber;
|
||||||
|
|
||||||
use crate::config::{load_config, AppConfig};
|
use crate::config::{load_config, AppConfig};
|
||||||
|
@ -21,23 +19,14 @@ 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(".", "joystick-log");
|
|
||||||
let (non_blocking, _gaurd) = tracing_appender::non_blocking(file_appender);
|
let (non_blocking, _gaurd) = tracing_appender::non_blocking(file_appender);
|
||||||
tracing_subscriber::fmt()
|
tracing_subscriber::fmt()
|
||||||
.with_writer(non_blocking)
|
.with_writer(non_blocking)
|
||||||
.with_max_level(tracing::Level::DEBUG)
|
.with_max_level(tracing::Level::DEBUG)
|
||||||
|
.with_ansi(false)
|
||||||
.init();
|
.init();
|
||||||
}
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
{
|
|
||||||
tracing_subscriber::fmt()
|
|
||||||
// .compact()
|
|
||||||
.pretty()
|
|
||||||
.with_max_level(tracing::Level::DEBUG)
|
|
||||||
.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
let span = tracing::span!(Level::TRACE, "main");
|
let span = tracing::span!(Level::TRACE, "main");
|
||||||
let _enter = span.enter();
|
let _enter = span.enter();
|
||||||
|
|
|
@ -37,7 +37,7 @@ pub struct TrackerState {
|
||||||
pub identity_boxes: Vec<NormalizedBoxCoords>,
|
pub identity_boxes: Vec<NormalizedBoxCoords>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument]
|
#[instrument(skip(rt, mec))]
|
||||||
pub async fn start_socketserver(
|
pub async fn start_socketserver(
|
||||||
rt: Handle,
|
rt: Handle,
|
||||||
mec: Sender<ApplicationEvent>,
|
mec: Sender<ApplicationEvent>,
|
||||||
|
@ -70,7 +70,7 @@ pub async fn start_socketserver(
|
||||||
connection_state.is_connected.store(false, Ordering::SeqCst);
|
connection_state.is_connected.store(false, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument]
|
#[instrument(skip(stream, mec))]
|
||||||
async fn accept_connection(
|
async fn accept_connection(
|
||||||
peer: SocketAddr,
|
peer: SocketAddr,
|
||||||
stream: TcpStream,
|
stream: TcpStream,
|
||||||
|
@ -85,7 +85,7 @@ async fn accept_connection(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument]
|
#[instrument(skip(stream, mec))]
|
||||||
async fn handle_connection(
|
async fn handle_connection(
|
||||||
peer: SocketAddr,
|
peer: SocketAddr,
|
||||||
stream: TcpStream,
|
stream: TcpStream,
|
||||||
|
|
|
@ -74,7 +74,7 @@ impl LiveViewPanel {
|
||||||
|
|
||||||
click_handler.connect_pressed(move |gesture, _id, x, y| {
|
click_handler.connect_pressed(move |gesture, _id, x, y| {
|
||||||
gesture.set_state(gtk::EventSequenceState::Claimed);
|
gesture.set_state(gtk::EventSequenceState::Claimed);
|
||||||
LiveViewPanel::gesture_callback(&handler_picture, &tracker_state, x, y)
|
LiveViewPanel::click_gesture_callback(&handler_picture, &tracker_state, x, y)
|
||||||
});
|
});
|
||||||
|
|
||||||
overlay_box.add_controller(click_handler);
|
overlay_box.add_controller(click_handler);
|
||||||
|
@ -101,24 +101,7 @@ impl LiveViewPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gesture_callback(
|
fn click_gesture_callback(
|
||||||
overlay: &Picture,
|
|
||||||
tracker_state: &Arc<Mutex<TrackerState>>,
|
|
||||||
x_coord: f64,
|
|
||||||
y_coord: f64,
|
|
||||||
) {
|
|
||||||
let x_size = overlay.size(gtk::Orientation::Horizontal);
|
|
||||||
let y_size = overlay.size(gtk::Orientation::Vertical);
|
|
||||||
let x_coord = x_coord as f32 / x_size as f32;
|
|
||||||
let y_coord = y_coord as f32 / y_size as f32;
|
|
||||||
|
|
||||||
if let Ok(mut ts) = tracker_state.lock() {
|
|
||||||
ts.highlighted_id = calc_box_under_mouse(&ts.identity_boxes, x_coord, y_coord);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn motion_callback(
|
|
||||||
overlay: &Picture,
|
overlay: &Picture,
|
||||||
tracker_state: &Arc<Mutex<TrackerState>>,
|
tracker_state: &Arc<Mutex<TrackerState>>,
|
||||||
x_coord: f64,
|
x_coord: f64,
|
||||||
|
@ -136,6 +119,22 @@ impl LiveViewPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn motion_callback(
|
||||||
|
overlay: &Picture,
|
||||||
|
tracker_state: &Arc<Mutex<TrackerState>>,
|
||||||
|
x_coord: f64,
|
||||||
|
y_coord: f64,
|
||||||
|
) {
|
||||||
|
let x_size = overlay.size(gtk::Orientation::Horizontal);
|
||||||
|
let y_size = overlay.size(gtk::Orientation::Vertical);
|
||||||
|
let x_coord = x_coord as f32 / x_size as f32;
|
||||||
|
let y_coord = y_coord as f32 / y_size as f32;
|
||||||
|
|
||||||
|
if let Ok(mut ts) = tracker_state.lock() {
|
||||||
|
ts.highlighted_id = calc_box_under_mouse(&ts.identity_boxes, x_coord, y_coord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_top_level(&self) -> &Box {
|
pub fn get_top_level(&self) -> &Box {
|
||||||
&self.top_level
|
&self.top_level
|
||||||
}
|
}
|
||||||
|
@ -149,7 +148,11 @@ impl LiveViewPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calc_box_under_mouse(boxes: &Vec<NormalizedBoxCoords>, x_coord: f32, y_coord: f32) -> Option<u32> {
|
fn calc_box_under_mouse(
|
||||||
|
boxes: &Vec<NormalizedBoxCoords>,
|
||||||
|
x_coord: f32,
|
||||||
|
y_coord: f32,
|
||||||
|
) -> Option<u32> {
|
||||||
let mut mouse_over: Vec<NormalizedBoxCoords> = vec![];
|
let mut mouse_over: Vec<NormalizedBoxCoords> = vec![];
|
||||||
|
|
||||||
for nb in boxes.iter() {
|
for nb in boxes.iter() {
|
||||||
|
@ -161,11 +164,7 @@ fn calc_box_under_mouse(boxes: &Vec<NormalizedBoxCoords>, x_coord: f32, y_coord:
|
||||||
mouse_over.push(nb.clone());
|
mouse_over.push(nb.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if mouse_over.len() == 1 {
|
if mouse_over.len() > 1 {
|
||||||
// the length is one, why would the unwrap fail
|
|
||||||
let new_id = mouse_over.first().expect("Length one vec had no first");
|
|
||||||
return Some(new_id.id);
|
|
||||||
} else if mouse_over.len() > 1 {
|
|
||||||
let mut x_coords = mouse_over
|
let mut x_coords = mouse_over
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|b| [b.x1, b.x2])
|
.flat_map(|b| [b.x1, b.x2])
|
||||||
|
@ -185,28 +184,24 @@ fn calc_box_under_mouse(boxes: &Vec<NormalizedBoxCoords>, x_coord: f32, y_coord:
|
||||||
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
|
||||||
|
// to be the highlighted one
|
||||||
mouse_over.sort_by(|a, b| {
|
mouse_over.sort_by(|a, b| {
|
||||||
// a is valid for cutting in line if the
|
let result = ((a.area() - overlap_area) / a.area()) - ((b.area() - overlap_area) / b.area());
|
||||||
// overlap area is greater than 75% of a's area
|
if 0.0001 > result && result > -0.0001 {
|
||||||
let a_overlap = overlap_area >= 0.75 * a.area();
|
Ordering::Equal
|
||||||
let b_overlap = overlap_area >= 0.75 * b.area();
|
} else if result > 0.0 {
|
||||||
|
|
||||||
match (a_overlap, b_overlap) {
|
|
||||||
// if the areas are not valid for cutting in line or both are
|
|
||||||
// do the sorting based on the id, and let the hover affect
|
|
||||||
// force the user to decide
|
|
||||||
(true, true) | (false, false) => {
|
|
||||||
if a.id > b.id {
|
|
||||||
Ordering::Greater
|
Ordering::Greater
|
||||||
} else {
|
} else {
|
||||||
Ordering::Less
|
Ordering::Less
|
||||||
}
|
}
|
||||||
}
|
|
||||||
(false, true) => Ordering::Less,
|
|
||||||
(true, false) => Ordering::Greater,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
mouse_over.iter().map(|x| x.id).collect::<Vec<u32>>().first().copied()
|
mouse_over
|
||||||
|
.iter()
|
||||||
|
.map(|x| x.id)
|
||||||
|
.collect::<Vec<u32>>()
|
||||||
|
.first()
|
||||||
|
.copied()
|
||||||
}
|
}
|
|
@ -216,9 +216,31 @@ pub fn build_ui(app: &Application, config: Arc<RwLock<AppConfig>>, runtime: Hand
|
||||||
id_label.set_text(id.to_string().as_str());
|
id_label.set_text(id.to_string().as_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some (ids) = ids {
|
if let Some(mut ids) = ids {
|
||||||
let old_len = items.n_items();
|
let mut to_delete_indexes: Vec<u32> = vec![];
|
||||||
items.splice(0, old_len, &ids.iter().map(|x| x.as_str()).collect::<Vec<&str>>()[0..])
|
|
||||||
|
// 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
|
glib::ControlFlow::Continue
|
||||||
|
@ -328,6 +350,10 @@ fn draw_boxes(width: i32, height: i32, ctx: &Context, tracker_state: &Arc<Mutex<
|
||||||
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 {
|
||||||
|
ctx.set_source_rgb(1.0, 1.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
let b = nb.into_relative(width, height);
|
let b = nb.into_relative(width, height);
|
||||||
ctx.rectangle(
|
ctx.rectangle(
|
||||||
b.x1 as f64,
|
b.x1 as f64,
|
||||||
|
|
Loading…
Reference in a new issue