#!/usr/bin/perl #*************************************************************************** # fixmp3 # ------------------- # Started : January 14 2001 # This Version : v. 0.30.0 - October 18 2001 # copyright : (C) 2001 by Afra Ahmad # email : afra@prongs.org # homepage : http://www.prongs.org/fixmp3 # changelog : CHANGELOG file # *************************************************************************** #*************************************************************************** # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # *************************************************************************** use MP3::Info qw(:all); ; use File::Find; use File::Basename; use Getopt::Long; use Cwd; use strict; my $version="v.0.30"; my ($input,$input_artist,$input_title,$input_album); my ($track_number,$input_comments,$i,$move_command); # The options my ($help,@mp3files,$playlist,$startdir,$file_correct,$tag_correct,$edit_all); my ($put_album_name,$version_requested,$ask_track,$logfile,$no_overwrite); my ($fix_mp3file,$put_album_name,$recursive,$clean_up_filename,$lowercase); # Process the command line options GetOptions ("help" => \$help, "file=s" => \@mp3files, "directory=s" => \$startdir, "playlist=s" => \$playlist, "correct" => \$file_correct, "lowercase" => \$lowercase, "tags" => \$tag_correct, "edit" => \$edit_all, "album" => \$put_album_name, "track" => \$ask_track, "version" => \$version_requested, "no-overwrite" => \$no_overwrite, "logfile=s" => \$logfile, "recursive" => \$recursive); &usage if ($help); # help requested if ($version_requested){ print "fixmp3 ".$version ."\n"; # version number was asked. exit(0); # exit after printing it. } $file_correct=1 if ($put_album_name || $ask_track); # no directory specified or files. if (!$startdir && !@mp3files){ print "You must specify a directory or file(s) to work on!\n\n"; &usage; } if ($lowercase && !$file_correct){ print "You must specify to correct the filenames, with the -c option, to lowercase them.\n"; &usage; } if ($startdir){ # just clean up the directory name if it exists, and check if it exists. die "$startdir does not exist!" if (!-d $startdir); if ($startdir !~ /^\//){ # full path name not specified. So let's add it. $startdir = cwd() ."/".$startdir; } } # get a listing of the mp3s recursively... my ($all_mp3s,$dir_count,$file_count)=&search_directories($startdir) if ($startdir); my ($processed_mp3_files)=&process_mp3_files(\@mp3files) if (@mp3files); # if files specified, process them. open (LOG, ">$logfile") || die "Cannot open $logfile: $!" if ($logfile);# Open the log file if specified if ($tag_correct || $file_correct || $edit_all){ # process each file if needed if ($processed_mp3_files){ # process each mp3 file individually. for ($i=0;$i<@$processed_mp3_files;$i++){ &fix_mp3($processed_mp3_files->[$i]); } } # Now process the directory if directory is specified. if ($all_mp3s){ foreach (@$all_mp3s){ &fix_mp3($_); # subroutine to manipulate the tags and filenames } } } if ($playlist){ # We need to get a fresh listing of the MP3s (in case any of the filenames were changed from above) ($all_mp3s,$dir_count,$file_count)=&search_directories($startdir); # get a listing of the mp3s recursively... &create_playlist($all_mp3s,$playlist); # create the playlist &print_output("Created playlist in $playlist.\n"); } # the summary of what has been done, clean up and exit... $file_count = scalar(@mp3files)+ $file_count; my $final_results="Total directories processed: $dir_count\n"; $final_results .= "Total mp3 files processed: $file_count\n"; &print_output($final_results); close (LOG) if ($logfile); # close the logfile.. exit(0); sub fix_mp3{ my $file=shift; my ($status,$edit_tag,$confirm,$basename); $basename=basename($file); # basename of the file itself. &print_output("Processing $file\n"); my $mp3 = new MP3::Info $file; my $artist=$mp3->artist; my $song=$mp3->title; my $album=$mp3->album; # get the name of the directory we are at... my $directory=dirname($file); $directory = $directory."/"; # current tag summary. &print_output ("Artist: $artist\nSong Title: $song\nAlbum: $album\n") if ($artist); if ($edit_all){ # user chose to edit all the tags of all mp3s. print "Delete tags for $basename [y/n]: "; $confirm=;chomp ($confirm); if ($confirm =~ /[Yy]/){ $edit_tag=1; } } if (!$artist && $edit_tag != 1 && $tag_correct){ # If no tag is found, give the user the option to add one. &print_output ("No tag found for $file.\n"); print "Should we create some tag information? [y/n] "; $input=;chomp $input; if ($input =~ /[Yy]/){ $edit_tag=1; } } if ($edit_tag ==1){ $status = remove_mp3tag($file); # remove tag - in case.. #print "Tag Removal: $status\n"; # input the following information for the tag. print "Artist: "; $input_artist=;chomp $input_artist; print "Song Title: "; $input_title=;chomp $input_title; print "Album: "; $input_album=;chomp $input_album; print "Comments: ";$input_comments=;chomp $input_comments; # set the new mp3 tag.. set_mp3tag ($file, $input_title, $input_artist, $input_album,"", $input_comments); print "\n"; $mp3 = new MP3::Info $file; $artist=$mp3->artist; $song=$mp3->title; $album=$mp3->album; &print_output ("Altered Artist: $artist\nAltered Song Title: $song\nAltered Album: $album\n") if ($artist); } if ($file_correct){ $artist =~ s/[\s+\(\)]/_/g; $song =~ s/\'//g; $song =~ s/[\s+\(\)]/_/g; $album =~ s/[\s+\(\)]/_/g; if ($ask_track){ print "Track Number (if any): "; $track_number=;chomp $track_number; } if ($basename =~ /^\d+/){ print "number: $1"."\n"; } if ($artist && $song){ # only if the tags exist, move the file. $track_number = "0".$track_number if length($track_number) == 1; # put a "0" before single digit track number. my $filename = $directory; $filename .= $track_number."-" if ($track_number); # insert the track number in the filename $filename .= $artist."-".$album."-".$song.".mp3" if ($put_album_name && length($album) >= 1); # artist $filename .= $artist."-".$song.".mp3" if (!$put_album_name || !$album); # no artist or track info. if ($lowercase){$filename =~ tr/A-Z/a-z/;} system ("mv \"".$file."\" \"".$filename ."\"") if ($file ne $filename); &print_output ("New Filename: ".$filename."\n\n"); } else{ &print_output("This file cannot be renamed as a empty tag is present. No filename change was made.\n"); &print_output( "You may want to select the option to edit the tags, with the --tags option.\n\n") if (!$tag_correct); } } # end if $file_correct &print_output("----------------------------------------\n"); &print_output("\n"); return; } # end process_mp3 sub search_directories{ my ($dir)=@_; my (@dirtrax,@full_trax,@dirs,$dir_count,$file_count,$x)=(0,0,0,0,0,0); if ($recursive){ # recursive find sub{push @dirs,$File::Find::name if -d;},$startdir; # find all directories recursively } else{ # not recursive push (@dirs,$dir); } foreach(sort @dirs) { $dir_count++; #print "Processing directory $_...\n"; $dir=$_; # current directory $dir =~ s/\/$//; # open the directory and find all the .mp3 files... opendir DIR, "$_"; #for ($x=0;$x<@formats;$x++){ @dirtrax = sort grep /(.mp3)$/, readdir DIR; #} closedir DIR; foreach (@dirtrax) { # for all the mp3 files found in a directory... my $full_name=$dir."/".$_."\n"; # the full UNIX directory location of the mp3 file $file_count++; push (@full_trax,$dir."/".$_); } } # end foreach sort @dirs return (\@full_trax,$dir_count,$file_count); } sub create_playlist{ # create a playlist alphabetically from the MP3 files in the directories. my ($mp3s,$playlist)=@_; my ($i, $open_filetag); $open_filetag="+>$playlist" if (!$no_overwrite); $open_filetag="+>>$playlist" if ($no_overwrite); open (PLAYLIST, $open_filetag) || die "Error opening $playlist: $!"; for ($i=0;$i<@$mp3s;$i++){ print PLAYLIST $mp3s->[$i]."\n"; } close (PLAYLIST); } # end playlist sub process_mp3_files(){ my ($mp3_files)=@_; my (@processed); #process each file to make sure they exist... for (my $x=0;$x<@$mp3_files;$x++){ if (!-f $mp3_files->[$x]){ &print_output("There is no such file called $mp3_files->[$x]!\n") } else{ push (@processed,$mp3_files->[$x]); } } return (\@processed); # send back the new list of mp3files } sub print_output(){ # Output a message to a logfile, or STDOUT depending on what the user chose. my ($msg)=@_; print LOG $msg if ($logfile); print $msg; return; } sub usage(){ print < [options] -d, --directory=directory The directory where the mp3s are kept. This will be searched recursively -f, --file=file.mp3 Process a MP3 file. -r, --recursive Process the directory recursively. Default is non-recursive. -p, --playlist=playlist The file in which a playlist should be stored -n, --no-overwrite Do not overwrite the playlist file: just append. Default: off. -h, --help Display help -c, --correct Correct the filenames of the mp3s according to Artist and Song, ie. Artist-Song.mp3 --lowercase Lowercase the filenames. Must be used with the -c option. --tags Correct the tags of the mp3s with user input (if no tags exists for an mp3) -e, --edit Edit all tags of the mp3 files with user input whether tags exist or not. -a, --album The altered filename should contain the name of the Album: Artist-Album-Song.mp3 --track The altered filename should contain the track number (user inputted) -v, --version Print the version and exit. --logfile=logfile Log actions into a logfile. STDOUT exit(0); }