#!/usr/bin/perl # $Revision: 1.14 $ # Mac OS X 10.6 defaults to 64-bit Perl 5.10, which isn't compatible # with the 32-bit MacPerl package used by this script. # To get this running under 10.6, you either need to change the #! line above to: # #!/usr/bin/perl5.8.8 # or you need to set the environment variable VERSIONER_PERL_VERSION to "5.8.8" # (without the quotes). See "man perl" in 10.6 for more options. use strict; use warnings; use Cwd; use File::Basename; my $DOWNLOADER = "wget"; my $USE_SUBFOLDER = 0; my @FILES; my $DEBUG = 0; my $PLATYPUS = 0; my $DARWIN = 0; if ($^O eq "darwin") { $DARWIN = 1; } my $WIN32 = 0; if ($^O eq "MSWin32") { $WIN32 = 1; } BEGIN { if ($^O eq "MSWin32") { require Win32::FileOp; import Win32::FileOp; } if ($^O eq "darwin") { require MacPerl; import MacPerl; } } # Don't buffer output! $| = 1; ################################################################################# sub Fail { print shift() . "\n"; if ($WIN32) { print "\nPress ENTER to exit.\n"; <>; } exit 1; } ################################################################################# # Use these open() and select() lines (and the close() at the bottom) for debugging. #open(LOG, ">/tmp/m3u2mp3.log"); #select(LOG); if ((exists $ENV{PLATYPUS}) && ($ENV{PLATYPUS} eq "1")) { if ($DEBUG) { print "We're running under Platypus.\n" } $PLATYPUS = 1; $DOWNLOADER = "curl --location --remote-name"; # I don't use wget under Platypus anymore, because I can't guarantee # it will be on everyone's system. Also, you can't modify the PATH # in system calls from Perl under Platypus, so I have to hard-code the path # or look in a bunch of places for it (ick). # Also, running under Platypus makes wget think there's no TTY, # and forcing the "bar" progress meter makes the output look bad, # so you have to use the "dot:mega" style. #$DOWNLOADER = "/sw/bin/wget --progress=dot:mega"; # All in all, curl is much better and guaranteed to be in Mac OS X (10.4 and higher only?) # First arg under Platypus is the name of the app. #shift @ARGV; # Check that there are still some args left! if ($#ARGV < 0) { Fail("You need to drop M3U files onto the icon!"); } } if ($#ARGV < 0) { opendir(DIR, "."); my @choices = grep(/\.m3u$/i, readdir(DIR)); closedir(DIR); if (scalar(@choices)) { print "Download these M3U files:\n"; print map { " $_\n" } @choices; print "\n[Y/n] "; my $answer = <>; chomp $answer; if (($answer eq "") || ($answer =~ m/y/i)) { @FILES = @choices; } else { Fail("Operation cancelled by user."); } } else { if ($WIN32) { my $m3u = OpenDialog(title=>"Please select your M3U file", filters=>{'M3U Files'=>'*.m3u'}); if ($m3u) { chdir(dirname($m3u)) || Fail("Cannot open the directory of '$m3u'"); @FILES = (basename($m3u)); } else { Fail("M3U selection cancelled by user.") } } else { # There are no CLI arguments, there are no M3U files in the # current directory, and we're not in $WIN32 so I can't # bring up a GUI to select an M3U file. Fail("USAGE: $0 \n\nWithout any arguments, if there are any M3U files in the current directory,\nm3u2mp3 will prompt you to use those."); } } } else { # Use the command-line arguments, filtered for valid extensions. @FILES = grep(/\.m3u$/i, @ARGV); @ARGV = (); # Clear @ARGV so later calls to "<>" will work right. } my $m3uCount = 0; my $origDir = cwd(); foreach my $file (@FILES) { $m3uCount++; my @downloads; open(F, "$file") || Fail("Cannot open file '$file'!"); chdir(dirname($file)) || Fail("Cannot open the directory of '$file'"); my @lines = ; # slurp it all in; yeah, I know it's inefficient... close(F); print "\n###################################################################\n"; print "M3U file #$m3uCount of " . scalar(@FILES) . ": $file"; print "\n###################################################################\n"; foreach my $line (@lines) { if ($DEBUG) { print "\nExamining line \"$line\"" } # Skip M3U comment lines. if ($line =~ /^#/) { next; } # Allow use of local paths ($file starts with a "/"). if($line =~ m/^\//i) { $line = "file://$line"}; # Strip newlines and carriage-returns from each line $line =~ s/\n//; $line =~ s/\r//; if ($line) { push(@downloads, $line); } } if ((scalar(@downloads) > 1) && ($USE_SUBFOLDER || ($DARWIN && MacPerl::Answer("More than one file will be downloaded.\nUse subfolders?", "Yes", "No")))) { # There is more than 1 file in this file, so download into a subfolder. $USE_SUBFOLDER = 1; # remember for next M3U w/ multiple downloads my $dir = basename($file); $dir =~ s/\.m3u//i; if (! -d $dir) { mkdir($dir) or warn "Could not create the download subfolder $dir\n" } chdir($dir) or warn "Could not 'cd' into the download subfolder $dir\n"; # We're now down in the subfolder, and are ready to download. # We don't need to explicitly 'cd ..' out of the subfolder, # as we will later 'cd' back to the $origDir (the directory # we were in when the script started). We need to be back in # $origDir as there may be other M3U files to process there, # or there may be other command-line arguments with relative # paths (relative to $origDir). } # We have all the MP3 links from this M3U now, so download them. my $downloadCount = 0; foreach my $download (@downloads) { $downloadCount++; print "Downloading #$downloadCount of " . scalar(@downloads) . " (from file #$m3uCount of " . scalar(@FILES) . ")\n"; `$DOWNLOADER "$download"`; print "\n###################################################################\n"; } chdir($origDir) or warn "Could not 'cd' back to the original directory: $origDir\n"; } # end of FOREACH loop if ($WIN32) { print "\nPress ENTER to exit.\n"; <>; } #close(LOG);