mirror of
https://github.com/iluvcapra/ptulsconv.git
synced 2026-01-01 01:10:47 +00:00
Work on rewrting the parser
This commit is contained in:
0
ptulsconv/docparser/__init__.py
Normal file
0
ptulsconv/docparser/__init__.py
Normal file
248
ptulsconv/docparser/doc_parser_visitor.py
Normal file
248
ptulsconv/docparser/doc_parser_visitor.py
Normal file
@@ -0,0 +1,248 @@
|
||||
from parsimonious.nodes import NodeVisitor, Node
|
||||
from collections import namedtuple
|
||||
|
||||
# _SessionDescriptor = namedtuple('_SessionDescriptor',
|
||||
# "header files clips plugins tracks markers")
|
||||
#
|
||||
# _HeaderDescriptor = namedtuple('_HeaderDescriptor',
|
||||
# "session_name sample_rate bit_depth start_timecode "
|
||||
# "timecode_format timecode_drop_frame "
|
||||
# "count_audio_tracks count_clips count_files")
|
||||
#
|
||||
# _TrackDescriptor = namedtuple("_TrackDescriptor",
|
||||
# "name comments user_delay_samples state plugins "
|
||||
# "clips")
|
||||
#
|
||||
# _TrackClipDescriptor = namedtuple("_TrackClipDescriptor",
|
||||
# "channel event clip_name start_time end_time "
|
||||
# "duration timestamp state")
|
||||
#
|
||||
# _PluginDescriptor = namedtuple("_PluginDescriptor",
|
||||
# "manufacturer plugin_name version format stems "
|
||||
# "count_instances")
|
||||
#
|
||||
# _MarkerDescriptor = namedtuple("_MarkerDescriptor",
|
||||
# "number location time_reference units name "
|
||||
# "comments")
|
||||
#
|
||||
# _FileDescriptor = namedtuple("_FileDescriptor", "filename path")
|
||||
|
||||
|
||||
class SessionDescriptor:
|
||||
def __init__(self, **kwargs):
|
||||
self.header = kwargs['header']
|
||||
self.files = kwargs['files']
|
||||
self.clips = kwargs['clips']
|
||||
self.plugins = kwargs['plugins']
|
||||
self.tracks = kwargs['tracks']
|
||||
self.markers = kwargs['markers']
|
||||
|
||||
|
||||
class HeaderDescriptor:
|
||||
def __init__(self, **kwargs):
|
||||
self.session_name = kwargs['session_name']
|
||||
self.sample_rate = kwargs['sample_rate']
|
||||
self.bit_depth = kwargs['bit_depth']
|
||||
self.start_timecode = kwargs['start_timecode']
|
||||
self.timecode_format = kwargs['timecode_format']
|
||||
self.timecode_drop_frame = kwargs['timecode_drop_frame']
|
||||
self.count_audio_tracks = kwargs['count_audio_tracks']
|
||||
self.count_clips = kwargs['count_clips']
|
||||
self.count_files = kwargs['count_files']
|
||||
|
||||
|
||||
class TrackDescriptor:
|
||||
def __init__(self, **kwargs):
|
||||
self.name = kwargs['name']
|
||||
self.comments = kwargs['comments']
|
||||
self.user_delay_samples = kwargs['user_delay_samples']
|
||||
self.state = kwargs['state']
|
||||
self.plugins = kwargs['plugins']
|
||||
self.clips = kwargs['clips']
|
||||
|
||||
|
||||
class FileDescriptor(dict):
|
||||
pass
|
||||
|
||||
|
||||
class TrackClipDescriptor:
|
||||
def __init__(self, **kwargs):
|
||||
self.channel = kwargs['channel']
|
||||
self.event = kwargs['event']
|
||||
self.clip_name = kwargs['clip_name']
|
||||
self.start_time = kwargs['start_time']
|
||||
self.end_time = kwargs['end_time']
|
||||
self.duration = kwargs['duration']
|
||||
self.timestamp = kwargs['timestamp']
|
||||
self.state = kwargs['state']
|
||||
|
||||
|
||||
class ClipDescriptor(dict):
|
||||
pass
|
||||
|
||||
|
||||
class PluginDescriptor(dict):
|
||||
pass
|
||||
|
||||
|
||||
class MarkerDescriptor:
|
||||
def __init__(self, **kwargs):
|
||||
self.number = kwargs['number']
|
||||
self.location = kwargs['location']
|
||||
self.time_reference = kwargs['time_reference']
|
||||
self.units = kwargs['units']
|
||||
self.name = kwargs['name']
|
||||
self.comments = kwargs['comments']
|
||||
|
||||
|
||||
|
||||
class DocParserVisitor(NodeVisitor):
|
||||
|
||||
@staticmethod
|
||||
def visit_document(_, visited_children) -> SessionDescriptor:
|
||||
files = next(iter(visited_children[1]), None)
|
||||
clips = next(iter(visited_children[2]), None)
|
||||
plugins = next(iter(visited_children[3]), None)
|
||||
tracks = next(iter(visited_children[4]), None)
|
||||
markers = next(iter(visited_children[5]), None)
|
||||
|
||||
return SessionDescriptor(header=visited_children[0],
|
||||
files=files,
|
||||
clips=clips,
|
||||
plugins=plugins,
|
||||
tracks=tracks,
|
||||
markers=markers)
|
||||
|
||||
@staticmethod
|
||||
def visit_header(_, visited_children):
|
||||
|
||||
tc_drop = False
|
||||
for _ in visited_children[20]:
|
||||
tc_drop = True
|
||||
|
||||
return HeaderDescriptor(session_name=visited_children[2],
|
||||
sample_rate=visited_children[6],
|
||||
bit_depth=visited_children[10],
|
||||
start_timecode=visited_children[15],
|
||||
timecode_format=visited_children[19],
|
||||
timecode_drop_frame=tc_drop,
|
||||
count_audio_tracks=visited_children[25],
|
||||
count_clips=visited_children[29],
|
||||
count_files=visited_children[33])
|
||||
|
||||
@staticmethod
|
||||
def visit_files_section(_, visited_children):
|
||||
return list(map(lambda child: FileDescriptor(filename=child[0], path=child[2]), visited_children[2]))
|
||||
|
||||
@staticmethod
|
||||
def visit_clips_section(_, visited_children):
|
||||
channel = next(iter(visited_children[2][3]), 1)
|
||||
|
||||
return list(map(lambda child: ClipDescriptor(clip_name=child[0], file=child[2], channel=channel),
|
||||
visited_children[2]))
|
||||
|
||||
@staticmethod
|
||||
def visit_plugin_listing(_, visited_children):
|
||||
return list(map(lambda child: PluginDescriptor(manufacturer=child[0],
|
||||
plugin_name=child[2],
|
||||
version=child[4],
|
||||
format=child[6],
|
||||
stems=child[8],
|
||||
count_instances=child[10]),
|
||||
visited_children[2]))
|
||||
|
||||
@staticmethod
|
||||
def visit_track_block(_, visited_children):
|
||||
track_header, track_clip_list = visited_children
|
||||
clips = []
|
||||
for clip in track_clip_list:
|
||||
if clip[0] is not None:
|
||||
clips.append(clip[0])
|
||||
|
||||
plugins = []
|
||||
for plugin_opt in track_header[16]:
|
||||
for plugin in plugin_opt[1]:
|
||||
plugins.append(plugin[1])
|
||||
|
||||
return TrackDescriptor(
|
||||
name=track_header[2],
|
||||
comments=track_header[6],
|
||||
user_delay_samples=track_header[10],
|
||||
state=track_header[14],
|
||||
plugins=plugins,
|
||||
clips=clips
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def visit_track_listing(_, visited_children):
|
||||
return visited_children[1]
|
||||
|
||||
@staticmethod
|
||||
def visit_track_clip_entry(_, visited_children):
|
||||
timestamp = None
|
||||
if isinstance(visited_children[14], list):
|
||||
timestamp = visited_children[14][0][0]
|
||||
|
||||
return TrackClipDescriptor(channel=visited_children[0],
|
||||
event=visited_children[3],
|
||||
clip_name=visited_children[6],
|
||||
start_time=visited_children[8],
|
||||
end_time=visited_children[10],
|
||||
duration=visited_children[12],
|
||||
timestamp=timestamp,
|
||||
state=visited_children[15])
|
||||
|
||||
@staticmethod
|
||||
def visit_track_state_list(_, visited_children):
|
||||
states = []
|
||||
for next_state in visited_children:
|
||||
states.append(next_state[0][0].text)
|
||||
return states
|
||||
|
||||
@staticmethod
|
||||
def visit_track_clip_state(node, _):
|
||||
return node.text
|
||||
|
||||
@staticmethod
|
||||
def visit_markers_listing(_, visited_children):
|
||||
markers = []
|
||||
|
||||
for marker in visited_children[2]:
|
||||
markers.append(marker)
|
||||
|
||||
return markers
|
||||
|
||||
@staticmethod
|
||||
def visit_marker_record(_, visited_children):
|
||||
return MarkerDescriptor(number=visited_children[0],
|
||||
location=visited_children[3],
|
||||
time_reference=visited_children[5],
|
||||
units=visited_children[8],
|
||||
name=visited_children[10],
|
||||
comments=visited_children[12])
|
||||
|
||||
@staticmethod
|
||||
def visit_formatted_clip_name(_, visited_children):
|
||||
return visited_children[1].text
|
||||
|
||||
@staticmethod
|
||||
def visit_string_value(node, _):
|
||||
return node.text.strip(" ")
|
||||
|
||||
@staticmethod
|
||||
def visit_integer_value(node, _):
|
||||
return int(node.text)
|
||||
|
||||
# def visit_timecode_value(self, node, visited_children):
|
||||
# return node.text.strip(" ")
|
||||
|
||||
@staticmethod
|
||||
def visit_float_value(node, _):
|
||||
return float(node.text)
|
||||
|
||||
def visit_block_ending(self, node, visited_children):
|
||||
pass
|
||||
|
||||
def generic_visit(self, node, visited_children):
|
||||
""" The generic visit method. """
|
||||
return visited_children or node
|
||||
73
ptulsconv/docparser/ptuls_grammar.py
Normal file
73
ptulsconv/docparser/ptuls_grammar.py
Normal file
@@ -0,0 +1,73 @@
|
||||
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 float_value " 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
|
||||
|
||||
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 = ~"[^\t\n]*"
|
||||
integer_value = ~"\d+"
|
||||
float_value = ~"\d+(\.\d+)?"
|
||||
isp = ~"[^\d\t\n]*"
|
||||
""")
|
||||
Reference in New Issue
Block a user