From c4315917d8888e5848a3cf37f9a83260c71a572a Mon Sep 17 00:00:00 2001 From: Mitchell R Date: Sun, 10 May 2026 20:04:43 +0200 Subject: [PATCH] fix: resolve all Rust compile errors in kiosk app --- kiosk/Cargo.toml | 3 +- kiosk/src/main.rs | 1 + kiosk/src/pipeline.rs | 64 ++++++++++++++++++++++--------------------- kiosk/src/server.rs | 2 +- kiosk/src/ui.rs | 4 +-- 5 files changed, 39 insertions(+), 35 deletions(-) diff --git a/kiosk/Cargo.toml b/kiosk/Cargo.toml index c2e3db6..cfec0fa 100644 --- a/kiosk/Cargo.toml +++ b/kiosk/Cargo.toml @@ -27,4 +27,5 @@ tokio = { version = "1", features = ["rt-multi-thread", "macros", "time", "fs"] # Misc dirs = "6" tracing = "0.1" -tracing-subscriber = "0.3" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } +hostname = "0.4" diff --git a/kiosk/src/main.rs b/kiosk/src/main.rs index 45baab6..ec17f00 100644 --- a/kiosk/src/main.rs +++ b/kiosk/src/main.rs @@ -3,6 +3,7 @@ mod bundle; mod pipeline; mod ui; +use gtk4::prelude::ApplicationExtManual; use tracing_subscriber::EnvFilter; fn main() { diff --git a/kiosk/src/pipeline.rs b/kiosk/src/pipeline.rs index 9f1e4c5..f651114 100644 --- a/kiosk/src/pipeline.rs +++ b/kiosk/src/pipeline.rs @@ -3,7 +3,7 @@ use gstreamer::{self as gst, Element, Pipeline}; use tracing::{error, info, warn}; /// Create a GStreamer pipeline for an RTSP camera that outputs to a GTK4 paintable sink. -/// Returns (pipeline, paintable_sink) — the sink's "paintable" property drives a gtk4::Picture. +/// Returns (pipeline, paintable_sink). pub fn create_camera_pipeline(name: &str, rtsp_uri: &str) -> Option<(Pipeline, Element)> { let pipeline_name = format!("cam-{name}"); let pipeline = Pipeline::with_name(&pipeline_name); @@ -15,13 +15,7 @@ pub fn create_camera_pipeline(name: &str, rtsp_uri: &str) -> Option<(Pipeline, E .build() .ok()?; - let depay_h264 = gst::ElementFactory::make("rtph264depay").build().ok(); - let depay_h265 = gst::ElementFactory::make("rtph265depay").build().ok(); - let parse_h264 = gst::ElementFactory::make("h264parse").build().ok(); - let parse_h265 = gst::ElementFactory::make("h265parse").build().ok(); - let decode = gst::ElementFactory::make("avdec_h264").build() - .or_else(|| gst::ElementFactory::make("decodebin").build().ok()); - + let decode = gst::ElementFactory::make("decodebin").build().ok()?; let convert = gst::ElementFactory::make("videoconvert").build().ok()?; let sink = gst::ElementFactory::make("gtk4paintablesink") @@ -33,37 +27,45 @@ pub fn create_camera_pipeline(name: &str, rtsp_uri: &str) -> Option<(Pipeline, E let queue = gst::ElementFactory::make("queue") .property("max-size-buffers", 1u32) - .property("leaky", 2u32) // downstream + .property("leaky", 2u32) .build() .ok()?; - pipeline.add_many([&src, &queue, &convert, &sink]).ok()?; - gst::Element::link_many([&queue, &convert, &sink]).ok()?; + pipeline.add_many([&src, &decode, &queue, &convert, &sink]).ok()?; - // rtspsrc has dynamic pads — connect on pad-added - let queue_weak = queue.downgrade(); - let pipeline_name_clone = pipeline_name.clone(); + // rtspsrc → decodebin (dynamic pads) + let decode_weak = decode.downgrade(); src.connect_pad_added(move |_src, pad| { - let caps = pad.current_caps().or_else(|| pad.query_caps(None)); - let caps_str = caps.map(|c| c.to_string()).unwrap_or_default(); - - // Only link video pads - if !caps_str.contains("video") && !caps_str.contains("264") && !caps_str.contains("265") { - return; - } - - info!("[{pipeline_name_clone}] linking pad: {caps_str}"); - - let Some(queue) = queue_weak.upgrade() else { return }; - if pad.link(&queue.static_pad("sink").unwrap()).is_err() { - warn!("[{pipeline_name_clone}] pad link failed"); + let Some(decode) = decode_weak.upgrade() else { return }; + let sink_pad = decode.static_pad("sink").unwrap(); + if !sink_pad.is_linked() { + let _ = pad.link(&sink_pad); } }); - // For decodebin-style pipelines, we might need more complex linking. - // For now, rtspsrc → queue → convert → sink works for raw decode. - // The actual decode happens if we insert depay+parse+decoder elements. - // TODO: auto-detect codec and insert appropriate decoder chain. + // decodebin → queue → convert → sink (dynamic pads, video only) + let queue_weak = queue.downgrade(); + let pipeline_name_clone = pipeline_name.clone(); + decode.connect_pad_added(move |_decode, pad| { + let caps = pad.current_caps().unwrap_or_else(|| pad.query_caps(None)); + let caps_str = caps.to_string(); + + if !caps_str.starts_with("video/") { + return; + } + + info!("[{pipeline_name_clone}] decodebin video pad: {caps_str}"); + + let Some(queue) = queue_weak.upgrade() else { return }; + let sink_pad = queue.static_pad("sink").unwrap(); + if !sink_pad.is_linked() { + if pad.link(&sink_pad).is_err() { + warn!("[{pipeline_name_clone}] decodebin pad link failed"); + } + } + }); + + gst::Element::link_many([&queue, &convert, &sink]).ok()?; info!("[{pipeline_name}] pipeline created for {rtsp_uri}"); Some((pipeline, sink)) diff --git a/kiosk/src/server.rs b/kiosk/src/server.rs index 08006a9..5d209e5 100644 --- a/kiosk/src/server.rs +++ b/kiosk/src/server.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use std::time::Duration; use serde::Deserialize; -use tracing::{info, warn}; +use tracing::info; use crate::bundle::KioskBundle; diff --git a/kiosk/src/ui.rs b/kiosk/src/ui.rs index ca718fd..9a22b16 100644 --- a/kiosk/src/ui.rs +++ b/kiosk/src/ui.rs @@ -6,7 +6,7 @@ use gtk4::{self as gtk, Application, ApplicationWindow, Box as GtkBox, Grid, Lab use gstreamer::prelude::*; use tracing::{info, warn}; -use crate::bundle::{BundleLayout, KioskBundle}; +use crate::bundle::KioskBundle; use crate::pipeline; use crate::server; @@ -29,7 +29,7 @@ fn activate(app: &Application) { let provider = gtk::CssProvider::new(); provider.load_from_string("window { background-color: #1a1a2e; }"); gtk::style_context_add_provider_for_display( - &window.display(), + &WidgetExt::display(&window), &provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, );