From 48f70ac7a3c418b25b016d823aab581fed210c42 Mon Sep 17 00:00:00 2001 From: polyesterswing Date: Sat, 27 Jul 2024 12:46:43 +0530 Subject: [PATCH 1/4] feat: pausing and quitting --- src/main.rs | 74 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/src/main.rs b/src/main.rs index ac60fea..ce27fda 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,19 @@ use opencv::core::VecN; use opencv::prelude::*; use opencv::{core, imgproc, videoio, Result}; -use std::sync::mpsc; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::{mpsc, Arc}; +use std::time::Duration; use std::{thread, time}; -use crossterm::{execute, cursor::{MoveTo, Hide}, terminal::{Clear, ClearType}}; -use std::io::{stdout, Write}; +use crossterm::event::{self, Event, KeyCode, KeyEvent}; +use crossterm::terminal; +use crossterm::{ + cursor::{Hide, MoveTo}, + execute, + terminal::{disable_raw_mode, enable_raw_mode, Clear, ClearType}, +}; +use std::io; fn map_range(from_range: (i32, i32), to_range: (i32, i32), s: i32) -> i32 { to_range.0 + (s - from_range.0) * (to_range.1 - to_range.0) / (from_range.1 - from_range.0) @@ -39,6 +47,17 @@ fn find_colors(frame: &Mat, gray: &Mat, table: &str, table_len: usize) -> Result } fn main() -> Result<()> { + enable_raw_mode().unwrap(); + + let mut stdout = io::stdout(); + + execute!(stdout, terminal::EnterAlternateScreen).unwrap(); + + let is_running = Arc::new(AtomicBool::new(true)); + let is_running_clone = is_running.clone(); + + let mut is_paused = false; + let ascii_table = " .'`^\",:;Il!i><~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$"; let ascii_table_len = ascii_table.len(); @@ -55,10 +74,10 @@ fn main() -> Result<()> { // time b/w each frame let frame_delay = time::Duration::from_millis((1000.0 / fps) as u64); - let (tx, rx) = mpsc::channel(); - execute!(stdout(), Hide).unwrap(); + let (tx, rx) = mpsc::sync_channel(50); + execute!(stdout, Hide).unwrap(); - thread::spawn(move || loop { + let handle = thread::spawn(move || loop { let mut frame = Mat::default(); cam.read(&mut frame).unwrap(); @@ -80,14 +99,47 @@ fn main() -> Result<()> { tx.send(find_colors(&smaller, &gray, ascii_table, ascii_table_len).unwrap()) .unwrap(); } + + if !is_running_clone.load(Ordering::Relaxed) { + break; + } }); - for received in rx { - execute!(stdout(), MoveTo(0, 0)).unwrap(); - execute!(stdout(), Clear(ClearType::Purge)).unwrap(); - print!("{}", received); - thread::sleep(frame_delay); + for received in &rx { + if !is_running.load(Ordering::Relaxed) { + handle.join().unwrap(); + drop(rx); + break; + } + + if !is_paused { + execute!(stdout, MoveTo(0, 0)).unwrap(); + execute!(stdout, Clear(ClearType::Purge)).unwrap(); + print!("{}", received); + + thread::sleep(frame_delay); + } + + if event::poll(Duration::from_millis(0)).unwrap() { + match event::read().unwrap() { + Event::Key(KeyEvent { + code: KeyCode::Char('q'), + .. + }) => { + is_running.store(false, Ordering::Relaxed); + } + Event::Key(KeyEvent { + code: KeyCode::Char(' '), + .. + }) => { + is_paused = !is_paused; + } + _ => {} + } + } } + execute!(stdout, terminal::LeaveAlternateScreen).unwrap(); + disable_raw_mode().unwrap(); Ok(()) } From 2d4ce8744f636327c5bb69908e84488220c2a7a4 Mon Sep 17 00:00:00 2001 From: polyesterswing Date: Sat, 27 Jul 2024 13:38:47 +0530 Subject: [PATCH 2/4] fix: play from the frame that was last paused --- src/main.rs | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/main.rs b/src/main.rs index ce27fda..b962421 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,18 +1,19 @@ use opencv::core::VecN; use opencv::prelude::*; use opencv::{core, imgproc, videoio, Result}; -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{mpsc, Arc}; +use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; use std::{thread, time}; + use crossterm::event::{self, Event, KeyCode, KeyEvent}; -use crossterm::terminal; use crossterm::{ - cursor::{Hide, MoveTo}, + cursor::{Hide, Show, MoveTo}, execute, terminal::{disable_raw_mode, enable_raw_mode, Clear, ClearType}, }; +use crossterm::terminal; use std::io; fn map_range(from_range: (i32, i32), to_range: (i32, i32), s: i32) -> i32 { @@ -53,9 +54,6 @@ fn main() -> Result<()> { execute!(stdout, terminal::EnterAlternateScreen).unwrap(); - let is_running = Arc::new(AtomicBool::new(true)); - let is_running_clone = is_running.clone(); - let mut is_paused = false; let ascii_table = @@ -91,28 +89,23 @@ fn main() -> Result<()> { 0.0, imgproc::INTER_AREA, ) - .unwrap(); + .unwrap(); let mut gray = Mat::default(); imgproc::cvt_color_def(&smaller, &mut gray, imgproc::COLOR_BGR2GRAY).unwrap(); - tx.send(find_colors(&smaller, &gray, ascii_table, ascii_table_len).unwrap()) - .unwrap(); + let Ok(_) = tx.send(find_colors(&smaller, &gray, ascii_table, ascii_table_len).unwrap()) else { + break; + }; } - if !is_running_clone.load(Ordering::Relaxed) { - break; - } }); - for received in &rx { - if !is_running.load(Ordering::Relaxed) { - handle.join().unwrap(); - drop(rx); - break; - } + loop { if !is_paused { + let received = rx.recv().unwrap(); + execute!(stdout, MoveTo(0, 0)).unwrap(); execute!(stdout, Clear(ClearType::Purge)).unwrap(); print!("{}", received); @@ -126,7 +119,9 @@ fn main() -> Result<()> { code: KeyCode::Char('q'), .. }) => { - is_running.store(false, Ordering::Relaxed); + // breaking here drops rx, preventing tx from sending which then breaks the other + // thread + break; } Event::Key(KeyEvent { code: KeyCode::Char(' '), @@ -140,6 +135,7 @@ fn main() -> Result<()> { } execute!(stdout, terminal::LeaveAlternateScreen).unwrap(); + execute!(stdout, Show).unwrap(); disable_raw_mode().unwrap(); Ok(()) } From 830683b55d306053dbe7bb5e96db4e01880a43fb Mon Sep 17 00:00:00 2001 From: polyesterswing Date: Sat, 27 Jul 2024 13:56:17 +0530 Subject: [PATCH 3/4] feat: add speed multipliers --- src/main.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index b962421..84c4524 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,6 +55,7 @@ fn main() -> Result<()> { execute!(stdout, terminal::EnterAlternateScreen).unwrap(); let mut is_paused = false; + let mut time_multiplier = 1.0; let ascii_table = " .'`^\",:;Il!i><~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$"; @@ -110,7 +111,7 @@ fn main() -> Result<()> { execute!(stdout, Clear(ClearType::Purge)).unwrap(); print!("{}", received); - thread::sleep(frame_delay); + thread::sleep(frame_delay.mul_f32(time_multiplier)); } if event::poll(Duration::from_millis(0)).unwrap() { @@ -129,6 +130,18 @@ fn main() -> Result<()> { }) => { is_paused = !is_paused; } + Event::Key(KeyEvent { + code: KeyCode::Char('l'), + .. + }) => { + time_multiplier = time_multiplier * 2.0; + } + Event::Key(KeyEvent { + code: KeyCode::Char('j'), + .. + }) => { + time_multiplier = time_multiplier / 2.0; + } _ => {} } } From 1b43ed35327c295250ff79a42b8e716df2440417 Mon Sep 17 00:00:00 2001 From: polyesterswing Date: Sat, 27 Jul 2024 13:57:52 +0530 Subject: [PATCH 4/4] fix: cargo warnings --- src/main.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/main.rs b/src/main.rs index 84c4524..ae4bb94 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,19 +1,17 @@ use opencv::core::VecN; use opencv::prelude::*; use opencv::{core, imgproc, videoio, Result}; -use std::sync::{mpsc, Arc}; -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::mpsc; use std::time::Duration; use std::{thread, time}; - use crossterm::event::{self, Event, KeyCode, KeyEvent}; +use crossterm::terminal; use crossterm::{ - cursor::{Hide, Show, MoveTo}, + cursor::{Hide, MoveTo, Show}, execute, terminal::{disable_raw_mode, enable_raw_mode, Clear, ClearType}, }; -use crossterm::terminal; use std::io; fn map_range(from_range: (i32, i32), to_range: (i32, i32), s: i32) -> i32 { @@ -76,7 +74,7 @@ fn main() -> Result<()> { let (tx, rx) = mpsc::sync_channel(50); execute!(stdout, Hide).unwrap(); - let handle = thread::spawn(move || loop { + thread::spawn(move || loop { let mut frame = Mat::default(); cam.read(&mut frame).unwrap(); @@ -90,20 +88,20 @@ fn main() -> Result<()> { 0.0, imgproc::INTER_AREA, ) - .unwrap(); + .unwrap(); let mut gray = Mat::default(); imgproc::cvt_color_def(&smaller, &mut gray, imgproc::COLOR_BGR2GRAY).unwrap(); - let Ok(_) = tx.send(find_colors(&smaller, &gray, ascii_table, ascii_table_len).unwrap()) else { + let Ok(_) = + tx.send(find_colors(&smaller, &gray, ascii_table, ascii_table_len).unwrap()) + else { break; }; } - }); loop { - if !is_paused { let received = rx.recv().unwrap();