From 0a727e0528c2b26c5cefb9bbf13f6b356e6fb3db Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Fri, 16 Oct 2020 10:11:36 +0200 Subject: [PATCH] add a command to jump to an arbitrary time --- sndplay/src/command.rs | 36 ++++++++++++++++++++++++++++++++++-- sndplay/src/main.rs | 31 ++++++++++++++++++++++++++----- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/sndplay/src/command.rs b/sndplay/src/command.rs index 802908b..3f5ecde 100644 --- a/sndplay/src/command.rs +++ b/sndplay/src/command.rs @@ -1,7 +1,8 @@ use libc::{termios, tcgetattr, tcsetattr}; use std::sync::mpsc; -use std::io::Read; +use std::io::{Read, BufRead}; use std::thread; +use nihav_core::frame::NATimePoint; #[derive(Clone,Copy,Debug,PartialEq)] pub enum Command { @@ -12,8 +13,11 @@ pub enum Command { Pause, Back(u8), Forward(u8), + Seek(u64), Repeat, Next, + PauseDisplay, + ResumeDisplay, Quit, } @@ -29,6 +33,14 @@ impl CmdLineState { unsafe { tcsetattr(0, 0, &new_state); } Self { orig_state } } + pub fn new_normal() -> Self { + let mut orig_state: termios = unsafe { std::mem::uninitialized() }; + unsafe { tcgetattr(0, &mut orig_state); } + let mut new_state = orig_state; + new_state.c_lflag |= libc::ECHO | libc::ICANON; + unsafe { tcsetattr(0, 0, &new_state); } + Self { orig_state } + } pub fn restore(&self) { unsafe { tcsetattr(0, 0, &self.orig_state); } } @@ -60,6 +72,26 @@ pub fn start_reader() -> (thread::JoinHandle<()>, mpsc::Receiver) { b'-' => { sender.send(Command::VolumeDown).unwrap(); }, b'd' | b'D' => { sender.send(Command::Debug).unwrap(); }, b'm' | b'M' => { sender.send(Command::Mute).unwrap(); }, + b'j' | b'J' => { + sender.send(Command::PauseDisplay).unwrap(); + let cstate = CmdLineState::new_normal(); + // wait so that the main thread stops displaying + thread::sleep(std::time::Duration::from_millis(500)); + print!("\nJump to: "); + let mut str = String::new(); + let ret = file.read_line(&mut str); + cstate.restore(); + sender.send(Command::ResumeDisplay).unwrap(); + + if ret.is_ok() && str.len() > 1 { + str.pop(); // newline + if let Ok(NATimePoint::Milliseconds(time)) = str.parse::() { + sender.send(Command::Seek(time)).unwrap(); + } else { + println!("wrong time"); + } + } + }, _ => {}, }; }, @@ -98,4 +130,4 @@ pub fn start_reader() -> (thread::JoinHandle<()>, mpsc::Receiver) { } } }), cmd_receiver) -} \ No newline at end of file +} diff --git a/sndplay/src/main.rs b/sndplay/src/main.rs index 66def2b..377c2d1 100644 --- a/sndplay/src/main.rs +++ b/sndplay/src/main.rs @@ -335,15 +335,18 @@ impl Player { if !self.paused { device.resume(); } + let mut no_display = false; 'main: loop { let cur_time = decoder.samplepos.saturating_sub(u64::from(device.size() / 2 / u32::from(dst_info.channels))); let full_ms = cur_time * 1000 / u64::from(arate); let timestr = format_time(full_ms); let disp_vol = if self.mute { 0 } else { self.volume }; - if !self.debug { - print!("> {} / {} {}% \r", timestr, duration_str, disp_vol); - } else { - print!("> {} / {} |{}| {}% \r", timestr, duration_str, device.size(), disp_vol); + if !no_display { + if !self.debug { + print!("> {} / {} {}% \r", timestr, duration_str, disp_vol); + } else { + print!("> {} / {} |{}| {}% \r", timestr, duration_str, device.size(), disp_vol); + } } std::io::stdout().flush().unwrap(); if device.size() < underfill_limit && !self.paused && refill_limit < (1 << 20) { @@ -403,6 +406,20 @@ impl Player { device.resume(); } }, + Command::Seek(seek_time) => { + device.pause(); + device.clear(); + let _ret = decoder.seek(seek_time); + while !eof && device.size() < refill_limit { + eof = decoder.refill(&device); + } + if eof { + break 'main; + } + if !self.paused { + device.resume(); + } + }, Command::Quit => { device.pause(); self.ended = true; @@ -449,8 +466,12 @@ impl Player { Command::Debug => { self.debug = !self.debug; }, + Command::PauseDisplay => { no_display = true; }, + Command::ResumeDisplay => { no_display = false; }, }; - print!("\r{:60}\r", ' '); + if !no_display { + print!("\r{:60}\r", ' '); + } } thread::sleep(Duration::from_millis(200)); } -- 2.39.5