diff --git a/pycmx/__init__.py b/pycmx/__init__.py index 09d503e..d405a0b 100644 --- a/pycmx/__init__.py +++ b/pycmx/__init__.py @@ -1,5 +1,6 @@ # pycmx init -from .parse_cmx_events import parse_cmx3600 +from .parse_cmx_events import parse_cmx3600, Transition, Event, Edit +from . import parse_cmx_events __version__ = '0.6' diff --git a/pycmx/parse_cmx_events.py b/pycmx/parse_cmx_events.py index 5137f7f..2b263b0 100644 --- a/pycmx/parse_cmx_events.py +++ b/pycmx/parse_cmx_events.py @@ -54,10 +54,36 @@ class Edit: self.clip_name_statement = clip_name_statement self.source_file_statement = source_file_statement + @property + def transition(self): + return Transition(self.edit_statement.trans, self.edit_statement.trans_op) + + @property + def source_in(self): + return self.edit_statement.source_in + + @property + def source_out(self): + return self.edit_statement.source_out + + @property + def record_in(self): + return self.edit_statement.record_in + + @property + def record_out(self): + return self.edit_statement.record_out + @property def source(self): return self.edit_statement.source + + @property + def source_file(self): + return self.source_file_statement.filename + + @property def clip_name(self): if self.clip_name_statement != None: @@ -129,5 +155,85 @@ class Event: - +class Transition: + """Represents a CMX transition, a wipe, dissolve or cut.""" + + Cut = "C" + Dissolve = "D" + 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 Transition.Cut + elif self.dissolve: + return Transition.Dissolve + elif self.wipe: + return Transition.Wipe + elif self.key_background: + return Transition.KeyBackground + elif self.key_foreground: + return Transition.Key + elif self.key_out: + return Transition.KeyOut + + @property + def cut(self): + "`True` if this transition is a cut." + return self.transition == 'C' + + @property + def dissolve(self): + "`True` if this traansition is a dissolve." + return self.transition == 'D' + + + @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__()})""" diff --git a/tests/test_parse.py b/tests/test_parse.py index d1e507c..67b04db 100644 --- a/tests/test_parse.py +++ b/tests/test_parse.py @@ -21,19 +21,45 @@ class TestParse(TestCase): def test_events(self): - edl = pycmx.parse_cmx3600("tests/edls/TEST.edl") events = list( edl.events ) self.assertEqual( int(events[0].number) , 1) self.assertEqual( events[0].edits[0].source , "OY_HEAD_") self.assertEqual( events[0].edits[0].clip_name , "HEAD LEADER MONO") + self.assertEqual( events[0].edits[0].source_file , "OY_HEAD_LEADER.MOV") + self.assertEqual( events[0].edits[0].source_in , "00:00:00:00") + self.assertEqual( events[0].edits[0].source_out , "00:00:00:00") + self.assertEqual( events[0].edits[0].record_in , "01:00:00:00") + self.assertEqual( events[0].edits[0].record_out , "01:00:08:00") + self.assertTrue( events[0].edits[0].transition.kind == pycmx.Transition.Cut) + + + def test_multi_edit_events(self): + edl = pycmx.parse_cmx3600("tests/edls/TEST.edl") + events = list( edl.events ) + self.assertEqual( int(events[42].number) , 43) + self.assertEqual( len(events[42].edits), 2) + + self.assertEqual( events[42].edits[0].source , "TC_R1_V1") self.assertEqual( events[42].edits[0].clip_name , "TC R1 V1.2 TEMP1 FX ST.WAV") + self.assertEqual( events[42].edits[0].source_in , "00:00:00:00") + self.assertEqual( events[42].edits[0].source_out , "00:00:00:00") + self.assertEqual( events[42].edits[0].record_in , "01:08:56:09") + self.assertEqual( events[42].edits[0].record_out , "01:08:56:09") + self.assertTrue( events[42].edits[0].transition.kind == pycmx.Transition.Cut) + self.assertEqual( events[42].edits[1].source , "TC_R1_V6") self.assertEqual( events[42].edits[1].clip_name , "TC R1 V6 TEMP2 ST FX.WAV") + self.assertEqual( events[42].edits[1].source_in , "00:00:00:00") + self.assertEqual( events[42].edits[1].source_out , "00:00:00:00") + self.assertEqual( events[42].edits[1].record_in , "01:08:56:09") + self.assertEqual( events[42].edits[1].record_out , "01:08:56:11") + self.assertTrue( events[42].edits[1].transition.kind == pycmx.Transition.Dissolve) +