libminau 0.1.0

A library version of Minau, a music player built directly on top of Symphonia and CPAL.
Documentation
use std::path::Path;
use std::sync::{Arc, Mutex};
use std::{fs::File, process::exit};
use symphonia::core::codecs::{CODEC_TYPE_NULL, Decoder, DecoderOptions};
use symphonia::core::formats::{FormatOptions, FormatReader};
use symphonia::core::io::MediaSourceStream;
use symphonia::core::meta::MetadataOptions;
use symphonia::core::probe::Hint;


pub struct Player {
    pub format: Arc<Mutex<Box<dyn FormatReader>>>,
    pub decoder: Arc<Mutex<Box<dyn Decoder>>>,
    pub track_id: u32,
    pub sample_rate: u32,
    pub channels: u16,
    pub path: String,
}

impl Clone for Player {
    fn clone(&self) -> Self {
        Player::new(&self.path)
    }
}

impl Player {
    pub fn new<P: AsRef<Path>>(path: P) -> Self {
        let path_str = path.as_ref().to_str().unwrap().to_string();

        let file = File::open(&path).unwrap_or_else(|e| {
            eprintln!("Failed to open {}: {}", path_str, e);
            exit(1);
        });

        let mss = MediaSourceStream::new(Box::new(file), Default::default());

        let mut hint = Hint::new();
        if let Some(ext) = path.as_ref().extension() {
            hint.with_extension(ext.to_str().unwrap());
        }

        let meta_opts: MetadataOptions = Default::default();
        let fmt_opts: FormatOptions = Default::default();

        let probed = symphonia::default::get_probe()
            .format(&hint, mss, &fmt_opts, &meta_opts)
            .unwrap_or_else(|e| {
                eprintln!("Failed to probe format: {}", e);
                exit(1);
            });

        let format = probed.format;

        let track = format
            .tracks()
            .iter()
            .find(|t| t.codec_params.codec != CODEC_TYPE_NULL)
            .unwrap_or_else(|| {
                eprintln!("No supported audio track found");
                exit(1);
            });

        let track_id = track.id;
        let codec_params = &track.codec_params;

        // codec_paramsから情報を先に取得
        let sample_rate = codec_params.sample_rate.unwrap_or_else(|| {
            eprintln!("No sample rate information found");
            exit(1);
        });

        let channels = codec_params.channels.map(|c| c.count() as u16).unwrap_or(2);

        let dec_opts: DecoderOptions = Default::default();
        let decoder = symphonia::default::get_codecs()
            .make(codec_params, &dec_opts)
            .unwrap_or_else(|e| {
                eprintln!("Failed to create decoder: {}", e);
                exit(1);
            });

        Self {
            format: Arc::new(Mutex::new(format)),
            decoder: Arc::new(Mutex::new(decoder)),
            track_id,
            sample_rate,
            channels,
            path: path_str,
        }
    }

    pub fn sample_rate(&self) -> u32 {
        self.sample_rate
    }

    pub fn channels(&self) -> u16 {
        self.channels
    }
}