use matroska::{Audio, Matroska, Settings};
use rand::Rng;
use symphonia::core::audio::Channels;
use crate::info::*;
#[derive(Debug, Clone)]
pub struct Prot {
pub info: Info,
file_path: Option<String>,
file_paths: Option<Vec<Vec<String>>>,
file_paths_dictionary: Option<Vec<String>>,
track_ids: Option<Vec<u32>>,
track_paths: Option<Vec<String>>,
duration: f64,
}
impl Prot {
pub fn new(file_path: &String) -> Self {
let info = Info::new(file_path.clone());
let mut this = Self {
info,
file_path: Some(file_path.clone()),
file_paths: None,
file_paths_dictionary: None,
track_ids: None,
track_paths: None,
duration: 0.0,
};
this.refresh_tracks();
this
}
pub fn new_from_file_paths(file_paths: &Vec<Vec<String>>) -> Self {
let mut file_paths_dictionary = Vec::new();
for file_path in file_paths {
for path in file_path {
if !file_paths_dictionary.contains(path) {
file_paths_dictionary.push(path.clone());
}
}
}
let info = Info::new_from_file_paths(file_paths_dictionary.clone());
let mut this = Self {
info,
file_path: None,
file_paths: Some(file_paths.clone()),
file_paths_dictionary: Some(file_paths_dictionary),
track_ids: None,
track_paths: None,
duration: 0.0,
};
this.refresh_tracks();
this
}
pub fn refresh_tracks(&mut self) {
let mut longest_duration = 0.0;
if let Some(file_paths) = &self.file_paths {
let mut track_paths: Vec<String> = Vec::new();
for file_path in file_paths {
let random_number = rand::thread_rng().gen_range(0..file_path.len());
let track_path = file_path[random_number].clone();
let index_in_dictionary = self
.file_paths_dictionary
.as_ref()
.unwrap()
.iter()
.position(|x| *x == track_path)
.unwrap();
let duration = self.info.get_duration(index_in_dictionary as u32).unwrap();
if duration > longest_duration {
longest_duration = duration;
self.duration = longest_duration;
}
track_paths.push(track_path);
}
self.track_paths = Some(track_paths);
return;
}
if !self.file_path.is_some() {
return;
}
let file_path = self.file_path.as_ref().unwrap();
let file = std::fs::File::open(file_path).unwrap();
let mka: Matroska = Matroska::open(file).expect("Could not open file");
let mut track_index_array: Vec<u32> = Vec::new();
mka.attachments.iter().for_each(|attachment| {
if attachment.name == "play_settings.json" {
let json_data: serde_json::Value =
serde_json::from_slice(&attachment.data).unwrap();
let encoder_version = json_data["encoder_version"].as_f64();
json_data["play_settings"]["tracks"]
.as_array()
.unwrap()
.iter()
.for_each(|track| {
if let Some(_version) = encoder_version {
let indexes = track["ids"].as_array().unwrap();
if indexes.len() == 0 {
return;
}
let random_number = rand::thread_rng().gen_range(0..indexes.len());
let index = indexes[random_number].to_string().parse::<u32>().unwrap();
if let Some(track_duration) = self.info.get_duration(index) {
if track_duration > longest_duration {
longest_duration = track_duration;
self.duration = longest_duration;
}
}
track_index_array.push(index);
} else {
let starting_index =
track["startingIndex"].to_string().parse::<u32>().unwrap() + 1;
let length = track["length"].to_string().parse::<u32>().unwrap();
let index = rand::thread_rng()
.gen_range(starting_index..(starting_index + length));
if let Some(track_duration) = self.info.get_duration(index) {
if track_duration > longest_duration {
longest_duration = track_duration;
self.duration = longest_duration;
}
}
track_index_array.push(index);
}
});
}
});
self.track_ids = Some(track_index_array);
}
fn get_audio_settings(file_path: &str) -> Audio {
let file = std::fs::File::open(file_path).unwrap();
let symph = get_probe_result_from_string(file_path);
symph.format.tracks();
let first_track = &symph.format.tracks().first().unwrap().codec_params;
let channels = {
let channels_option = first_track.channels.unwrap_or(Channels::FRONT_CENTRE);
channels_option.iter().count()
};
let mut bit_depth = None;
if let Some(bits) = first_track.bits_per_sample {
bit_depth = Some(bits as u64)
}
let audio = Audio {
sample_rate: first_track.sample_rate.unwrap() as f64,
channels: channels as u64,
bit_depth,
};
audio
}
pub fn get_keys(&self) -> Vec<u32> {
if let Some(track_paths) = &self.track_paths {
return (0..track_paths.len() as u32).collect();
}
if let Some(track_ids) = &self.track_ids {
return (0..track_ids.len() as u32).collect();
}
Vec::new()
}
pub fn get_ids(&self) -> Vec<String> {
if let Some(track_paths) = &self.track_paths {
return track_paths.clone();
}
if let Some(track_ids) = &self.track_ids {
return track_ids.into_iter().map(|id| format!("{}", id)).collect();
}
Vec::new()
}
pub fn enumerated_list(&self) -> Vec<(u16, String, Option<u32>)> {
let mut list: Vec<(u16, String, Option<u32>)> = Vec::new();
if let Some(track_paths) = &self.track_paths {
for (index, file_path) in track_paths.iter().enumerate() {
list.push((index as u16, String::from(file_path), None));
}
return list;
}
if let Some(track_ids) = &self.track_ids {
for (index, track_id) in track_ids.iter().enumerate() {
list.push((
index as u16,
String::from(self.file_path.as_ref().unwrap()),
Some(*track_id),
));
}
return list;
}
list
}
pub fn get_duration(&self) -> &f64 {
&self.duration
}
pub fn get_length(&self) -> usize {
if let Some(file_paths) = &self.file_paths {
return file_paths.len();
}
if let Some(track_ids) = &self.track_ids {
return track_ids.len();
}
0
}
pub fn get_file_paths_dictionary(&self) -> Vec<String> {
match &self.file_paths_dictionary {
Some(dictionary) => dictionary.to_vec(),
None => Vec::new(),
}
}
}