Skip to main content

proteus_lib/
prot.rs

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        // Add all file paths to file_paths_dictionary
40        // but do not add duplicates
41        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    // fn get_duration_from_file_path(file_path: &String) -> f64 {
67    //     let file = std::fs::File::open(file_path).unwrap();
68    //     let symphonia: Symphonia = Symphonia::open(file).expect("Could not open file");
69    // }
70
71    pub fn refresh_tracks(&mut self) {
72        let mut longest_duration = 0.0;
73
74        if let Some(file_paths) = &self.file_paths {
75            // Choose random file path from each file_paths array
76            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            // Only print if name is "play_settings.json"
115            if attachment.name == "play_settings.json" {
116                // read json data from attachment.data to object
117                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                // For each track in json_data, print the track number
123                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                            // Get random number between starting_index and starting_index + length
148                            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        // let mka: Matroska = Matroska::open(file).expect("Could not open file");
196
197        // let first_audio_settings = mka
198        //     .tracks
199        //     .iter()
200        //     .find_map(|track| {
201        //         if let Settings::Audio(audio_settings) = &track.settings {
202        //             Some(audio_settings.clone()) // assuming you want to keep the settings, and they are cloneable
203        //         } else {
204        //             None
205        //         }
206        //     })
207        //     .expect("Could not find audio settings");
208
209        // first_audio_settings
210    }
211
212    pub fn get_keys(&self) -> Vec<u32> {
213        // This should just be a range from 0 to the length of the track_paths or track_ids array
214        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}