2 # Copyright (c) 2007 Jesus Climent <jesus.climent@hispalinux.es>
3 # This code is hereby licensed for public consumption under either the
4 # GNU GPL v2 or greater, or Larry Wall's Artistic license - your choice.
6 # You should have received a copy of the GNU General Public License along
7 # with this program; if not, write to the Free Software Foundation, Inc.,
8 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10 # import those needed modules.
23 abcde.py - A Better CD Encoder - python release
24 Copyright (C) 2007 Jesus Climent <jesus.climent@hispalinux.es>
28 help = """This is abcde version """ + __version__ + """
30 usage: abcde.py [options] [tracks]
32 -1 Encode the whole CD in a single file
33 -a <action1[,action2]...>
35 cddb,read,normalize,encode,tag,move,replaygain,playlist,clean
36 -b Enable batch normalization
38 Specify a configuration file (overrides system and user config files)
40 Specify discid to resume from (only needed if you no longer have the cd)
42 Specify CDROM device to grab (flac uses a single-track flac file)
43 -D Debugging mode (equivalent to sh -x abcde)
44 -e Erase encoded track information from status file
45 -f Force operations that otherwise are considered harmful. Read "man abcde"
46 -g Use "lame --nogap" for MP3 encoding. Disables low disk and pipes flags
47 -h This help information
48 #-i Tag files while encoding, when possible (local only) -NWY-
49 -j <#> Number of encoder processes to run at once (localhost)
50 -k Keep the wav tracks for later use
51 -l Use low disk space algorithm
52 -L Use local CDDB storage directory
53 -n No lookup. Don't query CDDB, just create and use template
54 -N Noninteractive. Never prompt for anything
55 -m Modify playlist to include CRLF endings, to comply with some players
56 WARNING: Deprecated. Use \"cue\" action
58 Output file type(s) (vorbis,mp3,flac,spx,mpc,wav,m4a). Defaults to vorbis
59 -p Pad track numbers with 0's (if less than 10 tracks)
60 -P Use UNIX pipes to read+encode without wav files
62 Set quality level (high,medium,low)
64 Also encode on these remote hosts
65 -R Use local CDDB in recursive mode
67 Show dielfs from the CDDB info (year,genre)
68 -S <#> Set the CD speed
69 -t <#> Start the track numbering at a given number
70 -T <#> Same as -t but modifies tag numbering
71 -U Do NOT use UNICODE (UTF8) tags and comments
72 -v Show version number and exit
73 -V Be a bit more verbose about what is happening behind the scenes
74 -x Eject CD after all tracks are read
76 Add a comment to the CD tracks
77 -W <#> Concatenate CDs: -T #01 -w "CD #"
78 -z Use debug CDROMREADERSYNTAX option (needs cdparanoia)
80 Tracks is a space-delimited list of tracks to grab.
81 Ranges specified with hyphens are allowed (i.e., 1-5).
88 def addstatus(status,file):
90 file = open(file, "w")
92 log("error","file",file,"cannot be read")
95 def log(status,logstring):
96 if re.compile("info").match(status):
99 elif re.compile("warning").match(status):
102 elif re.compile("error").match(status):
104 status = "[ERROR] %s\n"
105 sys.stderr.write(status % logstring)
110 def f_seq_row (min,max):
115 log(error,"syntax error while processing track numbers")
118 def f_seq_line (min,max):
123 log(error,"syntax error while processing track numbers")
128 # get_first and get_last can be substituted by range[0] and range[:-1]
130 # checkstatus(string)
131 # Returns "0" if the string was found, returns 1 if it wasn't
132 # Puts the blurb content, if available, on stdout.
133 # Otherwise, returns "".
134 def checkstatus (string, file):
136 patern = re.compile("^"+string+"(=.*)?$")
139 file = open(file, "r")
141 log("error","file "+file+" cannot be read")
146 line = file.readline()
148 blurb.append(re.search(patern,line).string)
157 # checks where we can find a program in the path
159 for path in string.split(os.environ["PATH"], ":"):
160 if os.path.exists(os.path.join(path, program)):
161 return os.path.join(path, program)
167 opts, args = getopt.getopt(sys.argv[1:], "1a:bc:C:d:DefghjklLnNmopPqrRsStTUvVxwWz")
169 log("error","unknown error")
170 sys.stderr.write(usage % sys.argv[0])
175 for opt, optarg in opts:
177 if opt == "-1": o_onetrack = "y"
178 if opt == "-a": o_actions = optarg
179 if opt == "-b": o_batchnormalize = "y"
180 if opt == "-B": o_nobatchreplygain = "y"
182 o_configfile = str(optarg)
184 if not re.compile("\.\/").search(o_configfile):
185 o_configfile = os.environ.get("PWD", "./") + "/" + o_configfile
186 os.path.exists(o_configfile)
188 log("error",o_configfile+" cannot be read")
190 if re.compile("abcde\.").match(optarg):
193 o_discid = "abcde." + optarg
194 if opt == "-d": o_cdrom = optarg
195 if opt == "-D": o_debug = "y"
199 if opt == "-e": o_eraseencodedstatus = "y"
200 # if opt == "-E": o_encoding
201 if opt == "-f": o_force = "y"
202 if opt == "-g": o_nogap = "y"
203 if opt == "-j": o_maxprocs = optarg
204 if opt == "-k": o_keepwavs = "y"
205 if opt == "-l": o_lowdisk = "y"
206 if opt == "-L": o_localcddb = "y"
207 if opt == "-n": o_cddbavailable = "n"
208 if opt == "-m": o_dosplaylist = "y"
209 if opt == "-M": o_docue = "y"
210 if opt == "-N": o_interactive = "n"
211 if opt == "-o": o_outputtypes = optarg
212 if opt == "-p": o_padtracks = "y"
213 if opt == "-P": o_usepipes = "y"
214 if opt == "-q": o_qualitylevel = optarg
215 #if opt == "-r": o_remotehosts = optarg
216 if opt == "-R": o_localcddbrecursive = "y"
217 if opt == "-s": o_showcddbfields = "y"
218 if opt == "-S": o_cdspeed = optarg
219 if opt == "-t": o_starttracknumber = optarg
221 o_starttracknumber = optarg
222 o_starttracknumbertag = "y"
223 if opt == "-U": o_cddbproto = 5
225 print "This is abcde v", __version__
226 print "Usage: abcde.py [options] [tracks]"
227 print "abcde -h for extra help"
229 if opt == "-V": o_verbose = "y"
230 if opt == "-x": o_eject = "y"
231 # if opt == "-X": o_cue2discid = optarg
232 if opt == "-w": o_comment = optarg
234 if re.compile("^\d+$").search(optarg)
235 o_starttracknumber = optarg + "01"
236 o_starttracknumbertag = "y"
237 o_comment = "CD" + optarg
239 log("error","opt -W must be an integer")
243 #log("error","arguments were not correct")
248 ## checkstatus("test", "/tmp/status")
253 # -------------------------------
254 if __name__ == "__main__": main()