fixed picture's aspect ratio
This commit is contained in:
parent
f706157354
commit
3cb560093c
2 changed files with 57 additions and 20 deletions
|
@ -72,6 +72,7 @@ impl<'a> CoordState<'a> {
|
||||||
to_gui: Sender<GuiUpdate>,
|
to_gui: Sender<GuiUpdate>,
|
||||||
rt: Handle,
|
rt: Handle,
|
||||||
identity_boxes: Arc<Mutex<Vec<NormalizedBoxCoords>>>,
|
identity_boxes: Arc<Mutex<Vec<NormalizedBoxCoords>>>,
|
||||||
|
tracker_state: Arc<Mutex<TrackerState>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let this = CoordState {
|
let this = CoordState {
|
||||||
sck_outbound: None,
|
sck_outbound: None,
|
||||||
|
@ -91,11 +92,7 @@ impl<'a> CoordState<'a> {
|
||||||
pipeline: gstreamer_pipeline::WebcamPipeline::new(),
|
pipeline: gstreamer_pipeline::WebcamPipeline::new(),
|
||||||
keep_windows_pipe_alive: Arc::new(AtomicBool::new(true)),
|
keep_windows_pipe_alive: Arc::new(AtomicBool::new(true)),
|
||||||
|
|
||||||
tracker_state: Arc::new(Mutex::new(TrackerState {
|
tracker_state,
|
||||||
tracking_id: 0,
|
|
||||||
last_detect: Instant::now(),
|
|
||||||
has_active_connection: false,
|
|
||||||
}))
|
|
||||||
};
|
};
|
||||||
this.rt.spawn(crate::remote_sources::shared_video_pipe::create_outbound_pipe(
|
this.rt.spawn(crate::remote_sources::shared_video_pipe::create_outbound_pipe(
|
||||||
this.pipeline.sink_frame.clone(),
|
this.pipeline.sink_frame.clone(),
|
||||||
|
@ -202,12 +199,13 @@ pub async fn start_coordinator(
|
||||||
to_gui: Sender<GuiUpdate>,
|
to_gui: Sender<GuiUpdate>,
|
||||||
runtime: Handle,
|
runtime: Handle,
|
||||||
identity_boxes: Arc<Mutex<Vec<NormalizedBoxCoords>>>,
|
identity_boxes: Arc<Mutex<Vec<NormalizedBoxCoords>>>,
|
||||||
|
tracker_state: Arc<Mutex<TrackerState>>,
|
||||||
) {
|
) {
|
||||||
info!("Starting coordinator!");
|
info!("Starting coordinator!");
|
||||||
|
|
||||||
let mec = pin!(mec);
|
let mec = pin!(mec);
|
||||||
|
|
||||||
let mut state = CoordState::new(mec, to_mec, to_gui, runtime, identity_boxes);
|
let mut state = CoordState::new(mec, to_mec, to_gui, runtime, identity_boxes, tracker_state);
|
||||||
|
|
||||||
state.pipeline
|
state.pipeline
|
||||||
.pipeline
|
.pipeline
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::time::Instant;
|
||||||
|
|
||||||
use gtk::cairo::Context;
|
use gtk::cairo::Context;
|
||||||
|
use gtk::ffi::gtk_picture_set_keep_aspect_ratio;
|
||||||
use gtk::gdk::Paintable;
|
use gtk::gdk::Paintable;
|
||||||
use gtk::{glib, prelude::*, Box, Entry, Label, ListBox};
|
use gtk::{glib, prelude::*, AspectFrame, Box, Entry, Label, ListBox};
|
||||||
use gtk::{Application, ApplicationWindow, Button};
|
use gtk::{Application, ApplicationWindow, Button};
|
||||||
use log::error;
|
use log::{info, error};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::Handle;
|
||||||
use tokio_tungstenite::tungstenite::Message;
|
use tokio_tungstenite::tungstenite::Message;
|
||||||
|
|
||||||
use crate::config::{load_config, save_config};
|
use crate::config::{load_config, save_config};
|
||||||
use crate::coordinator::{start_coordinator, ApplicationEvent, MoveEvent};
|
use crate::coordinator::{start_coordinator, ApplicationEvent, MoveEvent};
|
||||||
|
use crate::remote_sources::TrackerState;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
|
@ -70,8 +73,8 @@ pub fn build_ui(app: &Application, runtime: Handle) {
|
||||||
let window = ApplicationWindow::builder()
|
let window = ApplicationWindow::builder()
|
||||||
.application(app)
|
.application(app)
|
||||||
.title("VCC Camera Controller")
|
.title("VCC Camera Controller")
|
||||||
.default_width(840)
|
// .default_width(840)
|
||||||
.default_height(480)
|
// .default_height(480)
|
||||||
.child(&main_box)
|
.child(&main_box)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -79,6 +82,12 @@ pub fn build_ui(app: &Application, runtime: Handle) {
|
||||||
let (to_mec, mec) = async_channel::unbounded::<ApplicationEvent>();
|
let (to_mec, mec) = async_channel::unbounded::<ApplicationEvent>();
|
||||||
let (to_gui, gui_recv) = async_channel::bounded::<GuiUpdate>(10);
|
let (to_gui, gui_recv) = async_channel::bounded::<GuiUpdate>(10);
|
||||||
let identity_boxes: Arc<Mutex<Vec<NormalizedBoxCoords>>> = Arc::new(Mutex::new(vec![]));
|
let identity_boxes: Arc<Mutex<Vec<NormalizedBoxCoords>>> = Arc::new(Mutex::new(vec![]));
|
||||||
|
let tracker_state = Arc::new(Mutex::new(TrackerState {
|
||||||
|
tracking_id: 0,
|
||||||
|
last_detect: Instant::now(),
|
||||||
|
has_active_connection: false,
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
runtime.spawn(start_coordinator(
|
runtime.spawn(start_coordinator(
|
||||||
mec,
|
mec,
|
||||||
|
@ -86,6 +95,7 @@ pub fn build_ui(app: &Application, runtime: Handle) {
|
||||||
to_gui,
|
to_gui,
|
||||||
runtime.clone(),
|
runtime.clone(),
|
||||||
identity_boxes.clone(),
|
identity_boxes.clone(),
|
||||||
|
tracker_state.clone(),
|
||||||
));
|
));
|
||||||
|
|
||||||
// let conn_status_label = Label::new(Some(&"No Connection".to_string()));
|
// let conn_status_label = Label::new(Some(&"No Connection".to_string()));
|
||||||
|
@ -134,22 +144,30 @@ pub fn build_ui(app: &Application, runtime: Handle) {
|
||||||
main_box.append(&left_box);
|
main_box.append(&left_box);
|
||||||
|
|
||||||
let webcam_picture = gtk::Picture::builder()
|
let webcam_picture = gtk::Picture::builder()
|
||||||
.height_request(480)
|
// .height_request(270)
|
||||||
.width_request(640)
|
.width_request(640)
|
||||||
.can_focus(false)
|
.can_focus(false)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let overlay_box = gtk::Overlay::new();
|
let overlay_box = gtk::Overlay::builder()
|
||||||
main_box.append(&overlay_box);
|
.build();
|
||||||
|
let aspect = AspectFrame::builder()
|
||||||
|
.ratio(16.0/9.0)
|
||||||
|
.obey_child(false)
|
||||||
|
.child(&overlay_box)
|
||||||
|
.build();
|
||||||
|
main_box.append(&aspect);
|
||||||
|
|
||||||
let drawable = gtk::DrawingArea::builder()
|
let drawable = gtk::DrawingArea::builder()
|
||||||
.content_height(480)
|
// .content_height(480)
|
||||||
.content_width(640)
|
// .content_width(640)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
drawable.set_draw_func(move |_, ctx, width, height| {
|
drawable.set_draw_func(move |_, ctx, width, height| {
|
||||||
draw_boxes(width, height,&ctx, identity_boxes.clone());
|
draw_boxes(width, height, &ctx, identity_boxes.clone(), tracker_state.clone());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
overlay_box.set_child(Some(&webcam_picture));
|
overlay_box.set_child(Some(&webcam_picture));
|
||||||
overlay_box.add_overlay(&drawable);
|
overlay_box.add_overlay(&drawable);
|
||||||
|
|
||||||
|
@ -186,8 +204,9 @@ pub fn build_ui(app: &Application, runtime: Handle) {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
glib::spawn_future_local(
|
glib::spawn_future_local(
|
||||||
glib::clone!(@weak axis_label, @weak button, @weak conn_status_label, @weak ip_entry, @weak port_entry, @strong gui_recv => async move {
|
glib::clone!(@weak axis_label, @weak button, @weak conn_status_label, @weak ip_entry, @weak port_entry, @strong gui_recv, @weak drawable => async move {
|
||||||
while let Ok(d) = gui_recv.recv().await {
|
while let Ok(d) = gui_recv.recv().await {
|
||||||
|
drawable.queue_draw();
|
||||||
match d {
|
match d {
|
||||||
GuiUpdate::MoveEvent(msg) => {
|
GuiUpdate::MoveEvent(msg) => {
|
||||||
axis_label.set_text(
|
axis_label.set_text(
|
||||||
|
@ -233,12 +252,25 @@ pub fn build_ui(app: &Application, runtime: Handle) {
|
||||||
window.present();
|
window.present();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_boxes(width: i32, height: i32, ctx: &Context, boxes: Arc<Mutex<Vec<NormalizedBoxCoords>>>) {
|
fn draw_boxes(width: i32, height: i32, ctx: &Context, boxes: Arc<Mutex<Vec<NormalizedBoxCoords>>>, tracker_state: Arc<Mutex<TrackerState>>) {
|
||||||
ctx.set_line_width(2.0);
|
ctx.set_line_width(5.0);
|
||||||
ctx.set_source_rgb(0.0, 1.0, 0.0);
|
ctx.select_font_face("Arial", gtk::cairo::FontSlant::Normal, gtk::cairo::FontWeight::Bold);
|
||||||
|
ctx.set_font_size(24.0);
|
||||||
|
|
||||||
|
let active: u32 = match tracker_state.lock() {
|
||||||
|
Ok(e) => e.tracking_id,
|
||||||
|
Err(_) => 0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
if let Ok(bxs) = boxes.lock() {
|
if let Ok(bxs) = boxes.lock() {
|
||||||
for nb in bxs.iter() {
|
for nb in bxs.iter() {
|
||||||
|
if nb.id == active {
|
||||||
|
ctx.set_source_rgb(1.0, 0.0, 0.0);
|
||||||
|
} else {
|
||||||
|
ctx.set_source_rgb(0.0, 0.0, 1.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,
|
||||||
|
@ -251,6 +283,13 @@ fn draw_boxes(width: i32, height: i32, ctx: &Context, boxes: Arc<Mutex<Vec<Norma
|
||||||
}
|
}
|
||||||
ctx.stroke()
|
ctx.stroke()
|
||||||
.expect("GTK Cario context did not have a stroke!");
|
.expect("GTK Cario context did not have a stroke!");
|
||||||
|
|
||||||
|
ctx.move_to(b.x1 as f64 + 5.0, b.y1 as f64 + 18.0);
|
||||||
|
ctx.set_source_rgb(0.0, 0.0, 0.0);
|
||||||
|
ctx.show_text(&format!("[{}]", b.id)).expect("Couldn't show text!");
|
||||||
|
|
||||||
|
ctx.stroke()
|
||||||
|
.expect("GTK Cario context did not have a stroke!");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error!("Could not get lock on boxes for drawing on the draw area!");
|
error!("Could not get lock on boxes for drawing on the draw area!");
|
||||||
|
|
Loading…
Reference in a new issue