Compare commits
2 commits
e59025f645
...
36e5afeb57
Author | SHA1 | Date | |
---|---|---|---|
|
36e5afeb57 | ||
|
ee0b8d571c |
7 changed files with 78 additions and 66 deletions
|
@ -131,7 +131,11 @@ impl<'a> CoordState<'a> {
|
||||||
let conn_string: String = {
|
let conn_string: String = {
|
||||||
let read_settings = self.settings.read().await;
|
let read_settings = self.settings.read().await;
|
||||||
|
|
||||||
format!("ws://{}:{}", read_settings.camera_ip, read_settings.camera_port.to_string())
|
format!(
|
||||||
|
"ws://{}:{}",
|
||||||
|
read_settings.camera_ip,
|
||||||
|
read_settings.camera_port.to_string()
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
match connect_async(conn_string).await {
|
match connect_async(conn_string).await {
|
||||||
|
@ -165,20 +169,21 @@ impl<'a> CoordState<'a> {
|
||||||
let conn_string: String = {
|
let conn_string: String = {
|
||||||
let read_settings = self.settings.read().await;
|
let read_settings = self.settings.read().await;
|
||||||
|
|
||||||
format!("ws://{}:{}", read_settings.tracker_ip, read_settings.tracker_port.to_string())
|
format!(
|
||||||
|
"ws://{}:{}",
|
||||||
|
read_settings.tracker_ip,
|
||||||
|
read_settings.tracker_port.to_string()
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.rt.spawn(
|
self.rt.spawn(remote_video_loop(
|
||||||
remote_video_loop(
|
|
||||||
conn_string,
|
conn_string,
|
||||||
self.pipeline.sink_frame.clone(),
|
self.pipeline.sink_frame.clone(),
|
||||||
self.to_mec.clone(),
|
self.to_mec.clone(),
|
||||||
self.keep_windows_pipe_alive.clone(),
|
self.keep_windows_pipe_alive.clone(),
|
||||||
self.tracker_state.clone(),
|
self.tracker_state.clone(),
|
||||||
self.rt.clone()
|
self.rt.clone(),
|
||||||
),
|
));
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn check_states(&mut self) {
|
pub async fn check_states(&mut self) {
|
||||||
|
@ -190,9 +195,7 @@ impl<'a> CoordState<'a> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.keep_windows_pipe_alive.load(Ordering::SeqCst) {
|
if !self.keep_windows_pipe_alive.load(Ordering::SeqCst) {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if !self.sck_alive_server.load(Ordering::SeqCst) {
|
if !self.sck_alive_server.load(Ordering::SeqCst) {
|
||||||
info!("Restarting socket server");
|
info!("Restarting socket server");
|
||||||
|
|
|
@ -94,7 +94,6 @@ pub async fn remote_video_loop(
|
||||||
|
|
||||||
// rate limit updates
|
// rate limit updates
|
||||||
sleep_until(Instant::now() + Duration::from_millis(50)).await;
|
sleep_until(Instant::now() + Duration::from_millis(50)).await;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,9 @@ impl WebcamPipeline {
|
||||||
let convert = ElementFactory::make("videoconvert")
|
let convert = ElementFactory::make("videoconvert")
|
||||||
.build()
|
.build()
|
||||||
.expect("Could not build video convert for GStreamer");
|
.expect("Could not build video convert for GStreamer");
|
||||||
|
let rate = ElementFactory::make("videorate")
|
||||||
|
.build()
|
||||||
|
.expect("Could not build the video rate element");
|
||||||
|
|
||||||
let tee = ElementFactory::make("tee")
|
let tee = ElementFactory::make("tee")
|
||||||
.build()
|
.build()
|
||||||
|
@ -51,11 +54,10 @@ impl WebcamPipeline {
|
||||||
.build()
|
.build()
|
||||||
.expect("Could not build videoscale for GStreamer");
|
.expect("Could not build videoscale for GStreamer");
|
||||||
|
|
||||||
let caps_string =
|
let caps_string = "video/x-raw,format=RGB,width=640,height=480,max-buffers=1,drop=true";
|
||||||
String::from("video/x-raw,format=RGB,width=640,height=480,max-buffers=1,drop=true");
|
|
||||||
// let caps_string = String::from("video/x-raw,format=RGB,max-buffers=1,drop=true");
|
// let caps_string = String::from("video/x-raw,format=RGB,max-buffers=1,drop=true");
|
||||||
let appsrc_caps =
|
let appsrc_caps =
|
||||||
gstreamer::Caps::from_str(&caps_string).expect("Couldn't create appsrc caps");
|
gstreamer::Caps::from_str(caps_string).expect("Couldn't create appsrc caps");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// let sink_frame = ElementFactory::make("appsink")
|
// let sink_frame = ElementFactory::make("appsink")
|
||||||
|
@ -82,6 +84,7 @@ impl WebcamPipeline {
|
||||||
.add_many(&[
|
.add_many(&[
|
||||||
&source,
|
&source,
|
||||||
&convert,
|
&convert,
|
||||||
|
&rate,
|
||||||
&tee,
|
&tee,
|
||||||
&queue_app,
|
&queue_app,
|
||||||
&sink_paintable,
|
&sink_paintable,
|
||||||
|
@ -94,7 +97,14 @@ impl WebcamPipeline {
|
||||||
source
|
source
|
||||||
.link(&convert)
|
.link(&convert)
|
||||||
.expect("Could not link video source to converter");
|
.expect("Could not link video source to converter");
|
||||||
convert.link(&tee).expect("Could not link converter to tee");
|
|
||||||
|
convert.link(&rate)
|
||||||
|
.expect("Could not link rate to tee");
|
||||||
|
|
||||||
|
rate.link_filtered(
|
||||||
|
&tee,
|
||||||
|
&gstreamer::caps::Caps::from_str("video/x-raw,framerate=15/1").expect("Could not build framerate caps"),
|
||||||
|
).expect("Could not link converter to rate");
|
||||||
|
|
||||||
let tee_src_1 = tee
|
let tee_src_1 = tee
|
||||||
.request_pad_simple("src_%u")
|
.request_pad_simple("src_%u")
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
|
use gtk::prelude::{ApplicationExt, ApplicationExtManual};
|
||||||
use gtk::{glib, Application};
|
use gtk::{glib, Application};
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use gtk::prelude::{ApplicationExt, ApplicationExtManual};
|
|
||||||
use simplelog::SimpleLogger;
|
use simplelog::SimpleLogger;
|
||||||
use std::{env, sync::Arc};
|
use std::{env, sync::Arc};
|
||||||
use tokio::{runtime, sync::RwLock};
|
use tokio::{runtime, sync::RwLock};
|
||||||
|
|
||||||
use crate::config::load_config;
|
use crate::config::load_config;
|
||||||
|
|
||||||
|
mod config;
|
||||||
mod coordinator;
|
mod coordinator;
|
||||||
mod gstreamer_pipeline;
|
mod gstreamer_pipeline;
|
||||||
mod joystick_source;
|
mod joystick_source;
|
||||||
mod remote_sources;
|
mod remote_sources;
|
||||||
mod config;
|
|
||||||
mod ui;
|
mod ui;
|
||||||
const APP_ID: &str = "net.nickiel.joystick-controller-client";
|
const APP_ID: &str = "net.nickiel.joystick-controller-client";
|
||||||
|
|
||||||
|
@ -50,4 +50,3 @@ fn main() -> glib::ExitCode {
|
||||||
|
|
||||||
exit_code
|
exit_code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,14 +14,13 @@ use crate::config::AppConfig;
|
||||||
use crate::coordinator::{start_coordinator, ApplicationEvent, MoveEvent};
|
use crate::coordinator::{start_coordinator, ApplicationEvent, MoveEvent};
|
||||||
use crate::remote_sources::TrackerState;
|
use crate::remote_sources::TrackerState;
|
||||||
|
|
||||||
|
mod settings_modal;
|
||||||
mod socket_panel;
|
mod socket_panel;
|
||||||
mod tracker_panel;
|
mod tracker_panel;
|
||||||
mod settings_modal;
|
|
||||||
|
|
||||||
use socket_panel::SocketPanel;
|
use socket_panel::SocketPanel;
|
||||||
use tracker_panel::TrackerPanel;
|
use tracker_panel::TrackerPanel;
|
||||||
|
|
||||||
|
|
||||||
pub enum GuiUpdate {
|
pub enum GuiUpdate {
|
||||||
SocketState(bool),
|
SocketState(bool),
|
||||||
MoveEvent(MoveEvent),
|
MoveEvent(MoveEvent),
|
||||||
|
@ -84,7 +83,6 @@ pub fn on_activate(app: &Application) {
|
||||||
|
|
||||||
app.set_menubar(Some(&menubar));
|
app.set_menubar(Some(&menubar));
|
||||||
info!("Menu bar set up");
|
info!("Menu bar set up");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_ui(app: &Application, config: Arc<RwLock<AppConfig>>, runtime: Handle) {
|
pub fn build_ui(app: &Application, config: Arc<RwLock<AppConfig>>, runtime: Handle) {
|
||||||
|
@ -101,7 +99,6 @@ pub fn build_ui(app: &Application, config: Arc<RwLock<AppConfig>>, runtime: Hand
|
||||||
.child(&main_box)
|
.child(&main_box)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
||||||
let rt = runtime.clone();
|
let rt = runtime.clone();
|
||||||
let config_modal_config = config.clone();
|
let config_modal_config = config.clone();
|
||||||
let connections_activate = gio::ActionEntry::builder("connections")
|
let connections_activate = gio::ActionEntry::builder("connections")
|
||||||
|
@ -114,7 +111,6 @@ pub fn build_ui(app: &Application, config: Arc<RwLock<AppConfig>>, runtime: Hand
|
||||||
|
|
||||||
app.add_action_entries([connections_activate]);
|
app.add_action_entries([connections_activate]);
|
||||||
|
|
||||||
|
|
||||||
// Main Event Channel
|
// Main Event Channel
|
||||||
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);
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use gtk::glib::{self, clone};
|
use gtk::glib::{self, clone};
|
||||||
use gtk::{prelude::{BoxExt, ButtonExt, EditableExt}, Application, ApplicationWindow, Box, Button, Entry, Label, Window};
|
use gtk::{
|
||||||
|
prelude::{BoxExt, ButtonExt, EditableExt},
|
||||||
|
Application, ApplicationWindow, Box, Button, Entry, Label, Window,
|
||||||
|
};
|
||||||
|
use log::{error, info};
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::Handle;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use log::{error, info};
|
|
||||||
|
|
||||||
use crate::config::{save_config, AppConfig};
|
use crate::config::{save_config, AppConfig};
|
||||||
|
|
||||||
|
|
||||||
pub struct ConnectionsModal {
|
pub struct ConnectionsModal {
|
||||||
pub window: Window,
|
pub window: Window,
|
||||||
|
|
||||||
|
@ -16,8 +18,12 @@ pub struct ConnectionsModal {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConnectionsModal {
|
impl ConnectionsModal {
|
||||||
pub fn new(app: &Application, parent: &ApplicationWindow, rt: &Handle, app_config: &Arc<RwLock<AppConfig>>) -> Self {
|
pub fn new(
|
||||||
|
app: &Application,
|
||||||
|
parent: &ApplicationWindow,
|
||||||
|
rt: &Handle,
|
||||||
|
app_config: &Arc<RwLock<AppConfig>>,
|
||||||
|
) -> Self {
|
||||||
// Send help :(
|
// Send help :(
|
||||||
let config_read = rt.block_on(async { app_config.read().await });
|
let config_read = rt.block_on(async { app_config.read().await });
|
||||||
|
|
||||||
|
@ -114,8 +120,7 @@ impl ConnectionsModal {
|
||||||
main_box.append(&quit_button);
|
main_box.append(&quit_button);
|
||||||
|
|
||||||
let new_ref = app_config.clone();
|
let new_ref = app_config.clone();
|
||||||
quit_button
|
quit_button.connect_activate(clone!(
|
||||||
.connect_activate(clone!(
|
|
||||||
@strong rt,
|
@strong rt,
|
||||||
@weak camera_ip_entry, @weak camera_port_entry,
|
@weak camera_ip_entry, @weak camera_port_entry,
|
||||||
@weak tracker_ip_entry, @weak tracker_port_entry,
|
@weak tracker_ip_entry, @weak tracker_port_entry,
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use async_channel::Sender;
|
use async_channel::Sender;
|
||||||
use gtk::{
|
use gtk::{
|
||||||
glib, prelude::{BoxExt, ButtonExt}, Box, Button
|
glib,
|
||||||
|
prelude::{BoxExt, ButtonExt},
|
||||||
|
Box, Button,
|
||||||
};
|
};
|
||||||
use log::error;
|
use log::error;
|
||||||
|
|
||||||
|
@ -37,13 +39,11 @@ impl SocketPanel {
|
||||||
&self.top_level
|
&self.top_level
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn button_label(&self, new_label: &str) {
|
pub fn button_label(&self, new_label: &str) {
|
||||||
self.connect_button.set_label(new_label);
|
self.connect_button.set_label(new_label);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect_button_callback(&self, to_mec: Sender<ApplicationEvent>) {
|
pub fn connect_button_callback(&self, to_mec: Sender<ApplicationEvent>) {
|
||||||
|
|
||||||
self.connect_button.connect_clicked(glib::clone!(@strong to_mec => move |_button| {
|
self.connect_button.connect_clicked(glib::clone!(@strong to_mec => move |_button| {
|
||||||
match to_mec.try_send(ApplicationEvent::StartCameraSocket) {
|
match to_mec.try_send(ApplicationEvent::StartCameraSocket) {
|
||||||
Ok(_) => {},
|
Ok(_) => {},
|
||||||
|
|
Loading…
Reference in a new issue