#[cfg(coverage)] #[tonic::async_trait] impl Relay for Handler { type StreamKeyboardStream = ReceiverStream>; type StreamMouseStream = ReceiverStream>; type CaptureVideoStream = VideoStream; type CaptureAudioStream = AudioStream; type StreamMicrophoneStream = ReceiverStream>; type StreamCameraStream = ReceiverStream>; async fn stream_keyboard( &self, req: Request>, ) -> Result, Status> { let (tx, rx) = tokio::sync::mpsc::channel(32); let kb = self.kb.clone(); let report_delay = live_keyboard_report_delay(); tokio::spawn(async move { let mut s = req.into_inner(); while let Some(pkt) = s.next().await.transpose()? { let _ = runtime_support::write_hid_report(&kb, &hid_endpoint(0), &pkt.data).await; tx.send(Ok(pkt)).await.ok(); if !report_delay.is_zero() { #[cfg(not(coverage))] tokio::time::sleep(report_delay).await; } } Ok::<(), Status>(()) }); Ok(Response::new(ReceiverStream::new(rx))) } async fn stream_mouse( &self, req: Request>, ) -> Result, Status> { let (tx, rx) = tokio::sync::mpsc::channel(32); let ms = self.ms.clone(); tokio::spawn(async move { let mut s = req.into_inner(); while let Some(pkt) = s.next().await.transpose()? { let _ = runtime_support::write_hid_report(&ms, &hid_endpoint(1), &pkt.data).await; tx.send(Ok(pkt)).await.ok(); } Ok::<(), Status>(()) }); Ok(Response::new(ReceiverStream::new(rx))) } async fn stream_microphone( &self, req: Request>, ) -> Result, Status> { let lease = self.upstream_media_rt.activate_microphone(); let Some(microphone_sink_permit) = self .upstream_media_rt .reserve_microphone_sink(lease.generation) .await else { return Err(Status::aborted( "microphone stream superseded before sink became available", )); }; let uac_dev = std::env::var("LESAVKA_UAC_DEV").unwrap_or_else(|_| "hw:UAC2Gadget,0".into()); let mut sink = runtime_support::open_voice_with_retry(&uac_dev) .await .map_err(|e| { self.upstream_media_rt.close_microphone(lease.generation); Status::internal(format!("{e:#}")) })?; let (tx, rx) = tokio::sync::mpsc::channel(1); let upstream_media_rt = self.upstream_media_rt.clone(); tokio::spawn(async move { let _microphone_sink_permit = microphone_sink_permit; let mut inbound = req.into_inner(); loop { if !upstream_media_rt.is_microphone_active(lease.generation) { break; } let next_packet = tokio::select! { packet = inbound.next() => packet, _ = tokio::time::sleep(Duration::from_millis(25)) => continue, }; let Some(mut pkt) = next_packet.transpose()? else { break; }; let plan = upstream_media_rt.plan_audio_pts(pkt.pts); tokio::time::sleep_until(plan.due_at).await; pkt.pts = plan.local_pts_us; sink.push(&pkt); } sink.finish(); upstream_media_rt.close_microphone(lease.generation); let _ = tx.send(Ok(Empty {})).await; Ok::<(), Status>(()) }); Ok(Response::new(ReceiverStream::new(rx))) } async fn stream_camera( &self, req: Request>, ) -> Result, Status> { let cfg = camera::current_camera_config(); let upstream_lease = self.upstream_media_rt.activate_camera(); let (session_id, relay) = self.camera_rt.activate(&cfg).await?; let camera_rt = self.camera_rt.clone(); let upstream_media_rt = self.upstream_media_rt.clone(); let (tx, rx) = tokio::sync::mpsc::channel(1); let frame_step_us = (1_000_000u64 / u64::from(cfg.fps.max(1))).max(1); tokio::spawn(async move { let mut s = req.into_inner(); loop { if !camera_rt.is_active(session_id) || !upstream_media_rt.is_camera_active(upstream_lease.generation) { break; } let next_packet = tokio::select! { packet = s.next() => packet, _ = tokio::time::sleep(Duration::from_millis(25)) => continue, }; let Some(mut pkt) = next_packet.transpose()? else { break; }; let plan = upstream_media_rt.plan_video_pts(pkt.pts, frame_step_us); tokio::time::sleep_until(plan.due_at).await; pkt.pts = plan.local_pts_us; relay.feed(pkt); } upstream_media_rt.close_camera(upstream_lease.generation); tx.send(Ok(Empty {})).await.ok(); Ok::<(), Status>(()) }); Ok(Response::new(ReceiverStream::new(rx))) } async fn capture_video( &self, req: Request, ) -> Result, Status> { self.capture_video_reply(req.into_inner()).await } async fn capture_audio( &self, _req: Request, ) -> Result, Status> { Err(Status::internal( "audio capture unavailable in coverage harness", )) } async fn paste_text(&self, req: Request) -> Result, Status> { self.paste_text_reply(req).await } async fn reset_usb(&self, _req: Request) -> Result, Status> { self.reset_usb_reply().await } async fn get_capture_power( &self, _req: Request, ) -> Result, Status> { self.get_capture_power_reply().await } async fn set_capture_power( &self, req: Request, ) -> Result, Status> { self.set_capture_power_reply(req).await } }