#!/usr/bin/python # decrap.py # Title: CUE sheet and m3u de-crapifier # Author: Ryan Stonecipher-Fisher # email: Ryan.Stonecipher.Fisher@gmail.com # Input: Album directory containing one .cue and one .m3u (and optionally one .log) file # Output: Thorough, ready-to-use album description # Version # 0.1 - testing - 05/19/06 # import modules for functionsimport sys # handles passed argumentsimport os # determines if files existimport dircache # used for directory listingimport re # used for regular expressionsimport math # used for floor() rounding function # read inputif len(sys.argv) != 2: # ensures that only one argument was passed print "decrap: missing directory argument" # explain argument error print "Try 'decrap --help' for more information." # suggest usage help sys.exit() # quit programelse: album_dir = sys.argv[1] # get the directory from the command # explain usage if --help is passedif album_dir == '--help': # check that passed value is --help print "Usage: decrap DIRECTORY" # print usage print "Prints useful output about DIRECTORY", # explain function print "for upload form on OiNK's." # explain function (continued) print "Directories must contain .cue and .m3u files." # show requirements print "Report bugs to <Ryan.Stonecipher.Fisher@gmail.com>." # give contact sys.exit() # quit program # check for a valid directoryif os.path.exists(album_dir): # check that the directory exists dir_files = dircache.listdir(album_dir+'/') # load the directory contentselse: # if the directory doesn't exist print album_dir + " is not a valid directory." # explain error print "Try 'decrap --help' for more information." # suggest usage sys.exit() # quit program # find cue, m3u, and log file(s) - we're gonna assume there's just one of eachcueways = ".cue|.Cue.|.cUe|.cuE|.CUe|.CuE|.cUE|.CUE" # every way to put .cue in the filesystemm3uways = ".m3u|.M3u|.m3U|.M3U" # every way to put .m3u in the filesystemlogways = ".log|.Log|.lOg|.loG|.LOg|.LoG|.lOG|.LOG" # every way to put .log in the filesystemcuefile = [foo for foo in dir_files if re.search(cueways, foo)] # list of cue filesm3ufile = [foo for foo in dir_files if re.search(m3uways, foo)] # list of m3u fileslogfile = [foo for foo in dir_files if re.search(logways, foo)] # find .log # cuesheet - readingif len(cuefile) == 0: # if no .cue was found print "FREAKOUT ERROR - NO CUE:" # show error print "decrap only works for directories with cue sheets." # suggest reason sys.exit() # quit programelse: # if a .cue was found cue = open(album_dir + cuefile[0], 'r') # open the .cue file for reading rawcue = cue.read().decode('cp1252').encode('UTF8') # read the .cue file cue.close() # close the .cue file cuelines = rawcue.split("\r\n") # split the .cue file into lines # ignore cuesheet data tracksdatalines = [foo for foo in cuelines if re.search("MODEx", foo)] # find data tracksif datalines != []: # if data tracks were found datastart = cuelines.index(datalines[0]) # get the index of the first data track trimmedcuelines = cuelines[0:(datastart-1)] # trim all subsequent tracks cuelines = trimmedcuelines # replace the original list # m3u - readingif len(m3ufile) == 0: # if no .m3u was found print "FREAKOUT ERROR - NO M3U:" # show error print "decrap only works for directories with m3u playlists." # suggest reason sys.exit() # quit programelse: # if a .m3u was found m3u = open(album_dir + m3ufile[0], 'r') # open the .m3u file for reading rawm3u = m3u.read().decode('cp1252').encode('UTF8') # read the .m3u file m3u.close() # close the .m3u file m3ulines = rawm3u.split("\n") # split the .m3u file into lines # cuesheet - yearcuedateline = [foo for foo in cuelines if re.search("REM DATE", foo)] # find lines with yearif len(cuedateline)==0: # if the logs has no year year = '*' # red flag the yearelse: # if a date exists year = cuedateline[0].split(" ")[2] # extract the year # cuesheet - album titletitles = [foo for foo in cuelines if re.search("TITLE", foo)] # find lines with titlesa_title = titles[0].split("TITLE ")[1].split('"')[1] # extract album title # cuesheet - album artistartists = [foo for foo in cuelines if re.search("PERFORMER ", foo)] # find lines with performersa_artist = artists[0].split("PERFORMER ")[1].split('"')[1] # extract album artist # cuesheet - track titlest_title=[] # declare list for track titlesx=1 # initialize counterwhile x<len(titles): # loop until title list is complete t_title.append(titles[x].split("TITLE ")[1].split('"')[1]) # add trimmed track titles to tracks list x+=1 # increment counter # cuesheet - track artistst_artist=[] # declare list for track artistsx=1 # reset counterwhile x<len(artists): # loop until artist list is complete t_artist.append(artists[x].split("PERFORMER ")[1].split('"')[1]) # add trimmed artist names to artist list x+=1 # increment counter # m3u - collecting timesm3usedlines = [foo for foo in m3ulines if re.search("EXTINF:", foo)] # find only lines that will contain lengthslengths=[] # declare empty list to hold lengthsx = 0 # reset counterwhile x<len(m3usedlines): # loop until length list is complete lengths.append(m3usedlines[x].split(",")[0].split("EXTINF:")[1]) # add trimmed lengths to length list x+=1 # increment counter # m3u - adding lengths to get timetotalseconds = 0 # initialize total time variablex = 0 # reset counterwhile x<len(lengths): # loop until all times have been added totalseconds+=int(lengths[x]) # convert strings to numbers for math x+=1 # increment counterhour = int(math.floor(totalseconds/3600.0)) # cast int on forced float for hoursminute = int(math.floor((totalseconds-hour*3600)/60.0)) # cast int on forced float for minutessecond = int(totalseconds - 3600 * hour - 60 * minute) # cast int on seconds to be safehours = str(hour) # convert hours into a stringif (minute < 10) and (hour != 0): # if there are hours minutes = '0' + str(minute) # -> minutes string with leading zeroelse: # if there are no hours minutes = str(minute) # -> minutes stringif (second < 10) and ((hour != 0) or (minute != 0)): # -> if there are hours or minutes seconds = '0' + str(second) # ->-> seconds string with leading zeroelse: # if there are seconds only seconds = str(second) # -> shortest... album... ever... # outputprint '\n[pre]Artist: ' + a_artist + '\nAlbum: ' + a_title # preformatting, album artist and titleif year != '*': # if a year was found print 'Year: ' + year # show album year # time outputif hours != '0': # only display hours if present print 'Length: ' + hours + ':' + minutes + ':' + seconds + '[/pre]\n' # hours:minutes:secondselse: # if hours are not present if minutes != '0': # ->if minutes are present print 'Length: ' + minutes + ':' + seconds + '[/pre]\n' # ->->minutes:seconds else: # ->if minutes aren't present print 'Length: ' + seconds + '[/pre]\n' # ->->shortest... album... ever # track listingx = 0 # reset counterwhile x<len(t_artist): # loop until track list is complete # print str(x) +'. 't_artist[x] + ' - ' + t_title[x] # use this line for track numbering print t_artist[x] + ' - ' + t_title[x] # i don't like track numbering x+= 1 # increment counter # check if a log existsif len(logfile) == 0: # if no log was found extra_files = 2 # ->cue and m3u are extra fileselse: # if a log was found extra_files = 3 # ->cue and m3u and log are extra files # see if the directory has mp3 or APE files then assume FLAC if chosen types arent present # this could be expanded for other formats under the assumption that only one format was usedif re.search(".mp3|.Mp3|.mP3|.MP3", foo): # test for moronic capitalization mp3s = [foo for foo in dir_files] # ->find mp3 files if len(mp3s) != 0: # ->if mp3 files were found format = 'mp3' # ->->format is mp3elif re.search(".ape|.Ape|.aPe|.apE|.APe|.ApE|.aPE|.APE", foo): # test for moronic capitalization apes = [foo for foo in dir_files] # ->find ape files if len(apes) != 0: # ->if ape files were found format = 'ape' # ->->format is apeelse: # not mp3 or ape format = 'FLAC' # ->format is FLAC (default) # print file descriptionprint '\n' + str(len(t_artist)+extra_files) + ' files:' # number of files presentprint str(len(t_artist)) + ' ' + format + ' files' # number and format of tracksprint cuefile[0], # .cue filenameprint '- EAC "Multiple WAV Files With Gaps... (Noncompliant)" CUE sheet' # cue explanationif extra_files == 3: # if a .log exists print logfile[0] + ' - EAC log' # ->.log filename and explanationprint m3ufile[0] + ' - playlist' # .m3u filename and explanation