A tool to sync music with your favorite devices
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

library: give precedence to lossless files

if a file with the same track id is found:
- if the database contains a lossy version, remove it and add the
lossless one
- if the database contains a lossless version and a lossy is found,
ignore it
- if formats are the same, keep both

Gee Sawra 65947ab7 74c78fd0

+94 -17
+12
.sqlx/query-48a8cf5231df8c8c8a04d3344a1bb50a36c30c3ba04b243f6d890f015bdd320d.json
··· 1 + { 2 + "db_name": "SQLite", 3 + "query": "\n DELETE FROM tracks WHERE track_id = ?1 AND extension != 'flac';\n ", 4 + "describe": { 5 + "columns": [], 6 + "parameters": { 7 + "Right": 1 8 + }, 9 + "nullable": [] 10 + }, 11 + "hash": "48a8cf5231df8c8c8a04d3344a1bb50a36c30c3ba04b243f6d890f015bdd320d" 12 + }
+20
.sqlx/query-493b425fcfd0735187a86abd4eea7c7912ce4e6fbcbbed1829c3c606ca699de1.json
··· 1 + { 2 + "db_name": "SQLite", 3 + "query": "\n SELECT 1 as \"exists\" FROM tracks WHERE track_id = ?1 AND extension = 'flac' LIMIT 1;\n ", 4 + "describe": { 5 + "columns": [ 6 + { 7 + "name": "exists", 8 + "ordinal": 0, 9 + "type_info": "Int" 10 + } 11 + ], 12 + "parameters": { 13 + "Right": 1 14 + }, 15 + "nullable": [ 16 + false 17 + ] 18 + }, 19 + "hash": "493b425fcfd0735187a86abd4eea7c7912ce4e6fbcbbed1829c3c606ca699de1" 20 + }
+29
src/db/instance.rs
··· 329 329 .collect()) 330 330 } 331 331 332 + pub async fn has_lossless(&self, track_id: &str) -> Result<bool, Error> { 333 + let mut conn = self.pool.acquire().await?; 334 + 335 + Ok(sqlx::query!( 336 + r#" 337 + SELECT 1 as "exists" FROM tracks WHERE track_id = ?1 AND extension = 'flac' LIMIT 1; 338 + "#, 339 + track_id, 340 + ) 341 + .fetch_optional(&mut *conn) 342 + .await? 343 + .is_some()) 344 + } 345 + 346 + pub async fn delete_lossy(&self, track_id: &str) -> Result<(), Error> { 347 + let mut conn = self.pool.acquire().await?; 348 + 349 + sqlx::query!( 350 + r#" 351 + DELETE FROM tracks WHERE track_id = ?1 AND extension != 'flac'; 352 + "#, 353 + track_id, 354 + ) 355 + .execute(&mut *conn) 356 + .await?; 357 + 358 + Ok(()) 359 + } 360 + 332 361 pub async fn tracks_by_state( 333 362 &self, 334 363 state: model::FileState,
+33 -17
src/library.rs
··· 7 7 where 8 8 P: Fn(&model::Track) + Clone + Send + Sync + 'static, 9 9 { 10 + // Cleanup removed files 11 + let track_iter = db 12 + .tracks_iter() 13 + .await 14 + .with_context(|| "Cannot create an iterator for existing tracks in database")?; 15 + 16 + while let Ok(track) = track_iter.recv().await { 17 + let track = track?; 18 + let tp = std::path::Path::new(&track.file_path); 19 + if !tp.exists() { 20 + db.delete(track.id) 21 + .await 22 + .with_context(|| "Cannot delete track from database.")?; 23 + } 24 + } 25 + 10 26 let sources = db 11 27 .directories() 12 28 .await ··· 37 53 { 38 54 |path, _| { 39 55 let id = (path.0.clone(), path.1.clone()); 40 - println!("{:?}", id); 41 56 Ok(tracks_set.contains(&id)) 42 57 } 43 58 }, ··· 50 65 .await?; 51 66 52 67 let totals = res.iter().fold((0, 0), |acc, r| (acc.0 + r.0, acc.1 + r.1)); 53 - 54 - // Cleanup removed files 55 - let track_iter = db 56 - .tracks_iter() 57 - .await 58 - .with_context(|| "Cannot create an iterator for existing tracks in database")?; 59 - 60 - while let Ok(track) = track_iter.recv().await { 61 - let track = track?; 62 - let tp = std::path::Path::new(&track.file_path); 63 - if !tp.exists() { 64 - db.delete(track.id) 65 - .await 66 - .with_context(|| "Cannot delete track from database.")?; 67 - } 68 - } 69 68 70 69 Ok(totals) 71 70 } ··· 141 140 if dc((&track.track_id.clone(), &p), db)? { 142 141 duplicate += 1; 143 142 continue; 143 + } 144 + 145 + if track.is_lossless() { 146 + // New is lossless. Remove any existing lossy versions. 147 + db.delete_lossy(&track.track_id) 148 + .await 149 + .with_context(|| "Failed to delete lossy tracks")?; 150 + } else { 151 + // New is lossy. Check if we should skip. 152 + if db 153 + .has_lossless(&track.track_id) 154 + .await 155 + .with_context(|| "Failed to check for lossless tracks")? 156 + { 157 + log::info!("Skipping lossy track {} because lossless version exists", p); 158 + continue; 159 + } 144 160 } 145 161 146 162 track.file_state = model::FileState::Copied;