diff options
author | Eugene Sandulenko | 2018-12-25 12:37:23 +0100 |
---|---|---|
committer | Eugene Sandulenko | 2018-12-25 12:37:23 +0100 |
commit | 1f6727eab85c8f544718deba6a820e1b71ee5c93 (patch) | |
tree | 5d86c27377baa8fac79ced213a8fe4b21a3a1344 /devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py | |
parent | b6e93680f449b6d988aeceac0c0a58218b2992d0 (diff) | |
download | scummvm-rg350-1f6727eab85c8f544718deba6a820e1b71ee5c93.tar.gz scummvm-rg350-1f6727eab85c8f544718deba6a820e1b71ee5c93.tar.bz2 scummvm-rg350-1f6727eab85c8f544718deba6a820e1b71ee5c93.zip |
DEVTOOLS: Rename blade_runner to create_bladerunner
Diffstat (limited to 'devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py')
-rw-r--r-- | devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py | 722 |
1 files changed, 722 insertions, 0 deletions
diff --git a/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py new file mode 100644 index 0000000000..4bc5bb7e23 --- /dev/null +++ b/devtools/create_bladerunner/subtitles/quotesSpreadsheetCreator/sortBladeRunnerWavs02.py @@ -0,0 +1,722 @@ +#!/usr/bin/python +# -*- coding: UTF-8 -*- +# +# Created by Praetorian (ShadowNate) for Classic Adventures in Greek +# classic.adventures.in.greek@gmail.com +# +# TODO update README +# TODO test recreation of TRE file (Especially in Credits which the original has a few special characters (font delegates)) +# +# DONE Add code and switch option: to get the blade runner installation directory as input, then find the TLK files and extract them with proper naming +# DONE fix proper names for sheets as per latest code changes +# +import os, sys, shutil +from os import walk, errno +import xlwt +import csv +import os.path +from xlwt import * +from audFileLib import * +from treFileLib import * + +# encoding=utf8 +#reload(sys) +#sys.setdefaultencoding('utf8') + +company_email = "classic.adventures.in.greek@gmail.com" +app_version = "0.50" +app_name = "sortBladeRunnerWavs" +app_name_spaced = "Sort Blade Runner Audio Speech Files" +stringReplacementForRootFolderWithExtractedFiles = "" +numReplaceStartingCharacters = 0 + +OUTPUT_XLS_FILENAME = 'out.xls' +OUTPUT_XLS_QUOTES_SHEET = 'INGQUO_E.TRE' + +supportedTLKInputFiles = [('1.TLK', 'TLK01'), ('2.TLK', 'TLK02'), ('3.TLK', 'TLK03'), ('A.TLK', 'TLK0A'), ('SPCHSFX.TLK', 'TLKSPCHSFX')] +supportedMIXInputFiles = ['STARTUP.MIX'] +# 15 TRE files +supportedExportedTREFiles = ['CLUES.TRE','ACTORS.TRE','CRIMES.TRE','CLUETYPE.TRE','KIA.TRE','SPINDEST.TRE','VK.TRE','OPTIONS.TRE','DLGMENU.TRE','ENDCRED.TRE','HELP.TRE','SCORERS.TRE','KIACRED.TRE','ERRORMSG.TRE','AUTOSAVE.TRE'] + +wavfiles = [] +wavfilesNoDups = [] +actorPropertyEntries = [] #[0]:id, [1]:ShortHand Name [2]:Full Name +actorPropertyEntriesWasInit = False + + +# strFileName should be the full file name (including extension) +def calculateFoldHash(strFileName): + i = 0 + hash = 0 + strParam = strFileName.upper() + lenFileName = len(strParam); + while i < lenFileName and i < 12: + groupSum = 0 + # work in groups of 4 bytes + for j in range(0, 4): + # LSB first, so the four letters in the string are re-arranged (first letter goes to lower place) + groupSum >>= 8; + if (i < lenFileName): + groupSum |= (ord(strParam[i]) << 24) + i += 1 + else: # if i >= lenFileName but still haven't completed the four byte loop add 0s + groupSum |= 0 + hash = ((hash << 1) | ((hash >> 31) & 1)) + groupSum + hash &= 0xFFFFFFFF # mask here! + #print (strParam +': ' +''.join('{:08X}'.format(hash))) + return hash + +# Fill the actorPropertyEntries table +def initActorPropertyEntries(): + global actorPropertyEntriesWasInit + global actorPropertyEntries + firstLine = True +# print "opening actornames" + with open("./actornames.txt") as tsv: + for line in csv.reader(tsv, dialect="excel-tab"): + #skip first line header + if firstLine == True: +# print "skippingHeader" + firstLine = False + else: + actorPropertyEntries.append(line) + actorPropertyEntriesWasInit = True + tsv.close() + +def getActorShortNameById(lookupActorId): + global actorPropertyEntriesWasInit + global actorPropertyEntries + if not actorPropertyEntriesWasInit: + return '' + else: + for actorEntryTmp in actorPropertyEntries: + if int(actorEntryTmp[0]) == int(lookupActorId): + return actorEntryTmp[1] + return '' + + +def getActorFullNameById(lookupActorId): + global actorPropertyEntriesWasInit + global actorPropertyEntries + if not actorPropertyEntriesWasInit: + return '' + else: + for actorEntryTmp in actorPropertyEntries: + if int(actorEntryTmp[0]) == int(lookupActorId): + return actorEntryTmp[2] + return '' + +def getActorIdByShortName(lookupActorShortName): + global actorPropertyEntriesWasInit + global actorPropertyEntries + if not actorPropertyEntriesWasInit: + return '' + else: + for actorEntryTmp in actorPropertyEntries: + if actorEntryTmp[1] == lookupActorShortName: + return actorEntryTmp[0].zfill(2) + return '' + +def getActorShortNameAndLocalQuoteIdByAUDHashID(audHashId): + actorId = 0 + actorShortName = '' + actorLocalQuoteId = 0 + if not actorPropertyEntriesWasInit: + print "Error actor properties were not initialized!" + return (actorId, actorShortName, actorLocalQuoteId) + + for actorEntryTmp in actorPropertyEntries: + if( (audHashId - (int(actorEntryTmp[0]) * 10000) ) >= 0) and ((audHashId - (int(actorEntryTmp[0]) * 10000)) < 10000): + actorId = int(actorEntryTmp[0]) + actorShortName = actorEntryTmp[1] + actorLocalQuoteId = audHashId - (actorId * 10000) + return (actorId, actorShortName, actorLocalQuoteId) + return (actorId, actorShortName, actorLocalQuoteId) + +# Aux. Ensure existence of output directory +def ensure_dir(directory): + try: + os.makedirs(directory) + except OSError as e: + if e.errno != errno.EEXIST: + raise + +# +# Reading in the INPUT TLK files and checking all the AUD file properties +# +def inputTLKsExtract(inputTLKpath, outputWAVpath): + # try to open all TLK file entries from supportedTLKInputFiles + # then per TLK file + # create an output folder in the OUTPUT PATH named TLK## for the 1, 2, 3 TLK and TLKSPCHSFX for the SPCHSFX.TLK + # printout: + # total entries + # total data size + # and per entry the + # fileID + # segment offset + # file size + print "Checking in %s for TLK files to extract to %s" % (inputTLKpath, outputWAVpath) + inputTLKFilesFound = [] + # breaking after first for loop yields only the top directory files, which is what we want + for (dirpath, dirnames, filenames) in walk(inputTLKpath): + for filename in filenames: + for tlkTuple in supportedTLKInputFiles: + if filename.upper() == tlkTuple[0]: + inputTLKFilesFound.append(tlkTuple) + break + for tmpTLKfileTuple in inputTLKFilesFound: + print "Found TLK: %s" % ('"' + inputTLKpath + tmpTLKfileTuple[0] + '"') + errorFound = False + inTLKFile = None + # + # Create output folder if not exists at output path + print "Ensuring output directory %s" % (os.path.join(outputWAVpath, tmpTLKfileTuple[1] )) + ensure_dir(os.path.join(outputWAVpath, tmpTLKfileTuple[1] ) ) + try: + inTLKFile = open(os.path.join(inputTLKpath,tmpTLKfileTuple[0]), 'rb') + except: + errorFound = True + print "Unexpected error:", sys.exc_info()[0] + raise + if not errorFound: + tmpBuff = inTLKFile.read(2) + # H: unsigned short (2 bytes) followed by I: unsigned int (4 bytes) + tlkFileEntriesNumTuple = struct.unpack('H', tmpBuff) + numOfEntriesToExtract = tlkFileEntriesNumTuple[0] + tmpBuff = inTLKFile.read(4) + tlkFileDataSegmentSizeTuple = struct.unpack('I', tmpBuff) + allTlkFileSize = tlkFileDataSegmentSizeTuple[0] + inTLKFile.seek(0, 2) # go to file end + allActualBytesInMixFile = inTLKFile.tell() + inTLKFile.seek(6, 0) # go to start of table of TLK file entries (right after the 6 bytes header) + # 2 + 4 = 6 bytes short MIX header + # 12 bytes per TLK entry in entries table + # quick size validation + print "Entries: %d, data segment %d bytes" % (numOfEntriesToExtract, allTlkFileSize) + if allActualBytesInMixFile != 2 + 4 + 12 * numOfEntriesToExtract + allTlkFileSize: + print "Error: TLK file size mismatch with reported size in header for %s!" % (tmpTLKfileTuple[0]) + else: + # + # 12 bytes per entry + # 4 bytes: ID + # 4 bytes: Offset in data segment + # 4 bytes: Size of data + # + for i in range(0, numOfEntriesToExtract): + inTLKFile.seek(2 + 4 + 12*i) + tmpBuff = inTLKFile.read(4) + tmpRdTuple = struct.unpack('I', tmpBuff) + idOfAUDEntry = tmpRdTuple[0] + tmpBuff = inTLKFile.read(4) + tmpRdTuple = struct.unpack('I', tmpBuff) + offsetOfAUDEntry = tmpRdTuple[0] + tmpBuff = inTLKFile.read(4) + tmpRdTuple = struct.unpack('I', tmpBuff) + sizeOfAUDEntry = tmpRdTuple[0] + print "Entry: %s, offset %s, data segment %s bytes" % (''.join('{:08X}'.format(idOfAUDEntry)), ''.join('{:08X}'.format(offsetOfAUDEntry)),''.join('{:08X}'.format(sizeOfAUDEntry))) + # + # put file in AUD object + # do we need AUD decode? + # create WAV from AUD + # write WAV to appropriate output folder + # Figure out proper naming for file + # then: + # AudFile aud; + # aud.loadAudFile(fs); (fs is file stream) + # aud.extract_as_wav(fs, offset, offset + int(sizeof(AudHeader)) + aud.header().size_in, target); + # + # + inTLKFile.seek(2 + 4 + 12*numOfEntriesToExtract + offsetOfAUDEntry) + if(offsetOfAUDEntry + sizeOfAUDEntry > allTlkFileSize): + print "Error: AUD file size mismatch with reported size in entry header!" + else: + audFileBuffer = inTLKFile.read(sizeOfAUDEntry) + if (len(audFileBuffer) == sizeOfAUDEntry): + # load Aud file + thisAudFile = audFile() + if (thisAudFile.loadAudFile(audFileBuffer, allTlkFileSize)): + # print "AUD file load successful!" + # find + # print "Emulating Wav write to appropriate folder..." + (actorID, actorSName, localQuoteId) = getActorShortNameAndLocalQuoteIdByAUDHashID(idOfAUDEntry) + targetSimpleFileName = actorSName + '_' + str(localQuoteId).zfill(4) + '_' + ''.join('{:08X}'.format(idOfAUDEntry)).upper()+'.WAV' + #print os.path.join(outputWAVpath, tmpTLKfileTuple[1], targetSimpleFileName) + if not os.path.isfile(os.path.join(outputWAVpath, tmpTLKfileTuple[1], targetSimpleFileName) ): + thisAudFile.extract_as_wav(audFileBuffer, os.path.join(outputWAVpath, tmpTLKfileTuple[1], targetSimpleFileName) ) + else: + print "Output file %s already exists. Skipping..." % (os.path.join(outputWAVpath, tmpTLKfileTuple[1], targetSimpleFileName)) + else: + print "Error while LOADING aud file!" + else: + print "Error while reading AUD file %s into mem buffer" % (''.join('{:08X}'.format(idOfAUDEntry))) + inTLKFile.close() + + + # SYS EXIT IS HERE ONLY FOR DEBUG PURPOSES OF PARSING TLK FILES - SHOULD BE COMMENTED OUT NORMALLY + # sys.exit(0) + return + +def inputMIXExtractTREs(inputMIXpath, excelOutBook = None): + print "Checking in %s for MIX files to extract TRE's from" % (inputMIXpath) + inputMIXFilesFound = [] + # breaking after first for loop yields only the top directory files, which is what we want + for (dirpath, dirnames, filenames) in walk(inputMIXpath): + for filename in filenames: + for mixFileName in supportedMIXInputFiles: + if filename.upper() == mixFileName: + inputMIXFilesFound.append(mixFileName) + break + for tmpMIXfileName in inputMIXFilesFound: + print "Found MIX: %s" % ('"' + inputMIXpath + tmpMIXfileName + '"') + errorFound = False + inMIXFile = None + # + try: + inMIXFile = open(os.path.join(inputMIXpath,tmpMIXfileName), 'rb') + except: + errorFound = True + print "Unexpected error:", sys.exc_info()[0] + raise + if not errorFound: + totalTREs = 0 + tmpBuff = inMIXFile.read(2) + # H: unsigned short (2 bytes) followed by I: unsigned int (4 bytes) + mixFileEntriesNumTuple = struct.unpack('H', tmpBuff) + numOfEntriesToExtract = mixFileEntriesNumTuple[0] + tmpBuff = inMIXFile.read(4) + mixFileDataSegmentSizeTuple = struct.unpack('I', tmpBuff) + allMixFileSize = mixFileDataSegmentSizeTuple[0] + inMIXFile.seek(0, 2) # go to file end + allActualBytesInMixFile = inMIXFile.tell() + inMIXFile.seek(6, 0) # go to start of table of MIX file entries (right after the 6 bytes header) + # 2 + 4 = 6 bytes short MIX header + # 12 bytes per MIX entry in entries table + # quick size validation + print "Entries: %d, data segment %d bytes" % (numOfEntriesToExtract, allMixFileSize) + if allActualBytesInMixFile != 2 + 4 + 12 * numOfEntriesToExtract + allMixFileSize: + print "Error: MIX file size mismatch with reported size in header for %s!" % (tmpMIXfileName) + else: + # + # 12 bytes per entry + # 4 bytes: ID + # 4 bytes: Offset in data segment + # 4 bytes: Size of data + # + for i in range(0, numOfEntriesToExtract): + foundTREFile = False + currTreFileName = 'UNKNOWN.TRE' + inMIXFile.seek(2 + 4 + 12*i) + tmpBuff = inMIXFile.read(4) + tmpRdTuple = struct.unpack('I', tmpBuff) + idOfMIXEntry = tmpRdTuple[0] + tmpBuff = inMIXFile.read(4) + tmpRdTuple = struct.unpack('I', tmpBuff) + offsetOfMIXEntry = tmpRdTuple[0] + tmpBuff = inMIXFile.read(4) + tmpRdTuple = struct.unpack('I', tmpBuff) + sizeOfMIXEntry = tmpRdTuple[0] + + for suppTREFileName in supportedExportedTREFiles: + if(idOfMIXEntry == calculateFoldHash(suppTREFileName)): + foundTREFile = True + currTreFileName = suppTREFileName + break + + if (foundTREFile == True): + print "Entry Name: %s, Entry ID: %s, offset %s, data segment %s bytes" % (currTreFileName, ''.join('{:08X}'.format(idOfMIXEntry)), ''.join('{:08X}'.format(offsetOfMIXEntry)),''.join('{:08X}'.format(sizeOfMIXEntry))) + # + # IF TRE FILE: + # put file in TRE object + # + # + inMIXFile.seek(2 + 4 + 12*numOfEntriesToExtract + offsetOfMIXEntry) + if(offsetOfMIXEntry + sizeOfMIXEntry > allMixFileSize): + print "Error: TRE file size mismatch with reported size in entry header!" + else: + treFileBuffer = inMIXFile.read(sizeOfMIXEntry) + if (len(treFileBuffer) == sizeOfMIXEntry): + # load TRE file + thisTreFile = treFile() + if (thisTreFile.loadTreFile(treFileBuffer, allMixFileSize)): + print "TRE file loaded" + if excelOutBook != None: + sh = excelOutBook.add_sheet(currTreFileName) + n = 0 # keeps track of rows + col1_name = 'Text Resource File: %s' % (currTreFileName) + sh.write(n, 0, col1_name) + # Second Row + n = 1 + col1_name = 'TextId' + col2_name = 'Text' + sh.write(n, 0, col1_name) + sh.write(n, 1, col2_name) + n+=1 + for m, e1 in enumerate(thisTreFile.stringEntriesLst, n): + sh.write(m, 0, e1[0]) + objStr = e1[1] + #print type (objUTF8SafeStr) # the type is STR here + # python strings are immutable (can't replace characters) but we have an issue with certain special characters in the ORIGINAL TRE (kiacred and endcred) + # (they are out of their order from their proper order in windwos-1252) + # so we need to create a new string. + objUTF8SafeStr = "" + for i in range(0, len(objStr)): + if (objStr[i] == '\x81'): + objUTF8SafeStr += 'ü' + elif (objStr[i] == '\x82'): + objUTF8SafeStr += 'é' + else: + objUTF8SafeStr += objStr[i] + #objUTF8Safe = objUTF8Safe.replace('\x81',u'u') #'ü' # this does not work + #objUTF8Safe = objUTF8Safe.replace('\x82',u'e') #'é' # this does not work + objUTF8Unicode = unicode(objUTF8SafeStr, 'utf-8') + sh.write(m, 1, objUTF8Unicode) + + + #for tupleIdString in thisTreFile.stringEntriesLst: + # #print "Id: %d\t Text: %s" % (tupleIdString[0], tupleIdString[1]) + # pass + totalTREs = totalTREs + 1 + else: + print "Error while LOADING TRE file!" + else: + print "Error while reading TRE file %s into mem buffer" % (''.join('{:08X}'.format(idOfMIXEntry))) + inMIXFile.close() + print "Total TREs: %d " % (totalTREs) + return + + +# +# Creating the OUTPUT XLS file with one sheet named as the @param sheet with entries based on the list1 (wav files, without duplicates) +# +def outputXLS(filename, sheet, list1, parseTREResourcesAlso = False, mixInputFolderPath = ''): + global stringReplacementForRootFolderWithExtractedFiles + global numReplaceStartingCharacters + book = xlwt.Workbook() + sh = book.add_sheet(sheet) +# First Row + n = 0 # keeps track of rows +# variables = [x, y, z] +# x_desc = 'Display' +# y_desc = 'Dominance' +# z_desc = 'Test' +# desc = [x_desc, y_desc, z_desc] +# +# +# #You may need to group the variables together +# #for n, (v_desc, v) in enumerate(zip(desc, variables)): +# for n, (v_desc, v) in enumerate(zip(desc, variables)): +# sh.write(n, 0, v_desc) +# sh.write(n, 1, v) + col1_name = 'BladeRunnerTLK In-Game dialogue / voiceover quotes' + sh.write(n, 0, col1_name) +# Second Row + n = 1 + col1_name = 'Filename' + col2_name = 'Quote' + col3_name = 'By Actor' + col4_name = 'Notes' + col5_name = 'To Actor' + col6_name = 'Resource' + col7_name = 'ShortHandFileName' + + sh.write(n, 0, col1_name) + sh.write(n, 1, col2_name) + sh.write(n, 2, col3_name) + sh.write(n, 3, col4_name) + sh.write(n, 4, col5_name) + sh.write(n, 5, col6_name) + sh.write(n, 6, col7_name) + + n+=1 + + for m, e1 in enumerate(list1, n): + twoTokensOfRelDirnameAndFilenameXLS = e1.split('&', 2) + if len(twoTokensOfRelDirnameAndFilenameXLS) == 3: + fourTokensOfFilename = twoTokensOfRelDirnameAndFilenameXLS[0].split('#', 3) + if len(fourTokensOfFilename) == 4: + # fix rogue _ chars in 3rd token of filename (split at '_') + tmpAUDFileName = fourTokensOfFilename[0] + '-' + fourTokensOfFilename[1] + '.AUD' + #ActorId-QuoteId.AUD + sh.write(m, 0, tmpAUDFileName) + twoTokensOfQuote = fourTokensOfFilename[2].split('-', 1) + if len(twoTokensOfQuote) == 2: + #Quote + sh.write(m, 1, twoTokensOfQuote[1]) + else: + #Quote + sh.write(m, 1, fourTokensOfFilename[2]) + #Notes + sh.write(m, 3, 'TODO') + #byActor + sh.write(m, 2, fourTokensOfFilename[3]) + #ResourceFolder + sh.write(m, 5, twoTokensOfRelDirnameAndFilenameXLS[1]) + #ShortHandFileName + tmpActorShortHand = getActorShortNameById(fourTokensOfFilename[0]) + shortHandFileName = tmpActorShortHand + '_' + fourTokensOfFilename[1] + '_' + fourTokensOfFilename[2] + '.WAV' + # real path of filename + realPathOfFileNameToLink = twoTokensOfRelDirnameAndFilenameXLS[2] + # checks if not empty + if stringReplacementForRootFolderWithExtractedFiles and numReplaceStartingCharacters > 0: + realPathOfFileNameToLink = realPathOfFileNameToLink.replace(realPathOfFileNameToLink[:numReplaceStartingCharacters], stringReplacementForRootFolderWithExtractedFiles) + + #works in Linux + Libreoffice + # also works in Windows + LibreOffice (run from msys) -- tried something like: + # python sortBladeRunnerWavs.py -p /g/WORKSPACE/BladeRunnerWorkspace/br-mixer-master/data/WAV -m "G:/WORKSPACE/BladeRunnerWorkspace/br-mixer-master/data/WAV" + #TODO put real full path for each file as FILE URL, and real (or approximate shorthand file name as alias) + hyperlinkAudioFormula = 'HYPERLINK("file://%s","%s")' % (realPathOfFileNameToLink, shortHandFileName) + sh.write(m, 6, Formula(hyperlinkAudioFormula)) + else: + sh.write(m, 0, e1) + #Notes + sh.write(m, 3, 'error') + else: + sh.write(m, 0, e1) + #Notes + sh.write(m, 3, 'error') + + + # works for filenames where some rogue greek characters exist + #sh.write(m, 0, str.decode("%s" % e1, 'utf-8')) + +# for m, e2 in enumerate(list2, n+1): +# sh.write(m, 1, e2) + + if parseTREResourcesAlso == True and mixInputFolderPath != '': + inputMIXExtractTREs(mixInputFolderPath, book) + # TODO add sheets + # TODO handle special string characters (to UTF-8) + + book.save(filename) + +# +# +# +# ######################## +# main +# 00_0000 -- DealsInInsects dupl TLK01, TLK0A +# 00_0510 -- ThinkingOfChangingJobs-Leon dupl TLK02, TLK03 +# 00-8520 -- WhatDoYouKnow dupl TLK01, TLK0A + +# Total unique quotes seems to be 5495! +# TODO rename files in folders to conform to the underscore '_' and '-' format (a few don't -- let's have them all conforming!) +# ######################### +# +if __name__ == "__main__": + TMProotFolderWithExtractedFiles = "" + TMProotFolderWithInputTLKFiles = "" + + extractWavFilesMode = False + extractTreFilesMode = False + + invalidSyntax = False +# print "Len of sysargv = %s" % (len(sys.argv)) + if len(sys.argv) == 2: + if(sys.argv[1] == '--help'or sys.argv[1] == '-h'): + print "%s %s supports Blade Runner (English version, CD edition)." % (app_name_spaced, app_version) + print "Created by Praetorian of the classic adventures in Greek team." + print "Always keep backups!" + print "--------------------" + print "Preparatory steps:" + print "1. Put actornames.txt file in the same folder with this tool." + print "--------------------" + print "%s takes has one mandatory argument, the folder of the extracted WAV files:" % (app_name_spaced) + print "Valid syntax: %s -ip [folderpath_for_TLK_Files] -op [folderpath_for_extracted_wav_Files] -m [stringPathToReplaceFolderpathInExcelLinks]" % (app_name) + print "The -op switch has an argument that is the path for extracted WAV files folder. The -op switch is REQUIRED always." + print "The -ip switch has an argument that is the path for the input (TLK or MIX) files folder (can be the same as the Blade Runner installation folder)." + print "The -m switch has an argument that is a replacement string for the path to the folder of extracted WAV files which will be used as a prefix for the links in the output XLS file." + print "The -xwav switch enables the WAV audio extract mode from the TLK files. It requires an INPUT path to be set with the -ip switch." + print "The -xtre switch enables the TRE parsing mode from the original MIX files. It requires an INPUT path to be set with the -ip switch." + print "If the app finishes successfully a sortedWavs.xls file will be created in the same folder with the app." + print "--------------------" + print "Thank you for using this app." + print "Please provide any feedback to: %s " % (company_email) + sys.exit() + elif(sys.argv[1] == '--version' or sys.argv[1] == '-v'): + print "%s %s supports Blade Runner (English version, CD edition)." % (app_name_spaced, app_version) + print "Please provide any feedback to: %s " % (company_email) + sys.exit() + else: + invalidSyntax = True + elif len(sys.argv) > 2: + for i in range(1, len(sys.argv)): + if( i < (len(sys.argv) - 1) and sys.argv[i][:1] == '-' and sys.argv[i+1][:1] != '-'): + if (sys.argv[i] == '-op'): + TMProotFolderWithExtractedFiles = sys.argv[i+1] + numReplaceStartingCharacters = len(TMProotFolderWithExtractedFiles) + elif (sys.argv[i] == '-ip'): + TMProotFolderWithInputTLKFiles = sys.argv[i+1] + elif (sys.argv[i] == '-m'): + stringReplacementForRootFolderWithExtractedFiles = sys.argv[i+1] + elif (sys.argv[i] == '-xwav'): + print "Extract WAVs from TLK files mode enabled." + extractWavFilesMode = True + elif (sys.argv[i] == '-xtre'): + print "Extract TRE mode enabled." + extractTreFilesMode = True + if not TMProotFolderWithExtractedFiles: # this argument is mandatory + invalidSyntax = True + + if (extractWavFilesMode == True or extractTreFilesMode == True) and (TMProotFolderWithInputTLKFiles == ''): + invalidSyntax = True + + if not invalidSyntax: + + # parse Actors files: + initActorPropertyEntries() +# for actorEntryTmp in actorPropertyEntries: +# print "Found actor: %s %s %s" % (actorEntryTmp[0], actorEntryTmp[1], actorEntryTmp[2]) + # + # Checking for the optional case of parsing the input TLK files to extract to WAV + # + if TMProotFolderWithInputTLKFiles != '': + if (extractWavFilesMode == True): + inputTLKsExtract(TMProotFolderWithInputTLKFiles, TMProotFolderWithExtractedFiles) + #if (extractTreFilesMode == True): + # inputMIXExtractTREs(TMProotFolderWithInputTLKFiles) + # + # Parsing the extracted WAV files + # + print "Parsing the extracted WAV audio files. Please wait (it could take a while)..." + for (dirpath, dirnames, filenames) in walk(TMProotFolderWithExtractedFiles): + for nameIdx, nameTmp in enumerate(filenames): + relDirName = '' +# os.path.split would Split the pathname path into a pair, (head, tail) where tail is the last pathname component and head is everything leading up to that. The tail part will never contain a slash + pathTokens = dirpath.split(os.path.sep) + for pTokenTmp in pathTokens: + if pTokenTmp.find("TLK") != -1: + relDirName = pTokenTmp +# print os.path.dirname(dirpath) +# print os.path.abspath(os.path.join(os.path.join(dirpath, nameTmp), os.pardir)) + filenames[nameIdx] = filenames[nameIdx] +'&' + relDirName + '&' + os.path.join(dirpath, nameTmp) + wavfiles.extend(filenames) +# break + for fileIdx, filenameTmp in enumerate(wavfiles): + twoTokensOfFilenameAndRelDirname = filenameTmp.split('&', 1) + if len(twoTokensOfFilenameAndRelDirname) != 2: + print "ERROR in filename and rel dirname split: %s" % (filenameTmp) + sys.exit(0) + twoTokensOfFilenameForExt = twoTokensOfFilenameAndRelDirname[0].split('.', 1) + if len(twoTokensOfFilenameForExt) == 2: + if twoTokensOfFilenameForExt[1] != 'WAV' and twoTokensOfFilenameForExt[1] != 'wav': + print "ERROR in proper extension (not WAV): %s" % (twoTokensOfFilenameAndRelDirname[0]) + sys.exit(0) + else: + print "ERROR in extension split: %s" % (twoTokensOfFilenameAndRelDirname[0]) + sys.exit(0) + #remove WAV extension here +# filenameTmp = twoTokensOfFilenameAndRelDirname[0] + '&' + twoTokensOfFilenameForExt[0] +# print "Found %s" % (filenameTmp) + + threeTokensOfFilename = twoTokensOfFilenameForExt[0].split('_', 2) + if len(threeTokensOfFilename) == 3: + # fix rogue _ chars in 3rd token of filename (split at '_') + threeTokensOfFilename[2] = threeTokensOfFilename[2].replace("_", "-") + # Replace first token + # replace actor name shorthand with ActorID in first part + tmpActorId = getActorIdByShortName(threeTokensOfFilename[0]) + tmpActorFullName = '' + if(tmpActorId != '' and tmpActorId is not None): + tmpActorFullName = getActorFullNameById(tmpActorId) + if(tmpActorFullName != '' and tmpActorFullName is not None): + threeTokensOfFilename[0] = tmpActorId.zfill(2) + threeTokensOfFilename.append(tmpActorFullName) + else: + #fatal error if something cannot convert to spot it immediately + print "ERROR in actorIdMatch match: %s %s" % (tmpActorId, twoTokensOfFilenameForExt[0]) + sys.exit(0) + else: + #fatal error if something cannot convert to spot it immediately + print "ERROR in shorthand match: %s %s" % (threeTokensOfFilename[0], twoTokensOfFilenameForExt[0]) + sys.exit(0) +# +# +# foundMatchForActorShortHand = False +# for actorEntryTmp in actorPropertyEntries: +# if actorEntryTmp[1] == threeTokensOfFilename[0]: +# threeTokensOfFilename[0] = actorEntryTmp[0].zfill(2) +# threeTokensOfFilename.append(actorEntryTmp[2]) +# foundMatchForActorShortHand = True +# break + # end of replace actor name shorthand + twoTokensOfFilenameForExt[0] = '#'.join(threeTokensOfFilename) + filenameTmp = twoTokensOfFilenameForExt[0] + '&' + twoTokensOfFilenameAndRelDirname[1] + wavfiles[fileIdx] = filenameTmp + else: + print "ERROR in spliting tokens on _: %s" % (filenameTmp) + sys.exit(0) + #sort in-place + # + # + wavfiles.sort() +# # +# # +# # Code for renaming non conforming filenames - just to be consistent in file naming +# # TO BE RUN ONCE FOR CONFORMANCE. No NEED TO Re-RUN +# # If its run though, comment this section and re-run the tool to get proper links in Excel file +# # +# for filenameSrcTmp in wavfiles: +# # get real full path from last token when split at & +# # create target full path from the parentdir of last token and the current state of first 3 tokens when splitting at '#' +# # report mismatch +# # print (BUT DON'T PROCEED AT THIS POINT) what you would rename to what. +# threeTokensOfFilenameAndRelDirname = filenameSrcTmp.split('&', 2) +# currentSrcFullPath = threeTokensOfFilenameAndRelDirname[2] +# fourTokensOfTargetFileName = threeTokensOfFilenameAndRelDirname[0].split('#', 3) +# tmpActorShortHand = getActorShortNameById(fourTokensOfTargetFileName[0]) +# targetFileName = tmpActorShortHand + '_' + fourTokensOfTargetFileName[1] + '_' + fourTokensOfTargetFileName[2] + '.WAV' +# # os.path.split would Split the pathname path into a pair, (head, tail) where tail is the last pathname component and head is everything leading up to that. The tail part will never contain a slash +# (srcParentDir, srcTail) = os.path.split(currentSrcFullPath) +# targetFullPath = os.path.join(srcParentDir, targetFileName) +# # os.rename(src, dst) +# if(currentSrcFullPath != targetFullPath): +# print currentSrcFullPath +# print targetFullPath +# os.rename(currentSrcFullPath, targetFullPath) + # + # END OF: Code for renaming non conforming filenames - just to be consistent in file naming + # + # + for filenameSrcTmp in wavfiles: + duplicateFound = False +# print "Converted %s" % (filenameSrcTmp) + # Weed out duplicates by copying to another table (quick and dirty) + twoTokensOfRelDirnameAndFilenameSrc = filenameSrcTmp.split('&', 2) + tmpRelDirNameSrc = twoTokensOfRelDirnameAndFilenameSrc[1] + threeTokensOfQuoteFilenameSrc = twoTokensOfRelDirnameAndFilenameSrc[0].split('#', 2) + #concatenate actorID and quoteID for search key + keyForDuplicateSearchSrc = threeTokensOfQuoteFilenameSrc[0] + threeTokensOfQuoteFilenameSrc[1] + for fileTargIdx, filenameTargTmp in enumerate(wavfilesNoDups): + twoTokensOfRelDirnameAndFilenameTarg = filenameTargTmp.split('&', 2) + tmpRelDirNameTarg = twoTokensOfRelDirnameAndFilenameTarg[1] + threeTokensOfQuoteFilenameTarg = twoTokensOfRelDirnameAndFilenameTarg[0].split('#', 2) + #concatenate actorID and quoteID for search key + keyForDuplicateSearchTarg = threeTokensOfQuoteFilenameTarg[0] + threeTokensOfQuoteFilenameTarg[1] + if(keyForDuplicateSearchSrc == keyForDuplicateSearchTarg): + #print "Found duplicate %s" % (filenameSrcTmp) + duplicateFound = True + wavfilesNoDups[fileTargIdx] = twoTokensOfRelDirnameAndFilenameTarg[0] + '&' + tmpRelDirNameSrc + ',' + tmpRelDirNameTarg + '&' + twoTokensOfRelDirnameAndFilenameTarg[2] + break + if(duplicateFound == False): + wavfilesNoDups.append(filenameSrcTmp) +# for filenameSrcTmp in wavfilesNoDups: +# print "Unique %s" % (filenameSrcTmp) + + print "Creating output excel %s file..." % (OUTPUT_XLS_FILENAME) + outputXLS(OUTPUT_XLS_FILENAME, OUTPUT_XLS_QUOTES_SHEET, wavfilesNoDups, extractTreFilesMode, TMProotFolderWithInputTLKFiles) + else: + invalidSyntax = True + + if invalidSyntax == True: + print "Invalid syntax\n Try: \n %s -op [folderpath_for_extracted_wav_Files] \n %s --help for more info \n %s --version for version info " % (app_name, app_name, app_name) + tmpi = 0 + for tmpArg in sys.argv: + if tmpi==0: #skip first argument + tmpi+=1 + continue + print "\nArgument: %s" % (tmpArg) + tmpi+=1 +else: + ## debug + #print '%s was imported from another module' % (app_name_spaced,) + pass |