import re import os import tempfile import sys import time import glob import subprocess import shutil from pprint import pprint, pformat import os.path #Globals startTime = int(time.time()) CURRDIR = re.sub('\\\\+', '/', os.getcwd()) + '/' FRONIMO = 'c:/apps/fronimo/fronimo.exe' FRONPDF = '-pt "Adobe PDF"' FRONMIDI = '-m' FRONTAB = '-t' WEBROOT = 'c:/website' TXT = '.txt' TABROOT = CURRDIR + '/tabs' ERRROOT = CURRDIR + '/mpuerr' ERRFILE= ERRROOT + TXT PDFTEMP = 'c:/temp/PDF' MIDITEMP = 'c:/apps/midicat' MIDI3SEC = 'c:/apps/dosbox/dosbox.exe -c "midicat -beat 6 ' # Don't try to duplicate these directories in tabs directory. BADDIRS = ['midi', 'tabs', 'pdf', 'other', 'videos', 'TEMP', 'old_dft.pls', 'fronimo', 'images', 'icons', 'index_files', 'ftp', 'facsimiles', 'making_lute_music_accessible_files', 'german', 'composers.old', 'sources.old'] # end Globals #Functions # for current func name, specify n = 0 or no argument. # for name of caller of current func, specify 1. # for name of caller of caller of current func, specify 2. etc. funcName = lambda n=0: sys._getframe(n + 1).f_code.co_name callerName = lambda n=1: sys._getframe(n + 1).f_code.co_name def removeFile(stFile): try: result = os.remove(stFile) except OSError: print("In ", callerName(), ": OSError: ", result, ". Cannot remove ", stFile, ".\n", file=sys.stderr) return False except: print("In", callerName(), ": Other error. Cannot remove ", stFile, ".\n", file=sys.stderr) return False return True # end removeFile # Checks if is newer than def newer(source, target): #If target doesn't exist source counts as newer if not(os.path.isfile(target)): return True if (os.path.getmtime(source) > os.path.getmtime(target)): # get rid of older file if not removeFile(target): # if we can't get rid of it, we will count the old file as "newer" # so as to avoid processing it further # error code will tag the problem return False return True else: return False # END newer # removeAncient function def removeAncient(currDir): arRemove = [] # Check for strays in child directories # First get list of FT3s and snarf everything except the base name reFt3 = re.compile(r'^.*[\\/](.*?)\.ft3$') # use a dict generator for faster lookup arFt3 = {reFt3.sub(r'\1', f):1 for f in glob.glob(os.path.join(currDir, "*.ft3"))} dirPdf = os.path.join(currDir, 'pdf') if os.path.exists(dirPdf): rePdf = re.compile(r'^.*[\\/](.*)\.pdf$') pdfs = glob.glob(os.path.join(dirPdf, '*.pdf')) #pprint(pdfs) for f in pdfs: pdf = rePdf.sub(r'\1', f) #print("[%s] [%s]" % (f, pdf)) if pdf not in arFt3: # the base of the PDF file does exist in the dict of FT3 bases #print("removing " + f) arRemove.append(f) #pprint(arRemove) dirMid = os.path.join(currDir, 'midi') if os.path.exists(dirMid): reMid = re.compile(r'^.*[\\/](.*)\.mid$') midis = glob.glob(os.path.join(dirMid, '*.mid')) #pprint(midis) for f in midis: mid = reMid.sub(r'\1', f) #print("[%s] [%s]" % (f, mid)) if mid not in arFt3: # the base of the MIDI file does exist in the dict of FT3 bases #print("removing " + f) arRemove.append(f) dirTab = os.path.join(currDir, 'tabs') if os.path.exists(dirTab): reTab = re.compile(r'^.*[\\/](.*)\.tab$') tabs = glob.glob(os.path.join(dirTab, '*.tab')) #pprint(tabs) for f in tabs: tab = reTab.sub(r'\1', f) #print("[%s] [%s]" % (f, tab)) if tab not in arFt3: # the base of the TAB file does exist in the dict of FT3 bases #print("removing " + f) arRemove.append(f) for file in arRemove: if not removeFile(file): continue #end removeAncient # removeStrays function def removeStrays(currDir): arMidiLocal = glob.glob(os.path.join(currDir, "*.mid")) arMidiTemp = glob.glob(os.path.join(MIDITEMP, "*.mid")) arPdfLocal = glob.glob(os.path.join(currDir, "*.pdf")) arPdfTemp = glob.glob(os.path.join(PDFTEMP, "*.pdf")) arRemove = arMidiLocal + arMidiTemp + arPdfLocal + arPdfTemp for file in arRemove: if not removeFile(file): continue #end removeStrays def makeDirectory(newDir): try: result = os.mkdir(newDir) except OSError: print(callerName(),": OSError creating directory ", newDir, " in ", currDir, "result = ", result, "\n", file=sys.stderr) return False except: print(callerName(),": other error creating directory ", newDir, " in ", currDir, ".\n", file=sys.stderr) return False return True # end makeDirectory def fronCmd(fronFile, oType, cDir): command = FRONIMO + " " + fronFile + " " + oType try: result = subprocess.call(command, timeout=6) # result = subprocess.Popen(command).wait() except subprocess.TimeoutExpired: print("fronCmd: ", oType, " creation process on", fronFile, " in ", cDir, " timed out after 6 seconds\n", file=sys.stderr) return False except OSError: print("fronCmd: ", oType, " creation process on ", fronFile, " in ", cDir, "failed. OSError =", result, ".\n", file=sys.stderr) return False except: print("fronCmd: ", oType, " creation process on ", fronFile, " in ", cDir, " failed.\n", file=sys.stderr) return False else: return True # end fronCmd # doPDF function # Creates PDF directory and file, as needed, and puts them in the right place." def doPDF(currDir, fronFile): pdfDir = os.path.join(currDir, "pdf") # Check if the current directory has a pdf sub-directory if not(os.path.isdir(pdfDir)): if not makeDirectory(pdfDir): return False fronPath = os.path.join(currDir, fronFile) pdfFile=fronFile.replace(".ft3", ".pdf") #peculiarity of pdf "printer" that it writes to temp folder pdfSrc = os.path.join(PDFTEMP, pdfFile) pdfDest = os.path.join(pdfDir, pdfFile) if newer(fronPath, pdfDest): # Make PDF file and place it in temp folder if not fronCmd(fronPath, FRONPDF, currDir): return False while not (os.path.isfile(pdfSrc)): time.sleep(0.1) # Move new PDF file to pdf directory from temporary location if not moveFile(pdfSrc, pdfDest): return False while not (os.path.isfile(pdfDest)): time.sleep(0.1) return True else: return False # end doPDF # doMidi function # Creates midi file, if needed, and puts it in the right place." def doMidi(currDir, fronFile): makeMidi = 0 midiDir = os.path.join(currDir, "midi") # Check if the current directory has a midi sub-directory if not os.path.isdir(midiDir): if not makeDirectory(midiDir): return False midiRoot = fronFile.replace(".ft3", "") fronPath = os.path.join(currDir, fronFile) absFron = os.path.abspath(fronPath) singleMidi = os.path.join(currDir, midiRoot) + ".mid" midiDest = os.path.join(midiDir, midiRoot) + ".mid" if not newer(fronPath, midiDest): return False # Fronimo -m writes midi file[s] to current directory # Make midi file[s] and place it/them in currDir if not fronCmd(fronPath, FRONMIDI, currDir): return False # check if we need to concatenate the midi files # if we have one simply ending in .mid, we don't if (os.path.isfile(singleMidi)): # newer() should have removed old file already from midi directory # Put it in the midi directory if not moveFile(singleMidi, midiDest): return False else: # otherwise, create one by concatenating the files. # and make a note that we have done so. print("Attn: More than one section for file ", fronPath, ".\n",file=sys.stderr) if not midiCat(currDir, midiRoot): print("af midiCat:cannot concatenate section midi files for ", fronPath, ".\n",file=sys.stderr) return False return True # end doMidi # midiCat takes Fronimo output from sections, concatenates it necessary, # and puts the concatenated file in the midi directory def midiCat(cDir, mRoot): stDosList = "" globArg = os.path.join(cDir, mRoot) globArg += "[0-9]*.mid" arMidis = glob.glob(globArg) if len(arMidis) <=1: print("midiCat: not enough arguments creating midis; globArgs= ", globArg, ".\n", file=sys.stderr) sys.stderr.flush() return False arMidis.sort() # moves generated by fronimo to MIDITEMP/[0-9]*.mid flCount = 0 for fl in arMidis: stDos = "%d.mid"%flCount stDest = os.path.join(MIDITEMP,stDos) if not moveFile(fl, stDest): continue stDosList += stDos + " " flCount += 1 stDosList = stDosList.rstrip() # puts concatenation result in MIDITMP/out.mid catCmd = MIDI3SEC + stDosList + " out.mid\" -c exit > NUL" try: subprocess.call(catCmd) except OSError: print("midiCat:OSError concatenating ", stDosList, " into ", "out.mid.\n", file=sys.stderr) return False except: print("midiCat:Other error concatenating", stDosList, " into ", "out.mid.\n", file=sys.stderr) return False midiSrc = os.path.join(MIDITEMP, "out.mid") while not (os.path.isfile(midiSrc)): time.sleep(0.1) midiDir = os.path.join(cDir, "midi") midiDest = os.path.join(midiDir, mRoot) midiDest = midiDest + ".mid" if not moveFile(midiSrc, midiDest): return False return True #End midiCat # Open error file def open_err(): # First, save old error file if it exists (save up to 10) if os.path.isfile(ERRFILE): #check old error files reErr = ERRROOT + '[0-9]' + TXT arErr = glob.glob(reErr) maxNum = 0 for f in arErr: num = int(f[-5]) if num > maxNum: maxNum = num if maxNum == 9: #Shuffle error files to make room for i in range(9): os.rename(ERRROOT + str(i+1) + TXT, ERRROOT + str(i) + TXT) os.rename(ERRFILE, ERRROOT + str(maxNum + 1) + TXT) sys.stderr.close() try: sys.stderr = open(ERRFILE, "w") except OSError: print ("OSError: Cannot open error File ", ERRFILE, " for writing.\n") return False except: print ("Other error: Cannot open error File ",ERRFILE," for writing.\n") return False return True # End open_err def getargs(argv): argc = len(argv) if argc == 1: # website directory is default starting place sDir = WEBROOT elif argc == 2: # or a starting directory specified on the command line. sDir = argv[1] else: print("Usage: argv[0] [single directory name].\n", file=sys.stderr) return("") if not (os.path.isdir(sDir)): print(sDir, " is not a directory.\n", file=sys.stderr) print("Usage: argv[0] [single directory name].\n", file=sys.stderr) return("") return(sDir) # End getArgs def moveFile(src, dest): # remove older file if it exists result = 0 if os.path.exists(dest): if not removeFile(dest): return False # Put new file in place try: result = os.rename(src, dest) except OSError: print(callerName(), ": OSError moving ", src, " to ", dest, " . OSError =", result, "\n", file=sys.stderr) return False except: print(callerName(), ": other error moving ", src, " to ", dest, ".\n", file=sys.stderr) return False else: return True # end MoveFile def copyFile(src, dest): # remove older file if it exists if not os.path.exists(src): print(callerName(), src, 'does not exist.') return False if os.path.exists(dest): if not removeFile(dest): return False # Put new file in place try: # result = shutil.copyfile(src, dest) result = os.rename(src, dest) except OSError: print(callerName(), ": OSError copying ", src, " to ", dest, " . OSError =", result, "\n", file=sys.stderr) return False except: print(callerName(), ": other error copying ", src, " to ", dest, ".\n", file=sys.stderr) return False else: return True # end copyFile # do_tab function # Creates TAB file, if needed, and puts it in the right place." # This needs to be invoked after doMidi def do_tab(currDir,fronFile): absFron = os.path.join(currDir, fronFile) tabPath=absFron.replace(".ft3", ".tab") tabCurr = currDir.replace(CURRDIR, CURRDIR + 'tabs/') # create directory tree, if needed if not os.path.isdir(tabCurr): os.makedirs(tabCurr) absTab = tabPath.replace(CURRDIR, TABROOT + '/') absMidi = absTab.replace(".tab", ".mid") # only process new .ft3s if newer(absFron, absTab): # tab file older or nonexistent # but has midi file been generated instead? # and is it older? if not newer(absFron,absMidi): return False else: # fronimo file not changed, so no need to generate tab file. return False # Make TAB file and place it in currDir if not fronCmd(absFron, FRONTAB, currDir): # if fronimo bombed return False # If fronimo did create a tab file if (os.path.exists(tabPath)): # Move it to the right place if not moveFile(tabPath, absTab): return False # Fronimo did not generate a tab file. else: # So copy the midi file instead. midiFile = fronFile.replace(".ft3", ".mid") midiDir = os.path.join(currDir, "midi") midiSrc = os.path.join(midiDir, midiFile) # Is there a midi file already in place (there should be)? # because we just did doMidi if (os.path.exists(midiSrc)): # yes, so copy it to the right place if not copyFile(midiSrc, absMidi): print(callername(), 'Cannot create TAB file.') return False else: # no, so complain print(midiSrc, " does not exist.\n", file=sys.stderr) return False return True # end do_tab # Walk the main directory tree def walk_tree(sDir): oldDir = "" tabCount = 0 midiCount = 0 pdfCount = 0 for root, dirs, files in os.walk(sDir): # Only when changing root directories do we collect a list of .ft3 files if root == oldDir: continue # Now we have a new "old directory" oldDir = root locDir = os.path.basename(root) # Won't find any .ft3 files in directory trees starting with BADDIRS # so don't make a directory in the tabs hierarchy # or try to process these for target in BADDIRS: result = root.find("\\" + target) if result != -1: break if result != -1: continue # Get a list of .ft3 files in this directory ft3s = [f for f in files if f.endswith('.ft3')] # Process each .ft3 file in the list. removeAncient(root) for fname in ft3s: if doMidi(root, fname): midiCount += 1 if do_tab(root, fname): tabCount += 1 if doPDF(root, fname): pdfCount += 1 # end for fname in ft3s # end if root != oldDir # After walking the directories. arCounts = [tabCount, midiCount, pdfCount] return(arCounts) # end walk_tree # print stats. def printStats(sTime, arCounts): endTime = int(time.time()) elapsedTime = endTime - sTime elapsedSeconds = elapsedTime % 3600 elapsedHours = int((elapsedTime - elapsedSeconds) / 3600) elapsedMinutes = elapsedSeconds / 60 elapsedSeconds = elapsedSeconds % 60 elapsedMinutes = int(elapsedMinutes - elapsedSeconds / 60) print("Update completed.\n", arCounts[0], " TAB files ",\ arCounts[1], " midi files and ", arCounts[2],\ " PDF files\nCreated in ", elapsedHours, " hours, ",\ elapsedMinutes, "minutes, and ", elapsedSeconds, "secs.") print("Type a key to exit: ") input() # end printStats def main(): # put TEMP file in startDir for Fronimo PDF output # Make sure that Adobe PDF output is set to "/*.pdf" # And that View Adobe PDF results is unchecked. # print("Is ADOBE PDF output set to ", PDFTEMP, "\\*.pdf\" in \"printing preferences\"\n", "and is \"View Adobe PDF Results\" unchecked, and Fronimo not running?(y/n)") # answer = input() # if (answer != "y"): sys.exit(0) startTime = int (time.time()) # Get start directory from command line # startDir = getargs(sys.argv) startDir = CURRDIR if startDir == "": sys.exit(0) if not open_err(): sys.exit(1) # Make a tab directory if not already there if not(os.path.isdir(TABROOT)): if not makeDirectory(TABROOT): print(" in ", funcName(), ": cannot make directory ", TABROOT, ".\n", file=sys.stderr) return False arCounts = walk_tree(startDir) printStats(startTime, arCounts) # end Main if __name__ == "__main__": main()