Deleted parse_cmx etc

Going to reimplement these
This commit is contained in:
Jamie Hardt
2018-12-24 00:49:00 -08:00
parent ce3d8088a1
commit e4b6036ab7
5 changed files with 30 additions and 289 deletions

View File

@@ -1,137 +0,0 @@
class CmxEvent:
"""Represents a source-record event.
Aside from exposing properites related to the raw CMX event itself,
(the `source_start`, `source_finish`, `transition` etc.) the event
also contains contextual information from the parsed CMX list, such as
`clip_name` and the frame counting mode in effect on the event.
"""
def __init__(self,title,number,clip_name,source_name,channels,
transition,source_start,source_finish,
record_start, record_finish, fcm_drop, remarks = [] ,
unrecognized = [], line_number = None):
self.title = title
self.number = number
self.clip_name = clip_name
self.source_name = source_name
self.channels = channels
self.transition = transition
self.source_start = source_start
self.source_finish = source_finish
self.record_start = record_start
self.record_finish = record_finish
self.fcm_drop = fcm_drop
self.remarks = remarks
self.unrecgonized = unrecognized
self.black = (source_name == 'BL')
self.aux_source = (source_name == 'AX')
self.line_number = line_number
def accept_statement(self, statement):
"""Used by the parser to attach clip names and notes to this event."""
statement_type = type(statement).__name__
if statement_type == 'AudioExt':
self.channels.appendExt(statement)
elif statement_type == 'Remark':
self.remarks.append(statement.text)
elif statement_type == 'SourceFile':
self.source_name = statement.filename
elif statement_type == 'ClipName':
self.clip_name = statement.name
elif statement_type == 'EffectsName':
self.transition.name = statement.name
def __repr__(self):
return f"""CmxEvent(title={self.title.__repr__()},number={self.number.__repr__()},\
clip_name={self.clip_name.__repr__()},source_name={self.source_name.__repr__()},\
channels={self.channels.__repr__()},transition={self.transition.__repr__()},\
source_start={self.source_start.__repr__()},source_finish={self.source_finish.__repr__()},\
record_start={self.source_start.__repr__()},record_finish={self.record_finish.__repr__()},\
fcm_drop={self.fcm_drop.__repr__()},remarks={self.remarks.__repr__()},line_number={self.line_number.__repr__()})"""
class CmxTransition:
"""Represents a CMX transition, a wipe, dissolve or cut."""
Cut = "C"
Dissolve = "V"
Wipe = "W"
KeyBackground = "KB"
Key = "K"
KeyOut = "KO"
def __init__(self, transition, operand):
self.transition = transition
self.operand = operand
self.name = ''
@property
def kind(self):
if self.cut:
return Cut
elif self.dissove:
return Dissolve
elif self.wipe:
return Wipe
elif self.key_background:
return KeyBackground
elif self.key_foreground:
return Key
elif self.key_out:
return KeyOut
@property
def cut(self):
"`True` if this transition is a cut."
return self.transition == Cut
@property
def dissolve(self):
"`True` if this traansition is a dissolve."
return self.transition == Dissolve
@property
def wipe(self):
"`True` if this transition is a wipe."
return self.transition.startswith('W')
@property
def effect_duration(self):
""""`The duration of this transition, in frames of the record target.
In the event of a key event, this is the duration of the fade in.
"""
return int(self.operand)
@property
def wipe_number(self):
"Wipes are identified by a particular number."
if self.wipe:
return int(self.transition[1:])
else:
return None
@property
def key_background(self):
"`True` if this is a key background event."
return self.transition == KeyBackground
@property
def key_foreground(self):
"`True` if this is a key foreground event."
return self.transition == Key
@property
def key_out(self):
"`True` if this is a key out event."
return self.transition == KeyOut
def __repr__(self):
return f"""CmxTransition(transition={self.transition.__repr__()},operand={self.operand.__repr__()})"""

View File

@@ -1,139 +0,0 @@
# pycmx
# (c) 2018 Jamie Hardt
from .util import NamedTupleParser
from .parse_cmx_statements import parse_cmx3600_statements
from .cmx_event import CmxEvent, CmxTransition
from collections import namedtuple
from re import compile, match
class CmxChannelMap:
"""
Represents a set of all the channels to which an event applies.
"""
chan_map = { "V" : (True, False, False),
"A" : (False, True, False),
"A2" : (False, False, True),
"AA" : (False, True, True),
"B" : (True, True, False),
"AA/V" : (True, True, True),
"A2/V" : (True, False, True)
}
def __init__(self, v=False, audio_channels=set()):
self._audio_channel_set = audio_channels
self.v = v
@property
def a1(self):
return self.get_audio_channel(1)
@a1.setter
def a1(self,val):
self.set_audio_channel(1,val)
@property
def a2(self):
return self.get_audio_channel(2)
@a2.setter
def a2(self,val):
self.set_audio_channel(2,val)
@property
def a3(self):
return self.get_audio_channel(3)
@a3.setter
def a3(self,val):
self.set_audio_channel(3,val)
@property
def a4(self):
return self.get_audio_channel(4)
@a4.setter
def a4(self,val):
self.set_audio_channel(4,val)
def get_audio_channel(self,chan_num):
return (chan_num in self._audio_channel_set)
def set_audio_channel(self,chan_num,enabled):
if enabled:
self._audio_channel_set.add(chan_num)
elif self.get_audio_channel(chan_num):
self._audio_channel_set.remove(chan_num)
def appendEvent(self, event_str):
alt_channel_re = compile('^A(\d+)')
if event_str in self.chan_map:
channels = self.chan_map[event_str]
self.v = channels[0]
self.a1 = channels[1]
self.a2 = channels[2]
else:
matchresult = match(alt_channel_re, event_str)
if matchresult:
self.set_audio_channel(int( matchresult.group(1)), True )
def appendExt(self, audio_ext):
self.a3 = ext.audio3
self.a4 = ext.audio4
def __repr__(self):
return f"CmxChannelMap(v={self.v.__repr__()}, audio_channels={self._audio_channel_set.__repr__()})"
def parse_cmx3600(file):
"""Accepts the path to a CMX EDL and returns a list of all events contained therein."""
statements = parse_cmx3600_statements(file)
parser = NamedTupleParser(statements)
parser.expect('Title')
title = parser.current_token.title
return event_list(title, parser)
def event_list(title, parser):
state = {"fcm_drop" : False}
events_result = []
this_event = None
while not parser.at_end():
if parser.accept('FCM'):
state['fcm_drop'] = parser.current_token.drop
elif parser.accept('Event'):
if this_event != None:
events_result.append(this_event)
raw_event = parser.current_token
channels = CmxChannelMap(v=False, audio_channels=set([]))
channels.appendEvent(raw_event.channels)
this_event = CmxEvent(title=title,number=int(raw_event.event), clip_name=None ,
source_name=raw_event.source,
channels=channels,
transition=CmxTransition(raw_event.trans, raw_event.trans_op),
source_start= raw_event.source_in,
source_finish= raw_event.source_out,
record_start= raw_event.record_in,
record_finish= raw_event.record_out,
fcm_drop= state['fcm_drop'],
line_number = raw_event.line_number)
elif parser.accept('AudioExt') or parser.accept('ClipName') or \
parser.accept('SourceFile') or parser.accept('EffectsName') or \
parser.accept('Remark'):
this_event.accept_statement(parser.current_token)
elif parser.accept('Trailer'):
break
else:
parser.next_token()
if this_event != None:
events_result.append(this_event)
return events_result

13
pycmx/parse_cmx_events.py Normal file
View File

@@ -0,0 +1,13 @@
# pycmx
# (c) 2018 Jamie Hardt
def events(statements=[]):
if statements[0].
class Event:
def __init__(self, statements):
self.statements = statements
def number():
return statements[0].event

View File

@@ -1,7 +1,5 @@
# Parsed Statement Data Structures
#
# These represent individual lines that have been typed and have undergone some light symbolic parsing.
# pycmx
# (c) 2018 Jamie Hardt
from .util import collimate
import re
@@ -29,7 +27,8 @@ def parse_cmx3600_statements(path):
with open(path,'r') as file:
lines = file.readlines()
line_numbers = count()
return [parse_cmx3600_line(line.strip(), line_number) for (line, line_number) in zip(lines,line_numbers)]
return [parse_cmx3600_line(line.strip(), line_number) \
for (line, line_number) in zip(lines,line_numbers)]
def edl_column_widths(event_field_length, source_field_length):
return [event_field_length,2, source_field_length,1,

View File

@@ -26,8 +26,10 @@ parser operations such as `accept()` and `expect()`
self.current_token = None
def peek(self):
"""Returns the token to come after the `current_token` without
popping the current token."""
"""
Returns the token to come after the `current_token` without
popping the current token.
"""
return self.tokens[0]
def at_end(self):
@@ -40,8 +42,10 @@ popping the current token."""
self.tokens = self.tokens[1:]
def accept(self, type_name):
"""If the next token.__name__ is `type_name`, returns true and advances
to the next token with `next_token()`."""
"""
If the next token.__name__ is `type_name`, returns true and advances
to the next token with `next_token()`.
"""
if self.at_end():
return False
elif (type(self.peek()).__name__ == type_name ):
@@ -53,7 +57,8 @@ to the next token with `next_token()`."""
def expect(self, type_name):
"""
If the next token.__name__ is `type_name`, the parser is advanced.
If it is not, an assertion failure occurs."""
If it is not, an assertion failure occurs.
"""
assert( self.accept(type_name) )