Skip to content

Commit 084f973

Browse files
Merge pull request #1601 from CapSoftware/cursor/export-pipeline-speed-cbf4
Export pipeline speed
2 parents 7b228c4 + 4186535 commit 084f973

File tree

25 files changed

+1325
-526
lines changed

25 files changed

+1325
-526
lines changed

apps/desktop/src-tauri/src/camera.rs

Lines changed: 1 addition & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -151,50 +151,6 @@ impl CameraPreviewManager {
151151
}
152152
}
153153

154-
// Resumes a paused camera preview. Uses window.show() which is safe, unlike
155-
// panel.order_front_regardless() which causes crashes after repeated use.
156-
pub fn resume(&mut self, window: &WebviewWindow) {
157-
if let Some(preview) = &mut self.preview
158-
&& preview.is_paused
159-
{
160-
preview.is_paused = false;
161-
preview
162-
.reconfigure
163-
.send(ReconfigureEvent::Resume)
164-
.map_err(|err| error!("Error sending camera preview resume event: {err}"))
165-
.ok();
166-
window
167-
.run_on_main_thread({
168-
let window = window.clone();
169-
move || {
170-
let _ = window.show();
171-
}
172-
})
173-
.ok();
174-
}
175-
}
176-
177-
pub fn is_paused(&self) -> bool {
178-
self.preview.as_ref().is_some_and(|p| p.is_paused)
179-
}
180-
181-
pub fn begin_shutdown_for_session(
182-
&mut self,
183-
expected_session_id: u64,
184-
) -> Option<oneshot::Receiver<()>> {
185-
if let Some(preview) = &self.preview
186-
&& preview.session_id != expected_session_id
187-
{
188-
info!(
189-
"Skipping camera preview close: session mismatch (expected {}, current {})",
190-
expected_session_id, preview.session_id
191-
);
192-
return None;
193-
}
194-
195-
self.begin_shutdown()
196-
}
197-
198154
pub fn begin_shutdown(&mut self) -> Option<oneshot::Receiver<()>> {
199155
let preview = self.preview.take()?;
200156
info!(
@@ -304,14 +260,6 @@ impl CameraPreviewManager {
304260

305261
Ok(())
306262
}
307-
308-
pub fn on_window_close_for_session(&mut self, expected_session_id: u64) {
309-
let _ = self.begin_shutdown_for_session(expected_session_id);
310-
}
311-
312-
pub fn on_window_close(&mut self) {
313-
let _ = self.begin_shutdown();
314-
}
315263
}
316264

317265
// Internal events for the persistent camera renderer architecture.
@@ -874,7 +822,7 @@ impl Renderer {
874822
let _ = self.device.poll(wgpu::PollType::Wait);
875823

876824
drop(std::mem::take(&mut self.texture));
877-
drop(std::mem::take(&mut self.aspect_ratio));
825+
self.aspect_ratio = Cached::default();
878826

879827
let surface = self.surface.take();
880828
let (drop_tx, drop_rx) = oneshot::channel();

apps/desktop/src-tauri/src/camera_legacy.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ pub async fn create_camera_preview_ws() -> (Sender<FFmpegVideoFrame>, u16, Cance
6060

6161
frame_tx_clone
6262
.send(WSFrame {
63-
data: frame.data(0).to_vec(),
63+
data: std::sync::Arc::new(frame.data(0).to_vec()),
6464
width: frame.width(),
6565
height: frame.height(),
6666
stride: frame.stride(0) as u32,

apps/desktop/src-tauri/src/export.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ pub async fn export_video(
111111
let _guard = if let Some(ref ed) = *editor {
112112
ed.export_active.store(true, Ordering::Release);
113113
tracing::info!("Pausing editor preview during export");
114-
tokio::time::sleep(std::time::Duration::from_millis(200)).await;
115114
Some(ExportActiveGuard(&ed.export_active))
116115
} else {
117116
None
@@ -367,7 +366,7 @@ pub async fn generate_export_preview(
367366
);
368367

369368
let frame = frame_renderer
370-
.render(
369+
.render_immediate(
371370
segment_frames,
372371
uniforms,
373372
&render_segment.cursor,
@@ -510,7 +509,7 @@ pub async fn generate_export_preview_fast(
510509
);
511510

512511
let frame = frame_renderer
513-
.render(segment_frames, uniforms, &segment_media.cursor, &mut layers)
512+
.render_immediate(segment_frames, uniforms, &segment_media.cursor, &mut layers)
514513
.await
515514
.map_err(|e| format!("Failed to render frame: {e}"))?;
516515

apps/desktop/src-tauri/src/frame_ws.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ pub enum WSFrameFormat {
7373

7474
#[derive(Clone)]
7575
pub struct WSFrame {
76-
pub data: Vec<u8>,
76+
pub data: std::sync::Arc<Vec<u8>>,
7777
pub width: u32,
7878
pub height: u32,
7979
pub stride: u32,
@@ -138,11 +138,11 @@ pub async fn create_watch_frame_ws(
138138
let borrowed = camera_rx.borrow();
139139
borrowed.as_deref().map(pack_ws_frame_ref)
140140
};
141-
if let Some(packed) = packed {
142-
if let Err(e) = socket.send(Message::Binary(packed)).await {
143-
tracing::error!("Failed to send initial frame to socket: {:?}", e);
144-
return;
145-
}
141+
if let Some(packed) = packed
142+
&& let Err(e) = socket.send(Message::Binary(packed)).await
143+
{
144+
tracing::error!("Failed to send initial frame to socket: {:?}", e);
145+
return;
146146
}
147147
}
148148

@@ -278,7 +278,7 @@ pub async fn create_frame_ws(frame_tx: broadcast::Sender<WSFrame>) -> (u16, Canc
278278
match incoming_frame {
279279
Ok(frame) => {
280280
let packed = pack_frame_data(
281-
frame.data,
281+
std::sync::Arc::unwrap_or_clone(frame.data),
282282
frame.stride,
283283
frame.height,
284284
frame.width,

apps/desktop/src-tauri/src/panel_manager.rs

Lines changed: 2 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,26 @@ use tokio::sync::RwLock;
66
use tracing::{debug, info, trace, warn};
77

88
#[cfg(target_os = "macos")]
9-
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9+
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
1010
pub enum PanelState {
11+
#[default]
1112
None,
1213
Creating,
1314
Ready,
1415
Destroying,
1516
}
1617

17-
#[cfg(target_os = "macos")]
18-
impl Default for PanelState {
19-
fn default() -> Self {
20-
Self::None
21-
}
22-
}
23-
2418
#[cfg(target_os = "macos")]
2519
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2620
pub enum PanelWindowType {
2721
Camera,
28-
Main,
29-
TargetSelectOverlay,
30-
InProgressRecording,
3122
}
3223

3324
#[cfg(target_os = "macos")]
3425
impl std::fmt::Display for PanelWindowType {
3526
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3627
match self {
3728
Self::Camera => write!(f, "Camera"),
38-
Self::Main => write!(f, "Main"),
39-
Self::TargetSelectOverlay => write!(f, "TargetSelectOverlay"),
40-
Self::InProgressRecording => write!(f, "InProgressRecording"),
4129
}
4230
}
4331
}
@@ -107,7 +95,6 @@ impl PanelManager {
10795
window_type, op_id
10896
);
10997
Some(PanelOperationGuard {
110-
window_type,
11198
operation_id: op_id,
11299
completed: false,
113100
})
@@ -136,87 +123,6 @@ impl PanelManager {
136123
}
137124
}
138125

139-
pub async fn try_begin_show(
140-
&self,
141-
window_type: PanelWindowType,
142-
) -> Option<PanelOperationGuard> {
143-
let mut panels = self.panels.write().await;
144-
let entry = panels.entry(window_type).or_default();
145-
146-
match entry.state {
147-
PanelState::Ready => {
148-
let op_id = self
149-
.operation_counter
150-
.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
151-
debug!(
152-
"Panel {}: beginning show operation (op_id={})",
153-
window_type, op_id
154-
);
155-
Some(PanelOperationGuard {
156-
window_type,
157-
operation_id: op_id,
158-
completed: true,
159-
})
160-
}
161-
PanelState::None => {
162-
debug!("Panel {}: show blocked - window doesn't exist", window_type);
163-
None
164-
}
165-
PanelState::Creating => {
166-
debug!(
167-
"Panel {}: show blocked - currently creating (op_id={})",
168-
window_type, entry.operation_id
169-
);
170-
None
171-
}
172-
PanelState::Destroying => {
173-
debug!(
174-
"Panel {}: show blocked - currently destroying (op_id={})",
175-
window_type, entry.operation_id
176-
);
177-
None
178-
}
179-
}
180-
}
181-
182-
pub async fn try_begin_destroy(
183-
&self,
184-
window_type: PanelWindowType,
185-
) -> Option<PanelOperationGuard> {
186-
let mut panels = self.panels.write().await;
187-
let entry = panels.entry(window_type).or_default();
188-
189-
match entry.state {
190-
PanelState::Ready | PanelState::Creating => {
191-
let op_id = self
192-
.operation_counter
193-
.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
194-
entry.state = PanelState::Destroying;
195-
entry.operation_id = op_id;
196-
debug!(
197-
"Panel {}: beginning destroy operation (op_id={})",
198-
window_type, op_id
199-
);
200-
Some(PanelOperationGuard {
201-
window_type,
202-
operation_id: op_id,
203-
completed: false,
204-
})
205-
}
206-
PanelState::None => {
207-
debug!("Panel {}: destroy skipped - already destroyed", window_type);
208-
None
209-
}
210-
PanelState::Destroying => {
211-
debug!(
212-
"Panel {}: destroy blocked - already destroying (op_id={})",
213-
window_type, entry.operation_id
214-
);
215-
None
216-
}
217-
}
218-
}
219-
220126
pub async fn mark_ready(&self, window_type: PanelWindowType, operation_id: u64) {
221127
let mut panels = self.panels.write().await;
222128
if let Some(entry) = panels.get_mut(&window_type) {
@@ -235,24 +141,6 @@ impl PanelManager {
235141
}
236142
}
237143

238-
pub async fn mark_destroyed(&self, window_type: PanelWindowType, operation_id: u64) {
239-
let mut panels = self.panels.write().await;
240-
if let Some(entry) = panels.get_mut(&window_type) {
241-
if entry.operation_id == operation_id && entry.state == PanelState::Destroying {
242-
entry.state = PanelState::None;
243-
info!(
244-
"Panel {}: marked destroyed (op_id={})",
245-
window_type, operation_id
246-
);
247-
} else {
248-
warn!(
249-
"Panel {}: mark_destroyed ignored - state mismatch (current state={:?}, current op={}, requested op={})",
250-
window_type, entry.state, entry.operation_id, operation_id
251-
);
252-
}
253-
}
254-
}
255-
256144
pub async fn force_reset(&self, window_type: PanelWindowType) {
257145
let mut panels = self.panels.write().await;
258146
if let Some(entry) = panels.get_mut(&window_type) {
@@ -293,7 +181,6 @@ impl PanelManager {
293181

294182
#[cfg(target_os = "macos")]
295183
pub struct PanelOperationGuard {
296-
pub window_type: PanelWindowType,
297184
pub operation_id: u64,
298185
completed: bool,
299186
}
@@ -303,10 +190,6 @@ impl PanelOperationGuard {
303190
pub fn mark_completed(&mut self) {
304191
self.completed = true;
305192
}
306-
307-
pub fn is_completed(&self) -> bool {
308-
self.completed
309-
}
310193
}
311194

312195
#[cfg(target_os = "macos")]

apps/desktop/src-tauri/src/screenshot_editor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ impl ScreenshotEditorInstances {
371371
);
372372

373373
let rendered_frame = frame_renderer
374-
.render(
374+
.render_immediate(
375375
segment_frames,
376376
uniforms,
377377
&cap_project::CursorEvents::default(),

apps/desktop/src-tauri/src/windows.rs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,9 @@ fn is_system_dark_mode() -> bool {
7575
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
7676
if let Ok(key) =
7777
hkcu.open_subkey("Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize")
78+
&& let Ok(value) = key.get_value::<u32, _>("AppsUseLightTheme")
7879
{
79-
if let Ok(value) = key.get_value::<u32, _>("AppsUseLightTheme") {
80-
return value == 0;
81-
}
80+
return value == 0;
8281
}
8382
false
8483
}
@@ -858,17 +857,17 @@ impl ShowCapWindow {
858857
}
859858

860859
#[cfg(not(target_os = "macos"))]
861-
if let Self::InProgressRecording { .. } = self {
862-
if let Some(window) = self.id(app).get(app) {
863-
let width = 320.0;
864-
let height = 150.0;
865-
let recording_monitor = CursorMonitorInfo::get();
866-
let (pos_x, pos_y) = recording_monitor.bottom_center_position(width, height, 120.0);
867-
let _ = window.set_position(tauri::LogicalPosition::new(pos_x, pos_y));
868-
window.show().ok();
869-
window.set_focus().ok();
870-
return Ok(window);
871-
}
860+
if let Self::InProgressRecording { .. } = self
861+
&& let Some(window) = self.id(app).get(app)
862+
{
863+
let width = 320.0;
864+
let height = 150.0;
865+
let recording_monitor = CursorMonitorInfo::get();
866+
let (pos_x, pos_y) = recording_monitor.bottom_center_position(width, height, 120.0);
867+
let _ = window.set_position(tauri::LogicalPosition::new(pos_x, pos_y));
868+
window.show().ok();
869+
window.set_focus().ok();
870+
return Ok(window);
872871
}
873872

874873
if !matches!(self, Self::Camera { .. } | Self::InProgressRecording { .. })
@@ -886,11 +885,6 @@ impl ShowCapWindow {
886885
None
887886
};
888887

889-
match self {
890-
Self::Main { .. } => {}
891-
_ => {}
892-
}
893-
894888
if let Self::Main {
895889
init_target_mode: Some(target_mode),
896890
} = self

0 commit comments

Comments
 (0)