X-Git-Url: https://git.nihav.org/?a=blobdiff_plain;f=sndplay%2Fsrc%2Fmain.rs;h=275826ff9f7db9d425b5efc9a3c37a12179ba3ef;hb=0a70659f1bac51dda65d0c8349a219c565b56c8c;hp=66def2b05250b0fe3f3fe5a32aa330e12c3fafec;hpb=b043bd0a14b04ddc4cf69b4701c2e1e6fe8e0111;p=nihav-player.git diff --git a/sndplay/src/main.rs b/sndplay/src/main.rs index 66def2b..275826f 100644 --- a/sndplay/src/main.rs +++ b/sndplay/src/main.rs @@ -2,11 +2,10 @@ extern crate libc; extern crate sdl2_sys; extern crate nihav_core; extern crate nihav_registry; -extern crate nihav_allstuff; use std::fs::File; use std::io::prelude::*; -use std::io::{BufReader, SeekFrom}; +use std::io::BufReader; use std::sync::mpsc; use std::time::Duration; use std::thread; @@ -16,16 +15,16 @@ use nihav_core::frame::*; use nihav_core::codecs::*; use nihav_core::demuxers::*; use nihav_core::soundcvt::*; -use nihav_registry::detect; -use nihav_allstuff::*; +mod allreg; mod command; use command::*; +mod demux; +use demux::*; struct Player { ended: bool, - dmx_reg: RegisteredDemuxers, - dec_reg: RegisteredDecoders, + full_reg: allreg::FullRegister, paused: bool, mute: bool, volume: u8, @@ -86,8 +85,14 @@ impl AudioDevice { } } +impl Drop for AudioDevice { + fn drop(&mut self) { + unsafe { sdl2_sys::SDL_CloseAudioDevice(self.device_id); } + } +} + struct Decoder<'a> { - demuxer: Demuxer<'a>, + demuxer: DemuxerObject<'a>, decoder: Box, dsupp: Box, buf: &'a mut Vec, @@ -102,7 +107,7 @@ struct Decoder<'a> { fn output_vol_i16(device: &AudioDevice, tmp: &mut Vec, src: &[i16], mute: bool, volume: u8) { if !mute { - tmp.truncate(0); + tmp.clear(); tmp.reserve(src.len()); let vol = i32::from(volume); for &sample in src.iter() { @@ -110,7 +115,7 @@ fn output_vol_i16(device: &AudioDevice, tmp: &mut Vec, src: &[i16], mute: b tmp.push(nsamp.min(32767).max(-32768) as i16); } } else { - tmp.truncate(0); + tmp.clear(); tmp.resize(src.len(), 0); } device.queue(&tmp); @@ -118,7 +123,7 @@ fn output_vol_i16(device: &AudioDevice, tmp: &mut Vec, src: &[i16], mute: b fn output_vol_u8(device: &AudioDevice, tmp: &mut Vec, src: &[u8], mute: bool, volume: u8) { if !mute { - tmp.truncate(0); + tmp.clear(); tmp.reserve(src.len()); let vol = i32::from(volume); for sample in src.chunks_exact(2) { @@ -127,7 +132,7 @@ fn output_vol_u8(device: &AudioDevice, tmp: &mut Vec, src: &[u8], mute: boo tmp.push(nsamp.min(32767).max(-32768) as i16); } } else { - tmp.truncate(0); + tmp.clear(); tmp.resize(src.len() / 2, 0); } device.queue(&tmp); @@ -142,9 +147,15 @@ impl<'a> Decoder<'a> { match self.decoder.decode(&mut self.dsupp, &pkt) { Ok(frm) => { let buf = frm.get_buffer(); + if let NABufferType::None = buf { + return false; + } if let Some(pts) = frm.ts.get_pts() { self.samplepos = NATimeInfo::ts_to_time(pts, u64::from(self.arate), frm.ts.tb_num, frm.ts.tb_den); } + if buf.get_audio_length() == 0 { + return false; + } let out_buf = convert_audio_frame(&buf, &self.dst_info, &self.dst_chmap).unwrap(); match out_buf { NABufferType::AudioI16(abuf) => { @@ -193,19 +204,21 @@ fn format_time(ms: u64) -> String { let s = ms / 1000; let ds = (ms % 1000) / 100; let (min, s) = (s / 60, s % 60); - if min == 0 { - format!("{}.{}", s, ds) + let (h, min) = (min / 60, min % 60); + if h == 0 { + if min == 0 { + format!("{}.{}", s, ds) + } else { + format!("{}:{:02}.{}", min, s, ds) + } } else { - format!("{}:{:02}.{}", min, s, ds) + format!("{}:{:02}:{:02}.{}", h, min, s, ds) } } impl Player { fn new() -> Self { - let mut dmx_reg = RegisteredDemuxers::new(); - nihav_register_all_demuxers(&mut dmx_reg); - let mut dec_reg = RegisteredDecoders::new(); - nihav_register_all_decoders(&mut dec_reg); + let full_reg = allreg::FullRegister::new(); unsafe { if sdl2_sys::SDL_Init(sdl2_sys::SDL_INIT_AUDIO) != 0 { @@ -216,48 +229,44 @@ impl Player { Self { ended: false, paused: false, - dmx_reg, dec_reg, + full_reg, volume: 100, mute: false, debug: false, buf: Vec::new(), } } - fn play_file(&mut self, name: &str, cmd_receiver: &mpsc::Receiver) { + fn play_file(&mut self, name: &str, cmd_receiver: &mpsc::Receiver, start_time: NATimePoint) { let ret = File::open(name); if ret.is_err() { println!("error opening {}", name); return; } - let mut file = ret.unwrap(); + let file = ret.unwrap(); + let file = BufReader::new(file); - let mut fr = FileReader::new_read(&mut file); + let mut fr = FileReader::new_read(file); let mut br = ByteReader::new(&mut fr); - let res = detect::detect_format(name, &mut br); - if res.is_none() { - println!("cannot detect format for {}", name); - return; - } - let (dmx_name, _) = res.unwrap(); - drop(br); - drop(fr); - let dmx_fact = self.dmx_reg.find_demuxer(dmx_name); - if dmx_fact.is_none() { - println!("no demuxer for format {}", dmx_name); + if br.peek_byte().is_err() { + println!("Cannot read {}", name); return; } - let dmx_fact = dmx_fact.unwrap(); + let (is_raw, start, end) = detect_tags(&mut br); - file.seek(SeekFrom::Start(0)).unwrap(); - let mut file = BufReader::new(file); - let mut fr = FileReader::new_read(&mut file); - let mut br = ByteReader::new(&mut fr); - let res = create_demuxer(dmx_fact, &mut br); - if res.is_err() { - println!("cannot create demuxer"); + let mut nfr: Box; + if start != 0 || end.is_some() { + //println!(" limiting range to {:X}-{:X}", start, end.unwrap_or(0)); + let file = fr.finish(); + nfr = Box::new(BoundedFileReader::new_read(file, start, end).unwrap()); + } else { + nfr = Box::new(fr); + } + let mut br = ByteReader::new(nfr.as_mut()); + let dmx = DemuxerObject::create(&mut br, &self.full_reg, name, is_raw); + if dmx.is_none() { + println!("No demuxer found!"); return; } - let dmx = res.unwrap(); let mut ainfo = None; let mut dec: Option<(Box, Box)> = None; @@ -267,7 +276,7 @@ impl Player { let s = dmx.get_stream(i).unwrap(); let info = s.get_info(); if info.is_audio() { - let decfunc = self.dec_reg.find_decoder(info.get_name()); + let decfunc = self.full_reg.dec_reg.find_decoder(info.get_name()); if decfunc.is_none() { println!("no decoder for {}", info.get_name()); continue; @@ -298,7 +307,7 @@ impl Player { let ch = ainfo.channels; println!("Playing {} [{}Hz {}ch]", name, arate, ch); - let ret = AudioDevice::open(arate, ch.max(2)); + let ret = AudioDevice::open(arate, ch.min(2)); if ret.is_none() { println!("cannot open output"); return; @@ -326,6 +335,10 @@ impl Player { let mut refill_limit = arate * u32::from(dspec.channels); let underfill_limit = (arate * u32::from(dspec.channels) / 4).max(block_limit); + if start_time != NATimePoint::None { + let _ret = decoder.demuxer.seek(start_time); + } + let mut eof = decoder.refill(&device); while !eof && device.size() < refill_limit { eof = decoder.refill(&device); @@ -335,15 +348,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 +419,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 +479,22 @@ impl Player { Command::Debug => { self.debug = !self.debug; }, + Command::PauseDisplay => { + no_display = true; + if !self.paused { + device.pause(); + } + }, + Command::ResumeDisplay => { + no_display = false; + if !self.paused { + device.resume(); + } + }, }; - print!("\r{:60}\r", ' '); + if !no_display { + print!("\r{:60}\r", ' '); + } } thread::sleep(Duration::from_millis(200)); } @@ -487,11 +531,29 @@ fn main() { return; } - for arg in args[1..].iter() { - player.play_file(arg, &cmd_receiver); - if player.ended { - break; - } + let mut aiter = args[1..].iter(); + let mut start_time = NATimePoint::None; + while let Some(arg) = aiter.next() { + match arg.as_str() { + "-start" => { + if let Some(arg) = aiter.next() { + if let Ok(val) = arg.parse() { + start_time = val; + } else { + println!("invalid time"); + } + } else { + println!("argument is required"); + } + }, + _ => { + player.play_file(arg, &cmd_receiver, start_time); + if player.ended { + break; + } + start_time = NATimePoint::None; + }, + }; } cmd_state.restore();