This commit is contained in:
Jamie Hardt
2019-10-09 19:56:24 -07:00
6 changed files with 162 additions and 35 deletions

View File

@@ -2,20 +2,25 @@ from ptulsconv.commands import convert
from optparse import OptionParser
import sys
parser = OptionParser()
parser.usage = "ptulsconv TEXT_EXPORT.txt"
parser.add_option('-i', dest='in_time', help="Don't output events occurring before this timecode, and offset"
" all events relative to this timecode.", metavar='TC')
parser.add_option('-o', dest='out_time', help="Don't output events occurring after this timecode.", metavar='TC')
parser.add_option('-P','--progress', default=False, action='store_true', dest='show_progress', help='Show progress bar.')
parser.add_option('-m','--include-muted', default=False, action='store_true', dest='include_muted', help='Read muted clips.')
def main():
parser = OptionParser()
parser.usage = "ptulsconv TEXT_EXPORT.txt"
parser.add_option('-i', dest='in_time', help="Don't output events occurring before this timecode, and offset"
" all events relative to this timecode.", metavar='TC')
parser.add_option('-o', dest='out_time', help="Don't output events occurring after this timecode.", metavar='TC')
parser.add_option('-P','--progress', default=False, action='store_true', dest='show_progress', help='Show progress bar.')
parser.add_option('-m','--include-muted', default=False, action='store_true', dest='include_muted', help='Read muted clips.')
if __name__ == "__main__":
(options, args) = parser.parse_args(sys.argv)
if len(args) < 2:
print("Error: No input file",file=sys.stderr)
parser.print_help(sys.stderr)
exit(-1)
sys.exit(-1)
convert(input_file=args[1], start=options.in_time, end=options.out_time, include_muted=options.include_muted,
progress=options.show_progress, output=sys.stdout)
if __name__ == "__main__":
main()

View File

@@ -1,19 +1,15 @@
import io
import json
import os.path
import sys
from xml.etree.ElementTree import TreeBuilder, tostring
import ptulsconv
from tqdm import tqdm
def fmp_dump(data, input_file_name, output):
doc = TreeBuilder(element_factory=None)
# field_map maps tags in the text export to fields in FMPXMLRESULT
# - tuple field 0 is a list of tags, the first tag with contents will be used as source
# - tuple field 1 is the field in FMPXMLRESULT
# - tuple field 2 the constructor/type of the field
field_map = ((['Title', 'PT.Session.Name'], 'Title', str),
# field_map maps tags in the text export to fields in FMPXMLRESULT
# - tuple field 0 is a list of tags, the first tag with contents will be used as source
# - tuple field 1 is the field in FMPXMLRESULT
# - tuple field 2 the constructor/type of the field
adr_field_map = ((['Title', 'PT.Session.Name'], 'Title', str),
(['Supv'], 'Supervisor', str),
(['Client'], 'Client', str),
(['Sc'], 'Scene', str),
@@ -44,6 +40,9 @@ def fmp_dump(data, input_file_name, output):
(['ADLIB'], 'Adlib', str),
(['OPT'], 'Optional', str))
def fmp_dump(data, input_file_name, output):
doc = TreeBuilder(element_factory=None)
doc.start('FMPXMLRESULT', {'xmlns': 'http://www.filemaker.com/fmpxmlresult'})
doc.start('ERRORCODE')
@@ -58,24 +57,20 @@ def fmp_dump(data, input_file_name, output):
doc.end('DATABASE')
doc.start('METADATA')
for field in field_map:
for field in adr_field_map:
tp = field[2]
ft = 'TEXT'
if tp is int or tp is float:
ft = 'NUMBER'
doc.start('FIELD', {'EMPTYOK': 'YES',
'MAXREPEAT': '1',
'NAME': field[1],
'TYPE': ft})
doc.start('FIELD', {'EMPTYOK': 'YES', 'MAXREPEAT': '1', 'NAME': field[1], 'TYPE': ft})
doc.end('FIELD')
doc.end('METADATA')
doc.start('RESULTSET', {'FOUND': str(len(data['events']))})
for event in data['events']:
doc.start('ROW')
for field in field_map:
for field in adr_field_map:
doc.start('COL')
doc.start('DATA')
for key_attempt in field[0]:
@@ -93,6 +88,24 @@ def fmp_dump(data, input_file_name, output):
output.write(xmlstr)
def dump_field_map(field_map_name, output=sys.stdout):
output.write("# Map of Tag fields to XML output columns\n")
output.write("# (in order of precedence)\n")
output.write("# \n")
field_map = []
if field_map_name == 'ADR':
field_map = adr_field_map
output.write("# ADR Table Fields\n")
output.write("# \n")
output.write("# Tag Name | FMPXMLRESULT Column | Type \n")
output.write("# -------------------------+----------------------+---------\n")
for field in field_map:
for tag in field[0]:
output.write("# %25s| %20s | %8s\n" % (tag[:25], field[1][:20], field[2].__name__))
def convert(input_file, output_format='fmpxml', start=None, end=None, progress=False, include_muted=False, output=sys.stdout):
with open(input_file, 'r') as file:
ast = ptulsconv.protools_text_export_grammar.parse(file.read())

View File

@@ -14,13 +14,13 @@ protools_text_export_grammar = Grammar(
files_section = files_header files_column_header file_record* block_ending
files_header = "F I L E S I N S E S S I O N" rs
files_column_header = "Filename " fs "Location" rs
files_column_header = "Filename" isp fs "Location" rs
file_record = string_value fs string_value rs
clips_section = clips_header clips_column_header clip_record* block_ending
clips_header = "O N L I N E C L I P S I N S E S S I O N" rs
clips_column_header = string_value fs string_value rs
clip_record = string_value fs string_value fs "[" integer_value "]" rs
clip_record = string_value fs string_value (fs "[" integer_value "]")? rs
plugin_listing = plugin_header plugin_column_header plugin_record* block_ending
plugin_header = "P L U G - I N S L I S T I N G" rs

View File

@@ -40,7 +40,9 @@ class DictionaryParserVisitor(NodeVisitor):
@staticmethod
def visit_clips_section(node, visited_children):
return list(map(lambda child: dict(clip_name=child[0], file=child[2], channel=child[5]),
channel = next(iter(visited_children[2][5]), 1)
return list(map(lambda child: dict(clip_name=child[0], file=child[2], channel=channel),
visited_children[2]))
@staticmethod

View File

@@ -54,10 +54,7 @@
<ListElem>
<AvProp id="ATTR" name="OMFI:ATTB:Kind" type="int32">1</AvProp>
<AvProp id="ATTR" name="OMFI:ATTB:Name" type="string">_ATN_CRM_LENGTH</AvProp>
<AvProp id="ATTR" name="OMFI:ATTB:IntAttribute" type="int32">
<xsl:value-of select="number(fmp:COL[12]) - number(fmp:COL[11])" />
</AvProp>
<AvProp id="ATTR" name="OMFI:ATTB:IntAttribute" type="int32">1</AvProp>
</ListElem>
<ListElem/>
</List>