ui: enhance notification countdown bar visibility and optimize daemon memory
This commit is contained in:
parent
0e620e2658
commit
5a1e503508
5 changed files with 71 additions and 21 deletions
|
|
@ -58,7 +58,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||
scythe::hyprland_binds::register_hyprland_binds(&initial_config);
|
||||
scythe::hyprland_binds::spawn_hyprland_reload_watcher();
|
||||
|
||||
let (frame_tx, frame_rx) = bounded::<Frame>(5);
|
||||
let (frame_tx, frame_rx) = bounded::<Frame>(2);
|
||||
let (cmd_tx, cmd_rx) = bounded::<Command>(32);
|
||||
let (mux_tx, mux_rx) = bounded::<Vec<Packet>>(4);
|
||||
let (audio_tx, audio_rx) = bounded::<Vec<f32>>(500);
|
||||
|
|
@ -372,7 +372,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||
let video_time_base = unsafe { (*(codec_ctx_ptr as *mut ffmpeg_next::ffi::AVCodecContext)).time_base };
|
||||
let audio_time_base = audio_codec_ctx_ptr.map(|p| unsafe { (*(p as *mut ffmpeg_next::ffi::AVCodecContext)).time_base });
|
||||
|
||||
let mut ring = HeapRb::<Packet>::new((config.replay_duration_sec as usize) * (config.fps as usize + 60) + 120);
|
||||
let ring_capacity = if config.replay_enabled {
|
||||
(config.replay_duration_sec as usize) * (config.fps as usize + 50) + 60
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let mut ring = HeapRb::<Packet>::new(ring_capacity);
|
||||
let mut normal_muxer: Option<Muxer> = None;
|
||||
let mut normal_recording = false;
|
||||
let mut normal_waiting_keyframe = false;
|
||||
|
|
@ -474,6 +479,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||
eprintln!("Error finalizing replay muxer: {}", e);
|
||||
} else {
|
||||
println!("Replay saved to {}!", full_path);
|
||||
#[cfg(target_os = "linux")]
|
||||
unsafe { libc::malloc_trim(0); }
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
|
|
@ -489,6 +496,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||
let mut latest_frame: Option<Frame> = None;
|
||||
let mut has_new_frame = false;
|
||||
let mut last_encoded_raw_ptr: usize = 0;
|
||||
let mut last_malloc_trim = std::time::Instant::now();
|
||||
|
||||
loop {
|
||||
crossbeam_channel::select! {
|
||||
|
|
@ -521,10 +529,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||
replay_state_clone.store(config.replay_enabled, Ordering::SeqCst);
|
||||
audio_muted_clone.store(config.audio_mode == "muted", Ordering::SeqCst);
|
||||
println!("Daemon config reloaded! Audio mode: {}", config.audio_mode);
|
||||
let new_capacity = (config.replay_duration_sec as usize) * (config.fps as usize + 60) + 120;
|
||||
let new_capacity = if config.replay_enabled {
|
||||
(config.replay_duration_sec as usize) * (config.fps as usize + 50) + 60
|
||||
} else {
|
||||
1
|
||||
};
|
||||
if ring.capacity().get() != new_capacity {
|
||||
ring = HeapRb::<Packet>::new(new_capacity);
|
||||
println!("Replay buffer resized to {} packets.", new_capacity);
|
||||
#[cfg(target_os = "linux")]
|
||||
unsafe { libc::malloc_trim(0); }
|
||||
}
|
||||
scythe::hyprland_binds::register_hyprland_binds(&config);
|
||||
audio_capture = match scythe::capture::audio::AudioCapture::new_with_device_mode_volumes_and_levels(
|
||||
|
|
@ -581,6 +595,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||
rec_base_audio_pts = -1;
|
||||
rec_state_clone.store(false, Ordering::SeqCst);
|
||||
rec_start_clone.store(0, Ordering::SeqCst);
|
||||
#[cfg(target_os = "linux")]
|
||||
unsafe { libc::malloc_trim(0); }
|
||||
},
|
||||
Command::ToggleRecording => {
|
||||
if normal_recording {
|
||||
|
|
@ -594,6 +610,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||
rec_base_audio_pts = -1;
|
||||
rec_state_clone.store(false, Ordering::SeqCst);
|
||||
rec_start_clone.store(0, Ordering::SeqCst);
|
||||
#[cfg(target_os = "linux")]
|
||||
unsafe { libc::malloc_trim(0); }
|
||||
} else {
|
||||
normal_recording = true;
|
||||
normal_waiting_keyframe = true;
|
||||
|
|
@ -672,6 +690,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||
recv(ticker) -> _ => {
|
||||
while ticker.try_recv().is_ok() {}
|
||||
|
||||
if last_malloc_trim.elapsed().as_secs() >= 5 {
|
||||
last_malloc_trim = std::time::Instant::now();
|
||||
#[cfg(target_os = "linux")]
|
||||
unsafe { libc::malloc_trim(0); }
|
||||
}
|
||||
|
||||
if !normal_recording && !config.replay_enabled {
|
||||
has_new_frame = false;
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ pub struct PipeWireStream {
|
|||
|
||||
impl PipeWireStream {
|
||||
pub fn new(node_id: u32, fd: OwnedFd) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let (tx, rx) = bounded(5);
|
||||
let (tx, rx) = bounded(2);
|
||||
|
||||
std::thread::spawn(move || {
|
||||
pw::init();
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ impl VaapiEncoder {
|
|||
(*frames_ctx).sw_format = AVPixelFormat::AV_PIX_FMT_NV12;
|
||||
(*frames_ctx).width = width as i32;
|
||||
(*frames_ctx).height = height as i32;
|
||||
(*frames_ctx).initial_pool_size = 20;
|
||||
(*frames_ctx).initial_pool_size = 6;
|
||||
|
||||
let ret = av_hwframe_ctx_init(hw_frames_ref);
|
||||
if ret < 0 {
|
||||
|
|
@ -291,7 +291,7 @@ impl VaapiEncoder {
|
|||
0,
|
||||
);
|
||||
if p != libc::MAP_FAILED {
|
||||
if self.dma_mmap_cache.len() >= 16 {
|
||||
if self.dma_mmap_cache.len() >= 4 {
|
||||
for (_, (old_p, old_size)) in self.dma_mmap_cache.drain() {
|
||||
libc::munmap(old_p, old_size);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -354,16 +354,26 @@ pub fn show_shadowplay_toast(title: &str, subtitle: &str, icon: ToastIcon) {
|
|||
cr.rectangle(0.5, 0.5, w - 1.0, h - 1.0);
|
||||
let _ = cr.stroke();
|
||||
|
||||
// 5. Animated countdown timer line on bottom edge
|
||||
// 5. Animated countdown timer line on bottom edge (high visibility)
|
||||
let progress = 1.0 - (elapsed / total_dur).clamp(0.0, 1.0);
|
||||
cr.set_source_rgba(1.0, 1.0, 1.0, 0.08 * alpha);
|
||||
cr.rectangle(0.0, h - 2.0, w, 2.0);
|
||||
let bar_h = 3.5;
|
||||
cr.set_source_rgba(1.0, 1.0, 1.0, 0.15 * alpha);
|
||||
cr.rectangle(0.0, h - bar_h, w, bar_h);
|
||||
let _ = cr.fill();
|
||||
|
||||
cr.set_source_rgba(active_accent.0, active_accent.1, active_accent.2, 0.75 * alpha);
|
||||
cr.rectangle(0.0, h - 2.0, w * progress, 2.0);
|
||||
let bar_w = (w * progress).max(0.0);
|
||||
cr.set_source_rgba(active_accent.0, active_accent.1, active_accent.2, 0.95 * alpha);
|
||||
cr.rectangle(0.0, h - bar_h, bar_w, bar_h);
|
||||
let _ = cr.fill();
|
||||
|
||||
if bar_w > 2.0 {
|
||||
cr.set_source_rgba(1.0, 1.0, 1.0, 0.85 * alpha);
|
||||
cr.set_line_width(1.5);
|
||||
cr.move_to(bar_w, h - bar_h);
|
||||
cr.line_to(bar_w, h);
|
||||
let _ = cr.stroke();
|
||||
}
|
||||
|
||||
gtk::glib::Propagation::Proceed
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -2224,12 +2224,20 @@ impl ScytheOverlayApp {
|
|||
egui::StrokeKind::Inside,
|
||||
);
|
||||
|
||||
// 5. Animated Countdown Timer Line (bottom edge)
|
||||
// 5. Animated Countdown Timer Line (bottom edge - high visibility)
|
||||
let progress = 1.0 - (elapsed / total_dur).clamp(0.0, 1.0);
|
||||
let bar_track = egui::Rect::from_min_size(egui::pos2(toast_rect.left(), toast_rect.bottom() - 2.0), egui::vec2(card_w, 2.0));
|
||||
painter.rect_filled(bar_track, CornerRadius::ZERO, Color32::from_rgba_unmultiplied(255, 255, 255, (16.0 * anim_alpha) as u8));
|
||||
let bar_rect = egui::Rect::from_min_size(egui::pos2(toast_rect.left(), toast_rect.bottom() - 2.0), egui::vec2(card_w * progress, 2.0));
|
||||
painter.rect_filled(bar_rect, CornerRadius::ZERO, Color32::from_rgba_unmultiplied(active_color.r(), active_color.g(), active_color.b(), (190.0 * anim_alpha) as u8));
|
||||
let bar_h = 3.5_f32;
|
||||
let bar_track = egui::Rect::from_min_size(egui::pos2(toast_rect.left(), toast_rect.bottom() - bar_h), egui::vec2(card_w, bar_h));
|
||||
painter.rect_filled(bar_track, CornerRadius::ZERO, Color32::from_rgba_unmultiplied(255, 255, 255, (30.0 * anim_alpha) as u8));
|
||||
let bar_w = (card_w * progress).max(0.0);
|
||||
let bar_rect = egui::Rect::from_min_size(egui::pos2(toast_rect.left(), toast_rect.bottom() - bar_h), egui::vec2(bar_w, bar_h));
|
||||
painter.rect_filled(bar_rect, CornerRadius::ZERO, Color32::from_rgba_unmultiplied(active_color.r(), active_color.g(), active_color.b(), (255.0 * anim_alpha) as u8));
|
||||
if bar_w > 2.0 {
|
||||
painter.line_segment(
|
||||
[egui::pos2(toast_rect.left() + bar_w, toast_rect.bottom() - bar_h), egui::pos2(toast_rect.left() + bar_w, toast_rect.bottom())],
|
||||
Stroke::new(1.5_f32, Color32::from_rgba_unmultiplied(255, 255, 255, (220.0 * anim_alpha) as u8)),
|
||||
);
|
||||
}
|
||||
|
||||
// Left icon area (centered vertically at x = 24.0)
|
||||
let icon_center = egui::pos2(toast_rect.left() + 24.0, toast_rect.center().y);
|
||||
|
|
@ -2768,12 +2776,20 @@ impl eframe::App for ShadowPlayToastApp {
|
|||
egui::StrokeKind::Inside,
|
||||
);
|
||||
|
||||
// 5. Animated Countdown Timer Line (bottom edge)
|
||||
// 5. Animated Countdown Timer Line (bottom edge - high visibility)
|
||||
let progress = 1.0 - (elapsed / total_dur).clamp(0.0, 1.0);
|
||||
let bar_track = egui::Rect::from_min_size(egui::pos2(rect.left(), rect.bottom() - 2.0), egui::vec2(320.0, 2.0));
|
||||
painter.rect_filled(bar_track, CornerRadius::ZERO, Color32::from_rgba_unmultiplied(255, 255, 255, (16.0 * anim_alpha) as u8));
|
||||
let bar_rect = egui::Rect::from_min_size(egui::pos2(rect.left(), rect.bottom() - 2.0), egui::vec2(320.0 * progress, 2.0));
|
||||
painter.rect_filled(bar_rect, CornerRadius::ZERO, Color32::from_rgba_unmultiplied(active_color.r(), active_color.g(), active_color.b(), (190.0 * anim_alpha) as u8));
|
||||
let bar_h = 3.5_f32;
|
||||
let bar_track = egui::Rect::from_min_size(egui::pos2(rect.left(), rect.bottom() - bar_h), egui::vec2(320.0, bar_h));
|
||||
painter.rect_filled(bar_track, CornerRadius::ZERO, Color32::from_rgba_unmultiplied(255, 255, 255, (30.0 * anim_alpha) as u8));
|
||||
let bar_w = (320.0 * progress).max(0.0);
|
||||
let bar_rect = egui::Rect::from_min_size(egui::pos2(rect.left(), rect.bottom() - bar_h), egui::vec2(bar_w, bar_h));
|
||||
painter.rect_filled(bar_rect, CornerRadius::ZERO, Color32::from_rgba_unmultiplied(active_color.r(), active_color.g(), active_color.b(), (255.0 * anim_alpha) as u8));
|
||||
if bar_w > 2.0 {
|
||||
painter.line_segment(
|
||||
[egui::pos2(rect.left() + bar_w, rect.bottom() - bar_h), egui::pos2(rect.left() + bar_w, rect.bottom())],
|
||||
Stroke::new(1.5_f32, Color32::from_rgba_unmultiplied(255, 255, 255, (220.0 * anim_alpha) as u8)),
|
||||
);
|
||||
}
|
||||
|
||||
// Left icon area (centered vertically at x = 24.0)
|
||||
let icon_center = egui::pos2(rect.left() + 24.0, rect.center().y);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue