mod db; extern crate walkdir; use rekordcrate::pdb::Page; use rekordcrate::pdb::PageError; use rekordcrate::pdb::PageIndex; use rekordcrate::pdb::Row::PlaylistEntry; use rekordcrate::pdb::string::DeviceSQLString; use rekordcrate::pdb::RowGroup; use rekordcrate::pdb::TrackId; use rekordcrate::pdb::PageType; use rekordcrate::pdb::Table; use rekordcrate::pdb::{Header, PlaylistTreeNode, PlaylistTreeNodeId}; use walkdir::WalkDir; use std::env; use std::fs::create_dir; use std::fs::create_dir_all; use std::{fs::exists, path::Path}; use db::Database; // Example fn main() -> Result<(), PageError> { let db = Database::load_from_pdb("ntr.pdb").unwrap(); println!("tracks: {}, playlists: {}", db.tracks.len(), db.nodes.len()); println!("tables: {:?}", db.header); println!("tables: {:?}", db.header.tables); db.export(&Path::new("./data/output.pdb"))?; // for n in db.nodes { // println!("{:?}", n); // } // let (_first_id, first) = db.tracks.first_key_value().unwrap(); // let (_last_id, last) = db.tracks.last_key_value().unwrap(); // println!("{:?}", first); // println!("{:?}", last); // // let pic = db.tracks.iter().find(|(_id, t)| t.artwork_id == ArtworkId(680)); // // match pic { // // Some(it) => println!("{:?}", it), // // None => println!("wasnt there"), // // } // create_dir_all("./data/PIONEER")?; // assert!(env::set_current_dir(&Path::new("./data")).is_ok()); // // strip the leading slash of the path to make it relative // let anlz = first.analyze_path.clone().into_string()?; // let anlz = anlz.strip_prefix("/").unwrap(); // let mp3 = first.file_path.clone().into_string()?; // let mp3 = mp3.strip_prefix("/").unwrap(); // println!("mp3={:?} exists={:?}", mp3, exists(mp3)); // println!("anlz={:?} exists={:?}", anlz, exists(anlz)); // let filename = "a680_m.jpg"; // for entry in WalkDir::new(".") // start from current directory // .into_iter() // .filter_map(Result::ok) // .filter(|e| e.file_type().is_file()) // { // if entry.file_name() == filename { // println!("Found: {}", entry.path().display()); // } // } // let first_table = db.header.tables.first(); // println!("first_table={:?}", first_table); // let mut export = Header::default(); // // let tracks = Table { page_type: PageType::Tracks, first_page: 0} // // println!("export={:?}", export); // let track_table = Table { // page_type: PageType::Tracks, // first_page: PageIndex(1), // last_page: PageIndex(1), // empty_candidate: 2, // }; // let tracks = vec![first, last]; // // let track_page = Page { // // page_index: PageIndex(1), // // page_type: PageType::Tracks, // // next_page: PageIndex(2), // // unknown1: 12, // // unknown2: 0, // // num_rows_small: 5, // // unknown3: 160, // // unknown4: 0, // // page_flags: PageFlags(36), // // free_size: 2302, // // used_size: 1740, // // unknown5: 1, // // num_rows_large: 4, // // unknown6: 0, // // unknown7: 0, // // row_groups: vec![row_groups], // // }; // let mut row_group = RowGroup::default(); // println!("track_table={:?}", track_table); // export.tables.push(track_table); // println!("export={:?}", export); // db.header.tables.iter().for_each(|t| println!("{:?}", t.page_type)); // // write header // // write page // // write row_groups // // // Add tables to header // // export.tables.push(track_table); // // export.tables.push(playlist_tree_table); // // export.tables.push(playlist_entries_table); // // export.tables.push(artwork_table); // // println!("Created PDB header with {} tables:", export.tables.len()); // // println!(" - {} tracks", db.tracks.len()); // // println!(" - {} playlist nodes", db.nodes.len()); // // println!(" - {} playlist entries", db.entries.values().map(|v| v.len()).sum::()); // // for (i, table) in export.tables.iter().enumerate() { // // println!(" Table {}: {:?} (pages {}-{})", // // i + 1, // // table.page_type, // // table.first_page.0, // // table.last_page.0 // // ); // // } Ok(()) } #[cfg(test)] mod tests { use rekordcrate::util::ColorIndex; use rekordcrate::pdb::{string::DeviceSQLString, ArtworkId}; use rekordcrate::pdb::{AlbumId, ArtistId, GenreId, KeyId, LabelId, Track, TrackId}; #[test] fn acemo() { let _first = Track { unknown1: 36, index_shift: 32, bitmask: 788224, sample_rate: 44100, composer_id: ArtistId(0), file_size: 14547692, unknown2: 67991645, unknown3: 42343, unknown4: 54995, artwork_id: ArtworkId(1), key_id: KeyId(1), orig_artist_id: ArtistId(0), label_id: LabelId(0), remixer_id: ArtistId(0), bitrate: 0, track_number: 7, tempo: 13299, genre_id: GenreId(0), album_id: AlbumId(1), artist_id: ArtistId(1), id: TrackId(1), disc_number: 0, play_count: 0, year: 2019, sample_depth: 16, duration: 436, unknown5: 41, color: ColorIndex::None, rating: 0, unknown6: 1, unknown7: 3, isrc: DeviceSQLString::empty(), unknown_string1: DeviceSQLString::empty(), unknown_string2: "1".parse().unwrap(), unknown_string3: "2".parse().unwrap(), unknown_string4: DeviceSQLString::empty(), message: DeviceSQLString::empty(), kuvo_public: "ON".parse().unwrap(), autoload_hotcues: "ON".parse().unwrap(), unknown_string5: DeviceSQLString::empty(), unknown_string6: DeviceSQLString::empty(), date_added: "2025-01-04".parse().unwrap(), release_date: DeviceSQLString::empty(), mix_name: DeviceSQLString::empty(), unknown_string7: DeviceSQLString::empty(), analyze_path: "/PIONEER/USBANLZ/P051/00018701/ANLZ0000.DAT".parse().unwrap(), analyze_date: "2025-07-10".parse().unwrap(), comment: "Visit https://acemo.bandcamp.com".parse().unwrap(), title: "Where They At??? Ft. John FM".parse().unwrap(), unknown_string8: DeviceSQLString::empty(), filename: "AceMo - All My Life - 07 Where They At- Ft. .mp3".parse().unwrap(), file_path: "/Contents/AceMo/All My Life/AceMo - All My Life - 07 Where They At- Ft. .mp3".parse().unwrap() }; let _last = Track { unknown1: 36, index_shift: 128, bitmask: 788224, sample_rate: 44100, composer_id: ArtistId(0), file_size: 12384711, unknown2: 197860019, unknown3: 42343, unknown4: 54995, artwork_id: ArtworkId(681), key_id: KeyId(20), orig_artist_id: ArtistId(0), label_id: LabelId(0), remixer_id: ArtistId(0), bitrate: 0, track_number: 6, tempo: 13600, genre_id: GenreId(0), album_id: AlbumId(333), artist_id: ArtistId(398), id: TrackId(847), disc_number: 0, play_count: 0, year: 2018, sample_depth: 16, duration: 367, unknown5: 41, color: ColorIndex::None, rating: 0, unknown6: 1, unknown7: 3, isrc: DeviceSQLString::empty(), unknown_string1: DeviceSQLString::empty(), unknown_string2: "1".parse().unwrap(), unknown_string3: "2".parse().unwrap(), unknown_string4: DeviceSQLString::empty(), message: DeviceSQLString::empty(), kuvo_public: "ON".parse().unwrap(), autoload_hotcues: "ON".parse().unwrap(), unknown_string5: DeviceSQLString::empty(), unknown_string6: DeviceSQLString::empty(), date_added: "2021-12-09".parse().unwrap(), release_date: DeviceSQLString::empty(), mix_name: DeviceSQLString::empty(), unknown_string7: DeviceSQLString::empty(), analyze_path: "/PIONEER/USBANLZ/P00E/000209C4/ANLZ0000.DAT".parse().unwrap(), analyze_date: "2023-06-02".parse().unwrap(), comment: "Visit https://endofperception.bandcamp.com".parse().unwrap(), title: "Ness - Orbital Debris".parse().unwrap(), unknown_string8: DeviceSQLString::empty(), filename: "End Of Perception - ЛаBа VA 002 - 06 Ness - .mp3".parse().unwrap(), file_path: "/Contents/End Of Perception/ЛаBа VA 002/End Of Perception - ЛаBа VA 002 - 06 Ness - .mp3".parse().unwrap(), }; } }