Fix misspelling of comma in script and manpage
[clinton/abcde.git] / abcde.py
1 #!/usr/bin/env python
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.
5 #
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
9 #
10 # $Id: abcde 232 2007-03-22 21:39:30Z data $
11
12 # import those needed modules.
13
14 import os
15 import re
16 import sys
17 import time
18 import getopt
19 import string
20 import select
21
22 __version__ = "1.0-$Revision$"
23
24 """
25 abcde.py - A Better CD Encoder - python release
26 Copyright (C) 2007 Jesus Climent <jesus.climent@hispalinux.es>
27
28 """
29
30 help = """This is abcde version """ + __version__ + """
31
32 usage: abcde.py [options] [tracks]
33 Options:
34 -1 Encode the whole CD in a single file
35 -a <action1[,action2]...>
36 Actions to perform:
37 cddb,read,normalize,encode,tag,move,replaygain,playlist,clean
38 -b Enable batch normalization
39 -c <file>
40 Specify a configuration file (overrides system and user config files)
41 -C <discid#>
42 Specify discid to resume from (only needed if you no longer have the cd)
43 -d <device>
44 Specify CDROM device to grab (flac uses a single-track flac file)
45 -D Debugging mode (equivalent to sh -x abcde)
46 -e Erase encoded track information from status file
47 -f Force operations that otherwise are considered harmful. Read "man abcde"
48 -g Use "lame --nogap" for MP3 encoding. Disables low disk and pipes flags
49 -h This help information
50 #-i Tag files while encoding, when possible (local only) -NWY-
51 -j <#> Number of encoder processes to run at once (localhost)
52 -k Keep the wav tracks for later use
53 -l Use low disk space algorithm
54 -L Use local CDDB storage directory
55 -n No lookup. Don't query CDDB, just create and use template
56 -N Noninteractive. Never prompt for anything
57 -m Modify playlist to include CRLF endings, to comply with some players
58 WARNING: Deprecated. Use \"cue\" action
59 -o <type1[,type2]...>
60 Output file type(s) (vorbis,mp3,flac,spx,mpc,wav,m4a). Defaults to vorbis
61 -p Pad track numbers with 0's (if less than 10 tracks)
62 -P Use UNIX pipes to read+encode without wav files
63 -q <level>
64 Set quality level (high,medium,low)
65 -r <host1[,host2]...>
66 Also encode on these remote hosts
67 -R Use local CDDB in recursive mode
68 -s <field>
69 Show dielfs from the CDDB info (year,genre)
70 -S <#> Set the CD speed
71 -t <#> Start the track numbering at a given number
72 -T <#> Same as -t but modifies tag numbering
73 -U Do NOT use UNICODE (UTF8) tags and comments
74 -v Show version number and exit
75 -V Be a bit more verbose about what is happening behind the scenes
76 -x Eject CD after all tracks are read
77 -w <comment>
78 Add a comment to the CD tracks
79 -W <#> Contatenate CDs: -T #01 -w "CD #"
80 -z Use debug CDROMREADERSYNTAX option (needs cdparanoia)
81
82 Tracks is a space-delimited list of tracks to grab.
83 Ranges specified with hyphens are allowed (i.e., 1-5).
84
85 """
86
87 def usage ():
88 print help
89
90 def addstatus(status,file):
91 try:
92 file = open(file, "w")
93 except:
94 log("error","file",file,"cannot be read")
95 return -1
96
97 def log(status,logstring):
98 if re.compile("info").match(status):
99 status = "[INFO]"
100 pass
101 elif re.compile("warning").match(status):
102 status = "[WARNING]"
103 pass
104 elif re.compile("error").match(status):
105 returncode = 1
106 status = "[ERROR] %s\n"
107 sys.stderr.write(status % logstring)
108 sys.exit(1)
109 else:
110 return 1
111
112 def f_seq_row (min,max):
113 try:
114 seq = range(min,max)
115 return seq
116 except:
117 log(error,"syntax error while processing track numbers")
118 return -1
119
120 def f_seq_line (min,max):
121 try:
122 seq = range(min,max)
123 return seq
124 except:
125 log(error,"syntax error while processing track numbers")
126 return -1
127
128 #usage()
129
130 # get_first and get_last can be substituted by range[0] and range[:-1]
131
132 # checkstatus(string)
133 # Returns "0" if the string was found, returns 1 if it wasn't
134 # Puts the blurb content, if available, on stdout.
135 # Otherwise, returns "".
136 def checkstatus (string, file):
137
138 patern = re.compile("^"+string+"(=.*)?$")
139
140 try:
141 file = open(file, "r")
142 except:
143 log("error","file "+file+" cannot be read")
144 return -1
145
146 blurb = []
147 while 1:
148 line = file.readline()
149 if line == "": break
150 blurb.append(re.search(patern,line).string)
151
152 print blurb
153 if blurb[-1]:
154 return 0
155 else:
156 return 1
157
158 # which(program)
159 # checks where we can find a program in the path
160 def which(program):
161 for path in string.split(os.environ["PATH"], ":"):
162 if os.path.exists(os.path.join(path, program)):
163 return os.path.join(path, program)
164
165
166
167 def main():
168 try:
169 opts, args = getopt.getopt(sys.argv[1:], "1a:bc:C:d:DefghjklLnNmopPqrRsStTUvVxwWz")
170 except:
171 log("error","unknown error")
172 sys.stderr.write(usage % sys.argv[0])
173 sys.exit(1)
174
175 try:
176 #abcde.setup()
177 for opt, optarg in opts:
178 print opt, optarg
179 if opt == "-1": o_onetrack = "y"
180 if opt == "-a": o_actions = optarg
181 if opt == "-b": o_batchnormalize = "y"
182 if opt == "-B": o_nobatchreplygain = "y"
183 if opt == "-c":
184 o_configfile = str(optarg)
185 try:
186 if not re.compile("\.\/").search(o_configfile):
187 o_configfile = os.environ.get("PWD", "./") + "/" + o_configfile
188 os.path.exists(o_configfile)
189 except:
190 log("error",o_configfile+" cannot be read")
191 if opt == "-C":
192 if re.compile("abcde\.").match(optarg):
193 o_discid = optarg
194 else:
195 o_discid = "abcde." + optarg
196 if opt == "-d": o_cdrom = optarg
197 if opt == "-D": o_debug = "y"
198 if opt == "-h":
199 usage()
200 sys.exit(1)
201 if opt == "-e": o_eraseencodedstatus = "y"
202 # if opt == "-E": o_encoding
203 if opt == "-f": o_force = "y"
204 if opt == "-g": o_nogap = "y"
205 if opt == "-j": o_maxprocs = optarg
206 if opt == "-k": o_keepwavs = "y"
207 if opt == "-l": o_lowdisk = "y"
208 if opt == "-L": o_localcddb = "y"
209 if opt == "-n": o_cddbavailable = "n"
210 if opt == "-m": o_dosplaylist = "y"
211 if opt == "-M": o_docue = "y"
212 if opt == "-N": o_interactive = "n"
213 if opt == "-o": o_outputtypes = optarg
214 if opt == "-p": o_padtracks = "y"
215 if opt == "-P": o_usepipes = "y"
216 if opt == "-q": o_qualitylevel = optarg
217 #if opt == "-r": o_remotehosts = optarg
218 if opt == "-R": o_localcddbrecursive = "y"
219 if opt == "-s": o_showcddbfields = "y"
220 if opt == "-S": o_cdspeed = optarg
221 if opt == "-t": o_starttracknumber = optarg
222 if opt == "-T":
223 o_starttracknumber = optarg
224 o_starttracknumbertag = "y"
225 if opt == "-U": o_cddbproto = 5
226 if opt == "-v":
227 print "This is abcde v", __version__
228 print "Usage: abcde.py [options] [tracks]"
229 print "abcde -h for extra help"
230 sys.exit(0)
231 if opt == "-V": o_verbose = "y"
232 if opt == "-x": o_eject = "y"
233 # if opt == "-X": o_cue2discid = optarg
234 if opt == "-w": o_comment = optarg
235 if opt == "-W":
236 if re.compile("^\d+$").search(optarg)
237 o_starttracknumber = optarg + "01"
238 o_starttracknumbertag = "y"
239 o_comment = "CD" + optarg
240 else:
241 log("error","opt -W must be an integer")
242 sys.exit(1)
243
244 except:
245 #log("error","arguments were not correct")
246 pass
247
248
249 #try:
250 ## checkstatus("test", "/tmp/status")
251 # pass
252 #except:
253 # sys.exit(1)
254
255 # -------------------------------
256 if __name__ == "__main__": main()
257
258 # b:is_python
259 # vim:tabstop=4: