Rename broken tag
[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: