Get rust annotator playing sound (if garbled)

This commit is contained in:
Josh Hansen 2023-05-30 15:18:12 -07:00
parent 775c039e03
commit a644ad5b0b
2 changed files with 82 additions and 54 deletions

View file

@ -5,4 +5,7 @@ edition = "2021"
[dependencies]
clap = { version = "4.3.0", features = ["derive"] }
cpal = "0.15.2"
crossterm = "0.26.1"
magic = "0.13.0"
minimp3 = "0.5.1"

View file

@ -1,9 +1,14 @@
use std::fs::File;
use std::path::PathBuf;
use std::process::exit;
use clap::{Parser, Subcommand};
use clap::Parser;
use cpal::traits::{DeviceTrait, StreamTrait};
use cpal::{self, traits::HostTrait};
use cpal::{OutputCallbackInfo, Stream, StreamConfig};
use crossterm::event::{Event, KeyCode, KeyModifiers};
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
use minimp3::{Decoder, Frame};
use std::sync::mpsc;
use std::sync::mpsc::{Receiver, Sender};
@ -12,29 +17,7 @@ use std::thread;
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
/// Optional name to operate on
name: Option<String>,
/// Sets a custom config file
#[arg(short, long, value_name = "FILE")]
config: Option<PathBuf>,
/// Turn debugging information on
#[arg(short, long, action = clap::ArgAction::Count)]
debug: u8,
#[command(subcommand)]
command: Option<Commands>,
}
#[derive(Subcommand)]
enum Commands {
/// does testing things
Test {
/// lists test values
#[arg(short, long)]
list: bool,
},
path: Vec<PathBuf>,
}
/// Input thread commands sent to main thread
@ -47,41 +30,19 @@ enum Command {
NextFile,
}
fn main() {
fn main() -> Result<(), magic::MagicError> {
let cli = Cli::parse();
// You can check the value provided by positional arguments, or option arguments
if let Some(name) = cli.name.as_deref() {
println!("Value for name: {name}");
}
let cookie = magic::Cookie::open(magic::CookieFlags::MIME_TYPE)?;
cookie.load(&vec!["/usr/share/misc/magic.mgc"])?;
if let Some(config_path) = cli.config.as_deref() {
println!("Value for config: {}", config_path.display());
}
let host = cpal::default_host();
// You can see how many times a particular flag or argument occurred
// Note, only flags can have multiple occurrences
match cli.debug {
0 => println!("Debug mode is off"),
1 => println!("Debug mode is kind of on"),
2 => println!("Debug mode is on"),
_ => println!("Don't be crazy"),
}
let device = host
.default_output_device()
.expect("failed to find output device");
// You can check for the existence of subcommands, and if found use their
// matches just as you would the top level cmd
match &cli.command {
Some(Commands::Test { list }) => {
if *list {
println!("Printing testing lists...");
} else {
println!("Not printing testing lists...");
}
}
None => {}
}
// Continued program logic goes here...
let config: StreamConfig = device.default_output_config().unwrap().into();
let (input_tx, input_rx): (Sender<Command>, Receiver<Command>) = mpsc::channel();
@ -105,7 +66,71 @@ fn main() {
}
});
let mut path_iter = cli.path.into_iter();
let mut stream: Option<Stream> = None;
loop {
while stream.is_none() {
let path = path_iter
.find(|path| cookie.file(&path).unwrap() == "audio/mpeg")
.unwrap();
// let path = path_iter.next().unwrap();
// let mime_type = cookie.file(&path)?;
// println!("Mime type: {}", mime_type);
println!("MP3 file: {}", path.display());
let file = File::open(path).unwrap();
let mut mp3dec = Decoder::new(file);
let mut mp3frame: Option<Frame> = None;
let mut mp3frame_idx: usize = 0;
let _stream = device
.build_output_stream(
&config,
move |data: &mut [i16], _: &OutputCallbackInfo| {
// write_data(data, channels, &mut next_value)
if mp3frame.is_none()
|| mp3frame_idx >= mp3frame.as_ref().unwrap().data.len()
{
mp3frame = Some(mp3dec.next_frame().unwrap());
mp3frame_idx = 0;
}
for out_frame in data.chunks_mut(2) {
out_frame[0] = mp3frame
.as_ref()
.unwrap()
.data
.get(mp3frame_idx)
.copied()
.unwrap_or(0);
out_frame[1] = mp3frame
.as_ref()
.unwrap()
.data
.get(mp3frame_idx + 1)
.copied()
.unwrap_or(0);
mp3frame_idx += 2;
}
},
|err| {},
None,
)
.unwrap();
_stream.play().unwrap();
stream = Some(_stream);
}
// Block main thread and react to commands received
let cmd = input_rx.recv();
println!("{:?}", cmd);