--- mp3roaster-0.2.0.orig/debian/README.debian +++ mp3roaster-0.2.0/debian/README.debian @@ -0,0 +1,12 @@ +MP3Roaster for Debian +-------------------------- + +This MP3roaster Debian GNU/Linux package, is based on the MP3Roaster +upstream version 0.2.0 available freely from http://mp3roaster.sf.net + +Consider reading the upstream README file in /usr/share/doc/mp3roaster/ +for any informations regarding to this software. + +Have a nice day, folks. + +Ivo Marino , $Date: 2004/05/19 14:35:45 $ --- mp3roaster-0.2.0.orig/debian/changelog +++ mp3roaster-0.2.0/debian/changelog @@ -0,0 +1,50 @@ +mp3roaster (0.2.0-5) unstable; urgency=low + + * [debian/control] Depend on normalize (Closes: #258675). + * [debian/control] Added normalize-audio as dependency (Closes: #287671). + + -- Ivo Marino Tue, 4 Jan 2005 12:44:05 +0100 + +mp3roaster (0.2.0-4) unstable; urgency=low + + * [debian/control] Added new dependency: libaudio-flac-perl, this pacakge + has finally just been accepted into Debian so now we can depend on it. + * [debian/copyright] Added specific license informations (GPL) in order + to be Debian policy compatible. + * [debian/conffiles] Added /etc/mp3roaster/mp3roasterrc to be lintian + compatible. + + -- Ivo Marino Tue, 8 Jun 2004 10:46:37 +0200 + +mp3roaster (0.2.0-3) unstable; urgency=low + + * [debian/control] Added more dependencies: flac, libogg-vorbis-header-perl + and libterm-readkey-perl. The dependency libaudio-flac-perl will be added + later once the package is available on Debian. + * [debian/control] Updated package description. + + -- Ivo Marino Fri, 28 May 2004 10:20:44 +0200 + +mp3roaster (0.2.0-2) unstable; urgency=low + + * Fixed serious bug which did not install the mp3roaster.pl script. + * [debian/rules] Introduced dh_install and dh_installdirs. + * Removed the debian/patches directory, we now use 100% debhelper. + + -- Ivo Marino Thu, 27 May 2004 23:39:10 +0200 + +mp3roaster (0.2.0-1) unstable; urgency=low + + * New upstream release. + * [debian/control] New standards version. + * [debian/rules] Removed debhelpet. + * The upstream man page has been recompressed with gzip -9. + + -- Ivo Marino Wed, 19 May 2004 16:58:13 +0200 + +mp3roaster (0.1.0-1) unstable; urgency=low + + * Initial release as Debian GNU/Linux package. + + -- Ivo Marino Wed, 17 Sep 2003 00:46:05 +0200 + --- mp3roaster-0.2.0.orig/debian/control +++ mp3roaster-0.2.0/debian/control @@ -0,0 +1,18 @@ +Source: mp3roaster +Section: sound +Priority: extra +Build-Depends: debhelper (>= 4.0.2) +Build-Depends-Indep: perl (>= 5.8.0-7) +Maintainer: Ivo Marino +Standards-Version: 3.6.1 + +Package: mp3roaster +Architecture: all +Depends: ${perl:Depends}, mpg321|mpg123, ogg123|vorbis-tools, flac, cdrecord, libterm-readkey-perl, libfile-mmagic-perl, libmp3-info-perl, libogg-vorbis-header-perl, libaudio-flac-perl, normalize|normalize-audio +Description: A Perl hack for burning audio CDs out of MP3/OGG/FLAC files + MP3Roaster is a Perl hack for burning audio CDs out of MP3, Ogg Vorbis and + FLAC files. The main highlights of this application are an easy to use command + line syntax and automatic volume leveling support for best audio CD quality. + . + In order to normalize the audio level of all files which will be burned on CDs + MP3roaster requires some free hard disk space. --- mp3roaster-0.2.0.orig/debian/copyright +++ mp3roaster-0.2.0/debian/copyright @@ -0,0 +1,24 @@ +This package was debianized by Ivo Marino + +It was downloaded from http://mp3roaster.sourceforge.net + +Copyright (C) 2002-2004 Ivo Marino +This is free software; see the source for copying conditions. There is +NO warranty; the author is NOT RESPONSIBLE for any use of this program. + + This package 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; version 2 dated June, 1991. + + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this package; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + +On Debian GNU/Linux systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. --- mp3roaster-0.2.0.orig/debian/docs +++ mp3roaster-0.2.0/debian/docs @@ -0,0 +1 @@ +Docs/README --- mp3roaster-0.2.0.orig/debian/examples +++ mp3roaster-0.2.0/debian/examples @@ -0,0 +1 @@ +Docs/examples/mp3roasterrc --- mp3roaster-0.2.0.orig/debian/manpages +++ mp3roaster-0.2.0/debian/manpages @@ -0,0 +1 @@ +Docs/man/mp3roaster.1.gz --- mp3roaster-0.2.0.orig/debian/watch +++ mp3roaster-0.2.0/debian/watch @@ -0,0 +1,2 @@ +version=2 +http://prdownloads.sourceforge.net/mp3roaster/mp3roaster-(.*)\.t(.*)gz debian uupdate --- mp3roaster-0.2.0.orig/debian/rules +++ mp3roaster-0.2.0/debian/rules @@ -0,0 +1,64 @@ +#!/usr/bin/make -f + +# Sample debian/rules that uses debhelper. +# GNU copyright 1997 to 1999 by Joey Hess. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS))) + CFLAGS += -g +endif +ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) + INSTALL_PROGRAM += -s +endif + +clean: + dh_testdir + dh_testroot + dh_clean +# rm -r $(CURDIR)/debian/mp3roaster + +build: + +install: + + mv mp3roaster.pl mp3roaster + dh_install + mv mp3roaster mp3roaster.pl + + dh_installdirs + +# Build architecture-independent files here. +binary-indep: install + dh_testdir + dh_testroot +# dh_installdebconf + dh_installdocs + dh_installexamples +# dh_installmenu +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_installinit +# dh_installcron + dh_installman + dh_installinfo +# dh_undocumented + dh_installchangelogs $(CURDIR)/Docs/ChangeLog + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_makeshlibs + dh_installdeb + dh_perl + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep + +.PHONY: clean binary-indep install --- mp3roaster-0.2.0.orig/debian/conffiles +++ mp3roaster-0.2.0/debian/conffiles @@ -0,0 +1 @@ +/etc/mp3roaster/mp3roasterrc --- mp3roaster-0.2.0.orig/debian/dirs +++ mp3roaster-0.2.0/debian/dirs @@ -0,0 +1 @@ +/etc/mp3roaster --- mp3roaster-0.2.0.orig/debian/install +++ mp3roaster-0.2.0/debian/install @@ -0,0 +1,2 @@ +mp3roaster /usr/bin +Docs/examples/mp3roasterrc /etc/mp3roaster --- mp3roaster-0.2.0.orig/debian/mp3roaster/etc/mp3roaster/mp3roasterrc +++ mp3roaster-0.2.0/debian/mp3roaster/etc/mp3roaster/mp3roasterrc @@ -0,0 +1,86 @@ +# +# MP3Roaster example configuration file +# +# $Id: mp3roasterrc,v 1.10 2004/02/21 15:14:11 eim Exp $ +# +# This is an example configuration file for MP3Roaster +# +# You can copy this file to ~/.mp3roaster/mp3roasterrc or to +# ~/.mp3roasterrc and adapt it to your needs, all variables which +# are listed here can also be passed via CLI options to mp3roaster +# + +# +# CDR DEV +# +# Configure here the SCSI ID target of your CD/RW recorder, you can +# execute % cdrecord -scanbus to scan the SCSI bus and find the ID of +# your CD/RW recorder. +# +# If you have an IDE CDR or CD/RW writer and you are running Linux kernel +# >= 2.6 you can specify directly your CDR or CD/RW recorder device by it's +# name on the /dev file system, e.g. /dev/cdrom, /dev/hdc, etc. +# +$config_cdr_dev = "/dev/cdrom"; + +# +# CDR SPEED +# +# Configure here the burn speed supported by your CD/RW recorder, +# if you don't know the maximum compatible burning speed of your +# CD/RW recorder I suggest to use 4 as burning speed value. +# +$config_cdr_speed = 16; + +# +# CDR DUMMY +# +# With this option you can enable or disable the cdrecord dummy mode, +# when dummy mode is enabled (option set to 1) cdrecord will perform +# all operations with laser turned off, I've added this option for +# testing purposes so leave it disabled in doubt. +# +$config_cdr_dummy = 0; + +# +# CDR DAO +# +# Use this option to record a CD in disk-at-once mode. +# This allows live CD tracks to be burned with no gaps between them. +# +$config_cdr_dao = 0; + +# +# TEMP DIR +# +# Configure here the temporary directory to use by MP3Roaster, +# this directory will hold all uncompressed WAV files during +# the burning process so it should be big enough to hold all +# the songs for your audio CD, after successful burning all +# the WAV files in this directory will be removed. +# +$config_temp_dir = "/tmp/wav"; + +# +# MP3 DECODER +# +# Choose your favorite mp3 decoder: mpg321 or mpg123. +# +$config_mp3_decoder = "mpg321"; + +# +# CHECK FILES +# +# Here you can enable or disable the check files tasks. +# +$config_check_files = 1; + +# +# WAV NORMALIZE +# +# Enable or disable the wav normalizing support, +# when this option is enabled (1) then all the wav files +# will be normalized to the same audio level, in order to +# do this you need normalize installed on your system. +# +$config_wav_normalize = 1; --- mp3roaster-0.2.0.orig/debian/mp3roaster/etc/mp3roasterrc +++ mp3roaster-0.2.0/debian/mp3roaster/etc/mp3roasterrc @@ -0,0 +1,86 @@ +# +# MP3Roaster example configuration file +# +# $Id: mp3roasterrc,v 1.10 2004/02/21 15:14:11 eim Exp $ +# +# This is an example configuration file for MP3Roaster +# +# You can copy this file to ~/.mp3roaster/mp3roasterrc or to +# ~/.mp3roasterrc and adapt it to your needs, all variables which +# are listed here can also be passed via CLI options to mp3roaster +# + +# +# CDR DEV +# +# Configure here the SCSI ID target of your CD/RW recorder, you can +# execute % cdrecord -scanbus to scan the SCSI bus and find the ID of +# your CD/RW recorder. +# +# If you have an IDE CDR or CD/RW writer and you are running Linux kernel +# >= 2.6 you can specify directly your CDR or CD/RW recorder device by it's +# name on the /dev file system, e.g. /dev/cdrom, /dev/hdc, etc. +# +$config_cdr_dev = "/dev/cdrom"; + +# +# CDR SPEED +# +# Configure here the burn speed supported by your CD/RW recorder, +# if you don't know the maximum compatible burning speed of your +# CD/RW recorder I suggest to use 4 as burning speed value. +# +$config_cdr_speed = 16; + +# +# CDR DUMMY +# +# With this option you can enable or disable the cdrecord dummy mode, +# when dummy mode is enabled (option set to 1) cdrecord will perform +# all operations with laser turned off, I've added this option for +# testing purposes so leave it disabled in doubt. +# +$config_cdr_dummy = 0; + +# +# CDR DAO +# +# Use this option to record a CD in disk-at-once mode. +# This allows live CD tracks to be burned with no gaps between them. +# +$config_cdr_dao = 0; + +# +# TEMP DIR +# +# Configure here the temporary directory to use by MP3Roaster, +# this directory will hold all uncompressed WAV files during +# the burning process so it should be big enough to hold all +# the songs for your audio CD, after successful burning all +# the WAV files in this directory will be removed. +# +$config_temp_dir = "/tmp/wav"; + +# +# MP3 DECODER +# +# Choose your favorite mp3 decoder: mpg321 or mpg123. +# +$config_mp3_decoder = "mpg321"; + +# +# CHECK FILES +# +# Here you can enable or disable the check files tasks. +# +$config_check_files = 1; + +# +# WAV NORMALIZE +# +# Enable or disable the wav normalizing support, +# when this option is enabled (1) then all the wav files +# will be normalized to the same audio level, in order to +# do this you need normalize installed on your system. +# +$config_wav_normalize = 1; --- mp3roaster-0.2.0.orig/debian/mp3roaster/usr/bin/mp3roaster +++ mp3roaster-0.2.0/debian/mp3roaster/usr/bin/mp3roaster @@ -0,0 +1,1379 @@ +#!/usr/bin/perl -w + +############################################################################# +# # +# IMPORTANT NOTE # +# # +# !!! THE AUTHOR IS ==NOT== RESPONSIBLE FOR ANY USE OF THIS PROGRAM !!! # +# # +# GPL LICENSE # +# # +# 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. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, # +# MA 02111-1307 USA # +# # +############################################################################# + +# +# $Id: mp3roaster.pl,v 1.29 2004/05/18 18:27:12 eim Exp $ +# +# ON-THE-FLY-VIEW TODO LIST +# +# . Move the @todo_array over to the RC file. +# . Complete WAV file support (WAV file time?). +# . Define and complete verbose/debug options mode. +# . Complete all the little TODO signed comments in the code. +# . Fix the clear line code (x75, see perldoc perldop). +# +# Check also the file Docs/TODO for further TODO informations. +# + + +# +# CPAN LIBS +# +use Getopt::Long; # For the input options +use File::Basename; # Get the basename of files +use File::Compare; # Compare files +use File::Path; # Get file path +use File::Copy; # Copy files or filehandles +use File::MMagic; # Guess file type +use Term::ReadKey; # Module for simple terminal control +use MPEG::MP3Info; # Allows to get MP3 infos +use Ogg::Vorbis::Header; # Perl extension for Ogg Vorbis streams +use Audio::FLAC; # Perl extension for FLAC files + + +# +# LIBS CONFIGURATIONS +# +# Getopt::Long configuration +Getopt::Long::Configure("no_auto_abbrev", "no_ignorecase"); + + +# +# IMPLICATIONS +# +# Turn strict on (vars, refs, subs), this implicates strict declaration +# of all variables this way no dynamic variables will be allocated. +use strict; + + +# +# USE GLOBAL VARS +# +# Jip, you see right: no global vars here, it's good code. + + +# +# DECLARE GLOBAL VARS +# +my $version = "0.2.0"; +my $appname = "mp3roaster"; +my $realname = "MP3Roaster"; +my $description = "A Perl hack for burning audio CDs out of MP3/OGG/FLACs"; + +# Declare configuration options +my $config_file_dir = "mp3roaster"; +my $config_file_name = "mp3roasterrc"; + +# Declare Getopt::Long vars +my %opthash; + + +# +# GET OPTIONS +# +GetOptions ( + + \%opthash, + + 'opt_cdr_dev|dev|D=s', + 'opt_cdr_speed|speed|s=i', + 'opt_cdr_dummy|dummy|d', + 'opt_cdr_dao|dao|a', + 'opt_temp_dir|temp|t=s', + 'opt_mp3_decoder|mp3dec|m=s', + 'opt_check_files|check|c', + 'opt_wav_normalize|normalize|n', + + 'verbose|v', + 'help|h', + 'version|V' +); + + +# +# FUNCTIONS +# + +# +# PRINT_ERROR +# +# This function composes and returns an error message. +# +sub print_error { + + my ($in_sub, $in_r_message) = @_; + + if (defined $in_sub) { + + return " \! ERROR in sub $in_sub\n $in_r_message\n\n"; + + } else { + + return " \! ERROR: $in_r_message\n\n"; + } +} + +# +# WHICH_CONFIG_FILE +# +# This function checks for a configuration file. +# If this file exists and is not world writable +# the function returns it's location path as string. +# +# If the configuration file is world writable we +# print out an error message and die. +# +# If no configuration is available we return undef. +# +sub which_config_file { + + my ($in_file_dir, $in_file_name) = @_; # directory and file + my $sub = "WHICH_CONFIG_FILE"; # subroutine name + + my $location; + my @location_array = ( + + "$ENV{'HOME'}/.$in_file_name", # HOME -> .FILE + "$ENV{'HOME'}/.$in_file_dir/$in_file_name", # HOME -> /.DIR -> FILE + "/etc/$in_file_name", # /ETC -> FILE + "/etc/$in_file_dir/$in_file_name" # /ETC -> /DIR -> FILE + ); + + foreach $location (@location_array) { + + # if file available + if (-r $location) { + + # if config file is world writable + if ((stat($location))[2] & 02) { + + # print error and die + die print_error ($sub, "$location should not be world-writable"); + } + + return $location; + } + } + + return undef; +} + +# +# READ_CONFIG_FILE_AND_OPTIONS +# +# This function reads the configuration file +# and returns a HASH with all configurations. +# +sub read_config_file_and_options { + + my ($in_config_file_location) = @_; # config file path + my $sub = "READ_CONFIG_FILE_AND_OPTIONS"; # subroutine name + my $oldRS; # file holder + my $rc; # file holder + + my $reference; + my %confhash; + my %refhash; + + # This variables are found in the configuration file and + # need to be declared here in order to follow `use strict` + my $config_cdr_dev; + my $config_cdr_speed; + my $config_cdr_dummy; + my $config_cdr_dao; + my $config_temp_dir; + my $config_mp3_decoder; + my $config_check_files; + my $config_wav_normalize; + + # This options MUST be defined in the configuration file + # or MUST be passed to the program as a command line option + %refhash = ( + + "config_cdr_dev" => \$config_cdr_dev, + "config_cdr_speed" => \$config_cdr_speed, + "config_cdr_dummy" => \$config_cdr_dummy, + "config_cdr_dao" => \$config_cdr_dao, + "config_temp_dir" => \$config_temp_dir, + "config_mp3_decoder" => \$config_mp3_decoder, + "config_check_files" => \$config_check_files, + "config_wav_normalize" => \$config_wav_normalize + ); + + open('RC', $in_config_file_location); # open file + + $oldRS = $/; + undef $/; + $rc = ; + + close('RC'); # close file + + unless(defined eval $rc) { # read data and check syntax + + die print_error($sub, "Found a syntax error in $in_config_file_location:\n $@"); + } + + $/ = $oldRS; + + # + # Procedure... + # + # 1. Check if option was given + # 2. Check if config var was given + # 3. Error + # + + # cycle all config variable names + foreach $reference (keys %refhash) { + + # $$foo holds the values from the config file + my $foo = $refhash{$reference}; + # print "FOO: $$foo\n"; + + # create option variable names + my $reference2 = $reference; + $reference2 =~ s/config/opt/i; + + # if option variable for `variable name` available + if (defined $opthash{$reference2}) { + + $confhash{$reference} = $opthash{$reference2}; + + if ($opthash{verbose}) { + print " OPTS: $reference2 => $opthash{$reference2}\n"; + } + + # if config variable for `variable name` available + } elsif (defined $$foo) { + + # + # Return error if only blank spaces where defined for an option + # in the configuration file, e.g.: $config_cdr_dev = " ", this is + # different from $config_cdr_dev = "" which will be stooped later + # + # TODO Add a regexp function which checks for one or more spaces + # or remove this option an let the functions check the values + # + if ($$foo eq " ") { + + die print_error($sub, "Just a blank value is set for option \"\$$reference\" in the\n configuration file, you need to fix your configuration file now\n or provide a correct value via the respective command line option."); + + } else { + + $confhash{$reference} = $$foo; + + if ($opthash{verbose}) { + print " CONF: $reference => $confhash{$reference}\n"; + } + } + + # if variable was not defined anywhere + } else { + $reference =~ s/config_//i; + die print_error($sub, "Option \"$reference\" was neither defined in the configuration file\n and neither as an option, please define this value somewhere."); + } + }; + + return %confhash; +} + +# +# FETCH_FILE_ARRAY +# +# This function checks if the file specified via +# ARGV exists and is a valid MP3 or OGG file via +# the check_file_type function. +# +# If the file is valid it will be copied to the +# files_array which will be returned by this function. +# +# This function can only return a good value in all bad +# cases it calls the print_error function and dies. +# +sub fetch_file_array { + + my $sub = "FETCH_FILE_ARRAY"; # subroutine name + my @file_array; # the file array + my $i = 0; # a simple counter + + foreach my $file (@ARGV) { + + if (-r $file) { + + if (defined check_file_type($file)) { + + $file_array[$i] = $file; + $i++; + + } else { + die print_error ($sub, "The file \"$file\" is not a valid MP3, OGG or FLAC file."); + } + + } else { + die print_error ($sub, "The file \"$file\" does not exist."); + } + } + + return @file_array; +} + +# +# FETCH_ATIP_TIME +# +# This function fetches the ATIP of the CD/RW Disc. +# We use the cdrecord application to get this infos. +# +# We return the ATIP time in seconds. +# +sub fetch_atip_time { + + my ($config_cdr_dev) = @_; + my $sub = "FETCH_ATIP_TIME"; + my $atip_sec; + my $atip_min; + my $atip_time; + + if (!$config_cdr_dev) { + + my $r_message = "You must specify the CDR/W drive id in the configuration file or with\n the option --drive x.y.z. Execute: % cdrecord \-scanbus for further details."; + die print_error($sub, $r_message); + } + + # open file and use "cdrecord -atip" to fetch ATIP info + open(CDINFO,"cdrecord -atip dev=".$config_cdr_dev." 2>&1 |"); + + while () { + + # fetch until timeout + next unless (/out:.+\((\d+):(\d+)/); + + # get the time vars + $atip_min = $1; + $atip_sec = $2; + } + + close CDINFO; + + # die if no CDR in Drive + unless ($atip_sec && $atip_min) { + + my $r_message = "No CD-R/W in the CDR/W writer."; + die print_error ($sub, $r_message); + } + + # + # Print out the ATIP time + # TODO : This should be printed out in verbose mode. + # + # printf " * %d:%.2d minutes available on CDR/W.\n",$atip_min,$atip_sec; + + # compose ATIP time in secs + $atip_time = ($atip_min * 60) + $atip_sec; + + return $atip_time; +} + +# +# CHECK_FILE_TYPE +# +# This function returns the extension of a file +# or undef if the file is not valid. +# +sub check_file_type { + + my ($file) = @_; + my $sub = "CHECK_FILE_TYPE"; + + my $ext; + + my $mm = new File::MMagic; + my $fh = new FileHandle "< $file"; + my $res = $mm->checktype_filehandle($fh); + + # + # Secrets of File::MMagic, this works only on Debian... + # + # if ($res eq "application/octet-stream"), we need to add + # if ($res eq "audio/mpeg"), for Red Hat and maybe also some other distro. + # + if ($res eq "application/octet-stream" || "audio/x-wav" || "audio/mpeg") { + + $ext = (split(/\./,$file))[-1]; + + if ($ext eq "wav"||"mp3"||"ogg"||"flac") { + + return $ext; + } + } + + return undef; +} + +# +# CHECK_FILE +# +# This function checks the filename of each $file +# in the @file_array using a specified syntax command, +# this command is passed to the functions as parameter. +# +sub check_file { + + my ($todo, @file_array) = @_; + my $sub = "CHECK_FILE"; # subroutine name + + # Browse through the MP3 Array + foreach my $file (@file_array) { + + # Make copy of actual file + my $file_tmp = $file; + + # unofficial Perl case + for ($todo) { + + # Check what is todo + if (/up2lowercase/) { + + # Lowercase in $file_tmp + $file_tmp =~ tr/A-Z/a-z/; + + } elsif (/rmspaces/) { + + # Remove spaces in $file_tmp + $file_tmp =~ tr/" "/"_"/; + + } elsif (/rmbrackets/) { + + # Remove brackets in $file_tmp + $file_tmp =~ tr/"("/"_"/; + $file_tmp =~ tr/")"/"_"/; + + } elsif (/rmquotes/) { + + # Remove quotes in $file_tmp + $file_tmp =~ tr/"'"/"_"/; + $file_tmp =~ tr/"""/"_"/; + + } elsif (/rmquestionmarks/) { + + # Remove quotes in $file_tmp + $file_tmp =~ tr/"?"/"_"/; + } + } + + # If original MP3 name is different from lowercased copy + if ($file_tmp ne $file) { + + # Check if there's already a file with the lowercased name + if (-e $file_tmp) { + + # If there's already a file which + # is the original, the same, rename it. + if (compare ("$file", "$file_tmp") == 0) { + + # Rename the file + rename ("$file" , "$file_tmp"); + + # Update the @file_array + $file = $file_tmp; + + # The File is not the same, big problem ! + # die with error message. + } else { + + # + # TODO + # Solve this extreme error case. + # + + print "\n"; + print "Can't Rename $file to $todo the file\n"; + print "there is already a $file_tmp named file\n"; + print "which is not equal\n"; + print "\n"; + + exit 1; + } + + # If there's no file with the lowercased name + } else { + + # Rename the file + rename ("$file" , "$file_tmp"); + + # Update the @file_array + $file = $file_tmp; + } + } + } + + print "$todo "; + return @file_array; +} + +# +# FETCH_FILE_TIME +# +# This is a generic function which calculates the +# total time of all MP3/OGG/FLAC files in the @file_array. +# +# The function calculates also the total fudge factor time +# which is the sum of all the seconds between two audio tracks, +# I've set it's value to 4 seconds. +# +# We have three dependences for this function: +# +# DEPENDENCY MODULE DEBIAN PACKAGE +# ------------------------------------------------- +# MPEG::MP3Info libmp3-info-perl +# Ogg::Vorbis::Header libogg-vorbis-header-perl +# Audio::FLAC libaudio-flac-perl (note) +# +# libaudio-flac-perl note: +# +# This package is currently not available on Debian GNU/Linux +# unstable, eim has packaged it and will upload it to the +# Mentors Debian Net server. +# +# That's all. +# +sub fetch_file_time { + + my (@file_array) = @_; + my $sub = "FETCH_FILE_TIME"; # subroutine name + + my $mp3info; # get_mp3info() return + my $ogg; # holds the Ogg::Vorbis::Header object + my $oggtime; # holds the ogg's length in seconds + my $flac; # holds the Audio::FLAC object + my $flactime; # holds the flac's length in seconds + + my $tot_secs; # sum of all file plus fudge seconds + + my $tot_min; # calculated file length in minutes + my $tot_sec; # calculated file length in seconds + + my $fudge = "4"; # fudge time value (preference) + my $tot_fudge_secs; # sum of all fudge seconds + + my $tot_fudge_min; # calculated fudge length in minutes + my $tot_fudge_sec; # calculated fudge length in seconds + + # Cycle the file array + foreach my $file (@file_array) { + + # if we treat a WAV file + if (check_file_type($file) eq "wav") { + + # + # TODO + # + # Add some way to check how long, in seconds, + # a WAV file is -- I have, actually, no fsck'n + # idea how to do this, suggestions are welcome. + # maybe libaudio-wav-perl can be useful. + # + print "\n\tFIXME: Time of WAV file $file will not be counted.\n\tWe need a way to fetch the play length time of WAV files.\n\n"; + + # if we treat a MP3 file + } elsif (check_file_type($file) eq "mp3") { + + # Fetch informations about the MP3 file via libmp3-info-perl. + $mp3info = get_mp3info($file); + + # Sum total seconds plus fudge factor + $tot_secs += ($mp3info->{MM}*60) + $mp3info->{SS} + $fudge; + + # if we treat a OGG file + } elsif (check_file_type($file) eq "ogg") { + + # + # We use Ogg::Vorbis::Header here + # Example: http://search.cpan.org/src/FOOF/libvorbis-perl-0.02/test.pl + # + my $ogg = Ogg::Vorbis::Header->load($file); + $oggtime = $ogg->info("length"); + + $tot_secs += $oggtime + $fudge; + + # if we treat a FLAC file + } elsif (check_file_type($file) eq "flac") { + + # + # We use Audio::FLAC here + # + my $flac = Audio::FLAC->new($file); + + $flactime = $flac->info("TOTALSAMPLES") / $flac->info("SAMPLERATE"); + + $tot_secs += $flactime + $fudge; + } + + # Calculating the total fudge factor time + $tot_fudge_secs += ($fudge); + } + + # Calculating $tot_min and $tot_sec + $tot_min = int $tot_secs/60; + $tot_sec = $tot_secs % 60; + + # Calculating $tot_fudge_min and $tot_fuge_sec + $tot_fudge_min = int $tot_fudge_secs/60; + $tot_fudge_sec = $tot_fudge_secs % 60; + + # Compose the MP3 time in secs + # $file_time = $tot_secs; + + # TODO + # This should become a verbose option + # Print out the file time + # printf " * %d:%.2d \(+ %d:%.2d fudge\) minutes of audio.\n", $tot_min, $tot_sec, $tot_fudge_min, $tot_fudge_sec; + + return $tot_secs; +} + +# +# COMPARE_FILE_ATIP +# +# This function compares the total time of the MP3/OGG/FLAC files +# with the ATIP time and warns you the songs won't fit on CDR/W. +# +sub compare_file_atip { + + my ($in_atip_time, $in_file_time) = @_; + my $key; + my @fifo; + + my $in_atip_min = int $in_atip_time/60; + my $in_file_min = int $in_file_time/60; + + # if file time is shorter than ATIP time + if ($in_file_time <= $in_atip_time) { + + print " * The audio files fit on CD\/RW\ (CD: $in_atip_min min / File: $in_file_min min\)\n"; + + } else { + + print " * WARNING: The files won\'t fit on CD\/RW \(CD: $in_atip_min min / File: $in_file_min min\)\n"; + } + + print " Do you want to continue? ([Any Key/n]) "; + + open(TTY,"&-"; + + # + # TODO Finish to implement toolame decoder support. + # toolame is available on Debian GNU/Linux and is free. + # lame is not free instead so toolame is the case (perhaps). + # + # } elsif (/toolame/) { + # + # $cmd = "toolame --decode $file $wavpath"; + # + + } else { + + die print_error($sub, "Configure a valid mp3 decoder.") + } + } + + $rc = system($cmd); + + if (!$rc) { + + $wav_array[$i] = $wavpath; + $i++; + + } else { + + die print_error($sub, "$file was not correctly decoded,\n $config_mp3_decoder error code $rc."); + } + + } else { + + $wav_array[$i] = $wavpath; + $i++; + } + + } elsif (check_file_type($file) eq "ogg") { + + $wavpath =~ s/ogg/wav/i; + $wavpath = $config_temp_dir."/".$wavpath; + + if (!check_for_wav_file($i, $file, $wavpath)) { + + # + # system and `` return to the perl code, exec not + # system returns the exit code `` not. + # + # ogg123 exits with error code 256 if the destination + # file already exists, mpg321 does not. + # + # Here we can also use oggdec which is available, as ogg123, + # in the Debian vorbis-tools package. Which one is better? + # + # % oggdec foo.wav will decode to foo.wav + # + $cmd = "ogg123 -d wav -f \"$wavpath\" \"$file\" 2>&-"; + $rc = system($cmd); + + if (!$rc) { + + $wav_array[$i] = $wavpath; + $i++; + + } else { + + die print_error($sub, "$file was not correctly decoded to $wavpath\n ogg123 error code $rc, try to remove $wavpath if exists."); + } + + } else { + + $wav_array[$i] = $wavpath; + $i++; + } + + } elsif (check_file_type($file) eq "flac") { + + $wavpath =~ s/flac/wav/i; + $wavpath = $config_temp_dir."/".$wavpath; + + if (!check_for_wav_file($i, $file, $wavpath)) { + + # + # system and `` return to the perl code, exec not + # system returns the exit code `` not. + # + $cmd = "flac -d -s \"$file\" -o \"$wavpath\" 2>&-"; + $rc = system($cmd); + + if (!$rc) { + + $wav_array[$i] = $wavpath; + $i++; + + } else { + + die print_error($sub, "$file was not correctly decoded to $wavpath\n flac error code $rc, try to remove $wavpath if exists."); + } + + } else { + + $wav_array[$i] = $wavpath; + $i++; + } + } + } + + return @wav_array; +} + +# +# WAV_NORMALIZE +# +# This function recalls normalize with the -m (mix) +# option in order to standardize the max volume level +# for all wav files in the temp directory, if execution +# is successfully we'll go back to main without any return +# value else we die with an error message. +# +sub wav_normalize { + + my ($config_temp_dir) = @_; + my $sub = "WAV_NORMALIZE"; + my $cmd; + my $rc; + + $cmd = "normalize -m $config_temp_dir/*.wav 2>&-"; + $rc = system($cmd); + + if ($rc) { + + die print_error($sub, "the normalizing process was not successful,\n normalize error code $rc."); + } +} + +# +# BURN +# +# This function burns all wav files to a CD/RW disc +# using the cdrecord application, if cdrecord returns +# an error code we print out an error message and die, +# else we go back to main without any return value. +# +sub burn { + + my ($config_cdr_dev, $config_cdr_speed, $config_cdr_dummy, $config_cdr_dao, @wav_array) = @_; + my $sub = "BURN"; + my $burn_wav_list; + my $cdrecord_options; + my $cmd; + my $rc; + + foreach my $wav (@wav_array) { + + $burn_wav_list = $burn_wav_list." \"$wav\""; + } + + $cdrecord_options = "dev=$config_cdr_dev speed=$config_cdr_speed gracetime=2 -eject -pad -audio -silent"; + + if ($config_cdr_dummy) { + + $cdrecord_options = $cdrecord_options." -dummy"; + } + + if ($config_cdr_dao) { + + $cdrecord_options = $cdrecord_options." -dao"; + } + + # Let's Burn Baby, Burn ! + $cmd = "cdrecord $cdrecord_options $burn_wav_list >/dev/null 2>&1"; + $rc = system($cmd); + + if ($rc) { + + die print_error($sub, "the burn process was not successful,\n cdrecord error code $rc."); + } +} + +# +# FLUSH_TEMP +# +# This Function removes all wav files of the WAV array +# from the temporary directory and returns the summarized +# number of all removed files. The temporary directory +# itself won't be remove because user could have set it +# to something like / which is anyway quite lame. +# +sub flush_temp { + + my (@wav_array) = @_; + my $i = 0; + + foreach my $wav (@wav_array) { + + unlink($wav); + $i++; + } + + return $i; +} + + +# +# MAIN +# +my $config_file_location; +my %confhash; +my @file_array; +my @wav_array; +my $todo; + +# +# TODO +# +# This should be definable in the RC file +# +my @todo_array = ( + + "up2lowercase", + "rmspaces", + "rmbrackets", + "rmquotes", + "rmquestionmarks" +); + +if (@ARGV) { + + print "\n"; + print "===========================================================================\n"; + print "$realname - $version - $description\n"; + print "===========================================================================\n\n"; + + # + # 1: check for configuration file + # + if (defined ($config_file_location = which_config_file($config_file_dir, $config_file_name))) { + + # + # 2: read configuration file and put all vars in a hash + # + print " * Options [ "; + %confhash = read_config_file_and_options($config_file_location); + + # print "dev ($confhash{config_cdr_dev}) "; + print "$confhash{config_cdr_speed}x "; + if ($confhash{config_cdr_dummy}) { print "dummy "; } + if ($confhash{config_cdr_dao}) { print "dao "; } + if ($confhash{config_check_files}) { print "filecheck "; } + if ($confhash{config_wav_normalize}) { print "normalize "; } + + print "]\n"; + + # + # 3: create the file array + # + @file_array = fetch_file_array; + + print " * Processing "; + + if (($#file_array) > 0) { + + printf "%d files.\n", $#file_array+1; + + } else { + + print "1 file.\n"; + } + + # + # 4: check files (optional) + # + if ($confhash{config_check_files}) { + + print " * Checking file [ "; + + foreach $todo (@todo_array) { + + @file_array = check_file($todo, @file_array); + } + + print "]\n"; + } + + # + # 5: check if files fit on CD/RW + # + compare_file_atip(fetch_atip_time($confhash{config_cdr_dev}), fetch_file_time(@file_array)); + + # + # 6: check the temp directory + # + if (check_temp($confhash{config_temp_dir})) { + + print " * Temporary directory available.\n"; + + } else { + + print " * Temporary directory created.\n"; + } + + # + # 7: decode MP3/OGG/FLAC files and get the wave array + # + print " * Decoding MP3/OGG/FLAC files to wav...\n"; + + @wav_array = file_decode($confhash{config_wav_normalize}, $confhash{config_temp_dir}, $confhash{config_mp3_decoder}, @file_array); + + # + # TODO + # clear the line with 80 chars, this could be done much better (x75, see perldoc perldop) + # + print "\r "; + + if (($#wav_array) > 0) { + + printf "\r done, %d files successfully decoded.\n", $#wav_array+1; + + } else { + + print "\r done, 1 file successfully decoded.\n"; + } + + # + # 8: normalize all the WAV files + # + if ($confhash{config_wav_normalize}) { + + print " * Normalizing wav files, please wait... "; + + wav_normalize($confhash{config_temp_dir}); + + print "done.\n"; + } + + # + # 9: now let's BURN + # + # TODO Debug this printf.. + # + # printf " * Burning %d files, please wait... ", ($#wav_array+1); + # + print " * Burning files, please wait... "; + burn($confhash{config_cdr_dev}, $confhash{config_cdr_speed}, $confhash{config_cdr_dummy}, $confhash{config_cdr_dao}, @wav_array); + print "done.\n"; + + # + # 10: flush all wav files in temporary directory + # + my $f = flush_temp(@wav_array); + if ($f > 1) { + + printf " * Removed %d wav files.\n\n", $f; + + } else { + + print " * Removed 1 wav file.\n\n"; + } + + exit 0; + + } else { + + die print_error(undef, "MP3Roaster configuration file is not available."); + } + + +# if version option +} elsif ($opthash{version}) { + +print < +with lots of help from Lorenzo Prince . + +Copyright (C) 2002-2004 Ivo Marino +This is free software; see the source for copying conditions. There is +NO warranty; the author is NOT RESPONSIBLE for any use of this program. +EOT + +exit 0; + + +# if no args or help option +} elsif ($#ARGV < 1 || $opthash{help}) { + + print < +EOT + exit 0; +} + +__END__ + +=head1 NAME + +mp3roaster - A Perl hack for burning audio CDs out of MP3/OGG/FLACs + +=head1 SYNOPSIS + +B [OPTION]... C + +=head1 DESCRIPTION + +B +A Perl hack for burning audio CDs out of MP3, OGG VORBIS and FLAC files. +The main highlights of this application are an easy to use command line syntax +and automatic volume leveling support for best audio CD quality. + +=head1 ENVIRONMENT + +Debian GNU/Linux. Red Hat Linux. + +=head1 OPTIONS + +All options have been imported, now we should add specific descriptions +for each option. + +=over 4 + +=item B<-d, --dev> + +CDR device to use + +=item B<-s, --speed> + +Burn speed + +=item B<-d, --dummy> + +Burn with laser off + +=item B<-a, --dao> + +Burn in disk-at-once (DAO) mode + +=item B<-t, --temp> + +Temporary directory + +=item B<-m, --mp3dec> + +MP3 decoder to use + +=item B<-c, --check> + +Check file before burning + +=item B<-n, --normalize> + +Normalize WAV files before burning + +=item B<-v, --verbose> + +Enable verbose output + +=item B<-h, --help> + +Show the help screen + +=item B<-V, --version> + +Show version and infos + +=back + +=head1 RETURN VALUE + +B returns 0 on success, 1 on error. + +=head1 DIAGNOSTICS + +This has to be written yet. + +=head1 EXAMPLES + +This has to be written yet. +Import examples from Docs/README + +=head1 FILES + +This has to be written yet. +Import files from Docs/README + +=head1 CAVEHEATS + +This has to be written yet. + +=head1 BUGS + +This has to be written yet. + +=head1 NOTES + +This has to be written yet. + +=head1 SEE ALSO + +This has to be written yet. + +=head1 AUTHOR + +=over 4 + +=item Ivo Marino + +=item Lorenzo Prince + +=back + +=head1 HISTORY + +This has to be written yet. + +=cut + +# vim: ts=8:sw=4:sts=4:et