apple / swift (push) Successful in 1m24s
release / apple (push) Successful in 10m3s
android / android (push) Successful in 13m31s
arch / build-publish (push) Successful in 13m39s
ci / web (push) Successful in 1m4s
ci / docs-site (push) Successful in 1m12s
windows-host / package (push) Successful in 16m40s
apple / screenshots (push) Successful in 6m38s
ci / bench (push) Successful in 5m26s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 3m9s
ci / rust (push) Successful in 20m46s
decky / build-publish (push) Successful in 30s
windows-msix / package (x64, C:\Users\Public\ffmpeg, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 3m15s
deb / build-publish (push) Successful in 8m50s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 45s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 12s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 12s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 12s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 4m31s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 7m6s
deb / build-publish-host (push) Successful in 9m52s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 6m44s
docker / deploy-docs (push) Successful in 28s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 7m4s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 16m35s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m45s
flatpak / build-publish (push) Failing after 8m6s
The pen plane from design/pen-tablet-input.md, protocol side only (the P1 uinput tablet injector will consume it): 0xCC kind 0x05 carries batches of state-full PenSamples (pressure, polar tilt + azimuth, barrel roll, hover distance, eraser tool, barrel buttons); PenTracker diffs samples into injector transitions so a lost datagram self-heals; HOST_CAP_PEN (0x10) gates sending and stays unadvertised until a real backend exists. C ABI: PunktfunkPenSample + punktfunk_connection_send_pen, documented in docs/embedding-the-c-abi.md §8. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
85 lines
4.4 KiB
Rust
85 lines
4.4 KiB
Rust
//! `WorkerArgs` (the pump's constructor payload) and `reject_from_close`.
|
|
|
|
use super::*;
|
|
use crate::clipboard::{ClipCommand, ClipEventCore};
|
|
use crate::config::{CompositorPref, GamepadPref, Mode};
|
|
use crate::error::Result;
|
|
use crate::input::InputEvent;
|
|
use crate::quic::{HdrMeta, HidOutput};
|
|
use std::sync::atomic::{AtomicBool, AtomicI64, AtomicU64};
|
|
use std::sync::mpsc::SyncSender;
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
pub(crate) struct WorkerArgs {
|
|
pub(crate) host: String,
|
|
pub(crate) port: u16,
|
|
pub(crate) mode: Mode,
|
|
pub(crate) compositor: CompositorPref,
|
|
pub(crate) gamepad: GamepadPref,
|
|
pub(crate) bitrate_kbps: u32,
|
|
pub(crate) video_caps: u8,
|
|
pub(crate) audio_channels: u8,
|
|
pub(crate) video_codecs: u8,
|
|
pub(crate) preferred_codec: u8,
|
|
pub(crate) display_hdr: Option<HdrMeta>,
|
|
pub(crate) client_caps: u8,
|
|
pub(crate) launch: Option<String>,
|
|
pub(crate) pin: Option<[u8; 32]>,
|
|
pub(crate) identity: Option<(String, String)>,
|
|
/// The embedder's connect budget (the same value `connect` bounds `ready_rx` with): the
|
|
/// dial loop re-dials a silent host within it, so a host still resuming from Wake-on-LAN
|
|
/// is caught the moment its network comes back instead of failing on the first attempt.
|
|
pub(crate) connect_timeout: std::time::Duration,
|
|
pub(crate) frames: Arc<FrameChannel>,
|
|
pub(crate) audio_tx: SyncSender<AudioPacket>,
|
|
pub(crate) rumble_tx: SyncSender<RumbleUpdate>,
|
|
/// Feed half of the rumble policy engine — its `Drop` (demux task end) marks the engine
|
|
/// closed, so the command API always observes connection teardown.
|
|
pub(crate) rumble_feed: super::rumble::RumbleFeed,
|
|
pub(crate) hidout_tx: SyncSender<HidOutput>,
|
|
pub(crate) hdr_meta_tx: SyncSender<HdrMeta>,
|
|
pub(crate) host_timing_tx: SyncSender<crate::quic::HostTiming>,
|
|
pub(crate) cursor_shape_tx: SyncSender<crate::quic::CursorShape>,
|
|
pub(crate) cursor_state_tx: SyncSender<crate::quic::CursorState>,
|
|
pub(crate) input_rx: tokio::sync::mpsc::UnboundedReceiver<InputEvent>,
|
|
pub(crate) mic_rx: tokio::sync::mpsc::Receiver<(u32, u64, Vec<u8>)>,
|
|
/// Pre-encoded 0xCC datagrams (rich input AND pen batches — see `NativeClient.rich_input_tx`).
|
|
pub(crate) rich_input_rx: tokio::sync::mpsc::UnboundedReceiver<Vec<u8>>,
|
|
pub(crate) ctrl_rx: tokio::sync::mpsc::Receiver<CtrlRequest>,
|
|
pub(crate) ctrl_tx: tokio::sync::mpsc::Sender<CtrlRequest>,
|
|
/// Inbound clipboard event plane feed — the control task pushes ClipState/ClipOffer, the
|
|
/// clipboard task pushes fetch data; drained by [`NativeClient::next_clip`].
|
|
pub(crate) clip_event_tx: SyncSender<ClipEventCore>,
|
|
/// Outbound clipboard fetch/serve/cancel commands from the embedder → [`crate::clipboard::run`].
|
|
pub(crate) clip_cmd_rx: tokio::sync::mpsc::UnboundedReceiver<ClipCommand>,
|
|
pub(crate) ready_tx: std::sync::mpsc::Sender<Result<Negotiated>>,
|
|
pub(crate) shutdown: Arc<AtomicBool>,
|
|
/// Deliberate-quit flag (see [`NativeClient::quit`]): the worker closes with the quit code if set.
|
|
pub(crate) quit: Arc<AtomicBool>,
|
|
pub(crate) mode_slot: Arc<std::sync::Mutex<Mode>>,
|
|
pub(crate) probe: Arc<Mutex<ProbeState>>,
|
|
pub(crate) frames_dropped: Arc<AtomicU64>,
|
|
pub(crate) fec_recovered: Arc<AtomicU64>,
|
|
pub(crate) hot_tids: Arc<Mutex<Vec<i32>>>,
|
|
/// The live clock offset (see [`NativeClient::clock_offset`]): the worker seeds it with the
|
|
/// connect-time estimate; the control task's mid-stream re-syncs update it.
|
|
pub(crate) clock_offset: Arc<AtomicI64>,
|
|
/// Decode-stage latency samples from the embedder (see [`NativeClient::decode_lat`]): the pump
|
|
/// drains a window mean into the adaptive-bitrate controller's decode signal.
|
|
pub(crate) decode_lat: Arc<Mutex<DecodeLatAcc>>,
|
|
}
|
|
|
|
/// The worker: QUIC handshake, then the input/datagram/control tasks + the blocking
|
|
/// data-plane pump.
|
|
/// The host's stated rejection, if this connection was closed with a typed application code
|
|
/// (see [`crate::reject`]) — `None` for local errors, bare/legacy closes (including our own
|
|
/// `LocallyClosed`), and transport failures, which keep their original error.
|
|
pub(crate) fn reject_from_close(conn: &quinn::Connection) -> Option<crate::reject::RejectReason> {
|
|
match conn.close_reason()? {
|
|
quinn::ConnectionError::ApplicationClosed(ac) => u32::try_from(u64::from(ac.error_code))
|
|
.ok()
|
|
.and_then(crate::reject::RejectReason::from_close_code),
|
|
_ => None,
|
|
}
|
|
}
|