Skip to content

Commit

Permalink
feat(cli): Add command to export playlists as M3U
Browse files Browse the repository at this point in the history
  • Loading branch information
Holzhaus committed Oct 12, 2022
1 parent 5d74f01 commit a5eaf21
Showing 1 changed file with 76 additions and 0 deletions.
76 changes: 76 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ enum Commands {
#[arg(value_name = "EXPORT_PATH")]
path: PathBuf,
},
/// Export the playlists from a Pioneer Database (`.PDB`) file to M3U files.
ExportPlaylists {
/// File to parse.
#[arg(value_name = "EXPORT_PATH")]
path: PathBuf,
/// Output directory to write M3U files to.
#[arg(value_name = "OUTPUT_DIR")]
output_dir: PathBuf,
},
/// Parse and dump a Rekordbox Analysis (`ANLZXXXX.DAT`) file.
DumpANLZ {
/// File to parse.
Expand Down Expand Up @@ -86,6 +95,72 @@ fn list_playlists(path: &Path) -> rekordcrate::Result<()> {
Ok(())
}

fn export_playlists(path: &Path, output_dir: &PathBuf) -> rekordcrate::Result<()> {
use rekordcrate::device::PlaylistNode;
use rekordcrate::pdb::{Track, TrackId};
use rekordcrate::DeviceExport;
use std::collections::HashMap;
use std::io::Write;

let mut export = DeviceExport::new(path.into());
export.load_pdb()?;
let playlists = export.get_playlists()?;
let mut tracks: HashMap<TrackId, Track> = HashMap::new();
export.get_tracks().try_for_each(|result| {
if let Ok(track) = result {
tracks.insert(track.id, track);
Ok(())
} else {
result.map(|_| ())
}
})?;

fn walk_tree(
export: &DeviceExport,
tracks: &HashMap<TrackId, Track>,
node: PlaylistNode,
path: &PathBuf,
) -> rekordcrate::Result<()> {
match node {
PlaylistNode::Folder(folder) => {
folder.children.into_iter().try_for_each(|child| {
walk_tree(export, tracks, child, &path.join(&folder.name))
})?;
}
PlaylistNode::Playlist(playlist) => {
let mut playlist_entries = export
.get_playlist_entries(playlist.id)
.collect::<rekordcrate::Result<Vec<(u32, TrackId)>>>()?;
playlist_entries.sort_by_key(|entry| entry.0);

std::fs::create_dir_all(path)?;
let playlist_path = path.join(format!("{}.m3u", playlist.name));

println!("{}", playlist_path.display());
let mut file = std::fs::File::create(playlist_path)?;
playlist_entries
.into_iter()
.filter_map(|(_index, id)| tracks.get(&id))
.try_for_each(|track| -> rekordcrate::Result<()> {
Ok(writeln!(
&mut file,
"{}",
track.file_path.clone().into_string()?
)?)
})?;
}
};

Ok(())
}

playlists
.into_iter()
.try_for_each(|node| walk_tree(&export, &tracks, node, output_dir))?;

Ok(())
}

fn list_settings(path: &Path) -> rekordcrate::Result<()> {
use rekordcrate::DeviceExport;

Expand Down Expand Up @@ -472,6 +547,7 @@ fn main() -> rekordcrate::Result<()> {
match &cli.command {
Commands::ListPlaylists { path } => list_playlists(path),
Commands::ListSettings { path } => list_settings(path),
Commands::ExportPlaylists { path, output_dir } => export_playlists(path, output_dir),
Commands::DumpPDB { path } => dump_pdb(path),
Commands::DumpANLZ { path } => dump_anlz(path),
Commands::DumpSetting { path } => dump_setting(path),
Expand Down

0 comments on commit a5eaf21

Please sign in to comment.