diff --git a/ptulsconv/__init__.py b/ptulsconv/__init__.py index b671e4a..95892a1 100644 --- a/ptulsconv/__init__.py +++ b/ptulsconv/__init__.py @@ -1,5 +1,3 @@ -from ptulsconv.docparser.ptuls_grammar import protools_text_export_grammar - __version__ = '1.0.5' __author__ = 'Jamie Hardt' __license__ = 'MIT' diff --git a/ptulsconv/docparser/pt_doc_parser.py b/ptulsconv/docparser/pt_doc_parser.py index e3582f0..e86a214 100644 --- a/ptulsconv/docparser/pt_doc_parser.py +++ b/ptulsconv/docparser/pt_doc_parser.py @@ -1,16 +1,90 @@ from parsimonious.nodes import NodeVisitor +from parsimonious.grammar import Grammar from .doc_entity import SessionDescriptor, HeaderDescriptor, TrackDescriptor, FileDescriptor, \ TrackClipDescriptor, ClipDescriptor, PluginDescriptor, MarkerDescriptor +protools_text_export_grammar = Grammar( + r""" + document = header files_section? clips_section? plugin_listing? track_listing? markers_listing? + header = "SESSION NAME:" fs string_value rs + "SAMPLE RATE:" fs float_value rs + "BIT DEPTH:" fs integer_value "-bit" rs + "SESSION START TIMECODE:" fs string_value rs + "TIMECODE FORMAT:" fs frame_rate " Drop"? " Frame" rs + "# OF AUDIO TRACKS:" fs integer_value rs + "# OF AUDIO CLIPS:" fs integer_value rs + "# OF AUDIO FILES:" fs integer_value rs block_ending + + frame_rate = ("60" / "59.94" / "30" / "29.97" / "25" / "24" / "23.976") + 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" 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 + + 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 + plugin_column_header = "MANUFACTURER " fs "PLUG-IN NAME " fs + "VERSION " fs "FORMAT " fs "STEMS " fs + "NUMBER OF INSTANCES" rs + plugin_record = string_value fs string_value fs string_value fs + string_value fs string_value fs string_value rs + + track_listing = track_listing_header track_block* + track_block = track_list_top ( track_clip_entry / block_ending )* + + track_listing_header = "T R A C K L I S T I N G" rs + track_list_top = "TRACK NAME:" fs string_value rs + "COMMENTS:" fs string_value rs + "USER DELAY:" fs integer_value " Samples" rs + "STATE: " track_state_list rs + ("PLUG-INS: " ( fs string_value )* rs)? + "CHANNEL " fs "EVENT " fs "CLIP NAME " fs + "START TIME " fs "END TIME " fs "DURATION " fs + ("TIMESTAMP " fs)? "STATE" rs + + track_state_list = (track_state " ")* + + track_state = "Solo" / "Muted" / "Inactive" / "Hidden" + + track_clip_entry = integer_value isp fs + integer_value isp fs + string_value fs + string_value fs string_value fs string_value fs (string_value fs)? + track_clip_state rs + + track_clip_state = ("Muted" / "Unmuted") + + markers_listing = markers_listing_header markers_column_header marker_record* + markers_listing_header = "M A R K E R S L I S T I N G" rs + markers_column_header = "# " fs "LOCATION " fs "TIME REFERENCE " fs + "UNITS " fs "NAME " fs "COMMENTS" rs + + marker_record = integer_value isp fs string_value fs integer_value isp fs + string_value fs string_value fs string_value rs + + fs = "\t" + rs = "\n" + block_ending = rs rs + string_value = ~r"[^\t\n]*" + integer_value = ~r"\d+" + float_value = ~r"\d+(\.\d+)?" + isp = ~r"[^\d\t\n]*" + """) + + def parse_document(path: str) -> SessionDescriptor: """ Parse a Pro Tools text export. :param path: path to a file :return: the session descriptor """ - from .ptuls_grammar import protools_text_export_grammar with open(path, 'r') as f: ast = protools_text_export_grammar.parse(f.read()) return DocParserVisitor().visit(ast) diff --git a/ptulsconv/docparser/ptuls_grammar.py b/ptulsconv/docparser/ptuls_grammar.py deleted file mode 100644 index e5d1e6a..0000000 --- a/ptulsconv/docparser/ptuls_grammar.py +++ /dev/null @@ -1,74 +0,0 @@ -from parsimonious.grammar import Grammar - -protools_text_export_grammar = Grammar( - r""" - document = header files_section? clips_section? plugin_listing? track_listing? markers_listing? - header = "SESSION NAME:" fs string_value rs - "SAMPLE RATE:" fs float_value rs - "BIT DEPTH:" fs integer_value "-bit" rs - "SESSION START TIMECODE:" fs string_value rs - "TIMECODE FORMAT:" fs frame_rate " Drop"? " Frame" rs - "# OF AUDIO TRACKS:" fs integer_value rs - "# OF AUDIO CLIPS:" fs integer_value rs - "# OF AUDIO FILES:" fs integer_value rs block_ending - - frame_rate = ("60" / "59.94" / "30" / "29.97" / "25" / "24" / "23.976") - 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" 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 - - 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 - plugin_column_header = "MANUFACTURER " fs "PLUG-IN NAME " fs - "VERSION " fs "FORMAT " fs "STEMS " fs - "NUMBER OF INSTANCES" rs - plugin_record = string_value fs string_value fs string_value fs - string_value fs string_value fs string_value rs - - track_listing = track_listing_header track_block* - track_block = track_list_top ( track_clip_entry / block_ending )* - - track_listing_header = "T R A C K L I S T I N G" rs - track_list_top = "TRACK NAME:" fs string_value rs - "COMMENTS:" fs string_value rs - "USER DELAY:" fs integer_value " Samples" rs - "STATE: " track_state_list rs - ("PLUG-INS: " ( fs string_value )* rs)? - "CHANNEL " fs "EVENT " fs "CLIP NAME " fs - "START TIME " fs "END TIME " fs "DURATION " fs - ("TIMESTAMP " fs)? "STATE" rs - - track_state_list = (track_state " ")* - - track_state = "Solo" / "Muted" / "Inactive" / "Hidden" - - track_clip_entry = integer_value isp fs - integer_value isp fs - string_value fs - string_value fs string_value fs string_value fs (string_value fs)? - track_clip_state rs - - track_clip_state = ("Muted" / "Unmuted") - - markers_listing = markers_listing_header markers_column_header marker_record* - markers_listing_header = "M A R K E R S L I S T I N G" rs - markers_column_header = "# " fs "LOCATION " fs "TIME REFERENCE " fs - "UNITS " fs "NAME " fs "COMMENTS" rs - - marker_record = integer_value isp fs string_value fs integer_value isp fs - string_value fs string_value fs string_value rs - - fs = "\t" - rs = "\n" - block_ending = rs rs - string_value = ~r"[^\t\n]*" - integer_value = ~r"\d+" - float_value = ~r"\d+(\.\d+)?" - isp = ~r"[^\d\t\n]*" - """) diff --git a/tests/unittests/test_tagging.py b/tests/unittests/test_tagging.py index b011127..fd9a516 100644 --- a/tests/unittests/test_tagging.py +++ b/tests/unittests/test_tagging.py @@ -1,5 +1,5 @@ import unittest -from ptulsconv.docparser import doc_entity, pt_doc_parser, ptuls_grammar, tag_compiler +from ptulsconv.docparser import doc_entity, pt_doc_parser, tag_compiler import os.path @@ -8,7 +8,7 @@ class TaggingIntegratedTests(unittest.TestCase): def test_event_list(self): with open(self.path, 'r') as f: - document_ast = ptuls_grammar.protools_text_export_grammar.parse(f.read()) + document_ast = pt_doc_parser.protools_text_export_grammar.parse(f.read()) document: doc_entity.SessionDescriptor = pt_doc_parser.DocParserVisitor().visit(document_ast) compiler = tag_compiler.TagCompiler() compiler.session = document @@ -28,7 +28,7 @@ class TaggingIntegratedTests(unittest.TestCase): def test_append(self): with open(self.path, 'r') as f: - document_ast = ptuls_grammar.protools_text_export_grammar.parse(f.read()) + document_ast = pt_doc_parser.protools_text_export_grammar.parse(f.read()) document: doc_entity.SessionDescriptor = pt_doc_parser.DocParserVisitor().visit(document_ast) compiler = tag_compiler.TagCompiler() compiler.session = document @@ -51,7 +51,7 @@ class TaggingIntegratedTests(unittest.TestCase): def test_successive_appends(self): with open(self.path, 'r') as f: - document_ast = ptuls_grammar.protools_text_export_grammar.parse(f.read()) + document_ast = pt_doc_parser.protools_text_export_grammar.parse(f.read()) document: doc_entity.SessionDescriptor = pt_doc_parser.DocParserVisitor().visit(document_ast) compiler = tag_compiler.TagCompiler() compiler.session = document