#!/usr/bin/perl use warnings; use strict; use Data::Dumper; use File::Basename; use File::Path; use Audio::FLAC::Header; use Getopt::Long; my $selected_output = "mp3"; my $mp3_dir = "../mp3"; my %flac_attribs = ( file_extension => qr/\.flac/, binary => "/usr/bin/flac", decode_arg => "-d", input_arg => "", output_arg => "-o", tags => { year => { vital => 1, name => "DATE" }, track_title => { vital => 1, name => "TITLE" }, track_number => { vital => 1, name => "TRACKNUMBER" }, track_artist => { vital => 1, name => "TRACKARTIST" }, album_title => { vital => 1, name => "ALBUM" }, album_artist => { vital => 1, name => "DISCARTIST" }, genre => { vital => 1, name => "GENRE" }, cddb_id => { vital => 1, name => "CDDB" }, }, ); my %outputs = ( mp3 => { base_dir => "../mp3", file_extension => ".mp3", binary => "/usr/bin/lame", standard_args => [ "-h", "-V", "--vbr-new", "--nohist" ], input_arg => "", output_arg => "", tags => { year => "--ty", track_title => "--tt", track_number => "--tn", track_artist => "--ta", album_title => "--tl", #album_artist => "", # Not used by lame genre => "--tg", }, }, ); foreach my $playlist (@ARGV) { open(PLAY, "<", $playlist) or die "Unable to open $playlist: $!\n"; TRACK: while() { chomp; my $filename = $_; print "Checking $filename...\n"; unless(check_file($filename)) { warn "Problem with $filename from playlist $playlist: unreadable/non-existent file!\n"; next TRACK; } my $flac = Audio::FLAC::Header->new($filename); unless($flac) { warn "Extracting tags from $filename failed!\n"; next; } my $flac_tag_ref = $flac->tags; my @required_tags; my %input_tags = %{$flac_attribs{tags}}; for (keys %input_tags) { push @required_tags, $input_tags{$_}{name} if($input_tags{$_}{vital}); } foreach my $req (@required_tags) { unless($flac_tag_ref->{$req}) { warn "Tag $req not found in $filename\n" unless($flac_tag_ref->{$req}); next TRACK; } } my %output_tags; foreach my $tag (keys %input_tags) { next unless($outputs{$selected_output}{tags}{$tag}); $output_tags{$tag} = $flac_tag_ref->{$input_tags{$tag}{name}}; } my $dirname = dirname($filename); my $target_dir = $mp3_dir ."/". $dirname . "/"; unless(-d $target_dir) { unless(mkpath($target_dir)) { warn "Couldn't make path $target_dir: $!\n"; } } unless(-d $target_dir) { warn "Unable to find $target_dir\n"; next TRACK; } my $flac_ext = $flac_attribs{file_extension}; my $wav_filename = $target_dir . basename($filename); $wav_filename =~ s/$flac_ext$/.wav/; ## Build the decode command line and run it. my @decode_cmd = (@flac_attribs{"binary","decode_arg","input_arg"}, $filename, $flac_attribs{output_arg}, $wav_filename); #Remove undef args my @temp_cmd = @decode_cmd; @decode_cmd = (); for (@temp_cmd) { push @decode_cmd, $_ if($_); } print "Going to decode $filename to $wav_filename\n"; #print Dumper(\@decode_cmd); system(@decode_cmd) == 0 or die "Conversion to wav file failed for $filename: $?\n"; unless(-e $wav_filename) { die "$wav_filename does not exist\n"; } ## Build the encode command line and run it. my %output_attribs = %{$outputs{$selected_output}}; my $output_ext = $output_attribs{file_extension}; my $output_filename = $wav_filename; $output_filename =~ s/\.wav$/$output_ext/; my @encode_cmd = ($output_attribs{binary}); push @encode_cmd, @{$output_attribs{standard_args}}; push @encode_cmd, ($output_attribs{input_arg}, $wav_filename, $output_attribs{output_arg}, $output_filename); foreach my $tag (keys %output_tags) { my $arg = $output_attribs{tags}{$tag}; push @encode_cmd, ($arg, $output_tags{$tag}); } @temp_cmd = @encode_cmd; @encode_cmd = (); for (@temp_cmd) { push @encode_cmd, $_ if($_); } print "Going to encode $wav_filename to $output_filename\n"; print Dumper(\@encode_cmd); system(@encode_cmd) == 0 or die "Conversion to $selected_output file failed for $filename: $?\n"; unless(-e $wav_filename) { die "$output_filename does not exist\n"; } unlink($wav_filename); } close(PLAY); } sub check_file { my $filename = shift; unless(-e $filename) { return 0; } if(-z $filename) { return 0; } unless(-r $filename) { return 0; } return 1; }