1use matroska::{Audio, Matroska, Settings};
2use rand::Rng;
3use symphonia::core::audio::Channels;
4
5use crate::info::*;
6
7#[derive(Debug, Clone)]
8pub struct Prot {
9 pub info: Info,
10 file_path: Option<String>,
11 file_paths: Option<Vec<Vec<String>>>,
12 file_paths_dictionary: Option<Vec<String>>,
13 track_ids: Option<Vec<u32>>,
14 track_paths: Option<Vec<String>>,
15 duration: f64,
16}
17
18impl Prot {
19 pub fn new(file_path: &String) -> Self {
20 let info = Info::new(file_path.clone());
21
22 let mut this = Self {
23 info,
24 file_path: Some(file_path.clone()),
25 file_paths: None,
26 file_paths_dictionary: None,
27 track_ids: None,
28 track_paths: None,
29 duration: 0.0,
30 };
31
32 this.refresh_tracks();
33
34 this
35 }
36
37 pub fn new_from_file_paths(file_paths: &Vec<Vec<String>>) -> Self {
38 let mut file_paths_dictionary = Vec::new();
39 for file_path in file_paths {
42 for path in file_path {
43 if !file_paths_dictionary.contains(path) {
44 file_paths_dictionary.push(path.clone());
45 }
46 }
47 }
48
49 let info = Info::new_from_file_paths(file_paths_dictionary.clone());
50
51 let mut this = Self {
52 info,
53 file_path: None,
54 file_paths: Some(file_paths.clone()),
55 file_paths_dictionary: Some(file_paths_dictionary),
56 track_ids: None,
57 track_paths: None,
58 duration: 0.0,
59 };
60
61 this.refresh_tracks();
62
63 this
64 }
65
66 pub fn refresh_tracks(&mut self) {
72 let mut longest_duration = 0.0;
73
74 if let Some(file_paths) = &self.file_paths {
75 let mut track_paths: Vec<String> = Vec::new();
77 for file_path in file_paths {
78 let random_number = rand::thread_rng().gen_range(0..file_path.len());
79 let track_path = file_path[random_number].clone();
80
81 let index_in_dictionary = self
82 .file_paths_dictionary
83 .as_ref()
84 .unwrap()
85 .iter()
86 .position(|x| *x == track_path)
87 .unwrap();
88 let duration = self.info.get_duration(index_in_dictionary as u32).unwrap();
89
90 if duration > longest_duration {
91 longest_duration = duration;
92 self.duration = longest_duration;
93 }
94
95 track_paths.push(track_path);
96 }
97
98 self.track_paths = Some(track_paths);
99
100 return;
101 }
102
103 if !self.file_path.is_some() {
104 return;
105 }
106
107 let file_path = self.file_path.as_ref().unwrap();
108 let file = std::fs::File::open(file_path).unwrap();
109
110 let mka: Matroska = Matroska::open(file).expect("Could not open file");
111
112 let mut track_index_array: Vec<u32> = Vec::new();
113 mka.attachments.iter().for_each(|attachment| {
114 if attachment.name == "play_settings.json" {
116 let json_data: serde_json::Value =
118 serde_json::from_slice(&attachment.data).unwrap();
119
120 let encoder_version = json_data["encoder_version"].as_f64();
121
122 json_data["play_settings"]["tracks"]
124 .as_array()
125 .unwrap()
126 .iter()
127 .for_each(|track| {
128 if let Some(_version) = encoder_version {
129 let indexes = track["ids"].as_array().unwrap();
130 if indexes.len() == 0 {
131 return;
132 }
133 let random_number = rand::thread_rng().gen_range(0..indexes.len());
134 let index = indexes[random_number].to_string().parse::<u32>().unwrap();
135 if let Some(track_duration) = self.info.get_duration(index) {
136 if track_duration > longest_duration {
137 longest_duration = track_duration;
138 self.duration = longest_duration;
139 }
140 }
141 track_index_array.push(index);
142 } else {
143 let starting_index =
144 track["startingIndex"].to_string().parse::<u32>().unwrap() + 1;
145 let length = track["length"].to_string().parse::<u32>().unwrap();
146
147 let index = rand::thread_rng()
149 .gen_range(starting_index..(starting_index + length));
150
151 if let Some(track_duration) = self.info.get_duration(index) {
152 if track_duration > longest_duration {
153 longest_duration = track_duration;
154 self.duration = longest_duration;
155 }
156 }
157
158 track_index_array.push(index);
159 }
160 });
161 }
162 });
163
164 self.track_ids = Some(track_index_array);
165 }
166
167 fn get_audio_settings(file_path: &str) -> Audio {
168 let file = std::fs::File::open(file_path).unwrap();
169
170 let symph = get_probe_result_from_string(file_path);
171
172 symph.format.tracks();
173
174 let first_track = &symph.format.tracks().first().unwrap().codec_params;
175
176 let channels = {
177 let channels_option = first_track.channels.unwrap_or(Channels::FRONT_CENTRE);
178 channels_option.iter().count()
179 };
180
181 let mut bit_depth = None;
182
183 if let Some(bits) = first_track.bits_per_sample {
184 bit_depth = Some(bits as u64)
185 }
186
187 let audio = Audio {
188 sample_rate: first_track.sample_rate.unwrap() as f64,
189 channels: channels as u64,
190 bit_depth,
191 };
192
193 audio
194
195 }
211
212 pub fn get_keys(&self) -> Vec<u32> {
213 if let Some(track_paths) = &self.track_paths {
215 return (0..track_paths.len() as u32).collect();
216 }
217
218 if let Some(track_ids) = &self.track_ids {
219 return (0..track_ids.len() as u32).collect();
220 }
221
222 Vec::new()
223 }
224
225 pub fn get_ids(&self) -> Vec<String> {
226 if let Some(track_paths) = &self.track_paths {
227 return track_paths.clone();
228 }
229
230 if let Some(track_ids) = &self.track_ids {
231 return track_ids.into_iter().map(|id| format!("{}", id)).collect();
232 }
233
234 Vec::new()
235 }
236
237 pub fn enumerated_list(&self) -> Vec<(u16, String, Option<u32>)> {
238 let mut list: Vec<(u16, String, Option<u32>)> = Vec::new();
239 if let Some(track_paths) = &self.track_paths {
240 for (index, file_path) in track_paths.iter().enumerate() {
241 list.push((index as u16, String::from(file_path), None));
242 }
243
244 return list;
245 }
246
247 if let Some(track_ids) = &self.track_ids {
248 for (index, track_id) in track_ids.iter().enumerate() {
249 list.push((
250 index as u16,
251 String::from(self.file_path.as_ref().unwrap()),
252 Some(*track_id),
253 ));
254 }
255
256 return list;
257 }
258
259 list
260 }
261
262 pub fn get_duration(&self) -> &f64 {
263 &self.duration
264 }
265
266 pub fn get_length(&self) -> usize {
267 if let Some(file_paths) = &self.file_paths {
268 return file_paths.len();
269 }
270
271 if let Some(track_ids) = &self.track_ids {
272 return track_ids.len();
273 }
274
275 0
276 }
277
278 pub fn get_file_paths_dictionary(&self) -> Vec<String> {
279 match &self.file_paths_dictionary {
280 Some(dictionary) => dictionary.to_vec(),
281 None => Vec::new(),
282 }
283 }
284}