fix(core): Use crossbeam select for zero-latency commands, persist portal permissions, and link downloads/vrec

This commit is contained in:
katR 2026-09-03 21:59:55 +05:30
parent 7a15b7f8ec
commit 8291b267aa
2 changed files with 81 additions and 70 deletions

View file

@ -183,72 +183,81 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
}
});
while let Ok(frame) = frame_rx.recv() {
while let Ok(cmd) = cmd_rx.try_recv() {
match cmd {
Command::ReloadConfig => {
config = vrec::config::VrecConfig::load();
replay_state_clone.store(config.replay_enabled, Ordering::SeqCst);
println!("Daemon config reloaded!");
let new_capacity = (config.replay_duration_sec * 120).max(120) as usize;
if ring.capacity().get() != new_capacity {
ring = HeapRb::<Packet>::new(new_capacity);
println!("Replay buffer resized to {} packets.", new_capacity);
loop {
crossbeam_channel::select! {
recv(cmd_rx) -> cmd_res => {
if let Ok(cmd) = cmd_res {
match cmd {
Command::ReloadConfig => {
config = vrec::config::VrecConfig::load();
replay_state_clone.store(config.replay_enabled, Ordering::SeqCst);
println!("Daemon config reloaded!");
let new_capacity = (config.replay_duration_sec * 120).max(120) as usize;
if ring.capacity().get() != new_capacity {
ring = HeapRb::<Packet>::new(new_capacity);
println!("Replay buffer resized to {} packets.", new_capacity);
}
},
Command::SaveReplay => {
if config.replay_enabled {
let drain = ring.iter().cloned().collect::<Vec<_>>();
println!("SaveReplay triggered: {} packets in ring buffer", drain.len());
let _ = mux_tx.try_send(drain);
}
},
Command::StartRecording => {
if !normal_recording {
normal_recording = true;
normal_waiting_keyframe = true;
rec_state_clone.store(true, Ordering::SeqCst);
let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_secs();
rec_start_clone.store(now, Ordering::SeqCst);
println!("StartRecording requested, waiting for keyframe...");
}
},
Command::StopRecording => {
if let Some(mut m) = normal_muxer.take() {
let _ = m.finalize();
println!("Stopped normal recording.");
}
normal_recording = false;
normal_waiting_keyframe = false;
rec_state_clone.store(false, Ordering::SeqCst);
rec_start_clone.store(0, Ordering::SeqCst);
},
Command::ToggleRecording => {
if normal_recording {
if let Some(mut m) = normal_muxer.take() {
let _ = m.finalize();
println!("Stopped normal recording.");
}
normal_recording = false;
normal_waiting_keyframe = false;
rec_state_clone.store(false, Ordering::SeqCst);
rec_start_clone.store(0, Ordering::SeqCst);
} else {
normal_recording = true;
normal_waiting_keyframe = true;
rec_state_clone.store(true, Ordering::SeqCst);
let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_secs();
rec_start_clone.store(now, Ordering::SeqCst);
println!("ToggleRecording: StartRecording requested, waiting for keyframe...");
}
},
Command::ToggleAudio => {
let cur = audio_muted_clone.load(Ordering::SeqCst);
audio_muted_clone.store(!cur, Ordering::SeqCst);
println!("Audio mute toggled: {}", !cur);
},
_ => {}
}
},
Command::SaveReplay => {
if config.replay_enabled {
let drain = ring.iter().cloned().collect::<Vec<_>>();
let _ = mux_tx.try_send(drain);
}
},
Command::StartRecording => {
if !normal_recording {
normal_recording = true;
normal_waiting_keyframe = true;
rec_state_clone.store(true, Ordering::SeqCst);
let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_secs();
rec_start_clone.store(now, Ordering::SeqCst);
println!("StartRecording requested, waiting for keyframe...");
}
},
Command::StopRecording => {
if let Some(mut m) = normal_muxer.take() {
let _ = m.finalize();
println!("Stopped normal recording.");
}
normal_recording = false;
normal_waiting_keyframe = false;
rec_state_clone.store(false, Ordering::SeqCst);
rec_start_clone.store(0, Ordering::SeqCst);
},
Command::ToggleRecording => {
if normal_recording {
if let Some(mut m) = normal_muxer.take() {
let _ = m.finalize();
println!("Stopped normal recording.");
}
normal_recording = false;
normal_waiting_keyframe = false;
rec_state_clone.store(false, Ordering::SeqCst);
rec_start_clone.store(0, Ordering::SeqCst);
} else {
normal_recording = true;
normal_waiting_keyframe = true;
rec_state_clone.store(true, Ordering::SeqCst);
let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_secs();
rec_start_clone.store(now, Ordering::SeqCst);
println!("ToggleRecording: StartRecording requested, waiting for keyframe...");
}
},
Command::ToggleAudio => {
let cur = audio_muted_clone.load(Ordering::SeqCst);
audio_muted_clone.store(!cur, Ordering::SeqCst);
println!("Audio mute toggled: {}", !cur);
},
_ => {}
}
}
}
},
recv(frame_rx) -> frame_res => {
let frame = match frame_res {
Ok(f) => f,
Err(_) => break,
};
while let Ok(mut audio_chunk) = audio_rx.try_recv() {
if audio_muted_clone.load(Ordering::Relaxed) {
@ -292,11 +301,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
if !normal_waiting_keyframe
&& let Some(muxer) = normal_muxer.as_mut() {
let _ = muxer.write_packet(&pkt);
}
}
}
}
}
}
}
}
});
#[cfg(unix)]

View file

@ -25,10 +25,10 @@ impl WaylandCapture {
})?;
let select_opts = ashpd::desktop::screencast::SelectSourcesOptions::default()
.set_multiple(true)
.set_cursor_mode(CursorMode::Hidden)
.set_sources(SourceType::Monitor | SourceType::Window)
.set_persist_mode(PersistMode::DoNot);
.set_multiple(false)
.set_cursor_mode(CursorMode::Embedded)
.set_sources(SourceType::Monitor | SourceType::Monitor)
.set_persist_mode(PersistMode::Application);
proxy.select_sources(&session, select_opts).await.map_err(|e| {
format!("Failed to select ScreenCast sources: {:?}", e)