use std::io;
use std::time::Instant;
use audio_streams::*;
use cros_async::Executor;
mod args;
mod error;
mod performance_data;
mod sys;
use crate::args::*;
use crate::error::Error;
use crate::error::Result;
use crate::performance_data::*;
use crate::sys::create_stream_source_generator as sys_create_stream_source_generators;
fn create_stream_source_generators(args: &Args) -> Box<dyn StreamSourceGenerator> {
match args.stream_source {
StreamSourceEnum::NoopStream => Box::new(NoopStreamSourceGenerator::new()),
StreamSourceEnum::Sys(stream_source) => {
sys_create_stream_source_generators(stream_source, args)
}
}
}
async fn run_playback(ex: &Executor, args: &Args) -> Result<PerformanceData> {
let mut data = PerformanceData::default();
let generator: Box<dyn StreamSourceGenerator> = create_stream_source_generators(args);
let num_channels = args.channels;
let format = args.format;
let frame_rate = args.rate;
let buffer_size = args.buffer_frames;
let iterations = args.iterations;
let mut stream_source = generator.generate().map_err(Error::GenerateStreamSource)?;
let start = Instant::now();
let (_, mut stream) = stream_source
.new_async_playback_stream(num_channels, format, frame_rate, buffer_size, ex)
.map_err(Error::CreateStream)?;
data.cold_start = start.elapsed();
let frame_size = args.format.sample_bytes() * args.channels;
let start = Instant::now();
let mut frames_played = 0;
for _ in 0..iterations {
let mut stream_buffer = stream
.next_playback_buffer(ex)
.await
.map_err(Error::FetchBuffer)?;
let bytes = stream_buffer
.copy_from(&mut io::repeat(0))
.map_err(Error::WriteBuffer)?;
stream_buffer.commit().await;
frames_played += bytes / frame_size;
data.records
.push(BufferConsumptionRecord::new(frames_played, start.elapsed()));
}
Ok(data)
}
fn main() -> Result<()> {
let args: Args = argh::from_env();
let ex = Executor::new().expect("Failed to create an executor");
let done = run_playback(&ex, &args);
match ex.run_until(done) {
Ok(Ok(data)) => {
let report = data.gen_report(args)?;
if args.debug {
data.print_records();
}
if args.json {
println!("{}", serde_json::to_string(&report)?);
} else {
print!("{}", report);
}
}
Ok(Err(e)) => eprintln!("{}", e),
Err(e) => eprintln!("Error happened in executor: {}", e),
}
Ok(())
}