Trim trailing whitespace
[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 # import those needed modules.
11
12 import os
13 import re
14 import sys
15 import time
16 import getopt
17 import string
18 import select
19
20 __version__ = "1.0"
21
22 """
23 abcde.py - A Better CD Encoder - python release
24 Copyright (C) 2007 Jesus Climent <jesus.climent@hispalinux.es>
25
26 """
27
28 help = """This is abcde version """ + __version__ + """
29
30 usage: abcde.py [options] [tracks]
31 Options:
32 -1     Encode the whole CD in a single file
33 -a <action1[,action2]...>
34        Actions to perform:
35        cddb,read,normalize,encode,tag,move,replaygain,playlist,clean
36 -b     Enable batch normalization
37 -c <file>
38        Specify a configuration file (overrides system and user config files)
39 -C <discid#>
40        Specify discid to resume from (only needed if you no longer have the cd)
41 -d <device>
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
57 -o <type1[,type2]...>
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
61 -q <level>
62        Set quality level (high,medium,low)
63 -r <host1[,host2]...>
64        Also encode on these remote hosts
65 -R     Use local CDDB in recursive mode
66 -s <field>
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
75 -w <comment>
76        Add a comment to the CD tracks
77 -W <#> Contatenate CDs: -T #01 -w "CD #"
78 -z     Use debug CDROMREADERSYNTAX option (needs cdparanoia)
79
80 Tracks is a space-delimited list of tracks to grab.
81 Ranges specified with hyphens are allowed (i.e., 1-5).
82
83 """
84
85 def usage ():
86         print help
87
88 def addstatus(status,file):
89         try:
90                 file = open(file, "w")
91         except:
92                 log("error","file",file,"cannot be read")
93                 return -1
94
95 def log(status,logstring):
96         if re.compile("info").match(status):
97                 status = "[INFO]"
98                 pass
99         elif re.compile("warning").match(status):
100                 status = "[WARNING]"
101                 pass
102         elif re.compile("error").match(status):
103                 returncode = 1
104                 status = "[ERROR] %s\n"
105                 sys.stderr.write(status % logstring)
106                 sys.exit(1)
107         else:
108                 return 1
109
110 def f_seq_row (min,max):
111         try:
112                 seq = range(min,max)
113                 return seq
114         except:
115                 log(error,"syntax error while processing track numbers")
116                 return -1
117
118 def f_seq_line (min,max):
119         try:
120                 seq = range(min,max)
121                 return seq
122         except:
123                 log(error,"syntax error while processing track numbers")
124                 return -1
125
126 #usage()
127
128 # get_first and get_last can be substituted by range[0] and range[:-1]
129
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):
135
136         patern = re.compile("^"+string+"(=.*)?$")
137
138         try:
139                 file = open(file, "r")
140         except:
141                 log("error","file "+file+" cannot be read")
142                 return -1
143
144         blurb = []
145         while 1:
146                 line = file.readline()
147                 if line == "": break
148                 blurb.append(re.search(patern,line).string)
149
150         print blurb
151         if blurb[-1]:
152                 return 0
153         else:
154                 return 1
155
156 # which(program)
157 # checks where we can find a program in the path
158 def which(program):
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)
162
163
164
165 def main():
166         try:
167                 opts, args = getopt.getopt(sys.argv[1:], "1a:bc:C:d:DefghjklLnNmopPqrRsStTUvVxwWz")
168         except:
169                 log("error","unknown error")
170                 sys.stderr.write(usage % sys.argv[0])
171                 sys.exit(1)
172
173         try:
174                 #abcde.setup()
175                 for opt, optarg in opts:
176                         print opt, optarg
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"
181                         if opt == "-c":
182                                 o_configfile = str(optarg)
183                                 try:
184                                         if not re.compile("\.\/").search(o_configfile):
185                                                 o_configfile = os.environ.get("PWD", "./") + "/" + o_configfile
186                                         os.path.exists(o_configfile)
187                                 except:
188                                         log("error",o_configfile+" cannot be read")
189                         if opt == "-C":
190                                 if re.compile("abcde\.").match(optarg):
191                                         o_discid = optarg
192                                 else:
193                                         o_discid = "abcde." + optarg
194                         if opt == "-d": o_cdrom = optarg
195                         if opt == "-D": o_debug = "y"
196                         if opt == "-h":
197                                 usage()
198                                 sys.exit(1)
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
220                         if opt == "-T":
221                                 o_starttracknumber = optarg
222                                 o_starttracknumbertag = "y"
223                         if opt == "-U": o_cddbproto = 5
224                         if opt == "-v":
225                                 print "This is abcde v", __version__
226                                 print "Usage: abcde.py [options] [tracks]"
227                                 print "abcde -h for extra help"
228                                 sys.exit(0)
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
233                         if opt == "-W":
234                                 if re.compile("^\d+$").search(optarg)
235                                         o_starttracknumber = optarg + "01"
236                                         o_starttracknumbertag = "y"
237                                         o_comment = "CD" + optarg
238                                 else:
239                                         log("error","opt -W must be an integer")
240                                         sys.exit(1)
241
242         except:
243                 #log("error","arguments were not correct")
244                 pass
245
246
247 #try:
248 ##      checkstatus("test", "/tmp/status")
249 #       pass
250 #except:
251 #       sys.exit(1)
252
253 # -------------------------------
254 if __name__ == "__main__": main()
255
256 # b:is_python
257 # vim:tabstop=4: