#!/usr/bin/perl -w #******************************************************************** # Program: # strip_id3v2 # Author: # Christian J. Robinson # Copyright: # September 08, 2000 - GNU GPL V2 # Purpose: # Write a copy of an mp3 or mp2 without the ID3v2/ID3v1 tag. # Assumptions: # - The file is actually an mp3 or mp2, and ends with an # appropriate suffix. # Known Limitations: # None. #******************************************************************** use strict; use Getopt::Std; use FileHandle; use File::Copy; my (%opts, $newfile, $addname); sub usage($); sub strip_id3($;$); sub strip_id3v2($$); getopts('12h', \%opts) or usage(1); usage(0) if $opts{'h'}; if ($opts{'1'} && $opts{'2'}) { $addname = '{sans ID3s}'; } elsif ($opts{'1'}) { $addname = '{sans ID3v1}'; } elsif ($opts{'2'}) { $addname = '{sans ID3v2}'; } else { $opts{2} = 1; $addname = '{sans ID3v2}'; } foreach my $file (@ARGV) { ($newfile = $file) =~ s/(.+)\.(mp[23])/$1 $addname.$2/i; print "Processing: $file\n"; if ($opts{'1'} && $opts{'2'}) { if (strip_id3v2($file, $newfile)) { print "Wrote: $newfile\n" if strip_id3($newfile); } else { print "Wrote: $newfile\n" if strip_id3($file, $newfile); } } elsif ($opts{'1'}) { print "Wrote: $newfile\n" if strip_id3($file, $newfile); } elsif ($opts{'2'}) { print "Wrote: $newfile\n" if strip_id3v2($file, $newfile); } } sub strip_id3($;$) { my $file = shift; my $newfile = shift; my ($tmp); my $origfile = $file; if ($newfile) { if (-e $newfile) { print "$newfile already exists, skipped.\n"; return 0; } if (! File::Copy::syscopy($file,$newfile)) { warn "Can't copy \"$file\" to \"$newfile\": $!\n"; return 0; } $file = $newfile; } if (! open(M, '+<' . $file)) { warn "Can't open \"$file\": $!\n"; return 0; } binmode(M); # No-op in Unix, necessary for Winblowz. M->autoflush(1); if (!seek (M, -128, 2)) { close (M); warn "Can't seek file: $!"; return 0; } if (! read (M, $tmp, 3)) { close (M); warn "Can't read file: $!"; return 0; } if ($tmp eq "TAG") { seek (M, -128, 2); } else { close(M); print "File doesn't have an ID3, skipped.\n"; if ($newfile && $file eq $newfile) { unlink($newfile); } return 0; } if (! truncate(M, tell(M))) { warn "Can't truncate \"$newfile\": $!"; return 0; } close(M); return $file; } sub strip_id3v2($$) { my $file = shift; my $newfile = shift; my ($data, @data); if (! open(M, $file)) { warn "Can't open \"$file\": $!\n"; return 0; } binmode(M); # No-op in Unix, necessary for Winblowz. read(M, $data, 3); unless ($data eq 'ID3') { print "$file doesn't have an ID3v2, skipped.\n"; close(M); return 0; } seek(M, 6, 0); read(M, $data, 4); @data = unpack('CCCC',$data); $data = $data[0]; $data = ($data << 7) | $data[1]; $data = ($data << 7) | $data[2]; $data = ($data << 7) | $data[3]; seek(M, $data + 10, 0); if (-e $newfile) { print "$newfile already exists, skipped.\n"; close(M); return 0; } if (! open(N, ">" . $newfile)) { warn "Can't open \"$newfile\": $!\n"; close(M); return 0; } binmode(N); # No-op in Unix, necessary for Winblowz. while (read(M, $data, 1024) == 1024) { print N $data; } print N $data; # Be sure to write the last chunk of data... close(N); close(M); return $newfile; } sub usage($) { my $exitval = shift; my $where; require File::Basename; my $basename = File::Basename::basename($0); if ($exitval) { $where = \*STDERR; } else { $where = \*STDOUT; } print $where <<"EOF"; Usage: $basename [options] files Options are: -1 Remove ID3 version 1 tags. -2 Remove ID3 version 2 tags. (Default) In order to remove both, specify both options. EOF exit $exitval; }