mirror of
https://github.com/iluvcapra/pycmx.git
synced 2025-12-31 17:00:53 +00:00
Compare commits
146 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c56d2066ad | ||
|
|
8b49a788ae | ||
|
|
b31450f03d | ||
|
|
5d14c3177a | ||
|
|
08dea6031d | ||
|
|
d23fa33558 | ||
|
|
fcc4732d1a | ||
|
|
47c1ad96f0 | ||
|
|
804f649570 | ||
|
|
58483198c3 | ||
|
|
aa01e9ad2d | ||
|
|
464052f510 | ||
|
|
3ba28a61dd | ||
|
|
b80339267a | ||
|
|
27d1073f8c | ||
|
|
0840ade312 | ||
|
|
a52e4329ce | ||
|
|
47772b21d0 | ||
|
|
7b4a76448e | ||
|
|
c6c5d15e09 | ||
|
|
c439ea1fbe | ||
|
|
68f118ab6b | ||
|
|
a20491297e | ||
|
|
9d57c2d374 | ||
|
|
1882cc5308 | ||
|
|
c57fe94335 | ||
|
|
007661ef38 | ||
|
|
f34c6dd4db | ||
|
|
eb89708bab | ||
|
|
9fde608fa0 | ||
|
|
4c4ca428f2 | ||
|
|
fe4e3b9d85 | ||
|
|
119467a884 | ||
|
|
b5a3285e64 | ||
|
|
af1c532a67 | ||
|
|
23667fb782 | ||
|
|
ce31cbb879 | ||
|
|
914e8d5525 | ||
|
|
21f8880099 | ||
|
|
348962c3f7 | ||
|
|
5e902d4926 | ||
|
|
44f751fd75 | ||
|
|
16e8754a7b | ||
|
|
fbf55ec2e6 | ||
|
|
1fab2c3d71 | ||
|
|
28c2344a53 | ||
|
|
dbf495f138 | ||
|
|
2483d94d7b | ||
|
|
dbe8a16eff | ||
|
|
dbbfc27196 | ||
|
|
f0c257f15f | ||
|
|
cbec18607a | ||
|
|
acb12b7d9d | ||
|
|
618f6422cc | ||
|
|
64001e8c78 | ||
|
|
69dc7ed1ce | ||
|
|
98b4ff9106 | ||
|
|
18c6ff658a | ||
|
|
0a4309ab77 | ||
|
|
50fea58724 | ||
|
|
4ceb4be7ab | ||
|
|
fbb2b8700d | ||
|
|
3f6ea4feee | ||
|
|
fcd84b1edf | ||
|
|
f85304d83b | ||
|
|
205c58e52c | ||
|
|
d3cdce6b99 | ||
|
|
32da584363 | ||
|
|
c74177953f | ||
|
|
5a4f57bd7e | ||
|
|
3e4c6d5955 | ||
|
|
11034dd9f1 | ||
|
|
bc02eb10fc | ||
|
|
9afe9d194d | ||
|
|
44e911d878 | ||
|
|
82814522d1 | ||
|
|
26b2f5274c | ||
|
|
30ee3e0be5 | ||
|
|
82fc5f21da | ||
|
|
d4353d1e68 | ||
|
|
15d14914ea | ||
|
|
f44d5c470c | ||
|
|
ca873af772 | ||
|
|
ab40ba1fa0 | ||
|
|
782b9f7425 | ||
|
|
483efdcc32 | ||
|
|
6867f9ac4a | ||
|
|
24272569e3 | ||
|
|
16afb8fc64 | ||
|
|
d1e3eb85d3 | ||
|
|
8d3bef2c09 | ||
|
|
e0b7025fff | ||
|
|
fbe9e9eeb9 | ||
|
|
168fd16473 | ||
|
|
e4b6036ab7 | ||
|
|
ce3d8088a1 | ||
|
|
9f41758b37 | ||
|
|
07407baf96 | ||
|
|
aa309a4458 | ||
|
|
2b8dd4c1c9 | ||
|
|
387158b07c | ||
|
|
741c9d95e8 | ||
|
|
53764900ba | ||
|
|
66791081be | ||
|
|
5e49c19ac2 | ||
|
|
4593729e3a | ||
|
|
703ba1140a | ||
|
|
0f06c4de5c | ||
|
|
920af8a86d | ||
|
|
57ea48e5e8 | ||
|
|
7e13978d9a | ||
|
|
f358704139 | ||
|
|
6201633956 | ||
|
|
2924ea548b | ||
|
|
88bf68c78e | ||
|
|
6d1ca12e42 | ||
|
|
829d98f4b4 | ||
|
|
8969e31969 | ||
|
|
484d2ae98f | ||
|
|
07652eaaa8 | ||
|
|
a9124e1f97 | ||
|
|
7e709241f8 | ||
|
|
731b8fcc00 | ||
|
|
597dceb9c5 | ||
|
|
c2c83d826a | ||
|
|
08dd1f956d | ||
|
|
989d52aaee | ||
|
|
b60610aa8b | ||
|
|
6611e38b9f | ||
|
|
abcce06865 | ||
|
|
9d586342be | ||
|
|
e5f632d8a4 | ||
|
|
30cd99431b | ||
|
|
cc76223cbc | ||
|
|
966f8c1ca4 | ||
|
|
1e7aea30d4 | ||
|
|
f8ab99226b | ||
|
|
7119be58ac | ||
|
|
d976f22b92 | ||
|
|
754abb1995 | ||
|
|
68c65f01e7 | ||
|
|
772fbeb909 | ||
|
|
8a2106f849 | ||
|
|
a90f6305c3 | ||
|
|
d9978a454e | ||
|
|
fd8a790983 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -7,3 +7,6 @@
|
||||
# Python egg metadata, regenerated from source files by setuptools.
|
||||
/*.egg-info
|
||||
/build/
|
||||
|
||||
# Vim Swapfiles
|
||||
*.swp
|
||||
|
||||
17
.travis.yml
Normal file
17
.travis.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
language: python
|
||||
python:
|
||||
- "3.7"
|
||||
- "3.6"
|
||||
- "3.5"
|
||||
- "2.7"
|
||||
script:
|
||||
- "python setup.py test"
|
||||
- "py.test tests/ -v --cov pycmx --cov-report term-missing"
|
||||
install:
|
||||
- "pip install setuptools"
|
||||
before_install:
|
||||
- "pip install coverage"
|
||||
- "pip install codecov"
|
||||
- "pip install pytest-cov==2.5.0"
|
||||
after_success:
|
||||
- "codecov"
|
||||
107
README.md
107
README.md
@@ -1,60 +1,85 @@
|
||||
# pycmx
|
||||
Python CMX3600 Edit Decision List Parser
|
||||
[](https://travis-ci.com/iluvcapra/pycmx)
|
||||
[](https://codecov.io/gh/iluvcapra/pycmx)
|
||||
[](https://pycmx.readthedocs.io/en/latest/?badge=latest)   [](https://pypi.org/project/pycmx/) 
|
||||
|
||||
The `pycmx` package provides a basic interface for parsing a CMX3600 EDL.
|
||||
|
||||
# pycmx
|
||||
|
||||
The `pycmx` package provides a basic interface for parsing a CMX 3600 EDL and its most most common variations.
|
||||
|
||||
## Features
|
||||
|
||||
* The major variations of the CMX3600, the standard, "File32" and "File128"
|
||||
* The major variations of the CMX 3600: the standard, "File32" and "File128"
|
||||
formats are automatically detected and properly read.
|
||||
* Preserves relationship between events and individual edits/clips.
|
||||
* Remark or comment fields with common recognized forms are read and
|
||||
available to the client, including clip name and source file data.
|
||||
* Symbolically decodes transitions and audio channels.
|
||||
* Does not parse or validate timecodes, does not enforce framerates, does not
|
||||
parameterize timecode or framerates in any way. This makes the parser more
|
||||
tolerant of EDLs with mixed rates.
|
||||
* Unrecognized lines are accessible on the `EditList` and `Event` classes
|
||||
along with the line numbers, to help the client diagnose problems with a
|
||||
list and give the client the ability to extend the package with their own
|
||||
parsing code.
|
||||
|
||||
## Usage
|
||||
|
||||
### Opening and Parsing EDL Files
|
||||
```
|
||||
import pycmx
|
||||
pycmx.parse_cmx3600("INS4_R1_010417.edl")
|
||||
print(events[5:8])
|
||||
>>> [CmxEvent(title='INS4_R1_010417', number='000006',
|
||||
clip_name='V1A-6A', source_name='A192C008_160909_R1BY',
|
||||
channels=CmxChannelMap(v=True,a1=False,a2=False,a3=False,a4=False),
|
||||
source_start='19:26:38:13', source_finish='19:27:12:03',
|
||||
record_start='01:00:57:15', record_finish='01:01:31:05',
|
||||
fcm_drop=False),
|
||||
CmxEvent(title='INS4_R1_010417', number='000007',
|
||||
clip_name='1-4A', source_name='A188C004_160908_R1BY',
|
||||
channels=CmxChannelMap(v=True,a1=False,a2=False,a3=False,a4=False),
|
||||
source_start='19:29:48:01', source_finish='19:30:01:00',
|
||||
record_start='01:01:31:05', record_finish='01:01:44:04',
|
||||
fcm_drop=False),
|
||||
CmxEvent(title='INS4_R1_010417', number='000008',
|
||||
clip_name='2G-3', source_name='A056C007_160819_R1BY',
|
||||
channels=CmxChannelMap(v=True,a1=False,a2=False,a3=False,a4=False),
|
||||
source_start='19:56:27:14', source_finish='19:56:41:00',
|
||||
record_start='01:01:44:04', record_finish='01:01:57:14',
|
||||
fcm_drop=False)]
|
||||
>>> import pycmx
|
||||
>>> with open("tests/edls/TEST.edl") as f
|
||||
... edl = pycmx.parse_cmx3600(f)
|
||||
...
|
||||
>>> edl.title
|
||||
'DC7 R1_v8.2'
|
||||
```
|
||||
|
||||
## Known Issues/Roadmap
|
||||
### Reading Events and Edits
|
||||
|
||||
To be addressed:
|
||||
* Does not decode transitions.
|
||||
* Does not decode "M2" speed changes.
|
||||
* Does not decode repair notes, audio notes or other Avid-specific notes.
|
||||
`EditList.events` is a generator...
|
||||
|
||||
May not be addressed:
|
||||
```
|
||||
>>> events = list( edl.events )
|
||||
>>> len(events)
|
||||
120
|
||||
>>> events[43].number
|
||||
'044'
|
||||
```
|
||||
|
||||
* Does not parse source list at end of EDL.
|
||||
...and events contain 1...n edits.
|
||||
|
||||
Probably beyond the scope of this module:
|
||||
* Does not parse timecode entries
|
||||
```
|
||||
>>> events[43].edits[0].source_in
|
||||
'00:00:00:00'
|
||||
>>> events[43].edits[0].transition.cut
|
||||
True
|
||||
>>> events[43].edits[0].record_out
|
||||
'01:10:21:10'
|
||||
```
|
||||
|
||||
## Should I Use This?
|
||||
### Acessing Transitions and Enabled Channels
|
||||
|
||||
At this time, this is (at best) alpha software and the interface will be
|
||||
changing often. It may be fun to experiment with but it is not suitable
|
||||
at this time for production code.
|
||||
|
||||
Contributions are welcome and will make this module production-ready all the
|
||||
faster! Please reach out or file a ticket!
|
||||
```
|
||||
>>> events[41].edits[0].transition.dissolve
|
||||
False
|
||||
>>> events[41].edits[1].transition.dissolve
|
||||
True
|
||||
>>> events[41].edits[0].clip_name
|
||||
'TC R1 V1.2 TEMP1 DX M.WAV'
|
||||
>>> events[41].edits[1].clip_name
|
||||
'TC R1 V6 TEMP2 M DX.WAV'
|
||||
|
||||
# parsed channel maps are also
|
||||
# available to the client
|
||||
>>> events[2].edits[0].channels.get_audio_channel(7)
|
||||
True
|
||||
>>> events[2].edits[0].channels.get_audio_channel(6)
|
||||
False
|
||||
>>> for c in events[2].edits[0].channels.channels:
|
||||
... print(f"Audio channel {c} is present")
|
||||
...
|
||||
Audio channel 7 is present
|
||||
>>> events[2].edits[0].channels.video
|
||||
False
|
||||
```
|
||||
|
||||
102
bin/edl2scenelist.py
Normal file
102
bin/edl2scenelist.py
Normal file
@@ -0,0 +1,102 @@
|
||||
import pycmx
|
||||
import re
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
import logging
|
||||
|
||||
|
||||
FORMAT = '%(asctime)-15s %(message)s'
|
||||
logging.basicConfig(format=FORMAT)
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
def all_video_edits(edl):
|
||||
for event in edl.events:
|
||||
for edit in event.edits:
|
||||
if edit.channels.video:
|
||||
yield edit
|
||||
|
||||
|
||||
def get_scene_name(edit, pattern):
|
||||
scene_extractor = re.compile(pattern, re.I)
|
||||
if edit.clip_name is None:
|
||||
return None
|
||||
else:
|
||||
match_data = re.match(scene_extractor, edit.clip_name)
|
||||
if match_data:
|
||||
return match_data[1]
|
||||
else:
|
||||
return edit.clip_name
|
||||
|
||||
def output_cmx(outfile, out_list):
|
||||
outfile.write("TITLE: SCENE LIST\r\n")
|
||||
outfile.write("FCM: NON-DROP FRAME\r\n")
|
||||
|
||||
for o in out_list:
|
||||
line = "%03i AX V C 00:00:00:00 00:00:00:00 %s %s\r\n" % (0, o['start'],o['end'])
|
||||
outfile.write(line)
|
||||
outfile.write("* FROM CLIP NAME: %s\r\n" % (o['scene']) )
|
||||
|
||||
|
||||
def output_cols(outfile, out_list):
|
||||
for o in out_list:
|
||||
outfile.write("%-12s\t%-12s\t%s\n" % (o['start'], o['end'], o['scene'] ))
|
||||
|
||||
|
||||
def scene_list(infile, outfile, out_format, pattern):
|
||||
|
||||
edl = pycmx.parse_cmx3600(infile)
|
||||
|
||||
current_scene_name = None
|
||||
|
||||
grouped_edits = [ ]
|
||||
|
||||
for edit in all_video_edits(edl):
|
||||
this_scene_name = get_scene_name(edit, pattern)
|
||||
if this_scene_name is not None:
|
||||
if current_scene_name != this_scene_name:
|
||||
grouped_edits.append([ ])
|
||||
current_scene_name = this_scene_name
|
||||
|
||||
grouped_edits[-1].append(edit)
|
||||
|
||||
out_list = [ ]
|
||||
for group in grouped_edits:
|
||||
out_list.append({
|
||||
'start': group[0].record_in,
|
||||
'end': group[-1].record_out,
|
||||
'scene': get_scene_name(group[0], pattern ) }
|
||||
)
|
||||
|
||||
if out_format == 'cmx':
|
||||
output_cmx(outfile, out_list)
|
||||
if out_format == 'cols':
|
||||
output_cols(outfile, out_list)
|
||||
else:
|
||||
log.warning(f"Format {out_format} unrecognized. Will use cmx.\n")
|
||||
output_cmx(outfile, out_list)
|
||||
|
||||
|
||||
def scene_list_cli():
|
||||
parser = argparse.ArgumentParser(description=
|
||||
'Read video events from an input CMX EDL and output events merged into scenes.')
|
||||
parser.add_argument('-o','--outfile', default=sys.stdout, type=argparse.FileType('w'),
|
||||
help='Output file. Default is stdout.')
|
||||
parser.add_argument('-f','--format', default='cmx', type=str,
|
||||
help='Output format. Options are cols and cmx, cmx is the default.')
|
||||
parser.add_argument('-p','--pattern', default='V?([A-Z]*[0-9]+)',
|
||||
help='RE pattern for extracting scene name from clip name. The default is "V?([A-Z]*[0-9]+)". ' + \
|
||||
'This pattern will be matched case-insensitively.')
|
||||
parser.add_argument('input_edl', default=sys.stdin, type=argparse.FileType('r'), nargs='?',
|
||||
help='Input file. Default is stdin.')
|
||||
args = parser.parse_args()
|
||||
|
||||
infile = args.input_edl
|
||||
|
||||
scene_list(infile=infile, outfile=args.outfile , out_format=args.format, pattern=args.pattern)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
scene_list_cli()
|
||||
4
docs/.buildinfo
Normal file
4
docs/.buildinfo
Normal file
@@ -0,0 +1,4 @@
|
||||
# Sphinx build info version 1
|
||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||
config: 9f647f525db0c82aadec132928a40ec5
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
BIN
docs/.doctrees/environment.pickle
Normal file
BIN
docs/.doctrees/environment.pickle
Normal file
Binary file not shown.
BIN
docs/.doctrees/index.doctree
Normal file
BIN
docs/.doctrees/index.doctree
Normal file
Binary file not shown.
1
docs/.gitignore
vendored
Normal file
1
docs/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
build/*
|
||||
19
docs/Makefile
Normal file
19
docs/Makefile
Normal file
@@ -0,0 +1,19 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
SOURCEDIR = source
|
||||
BUILDDIR = build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
35
docs/make.bat
Normal file
35
docs/make.bat
Normal file
@@ -0,0 +1,35 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=source
|
||||
set BUILDDIR=build
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
|
||||
|
||||
:end
|
||||
popd
|
||||
186
docs/source/conf.py
Normal file
186
docs/source/conf.py
Normal file
@@ -0,0 +1,186 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file does only contain a selection of the most common options. For a
|
||||
# full list see the documentation:
|
||||
# http://www.sphinx-doc.org/en/master/config
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.abspath('../../pycmx'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = u'pycmx'
|
||||
copyright = u'2018, Jamie Hardt'
|
||||
author = u'Jamie Hardt'
|
||||
|
||||
# The short X.Y version
|
||||
version = u''
|
||||
# The full version, including alpha/beta/rc tags
|
||||
release = u''
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx.ext.githubpages',
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
# source_suffix = ['.rst', '.md']
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = []
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = None
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
html_theme_options = {'collapse_navigation': False}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
#
|
||||
# The default sidebars (for documents that don't match any pattern) are
|
||||
# defined by theme itself. Builtin themes are using these templates by
|
||||
# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
|
||||
# 'searchbox.html']``.
|
||||
#
|
||||
# html_sidebars = {}
|
||||
|
||||
|
||||
# -- Options for HTMLHelp output ---------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'pycmxdoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'pycmx.tex', u'pycmx Documentation',
|
||||
u'Jamie Hardt', 'manual'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'pycmx', u'pycmx Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Texinfo output ----------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'pycmx', u'pycmx Documentation',
|
||||
author, 'pycmx', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Epub output -------------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = project
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#
|
||||
# epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#
|
||||
# epub_uid = ''
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
epub_exclude_files = ['search.html']
|
||||
|
||||
|
||||
# -- Extension configuration -------------------------------------------------
|
||||
|
||||
# -- Options for todo extension ----------------------------------------------
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = True
|
||||
20
docs/source/index.rst
Normal file
20
docs/source/index.rst
Normal file
@@ -0,0 +1,20 @@
|
||||
.. pycmx documentation master file, created by
|
||||
sphinx-quickstart on Wed Dec 26 21:51:43 2018.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to pycmx's documentation!
|
||||
=================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 5
|
||||
:caption: API Reference:
|
||||
|
||||
pycmx
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
7
docs/source/modules.rst
Normal file
7
docs/source/modules.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
pycmx
|
||||
=====
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
pycmx
|
||||
46
docs/source/pycmx.rst
Normal file
46
docs/source/pycmx.rst
Normal file
@@ -0,0 +1,46 @@
|
||||
pycmx package
|
||||
=============
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
pycmx.channel\_map module
|
||||
-------------------------
|
||||
|
||||
.. automodule:: pycmx.channel_map
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
pycmx.parse\_cmx\_events module
|
||||
-------------------------------
|
||||
|
||||
.. automodule:: pycmx.parse_cmx_events
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
pycmx.parse\_cmx\_statements module
|
||||
-----------------------------------
|
||||
|
||||
.. automodule:: pycmx.parse_cmx_statements
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
pycmx.util module
|
||||
-----------------
|
||||
|
||||
.. automodule:: pycmx.util
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: pycmx
|
||||
:members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
@@ -1,3 +1,17 @@
|
||||
# pycmx init
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
pycmx is a module for parsing CMX 3600-style EDLs. For more information and
|
||||
examples see README.md
|
||||
|
||||
from .parse_cmx import parse_cmx3600
|
||||
This module (c) 2018 Jamie Hardt. For more information on your rights to
|
||||
copy and reuse this software, refer to the LICENSE file included with the
|
||||
distribution.
|
||||
"""
|
||||
|
||||
__version__ = '1.0'
|
||||
__author__ = 'Jamie Hardt'
|
||||
|
||||
from .parse_cmx_events import parse_cmx3600
|
||||
from .transition import Transition
|
||||
from .event import Event
|
||||
from .edit import Edit
|
||||
|
||||
106
pycmx/channel_map.py
Normal file
106
pycmx/channel_map.py
Normal file
@@ -0,0 +1,106 @@
|
||||
# pycmx
|
||||
# (c) 2018 Jamie Hardt
|
||||
|
||||
from re import (compile, match)
|
||||
|
||||
class ChannelMap:
|
||||
"""
|
||||
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 video(self):
|
||||
'True if video is included'
|
||||
return self.v
|
||||
|
||||
@property
|
||||
def channels(self):
|
||||
'A generator for each audio channel'
|
||||
for c in self._audio_channel_set:
|
||||
yield c
|
||||
|
||||
@property
|
||||
def a1(self):
|
||||
"""True if A1 is included."""
|
||||
return self.get_audio_channel(1)
|
||||
|
||||
@a1.setter
|
||||
def a1(self,val):
|
||||
self.set_audio_channel(1,val)
|
||||
|
||||
@property
|
||||
def a2(self):
|
||||
"""True if A2 is included."""
|
||||
return self.get_audio_channel(2)
|
||||
|
||||
@a2.setter
|
||||
def a2(self,val):
|
||||
self.set_audio_channel(2,val)
|
||||
|
||||
@property
|
||||
def a3(self):
|
||||
"""True if A3 is included."""
|
||||
return self.get_audio_channel(3)
|
||||
|
||||
@a3.setter
|
||||
def a3(self,val):
|
||||
self.set_audio_channel(3,val)
|
||||
|
||||
@property
|
||||
def a4(self):
|
||||
"""True if A4 is included."""
|
||||
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):
|
||||
"""True if chan_num is included."""
|
||||
return (chan_num in self._audio_channel_set)
|
||||
|
||||
def set_audio_channel(self,chan_num,enabled):
|
||||
"""If enabled is true, chan_num will be included."""
|
||||
if enabled:
|
||||
self._audio_channel_set.add(chan_num)
|
||||
elif self.get_audio_channel(chan_num):
|
||||
self._audio_channel_set.remove(chan_num)
|
||||
|
||||
def _append_event(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 _append_ext(self, audio_ext):
|
||||
self.a3 = ext.audio3
|
||||
self.a4 = ext.audio4
|
||||
|
||||
def __or__(self, other):
|
||||
"""
|
||||
Return the logical union of this channel map with another
|
||||
"""
|
||||
out_v = self.video | other.video
|
||||
out_a = self._audio_channel_set | other._audio_channel_set
|
||||
|
||||
return ChannelMap(v=out_v,audio_channels = out_a)
|
||||
@@ -1,17 +0,0 @@
|
||||
class CmxEvent:
|
||||
def __init__(self,title,number,clip_name,source_name,channels,source_start,source_finish,
|
||||
record_start, record_finish, fcm_drop, remarks = [] , unrecognized = []):
|
||||
self.title = title
|
||||
self.number = number
|
||||
self.clip_name = clip_name
|
||||
self.source_name = source_name
|
||||
self.channels = channels
|
||||
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
|
||||
|
||||
|
||||
126
pycmx/edit.py
Normal file
126
pycmx/edit.py
Normal file
@@ -0,0 +1,126 @@
|
||||
# pycmx
|
||||
# (c) 2018 Jamie Hardt
|
||||
|
||||
from .transition import Transition
|
||||
from .channel_map import ChannelMap
|
||||
from .parse_cmx_statements import StmtEffectsName
|
||||
|
||||
class Edit:
|
||||
"""
|
||||
An individual source-to-record operation, with a source roll, source and
|
||||
recorder timecode in and out, a transition and channels.
|
||||
"""
|
||||
def __init__(self, edit_statement, audio_ext_statement, clip_name_statement, source_file_statement, trans_name_statement = None):
|
||||
self.edit_statement = edit_statement
|
||||
self.audio_ext = audio_ext_statement
|
||||
self.clip_name_statement = clip_name_statement
|
||||
self.source_file_statement = source_file_statement
|
||||
self.trans_name_statement = trans_name_statement
|
||||
|
||||
@property
|
||||
def line_number(self):
|
||||
"""
|
||||
Get the line number for the "standard form" statement associated with
|
||||
this edit. Line numbers a zero-indexed, such that the
|
||||
"TITLE:" record is line zero.
|
||||
"""
|
||||
return self.edit_statement.line_number
|
||||
|
||||
@property
|
||||
def channels(self):
|
||||
"""
|
||||
Get the :obj:`ChannelMap` object associated with this Edit.
|
||||
"""
|
||||
cm = ChannelMap()
|
||||
cm._append_event(self.edit_statement.channels)
|
||||
if self.audio_ext != None:
|
||||
cm._append_ext(self.audio_ext)
|
||||
return cm
|
||||
|
||||
@property
|
||||
def transition(self):
|
||||
"""
|
||||
Get the :obj:`Transition` object associated with this edit.
|
||||
"""
|
||||
if self.trans_name_statement:
|
||||
return Transition(self.edit_statement.trans, self.edit_statement.trans_op, self.trans_name_statement.name)
|
||||
else:
|
||||
return Transition(self.edit_statement.trans, self.edit_statement.trans_op, None)
|
||||
|
||||
@property
|
||||
def source_in(self):
|
||||
"""
|
||||
Get the source in timecode.
|
||||
"""
|
||||
return self.edit_statement.source_in
|
||||
|
||||
@property
|
||||
def source_out(self):
|
||||
"""
|
||||
Get the source out timecode.
|
||||
"""
|
||||
|
||||
return self.edit_statement.source_out
|
||||
|
||||
@property
|
||||
def record_in(self):
|
||||
"""
|
||||
Get the record in timecode.
|
||||
"""
|
||||
|
||||
return self.edit_statement.record_in
|
||||
|
||||
@property
|
||||
def record_out(self):
|
||||
"""
|
||||
Get the record out timecode.
|
||||
"""
|
||||
|
||||
return self.edit_statement.record_out
|
||||
|
||||
@property
|
||||
def source(self):
|
||||
"""
|
||||
Get the source column. This is the 8, 32 or 128-character string on the
|
||||
event record line, this usually references the tape name of the source.
|
||||
"""
|
||||
return self.edit_statement.source
|
||||
|
||||
@property
|
||||
def black(self):
|
||||
"""
|
||||
Black video or silence should be used as the source for this event.
|
||||
"""
|
||||
return self.source == "BL"
|
||||
|
||||
@property
|
||||
def aux_source(self):
|
||||
"""
|
||||
An auxiliary source is the source of this event.
|
||||
"""
|
||||
return self.source == "AX"
|
||||
|
||||
@property
|
||||
def source_file(self):
|
||||
"""
|
||||
Get the source file, as attested by a "* SOURCE FILE" remark on the
|
||||
EDL. This will return None if the information is not present.
|
||||
"""
|
||||
if self.source_file_statement is None:
|
||||
return None
|
||||
else:
|
||||
return self.source_file_statement.filename
|
||||
|
||||
@property
|
||||
def clip_name(self):
|
||||
"""
|
||||
Get the clip name, as attested by a "* FROM CLIP NAME" or "* TO CLIP
|
||||
NAME" remark on the EDL. This will return None if the information is
|
||||
not present.
|
||||
"""
|
||||
if self.clip_name_statement is None:
|
||||
return None
|
||||
else:
|
||||
return self.clip_name_statement.name
|
||||
|
||||
|
||||
111
pycmx/edit_list.py
Normal file
111
pycmx/edit_list.py
Normal file
@@ -0,0 +1,111 @@
|
||||
# pycmx
|
||||
# (c) 2018 Jamie Hardt
|
||||
|
||||
from .parse_cmx_statements import (StmtUnrecognized, StmtFCM, StmtEvent, StmtSourceUMID)
|
||||
from .event import Event
|
||||
from .channel_map import ChannelMap
|
||||
|
||||
class EditList:
|
||||
"""
|
||||
Represents an entire edit decision list as returned by `parse_cmx3600()`.
|
||||
|
||||
"""
|
||||
def __init__(self, statements):
|
||||
self.title_statement = statements[0]
|
||||
self.event_statements = statements[1:]
|
||||
|
||||
|
||||
@property
|
||||
def format(self):
|
||||
"""
|
||||
The detected format of the EDL. Possible values are: `3600`,`File32`,
|
||||
`File128`, and `unknown`
|
||||
"""
|
||||
first_event = next( (s for s in self.event_statements if type(s) is StmtEvent), None)
|
||||
|
||||
if first_event:
|
||||
if first_event.format == 8:
|
||||
return '3600'
|
||||
elif first_event.format == 32:
|
||||
return 'File32'
|
||||
elif first_event.format == 128:
|
||||
return 'File128'
|
||||
else:
|
||||
return 'unknown'
|
||||
else:
|
||||
return 'unknown'
|
||||
|
||||
|
||||
@property
|
||||
def channels(self):
|
||||
"""
|
||||
Return the union of every channel channel.
|
||||
"""
|
||||
|
||||
retval = ChannelMap()
|
||||
for event in self.events:
|
||||
for edit in event.edits:
|
||||
retval = retval | edit.channels
|
||||
|
||||
return retval
|
||||
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
"""
|
||||
The title of this edit list, as attensted by the 'TITLE:' statement on
|
||||
the first line.
|
||||
"""
|
||||
'The title of the edit list'
|
||||
return self.title_statement.title
|
||||
|
||||
|
||||
@property
|
||||
def unrecognized_statements(self):
|
||||
"""
|
||||
A generator for all the unrecognized statements in the list.
|
||||
"""
|
||||
for s in self.event_statements:
|
||||
if type(s) is StmtUnrecognized:
|
||||
yield s
|
||||
|
||||
|
||||
@property
|
||||
def events(self):
|
||||
'A generator for all the events in the edit list'
|
||||
is_drop = None
|
||||
current_event_num = None
|
||||
event_statements = []
|
||||
for stmt in self.event_statements:
|
||||
if type(stmt) is StmtFCM:
|
||||
is_drop = stmt.drop
|
||||
elif type(stmt) is StmtEvent:
|
||||
if current_event_num is None:
|
||||
current_event_num = stmt.event
|
||||
event_statements.append(stmt)
|
||||
else:
|
||||
if current_event_num != stmt.event:
|
||||
yield Event(statements=event_statements)
|
||||
event_statements = [stmt]
|
||||
current_event_num = stmt.event
|
||||
else:
|
||||
event_statements.append(stmt)
|
||||
|
||||
elif type(stmt) is StmtSourceUMID:
|
||||
break
|
||||
else:
|
||||
event_statements.append(stmt)
|
||||
|
||||
yield Event(statements=event_statements)
|
||||
|
||||
@property
|
||||
def sources(self):
|
||||
"""
|
||||
A generator for all of the sources in the list
|
||||
"""
|
||||
|
||||
for stmt in self.event_statements:
|
||||
if type(stmt) is StmtSourceUMID:
|
||||
yield stmt
|
||||
|
||||
|
||||
97
pycmx/event.py
Normal file
97
pycmx/event.py
Normal file
@@ -0,0 +1,97 @@
|
||||
# pycmx
|
||||
# (c) 2018 Jamie Hardt
|
||||
|
||||
from .parse_cmx_statements import (StmtEvent, StmtClipName, StmtSourceFile, StmtAudioExt, StmtUnrecognized, StmtEffectsName)
|
||||
from .edit import Edit
|
||||
|
||||
class Event:
|
||||
"""
|
||||
Represents a collection of :class:`Edit`s, all with the same event number.
|
||||
"""
|
||||
|
||||
def __init__(self, statements):
|
||||
self.statements = statements
|
||||
|
||||
@property
|
||||
def number(self):
|
||||
"""
|
||||
Return the event number.
|
||||
"""
|
||||
return int(self._edit_statements()[0].event)
|
||||
|
||||
@property
|
||||
def edits(self):
|
||||
"""
|
||||
Returns the edits. Most events will have a single edit, a single event
|
||||
will have multiple edits when a dissolve, wipe or key transition needs
|
||||
to be performed.
|
||||
"""
|
||||
edits_audio = list( self._statements_with_audio_ext() )
|
||||
clip_names = self._clip_name_statements()
|
||||
source_files= self._source_file_statements()
|
||||
|
||||
the_zip = [edits_audio]
|
||||
|
||||
if len(edits_audio) == 2:
|
||||
cn = [None, None]
|
||||
for clip_name in clip_names:
|
||||
if clip_name.affect == 'from':
|
||||
cn[0] = clip_name
|
||||
elif clip_name.affect == 'to':
|
||||
cn[1] = clip_name
|
||||
|
||||
the_zip.append(cn)
|
||||
else:
|
||||
if len(edits_audio) == len(clip_names):
|
||||
the_zip.append(clip_names)
|
||||
else:
|
||||
the_zip.append([None] * len(edits_audio) )
|
||||
|
||||
if len(edits_audio) == len(source_files):
|
||||
the_zip.append(source_files)
|
||||
elif len(source_files) == 1:
|
||||
the_zip.append( source_files * len(edits_audio) )
|
||||
else:
|
||||
the_zip.append([None] * len(edits_audio) )
|
||||
|
||||
# attach trans name to last event
|
||||
try:
|
||||
trans_statement = self._trans_name_statements()[0]
|
||||
trans_names = [None] * (len(edits_audio) - 1)
|
||||
trans_names.append(trans_statement)
|
||||
the_zip.append(trans_names)
|
||||
except IndexError:
|
||||
the_zip.append([None] * len(edits_audio) )
|
||||
|
||||
|
||||
return [ Edit(e1[0],e1[1],n1,s1,u1) for (e1,n1,s1,u1) in zip(*the_zip) ]
|
||||
|
||||
@property
|
||||
def unrecognized_statements(self):
|
||||
"""
|
||||
A generator for all the unrecognized statements in the event.
|
||||
"""
|
||||
for s in self.statements:
|
||||
if type(s) is StmtUnrecognized:
|
||||
yield s
|
||||
|
||||
def _trans_name_statements(self):
|
||||
return [s for s in self.statements if type(s) is StmtEffectsName]
|
||||
|
||||
def _edit_statements(self):
|
||||
return [s for s in self.statements if type(s) is StmtEvent]
|
||||
|
||||
def _clip_name_statements(self):
|
||||
return [s for s in self.statements if type(s) is StmtClipName]
|
||||
|
||||
def _source_file_statements(self):
|
||||
return [s for s in self.statements if type(s) is StmtSourceFile]
|
||||
|
||||
def _statements_with_audio_ext(self):
|
||||
for (s1, s2) in zip(self.statements, self.statements[1:]):
|
||||
if type(s1) is StmtEvent and type(s2) is StmtAudioExt:
|
||||
yield (s1,s2)
|
||||
elif type(s1) is StmtEvent:
|
||||
yield (s1, None)
|
||||
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
# pycmx
|
||||
# (c) 2018 Jamie Hardt
|
||||
|
||||
from .parse_cmx_statements import parse_cmx3600_statements
|
||||
from collections import namedtuple
|
||||
|
||||
class NamedTupleParser:
|
||||
|
||||
def __init__(self, tuple_list):
|
||||
self.tokens = tuple_list
|
||||
self.current_token = None
|
||||
|
||||
def peek(self):
|
||||
return self.tokens[0]
|
||||
|
||||
def at_end(self):
|
||||
return len(self.tokens) == 0
|
||||
|
||||
def next_token(self):
|
||||
self.current_token = self.peek()
|
||||
self.tokens = self.tokens[1:]
|
||||
|
||||
def accept(self, type_name):
|
||||
if self.at_end():
|
||||
return False
|
||||
elif (type(self.peek()).__name__ == type_name ):
|
||||
self.next_token()
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def expect(self, type_name):
|
||||
assert( self.accept(type_name) )
|
||||
|
||||
|
||||
class CmxChannelMap:
|
||||
|
||||
chan_map = { "V" : (True, False, False),
|
||||
"A" : (False, True, False),
|
||||
"A2" : (False, False, True),
|
||||
"AA" : (False, True, True),
|
||||
"B" : (True, True, False),
|
||||
"V/AA" : (True, True, True),
|
||||
"V/A2" : (True, False, True)
|
||||
}
|
||||
|
||||
|
||||
def __init__(self, v=False, a1=False, a2=False, a3=False, a4=False):
|
||||
self.v = v
|
||||
self.a1 = a1
|
||||
self.a2 = a2
|
||||
self.a3 = a3
|
||||
self.a4 = a4
|
||||
|
||||
|
||||
def appendEvent(self, event_str):
|
||||
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]
|
||||
|
||||
|
||||
def appendExt(self, audio_ext):
|
||||
self.a3 = ext.audio3
|
||||
self.a4 = ext.audio4
|
||||
|
||||
def __repr__(self):
|
||||
return "CmxChannelMap(v="+ self.v.__repr__( ) + \
|
||||
",a1=" + self.a1.__repr__() + \
|
||||
",a2=" + self.a2.__repr__() + \
|
||||
",a3=" + self.a3.__repr__() + \
|
||||
",a4=" + self.a4.__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)
|
||||
|
||||
|
||||
CmxEvent = namedtuple('CmxEvent',['title','number','clip_name',
|
||||
'source_name','channels','source_start','source_finish','record_start',
|
||||
'record_finish','fcm_drop'])
|
||||
|
||||
|
||||
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:
|
||||
event_t = CmxEvent(**this_event)
|
||||
events_result.append(event_t)
|
||||
|
||||
raw_event = parser.current_token
|
||||
channels = CmxChannelMap()
|
||||
channels.appendEvent(raw_event.channels)
|
||||
|
||||
this_event = {'title': title, 'number': raw_event.event, 'clip_name': None ,
|
||||
'source_name': raw_event.source,
|
||||
'channels': channels,
|
||||
'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']}
|
||||
elif parser.accept('AudioExt'):
|
||||
this_event['channels'].appendExt(parser.current_token)
|
||||
elif parser.accept('ClipName'):
|
||||
this_event['clip_name'] = parser.current_token.name
|
||||
elif parser.accept('SourceFile'):
|
||||
this_event['source_name'] = parser.current_token.filename
|
||||
elif parser.accept('Trailer'):
|
||||
break
|
||||
else:
|
||||
parser.next_token()
|
||||
|
||||
if this_event != None:
|
||||
event_t = CmxEvent(**this_event)
|
||||
events_result.append(event_t)
|
||||
|
||||
return events_result
|
||||
|
||||
21
pycmx/parse_cmx_events.py
Normal file
21
pycmx/parse_cmx_events.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# pycmx
|
||||
# (c) 2018 Jamie Hardt
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
from .parse_cmx_statements import (parse_cmx3600_statements, StmtEvent,StmtFCM )
|
||||
from .edit_list import EditList
|
||||
|
||||
def parse_cmx3600(f):
|
||||
"""
|
||||
Parse a CMX 3600 EDL.
|
||||
|
||||
Args:
|
||||
f : a file-like object, anything that's readlines-able.
|
||||
|
||||
Returns:
|
||||
An :class:`EditList`.
|
||||
"""
|
||||
statements = parse_cmx3600_statements(f)
|
||||
return EditList(statements)
|
||||
|
||||
@@ -1,31 +1,38 @@
|
||||
# pycmx
|
||||
# (c) 2018 Jamie Hardt
|
||||
|
||||
# Parsed Statement Data Structures
|
||||
#
|
||||
# These represent individual lines that have been typed and have undergone some light symbolic parsing.
|
||||
|
||||
from .util import collimate
|
||||
import re
|
||||
import sys
|
||||
from collections import namedtuple
|
||||
from itertools import count
|
||||
|
||||
from .util import collimate
|
||||
|
||||
StmtTitle = namedtuple("Title",["title","line_number"])
|
||||
StmtFCM = namedtuple("FCM",["drop","line_number"])
|
||||
StmtEvent = namedtuple("Event",["event","source","channels","trans",\
|
||||
"trans_op","source_in","source_out","record_in","record_out","format","line_number"])
|
||||
StmtAudioExt = namedtuple("AudioExt",["audio3","audio4","line_number"])
|
||||
StmtClipName = namedtuple("ClipName",["name","affect","line_number"])
|
||||
StmtSourceFile = namedtuple("SourceFile",["filename","line_number"])
|
||||
StmtRemark = namedtuple("Remark",["text","line_number"])
|
||||
StmtEffectsName = namedtuple("EffectsName",["name","line_number"])
|
||||
StmtSourceUMID = namedtuple("Source",["name","umid","line_number"])
|
||||
StmtSplitEdit = namedtuple("SplitEdit",["video","magnitue", "line_number"])
|
||||
StmtMotionMemory = namedtuple("MotionMemory",["source","fps"]) # FIXME needs more fields
|
||||
StmtUnrecognized = namedtuple("Unrecognized",["content","line_number"])
|
||||
|
||||
|
||||
StmtTitle = namedtuple("Title",["title"])
|
||||
StmtFCM = namedtuple("FCM",["drop"])
|
||||
StmtEvent = namedtuple("Event",["event","source","channels","trans","trans_op","source_in","source_out","record_in","record_out"])
|
||||
StmtAudioExt = namedtuple("AudioExt",["audio3","audio4"])
|
||||
StmtClipName = namedtuple("ClipName",["name"])
|
||||
StmtSourceFile = namedtuple("SourceFile",["filename"])
|
||||
StmtRemark = namedtuple("Remark",["text"])
|
||||
StmtTrailer = namedtuple("Trailer",["text"])
|
||||
StmtUnrecognized = namedtuple("Unrecognized",["content"])
|
||||
|
||||
|
||||
def parse_cmx3600_statements(path):
|
||||
with open(path,'rU') as file:
|
||||
lines = file.readlines()
|
||||
return [parse_cmx3600_line(line.strip()) for line in lines]
|
||||
def parse_cmx3600_statements(file):
|
||||
"""
|
||||
Return a list of every statement in the file argument.
|
||||
"""
|
||||
lines = file.readlines()
|
||||
line_numbers = count()
|
||||
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):
|
||||
def _edl_column_widths(event_field_length, source_field_length):
|
||||
return [event_field_length,2, source_field_length,1,
|
||||
4,2, # chans
|
||||
4,1, # trans
|
||||
@@ -34,78 +41,110 @@ def edl_column_widths(event_field_length, source_field_length):
|
||||
11,1,
|
||||
11,1,
|
||||
11]
|
||||
|
||||
def parse_cmx3600_line(line):
|
||||
|
||||
def _edl_m2_column_widths():
|
||||
return [2, # "M2"
|
||||
3,3, #
|
||||
8,8,1,4,2,1,4,13,3,1,1]
|
||||
|
||||
|
||||
def _parse_cmx3600_line(line, line_number):
|
||||
long_event_num_p = re.compile("^[0-9]{6} ")
|
||||
short_event_num_p = re.compile("^[0-9]{3} ")
|
||||
|
||||
if isinstance(line,str):
|
||||
if line.startswith("TITLE:"):
|
||||
return parse_title(line)
|
||||
return _parse_title(line,line_number)
|
||||
elif line.startswith("FCM:"):
|
||||
return parse_fcm(line)
|
||||
return _parse_fcm(line, line_number)
|
||||
elif long_event_num_p.match(line) != None:
|
||||
length_file_128 = sum(edl_column_widths(6,128))
|
||||
length_file_128 = sum(_edl_column_widths(6,128))
|
||||
if len(line) < length_file_128:
|
||||
return parse_long_standard_form(line, 32)
|
||||
return _parse_long_standard_form(line, 32, line_number)
|
||||
else:
|
||||
return parse_long_standard_form(line, 128)
|
||||
return _parse_long_standard_form(line, 128, line_number)
|
||||
elif short_event_num_p.match(line) != None:
|
||||
return parse_standard_form(line)
|
||||
return _parse_standard_form(line, line_number)
|
||||
elif line.startswith("AUD"):
|
||||
return parse_extended_audio_channels(line)
|
||||
return _parse_extended_audio_channels(line,line_number)
|
||||
elif line.startswith("*"):
|
||||
return parse_remark( line[1:].strip())
|
||||
elif line.startswith(">>>"):
|
||||
return parse_trailer_statement(line)
|
||||
return _parse_remark( line[1:].strip(), line_number)
|
||||
elif line.startswith(">>> SOURCE"):
|
||||
return _parse_source_umid_statement(line, line_number)
|
||||
elif line.startswith("EFFECTS NAME IS"):
|
||||
return _parse_effects_name(line, line_number)
|
||||
elif line.startswith("SPLIT:"):
|
||||
return _parse_split(line, line_number)
|
||||
elif line.startswith("M2"):
|
||||
return _parse_motion_memory(line, line_number)
|
||||
else:
|
||||
return parse_unrecognized(line)
|
||||
return _parse_unrecognized(line, line_number)
|
||||
|
||||
|
||||
def parse_title(line):
|
||||
def _parse_title(line, line_num):
|
||||
title = line[6:].strip()
|
||||
return StmtTitle(title=title)
|
||||
return StmtTitle(title=title,line_number=line_num)
|
||||
|
||||
def parse_fcm(line):
|
||||
def _parse_fcm(line, line_num):
|
||||
val = line[4:].strip()
|
||||
if val == "DROP FRAME":
|
||||
return StmtFCM(drop= True)
|
||||
return StmtFCM(drop= True, line_number=line_num)
|
||||
else:
|
||||
return StmtFCM(drop= False)
|
||||
return StmtFCM(drop= False, line_number=line_num)
|
||||
|
||||
def parse_long_standard_form(line,source_field_length):
|
||||
return parse_columns_for_standard_form(line, 6, source_field_length)
|
||||
def _parse_long_standard_form(line,source_field_length, line_number):
|
||||
return _parse_columns_for_standard_form(line, 6, source_field_length, line_number)
|
||||
|
||||
def parse_standard_form(line):
|
||||
return parse_columns_for_standard_form(line, 3, 8)
|
||||
def _parse_standard_form(line, line_number):
|
||||
return _parse_columns_for_standard_form(line, 3, 8, line_number)
|
||||
|
||||
def parse_extended_audio_channels(line):
|
||||
def _parse_extended_audio_channels(line, line_number):
|
||||
content = line.strip()
|
||||
if content == "AUD 3":
|
||||
return StmtAudioExt(audio3=True, audio4=False)
|
||||
return StmtAudioExt(audio3=True, audio4=False, line_number=line_number)
|
||||
elif content == "AUD 4":
|
||||
return StmtAudioExt(audio3=False, audio4=True)
|
||||
return StmtAudioExt(audio3=False, audio4=True, line_number=line_number)
|
||||
elif content == "AUD 3 4":
|
||||
return StmtAudioExt(audio3=True, audio4=True)
|
||||
return StmtAudioExt(audio3=True, audio4=True, line_number=line_number)
|
||||
else:
|
||||
return StmtUnrecognized(content=line)
|
||||
return StmtUnrecognized(content=line, line_number=line_number)
|
||||
|
||||
def parse_remark(line):
|
||||
def _parse_remark(line, line_number):
|
||||
if line.startswith("FROM CLIP NAME:"):
|
||||
return StmtClipName(name=line[15:].strip() )
|
||||
return StmtClipName(name=line[15:].strip() , affect="from", line_number=line_number)
|
||||
elif line.startswith("TO CLIP NAME:"):
|
||||
return StmtClipName(name=line[13:].strip(), affect="to", line_number=line_number)
|
||||
elif line.startswith("SOURCE FILE:"):
|
||||
return StmtSourceFile(filename=line[12:].strip() )
|
||||
return StmtSourceFile(filename=line[12:].strip() , line_number=line_number)
|
||||
else:
|
||||
return StmtRemark(text=line)
|
||||
return StmtRemark(text=line, line_number=line_number)
|
||||
|
||||
def parse_unrecognized(line):
|
||||
return StmtUnrecognized(content=line)
|
||||
def _parse_effects_name(line, line_number):
|
||||
name = line[16:].strip()
|
||||
return StmtEffectsName(name=name, line_number=line_number)
|
||||
|
||||
def parse_columns_for_standard_form(line, event_field_length, source_field_length):
|
||||
col_widths = edl_column_widths(event_field_length, source_field_length)
|
||||
def _parse_split(line, line_number):
|
||||
split_type = line[10:21]
|
||||
is_video = False
|
||||
if split_type.startswith("VIDEO"):
|
||||
is_video = True
|
||||
|
||||
split_mag = line[24:35]
|
||||
return StmtSplitEdit(video=is_video, magnitude=split_mag, line_number=line_number)
|
||||
|
||||
|
||||
def _parse_motion_memory(line, line_number):
|
||||
return StmtMotionMemory(source = "", fps="")
|
||||
|
||||
|
||||
def _parse_unrecognized(line, line_number):
|
||||
return StmtUnrecognized(content=line, line_number=line_number)
|
||||
|
||||
def _parse_columns_for_standard_form(line, event_field_length, source_field_length, line_number):
|
||||
col_widths = _edl_column_widths(event_field_length, source_field_length)
|
||||
|
||||
if sum(col_widths) > len(line):
|
||||
return StmtUnrecognized(content=line)
|
||||
return StmtUnrecognized(content=line, line_number=line_number)
|
||||
|
||||
column_strings = collimate(line,col_widths)
|
||||
|
||||
@@ -117,10 +156,12 @@ def parse_columns_for_standard_form(line, event_field_length, source_field_lengt
|
||||
source_in=column_strings[10].strip(),
|
||||
source_out=column_strings[12].strip(),
|
||||
record_in=column_strings[14].strip(),
|
||||
record_out=column_strings[16].strip())
|
||||
record_out=column_strings[16].strip(),
|
||||
line_number=line_number,
|
||||
format=source_field_length)
|
||||
|
||||
|
||||
def parse_trailer_statement(line):
|
||||
def _parse_source_umid_statement(line, line_number):
|
||||
trimmed = line[3:].strip()
|
||||
return StmtTrailer(trimmed)
|
||||
return StmtSourceUMID(name=None, umid=None, line_number=line_number)
|
||||
|
||||
|
||||
86
pycmx/transition.py
Normal file
86
pycmx/transition.py
Normal file
@@ -0,0 +1,86 @@
|
||||
# pycmx
|
||||
# (c) 2018 Jamie Hardt
|
||||
|
||||
class Transition:
|
||||
"""
|
||||
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, name=None):
|
||||
self.transition = transition
|
||||
self.operand = operand
|
||||
self.name = name
|
||||
|
||||
@property
|
||||
def kind(self):
|
||||
"""
|
||||
Return the kind of transition: Cut, Wipe, etc
|
||||
"""
|
||||
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 edit is a key background."
|
||||
return self.transition == KeyBackground
|
||||
|
||||
@property
|
||||
def key_foreground(self):
|
||||
"`True` if this edit is a key foreground."
|
||||
return self.transition == Key
|
||||
|
||||
@property
|
||||
def key_out(self):
|
||||
"""
|
||||
`True` if this edit is a key out. This material will removed from
|
||||
the key foreground and replaced with the key background.
|
||||
"""
|
||||
return self.transition == KeyOut
|
||||
@@ -4,7 +4,22 @@
|
||||
# Utility functions
|
||||
|
||||
def collimate(a_string, column_widths):
|
||||
'Splits a string into substrings that are column_widths length.'
|
||||
"""
|
||||
Split a list-type thing, like a string, into slices that are column_widths
|
||||
length.
|
||||
|
||||
>>> collimate("a b1 c2345",[2,3,3,2])
|
||||
['a ','b1 ','c23','45']
|
||||
|
||||
Args:
|
||||
a_string: The string to split. This parameter can actually be anything
|
||||
sliceable.
|
||||
column_widths: A list of integers, each one is the length of a column.
|
||||
|
||||
Returns:
|
||||
A list of slices. The len() of the returned list will *always* equal
|
||||
len(:column_widths:).
|
||||
"""
|
||||
|
||||
if len(column_widths) == 0:
|
||||
return []
|
||||
@@ -14,4 +29,3 @@ def collimate(a_string, column_widths):
|
||||
rest = a_string[width:]
|
||||
return [element] + collimate(rest, column_widths[1:])
|
||||
|
||||
|
||||
|
||||
2
pypi_upload.sh
Executable file
2
pypi_upload.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
python3 -m twine upload --repository-url https://upload.pypi.org/legacy/ dist/*
|
||||
11
setup.py
11
setup.py
@@ -4,16 +4,21 @@ with open("README.md", "r") as fh:
|
||||
long_description = fh.read()
|
||||
|
||||
setup(name='pycmx',
|
||||
version='0.2',
|
||||
version='1.0.1',
|
||||
author='Jamie Hardt',
|
||||
author_email='jamiehardt@me.com',
|
||||
description='CMX 3600 Edit Decision List Parser',
|
||||
long_description_content_type="text/markdown",
|
||||
long_description=long_description,
|
||||
url='https://github.com/iluvcapra/pycmx',
|
||||
classifiers=['Development Status :: 3 - Alpha',
|
||||
classifiers=['Development Status :: 5 - Production/Stable',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Topic :: Multimedia',
|
||||
'Topic :: Multimedia :: Video',
|
||||
'Topic :: Text Processing'],
|
||||
'Topic :: Text Processing',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
],
|
||||
packages=['pycmx'])
|
||||
|
||||
1
tests/__init__.py
Normal file
1
tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import test_parse
|
||||
1192
tests/edls/INS4_R1_010417.edl
Normal file
1192
tests/edls/INS4_R1_010417.edl
Normal file
File diff suppressed because it is too large
Load Diff
1561
tests/edls/INS4_R1_DX_092117.edl
Normal file
1561
tests/edls/INS4_R1_DX_092117.edl
Normal file
File diff suppressed because it is too large
Load Diff
1550
tests/edls/INS4_R2_DX_092117.edl
Normal file
1550
tests/edls/INS4_R2_DX_092117.edl
Normal file
File diff suppressed because it is too large
Load Diff
1588
tests/edls/INS4_R3_DX_092117.edl
Normal file
1588
tests/edls/INS4_R3_DX_092117.edl
Normal file
File diff suppressed because it is too large
Load Diff
1872
tests/edls/INS4_R4_DX_092117.edl
Normal file
1872
tests/edls/INS4_R4_DX_092117.edl
Normal file
File diff suppressed because it is too large
Load Diff
1810
tests/edls/INS4_R5_DX_092117.edl
Normal file
1810
tests/edls/INS4_R5_DX_092117.edl
Normal file
File diff suppressed because it is too large
Load Diff
1089
tests/edls/STP R1 v082517.edl
Normal file
1089
tests/edls/STP R1 v082517.edl
Normal file
File diff suppressed because it is too large
Load Diff
585
tests/edls/TEST.edl
Normal file
585
tests/edls/TEST.edl
Normal file
@@ -0,0 +1,585 @@
|
||||
TITLE: DC7 R1_v8.2
|
||||
FCM: NON-DROP FRAME
|
||||
001 OY_HEAD_ A2 C 00:00:00:00 00:00:00:00 01:00:00:00 01:00:08:00
|
||||
* FROM CLIP NAME: HEAD LEADER MONO
|
||||
* PATCH OY_HEAD_: FROM SOURCE 1 TO RECORD 2
|
||||
* SOURCE FILE: OY_HEAD_LEADER.MOV
|
||||
002 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:00:00:00 01:04:24:06
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
003 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:00:00:00 01:04:24:07
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
004 TC_R1_V6 A11 C 00:00:00:00 00:00:00:00 01:00:00:00 01:04:24:07
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST BG.WAV
|
||||
005 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:00:00:00 01:04:24:07
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
006 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:04:24:06 01:04:24:06
|
||||
006 TC_R1_V6 A D 002 00:00:00:00 00:00:00:00 01:04:24:06 01:04:24:08
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
007 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:04:24:07 01:04:42:08
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
008 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:04:24:07 01:04:45:16
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
009 TC_R1_V6 A11 C 00:00:00:00 00:00:00:00 01:04:24:07 01:04:45:19
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST BG.WAV
|
||||
010 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:04:24:08 01:04:35:19
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
011 TC_R1_V1 A C 00:00:00:00 00:00:00:00 01:04:35:19 01:04:46:16
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
012 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:04:42:08 01:04:42:08
|
||||
012 TC_R1_V6 A12 D 002 00:00:00:00 00:00:00:00 01:04:42:08 01:04:42:10
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
013 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:04:42:10 01:04:46:23
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
014 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:04:45:16 01:04:47:00
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
015 TC_R1_V6 A11 C 00:00:00:00 00:00:00:00 01:04:45:19 01:04:45:19
|
||||
015 TC_R1_V6 A11 D 002 00:00:00:00 00:00:00:00 01:04:45:19 01:04:45:21
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST BG.WAV
|
||||
016 TC_R1_V6 A11 C 00:00:00:00 00:00:00:00 01:04:45:21 01:04:46:23
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST BG.WAV
|
||||
017 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:04:46:16 01:05:47:12
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
018 TC_R1_V6 A11 C 00:00:00:00 00:00:00:00 01:04:46:23 01:04:46:23
|
||||
018 TC_R1_V6 A11 D 002 00:00:00:00 00:00:00:00 01:04:46:23 01:04:47:01
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST BG.WAV
|
||||
019 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:04:46:23 01:04:46:23
|
||||
019 TC_R1_V6 A12 D 002 00:00:00:00 00:00:00:00 01:04:46:23 01:04:47:01
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
020 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:04:47:00 01:05:47:12
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
021 TC_R1_V6 A11 C 00:00:00:00 00:00:00:00 01:04:47:01 01:05:47:12
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST BG.WAV
|
||||
022 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:04:47:01 01:05:47:12
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
023 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:05:47:12 01:06:08:06
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
024 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:05:47:12 01:07:27:09
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
025 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:05:47:12 01:07:27:09
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
026 TC_R1_V6 A11 C 00:00:00:00 00:00:00:00 01:05:47:12 01:10:21:10
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST BG.WAV
|
||||
027 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:06:08:06 01:07:27:01
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* A12 VOL = +3.0 DB PAN L100
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
028 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:07:27:09 01:07:27:09
|
||||
028 TC_R1_V1 A D 002 00:00:00:00 00:00:00:00 01:07:27:09 01:07:27:11
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* TO CLIP NAME: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
029 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:07:27:09 01:07:27:09
|
||||
029 TC_R1_V1 A7 D 002 00:00:00:00 00:00:00:00 01:07:27:09 01:07:27:11
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* TO CLIP NAME: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* PATCH TC_R1_V3: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
030 TC_R1_V1 A C 00:00:00:00 00:00:00:00 01:07:27:11 01:07:36:22
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
031 TC_R1_V1 A7 C 00:00:00:00 00:00:00:00 01:07:27:11 01:07:36:22
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
* PATCH TC_R1_V3: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
032 TC_R1_V1 A C 00:00:00:00 00:00:00:00 01:07:36:22 01:07:36:22
|
||||
032 TC_R1_V1 A D 002 00:00:00:00 00:00:00:00 01:07:36:22 01:07:37:00
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
* TO CLIP NAME: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
033 TC_R1_V1 A7 C 00:00:00:00 00:00:00:00 01:07:36:22 01:07:36:22
|
||||
033 TC_R1_V1 A7 D 002 00:00:00:00 00:00:00:00 01:07:36:22 01:07:37:00
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
* TO CLIP NAME: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
* PATCH TC_R1_V3: FROM SOURCE 2 TO RECORD 7
|
||||
* PATCH TC_R1_V3: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
034 TC_R1_V1 A C 00:00:00:00 00:00:00:00 01:07:37:00 01:07:49:01
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
035 TC_R1_V1 A7 C 00:00:00:00 00:00:00:00 01:07:37:00 01:07:49:01
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
* PATCH TC_R1_V3: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
036 TC_R1_V1 A C 00:00:00:00 00:00:00:00 01:07:49:01 01:07:49:01
|
||||
036 TC_R1_V1 A D 002 00:00:00:00 00:00:00:00 01:07:49:01 01:07:49:03
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
* TO CLIP NAME: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
037 TC_R1_V1 A7 C 00:00:00:00 00:00:00:00 01:07:49:01 01:07:49:01
|
||||
037 TC_R1_V1 A7 D 002 00:00:00:00 00:00:00:00 01:07:49:01 01:07:49:03
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
* TO CLIP NAME: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
* PATCH TC_R1_V3: FROM SOURCE 2 TO RECORD 7
|
||||
* PATCH TC_R1_V3: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
038 TC_R1_V1 A C 00:00:00:00 00:00:00:00 01:07:49:03 01:08:56:09
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
039 TC_R1_V1 A7 C 00:00:00:00 00:00:00:00 01:07:49:03 01:08:56:09
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
* PATCH TC_R1_V3: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
040 BL A12 C 00:00:00:00 00:00:00:00 01:08:56:00 01:08:56:00
|
||||
040 TC_R1_V6 A12 D 002 00:00:00:00 00:00:00:00 01:08:56:00 01:08:56:02
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: (NULL)
|
||||
041 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:08:56:02 01:10:21:10
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
042 TC_R1_V1 A C 00:00:00:00 00:00:00:00 01:08:56:09 01:08:56:09
|
||||
042 TC_R1_V6 A D 002 00:00:00:00 00:00:00:00 01:08:56:09 01:08:56:11
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 DX M.WAV
|
||||
043 TC_R1_V1 A7 C 00:00:00:00 00:00:00:00 01:08:56:09 01:08:56:09
|
||||
043 TC_R1_V6 A7 D 002 00:00:00:00 00:00:00:00 01:08:56:09 01:08:56:11
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* PATCH TC_R1_V3: FROM SOURCE 2 TO RECORD 7
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 FX ST.WAV
|
||||
044 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:08:56:11 01:10:21:10
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
045 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:08:56:11 01:10:21:10
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
046 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:10:21:10 01:11:34:01
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
047 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:10:21:10 01:11:54:07
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
048 TC_R1_V6 A11 C 00:00:00:00 00:00:00:00 01:10:21:10 01:11:54:07
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST BG.WAV
|
||||
049 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:10:21:10 01:11:54:07
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
050 LINE_02_ A5 C 00:00:00:00 00:00:00:00 01:11:36:10 01:11:37:10
|
||||
* FROM CLIP NAME: LINE 02_08.L.WAV
|
||||
* PATCH LINE_02_: FROM SOURCE 2 TO RECORD 5
|
||||
* SOURCE FILE: LINE 02_08.L.WAV
|
||||
051 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:11:36:23 01:11:46:01
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
052 TC_R1_V6 A2 C 00:00:00:00 00:00:00:00 01:11:46:01 01:11:47:08
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* A2 VOL = -3.0 DB PAN L100
|
||||
* PATCH TC_R1_V6: FROM SOURCE 1 TO RECORD 2
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
053 TC_R1_V6 A2 C 00:00:00:00 00:00:00:00 01:11:47:08 01:11:47:20
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* A2 VOL = -3.0 DB PAN L100
|
||||
* PATCH TC_R1_V6: FROM SOURCE 1 TO RECORD 2
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
054 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:11:47:19 01:11:48:07
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* A1 VOL = -3.0 DB PAN R100
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
055 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:11:48:07 01:11:54:07
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
056 TC_R1_V6 A11 C 00:00:00:00 00:00:00:00 01:11:54:07 01:12:09:17
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST BG.WAV
|
||||
057 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:11:54:07 01:12:10:04
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
058 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:11:54:07 01:12:12:10
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
059 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:11:54:07 01:12:17:01
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
060 BL A10 C 00:00:00:00 00:00:00:00 01:12:09:16 01:12:09:16
|
||||
060 TC_R1_V1 A10 D 002 00:00:00:00 00:00:00:00 01:12:09:16 01:12:09:18
|
||||
* TO CLIP NAME: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
* A10 VOL = +6.0 DB PAN L100
|
||||
* PATCH TC_R1_V1: FROM SOURCE 2 TO RECORD 10
|
||||
* SOURCE FILE: (NULL)
|
||||
061 TC_R1_V1 A10 C 00:00:00:00 00:00:00:00 01:12:09:18 01:12:26:22
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
* A10 VOL = +6.0 DB PAN L100
|
||||
* PATCH TC_R1_V1: FROM SOURCE 2 TO RECORD 10
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
062 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:12:10:04 01:12:10:04
|
||||
062 TC_R1_V6 A D 002 00:00:00:00 00:00:00:00 01:12:10:04 01:12:10:06
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
063 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:12:10:06 01:12:10:22
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
064 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:12:10:22 01:12:10:22
|
||||
064 TC_R1_V6 A D 002 00:00:00:00 00:00:00:00 01:12:10:22 01:12:11:00
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
065 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:12:11:00 01:12:17:01
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
066 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:12:12:10 01:12:17:01
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
067 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:12:17:01 01:12:27:00
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
068 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:12:17:01 01:12:27:00
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
069 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:12:17:01 01:12:27:00
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
070 TC_R1_V1 A10 C 00:00:00:00 00:00:00:00 01:12:26:22 01:12:26:22
|
||||
070 TC_R1_V1 A10 D 004 00:00:00:00 00:00:00:00 01:12:26:22 01:12:27:02
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
* TO CLIP NAME: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
* A10 VOL = +6.0 DB PAN L100
|
||||
* A10 VOL = +6.0 DB PAN L100
|
||||
* PATCH TC_R1_V1: FROM SOURCE 2 TO RECORD 10
|
||||
* PATCH TC_R1_V1: FROM SOURCE 2 TO RECORD 10
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
071 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:12:27:00 01:12:50:19
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
072 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:12:27:00 01:12:50:19
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
073 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:12:27:00 01:12:50:19
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
074 TC_R1_V1 A10 C 00:00:00:00 00:00:00:00 01:12:27:02 01:13:14:13
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
* A10 VOL = +6.0 DB PAN L100
|
||||
* PATCH TC_R1_V1: FROM SOURCE 2 TO RECORD 10
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
075 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:12:50:19 01:13:00:09
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
076 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:12:50:19 01:13:00:09
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
077 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:12:50:19 01:13:00:18
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* A7 VOL = +0.0 DB PAN R100
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
078 SROY-12B A C 17:03:33:22 17:03:40:16 01:13:00:09 01:13:07:03
|
||||
* FROM CLIP NAME: 20A-1A
|
||||
* SOURCE FILE: A079C004_170801_R0M8
|
||||
079 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:13:00:09 01:13:12:00
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
080 TC_R1_V6 A8 C 00:00:00:00 00:00:00:00 01:13:04:23 01:13:07:22
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* A8 VOL = -6.0 DB PAN L100
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 8
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
081 SROY-12B A2 C 17:13:10:23 17:13:12:22 01:13:07:00 01:13:08:23
|
||||
* FROM CLIP NAME: 20A-2A
|
||||
* PATCH SROY-12B: FROM SOURCE 1 TO RECORD 2
|
||||
* SOURCE FILE: A079C004_170801_R0M8
|
||||
082 TC_R1_V6 A8 C 00:00:00:00 00:00:00:00 01:13:07:22 01:13:07:22
|
||||
082 TC_R1_V6 A8 D 380 00:00:00:00 00:00:00:00 01:13:07:22 01:13:23:18
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* A8 VOL = -6.0 DB PAN L100
|
||||
* A8 VOL = +0.0 DB PAN L100
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 8
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 8
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* REPAIR: TRANSITION DURATION TRIMMED FROM 380 FRAMES DUE TO FORMAT LIMITS
|
||||
083 SROY-12B A C 17:03:42:07 17:03:43:11 01:13:08:18 01:13:09:22
|
||||
* FROM CLIP NAME: 20A-1A
|
||||
* SOURCE FILE: A079C004_170801_R0M8
|
||||
084 SROY-12B A2 C 17:13:02:03 17:13:03:13 01:13:09:17 01:13:11:03
|
||||
* FROM CLIP NAME: 20A-2A
|
||||
* PATCH SROY-12B: FROM SOURCE 1 TO RECORD 2
|
||||
* SOURCE FILE: A079C004_170801_R0M8
|
||||
085 SROY-12B A2 C 17:13:03:13 17:13:03:13 01:13:11:03 01:13:11:03
|
||||
085 SROY-12B A2 D 002 17:13:10:22 17:13:11:00 01:13:11:03 01:13:11:05
|
||||
* FROM CLIP NAME: 20A-2A
|
||||
* TO CLIP NAME: 20A-2A
|
||||
* PATCH SROY-12B: FROM SOURCE 1 TO RECORD 2
|
||||
* PATCH SROY-12B: FROM SOURCE 1 TO RECORD 2
|
||||
* SOURCE FILE: A079C004_170801_R0M8
|
||||
086 SROY-12B A2 C 17:13:11:00 17:13:12:05 01:13:11:05 01:13:12:10
|
||||
* FROM CLIP NAME: 20A-2A
|
||||
* PATCH SROY-12B: FROM SOURCE 1 TO RECORD 2
|
||||
* SOURCE FILE: A079C004_170801_R0M8
|
||||
087 SROY-12B A C 17:03:45:12 17:03:46:07 01:13:11:23 01:13:12:18
|
||||
* FROM CLIP NAME: 20A-1A
|
||||
* SOURCE FILE: A079C004_170801_R0M8
|
||||
088 SROY-12B A2 C 17:13:09:23 17:13:11:01 01:13:12:15 01:13:13:17
|
||||
* FROM CLIP NAME: 20A-2A
|
||||
* PATCH SROY-12B: FROM SOURCE 1 TO RECORD 2
|
||||
* SOURCE FILE: A079C004_170801_R0M8
|
||||
089 SROY-12B A C 17:03:47:02 17:03:48:08 01:13:13:13 01:13:14:19
|
||||
* FROM CLIP NAME: 20A-1A
|
||||
* SOURCE FILE: A079C004_170801_R0M8
|
||||
090 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:13:13:19 01:13:19:19
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
091 TC_R1_V1 A10 C 00:00:00:00 00:00:00:00 01:13:14:13 01:13:14:13
|
||||
091 TC_R1_V1 A10 D 010 00:00:00:00 00:00:00:00 01:13:14:13 01:13:14:23
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
* TO CLIP NAME: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
* A10 VOL = +6.0 DB PAN L100
|
||||
* A10 VOL = +6.0 DB PAN L100
|
||||
* PATCH TC_R1_V1: FROM SOURCE 2 TO RECORD 10
|
||||
* PATCH TC_R1_V1: FROM SOURCE 2 TO RECORD 10
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
092 SROY-12B A2 C 17:13:09:23 17:13:12:07 01:13:14:19 01:13:17:03
|
||||
* FROM CLIP NAME: 20A-2A
|
||||
* PATCH SROY-12B: FROM SOURCE 1 TO RECORD 2
|
||||
* SOURCE FILE: A079C004_170801_R0M8
|
||||
093 TC_R1_V1 A10 C 00:00:00:00 00:00:00:00 01:13:14:23 01:13:55:05
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
* A10 VOL = +6.0 DB PAN L100
|
||||
* PATCH TC_R1_V1: FROM SOURCE 2 TO RECORD 10
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
094 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:13:17:03 01:13:24:00
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
095 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:13:19:19 01:13:19:19
|
||||
095 TC_R1_V6 A12 D 020 00:00:00:00 00:00:00:00 01:13:19:19 01:13:20:15
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
096 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:13:20:15 01:14:04:18
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
097 TC_R1_V6 A8 C 00:00:00:00 00:00:00:00 01:13:23:18 01:13:23:20
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* A8 VOL = +0.0 DB PAN L100
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 8
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
098 TC_R1_V6 A8 C 00:00:00:00 00:00:00:00 01:13:23:20 01:13:38:00
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* A8 VOL = +0.0 DB PAN L100
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 8
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
099 SROY-12B A2 C 17:13:21:08 17:13:27:18 01:13:24:00 01:13:30:10
|
||||
* FROM CLIP NAME: 20A-2A
|
||||
* PATCH SROY-12B: FROM SOURCE 1 TO RECORD 2
|
||||
* SOURCE FILE: A079C004_170801_R0M8
|
||||
100 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:13:29:10 01:14:04:18
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
101 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:13:42:04 01:13:53:15
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* A7 VOL = +0.0 DB PAN R100
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
102 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:13:53:15 01:13:53:15
|
||||
102 TC_R1_V6 A7 D 002 00:00:00:00 00:00:00:00 01:13:53:15 01:13:53:17
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* A7 VOL = +0.0 DB PAN R100
|
||||
* A7 VOL = +2.0 DB PAN R100
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
103 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:13:53:17 01:14:04:18
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* A7 VOL = +2.0 DB PAN R100
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
104 TC_R1_V1 A10 C 00:00:00:00 00:00:00:00 01:13:55:05 01:13:55:05
|
||||
104 TC_R1_V1 A10 D 008 00:00:00:00 00:00:00:00 01:13:55:05 01:13:55:13
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
* TO CLIP NAME: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
* A10 VOL = +6.0 DB PAN L100
|
||||
* PATCH TC_R1_V1: FROM SOURCE 2 TO RECORD 10
|
||||
* PATCH TC_R1_V1: FROM SOURCE 2 TO RECORD 10
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
105 TC_R1_V1 A10 C 00:00:00:00 00:00:00:00 01:13:55:13 01:14:04:17
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
* PATCH TC_R1_V1: FROM SOURCE 2 TO RECORD 10
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
106 BL A11 C 00:00:00:00 00:00:00:00 01:14:00:21 01:14:00:21
|
||||
106 TC_R1_V6 A11 D 008 00:00:00:00 00:00:00:00 01:14:00:21 01:14:01:05
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* SOURCE FILE: (NULL)
|
||||
107 TC_R1_V6 A11 C 00:00:00:00 00:00:00:00 01:14:01:05 01:14:04:18
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST BG.WAV
|
||||
108 TC_R1_V1 A10 C 00:00:00:00 00:00:00:00 01:14:04:17 01:14:04:17
|
||||
108 BL A10 D 001 00:00:00:00 00:00:00:01 01:14:04:17 01:14:04:18
|
||||
* FROM CLIP NAME: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
* PATCH TC_R1_V1: FROM SOURCE 2 TO RECORD 10
|
||||
* SOURCE FILE: TC R1 V1.2 TEMP1 BG ST.WAV
|
||||
109 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:14:04:18 01:14:08:01
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* A7 VOL = +2.0 DB PAN R100
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
110 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:14:04:18 01:14:12:01
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
111 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:14:04:18 01:14:13:07
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
112 TC_R1_V6 A11 C 00:00:00:00 00:00:00:00 01:14:04:18 01:14:13:07
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST BG.WAV
|
||||
113 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:14:08:01 01:14:08:01
|
||||
113 TC_R1_V6 A7 D 002 00:00:00:00 00:00:00:00 01:14:08:01 01:14:08:03
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* A7 VOL = +2.0 DB PAN R100
|
||||
* A7 VOL = +0.0 DB PAN R100
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
114 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:14:08:03 01:14:13:07
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* A7 VOL = +0.0 DB PAN R100
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
115 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:14:12:01 01:14:12:01
|
||||
115 TC_R1_V6 A12 D 090 00:00:00:00 00:00:00:00 01:14:12:01 01:14:15:19
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* TO CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
116 TC_R1_V6 A C 00:00:00:00 00:00:00:00 01:14:13:07 01:16:55:17
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 M DX.WAV
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 M DX.WAV
|
||||
117 TC_R1_V6 A7 C 00:00:00:00 00:00:00:00 01:14:13:07 01:16:55:17
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST FX.WAV
|
||||
* PATCH TC_R1_V5: FROM SOURCE 2 TO RECORD 7
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST FX.WAV
|
||||
118 TC_R1_V6 A11 C 00:00:00:00 00:00:00:00 01:14:13:07 01:16:55:17
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST BG.WAV
|
||||
* PATCH TC_R1_V4: FROM SOURCE 2 TO RECORD 11
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST BG.WAV
|
||||
119 TC_R1_V6 A12 C 00:00:00:00 00:00:00:00 01:14:15:19 01:16:55:17
|
||||
* FROM CLIP NAME: TC R1 V6 TEMP2 ST MX.WAV
|
||||
* PATCH TC_R1_V7: FROM SOURCE 2 TO RECORD 12
|
||||
* SOURCE FILE: TC R1 V6 TEMP2 ST MX.WAV
|
||||
120 OY_TAIL_ A2 C 00:00:00:00 00:00:00:00 01:16:51:16 01:16:55:17
|
||||
* FROM CLIP NAME: TAIL LEADER STEREO
|
||||
* PATCH OY_TAIL_: FROM SOURCE 1 TO RECORD 2
|
||||
* SOURCE FILE: OY_TAIL LEADER.MOV
|
||||
*
|
||||
* ============================================================
|
||||
* Marker Metadata
|
||||
* ------------------------------------------------------------
|
||||
*
|
||||
* Sequence name: DC7 R1_v8.2
|
||||
* Number Color Marker Name Start TC End TC Duration Track Part Comment
|
||||
* 1 White WBROGO 01:02:12:00 V1 002_020 - Phone Screen - CU
|
||||
* 2 White WBROGO 01:02:33:08 V1 004_010 - Remove Coke Logo
|
||||
* 3 White WBROGO 01:03:00:16 V1 004_020 - Remove Logo - Equal
|
||||
* 4 White WBROGO 01:03:48:03 V1 004_015 - Remove Jack Jerk / line before he says "what"
|
||||
* 5 White WBROGO 01:03:55:08 V1 004_030 - Split screen - Comp other hand into shot
|
||||
* 6 White WBROGO 01:04:21:13 V1 004_040 - Split Screen - Simple
|
||||
* 7 White WBROGO 01:04:32:19 V1 008_010 - Phone Screen - CU
|
||||
* 8 White WBROGO 01:05:34:10 V1 008_015 - Phone Screen - Distant
|
||||
* 9 White WBROGO 01:05:44:00 V1 008_020 - Phone Screen - CU
|
||||
* 10 White WBROGO 01:06:00:01 V1 011_010 - Phone Screen - Distant
|
||||
* 11 White WBROGO 01:08:16:06 V1 016_005 - Add family photos on wall behind jack to match later when sees Ash dead
|
||||
* 12 White WBROGO 01:08:30:23 V1 016_007 - Add family photos on wall behind jack to match later when sees Ash dead
|
||||
* 13 White WBROGO 01:08:36:16 V1 016_010 - Make dog look less fake / reverse to extend timing
|
||||
* 14 Red SCOTT_H 01:08:57:12 V1 Color Note: Vignette or window to focus our eye into the mirror to see the dead body
|
||||
* 15 White WBROGO 01:09:43:14 V1 016_020 - Add family photos behind Jack
|
||||
* 16 White WBROGO 01:11:16:10 V1 018_020 - Add headstones / Stabalize
|
||||
* 17 White WBROGO 01:12:39:09 V1 020_015 - Phone Screen - CU - Comp video with push in
|
||||
* 18 Red SCOTT_H 01:12:58:19 V1 NEW VFX SHOT
|
||||
* 19 White SCOTT_H 01:12:59:01 V1 VFX shot morph for performance speed.
|
||||
* 20 White WBROGO 01:13:19:22 V1 020_020 - Phone Screen - CU
|
||||
* 21 White WBROGO 01:13:37:21 V1 020_030 - Phone Screen - CU
|
||||
* 22 White WBROGO 01:13:52:12 V1 020_040 - Phone Screen - CU - Match thumb to click
|
||||
* 23 White WBROGO 01:14:22:05 V1 021_010 - remove boom reflection / clean up light when actor leans back
|
||||
* 24 White WBROGO 01:15:01:14 V1 024_010 - Remove camera operator from mirror / Phone Screen / Add picture frames on wall to match Sc 16 when Jack sees Ash dead
|
||||
* 25 White WBROGO 01:15:24:17 V1 024_020 - Phone Screen CU
|
||||
* 26 Yellow SCOTT_H 01:08:26:16 V2 Speed change.
|
||||
*
|
||||
* 27 White WBROGO 01:09:59:14 V2 016_030 - Add family photos on wall
|
||||
* 28 White WBROGO 01:11:40:22 V2 018_030 - Add headstones
|
||||
* 29 Red SCOTT_H 01:11:41:11 V2 Moved retimed
|
||||
* 30 Red SCOTT_H 01:09:10:13 A6 KEEP IN TIME LINE. ADR OF DAVID for his moans etc...to keep in timeline in case needed by JE in the mix
|
||||
>>> SOURCE SROY-12B SROY-12B 060a2b340101010101010f00-13-00-00-00-{00000511-6f6e-53f5-060e2b347f7f2a80}
|
||||
* SOURCE FILE: A079C004_170801_R0M8
|
||||
1135
tests/edls/ToD_R4_LOCK3.1_030618_Video.edl
Normal file
1135
tests/edls/ToD_R4_LOCK3.1_030618_Video.edl
Normal file
File diff suppressed because it is too large
Load Diff
60
tests/edls/test_24psf.edl
Executable file
60
tests/edls/test_24psf.edl
Executable file
@@ -0,0 +1,60 @@
|
||||
TITLE: Test EDL 24
|
||||
|
||||
001 AX V C 01:00:00:00 01:00:59:24 00:00:00:00 00:00:59:24
|
||||
* FROM CLIP NAME: clip 1
|
||||
|
||||
002 AX AA C 00:00:00:00 00:01:30:00 00:00:00:00 00:01:30:00
|
||||
* FROM CLIP NAME: clip #2
|
||||
|
||||
003 AX V C 00:00:00:00 00:00:30:01 00:00:59:24 00:01:30:00
|
||||
* FROM CLIP NAME: clip -3
|
||||
AUD 3 4
|
||||
|
||||
004 AX V C 00:00:00:00 00:00:24:17 00:01:30:00 00:01:54:17
|
||||
* FROM CLIP NAME: clip $4
|
||||
|
||||
005 AX V C 00:00:00:00 00:00:24:17 00:01:30:00 00:01:54:17
|
||||
* FROM CLIP NAME: clip &5
|
||||
|
||||
006 AX AA C 00:00:29:01 00:00:29:01 00:01:59:01 00:01:59:01
|
||||
006 BL AA W001 025 00:00:00:00 00:00:10:20 00:01:59:01 00:02:10:21
|
||||
EFFECTS NAME IS Constant Power
|
||||
* FROM CLIP NAME: Test rename
|
||||
* TO CLIP NAME: BL
|
||||
|
||||
007 AX V C 01:00:00:00 01:00:05:00 00:02:01:10 00:02:06:10
|
||||
* FROM CLIP NAME: Black Video
|
||||
|
||||
008 AX V C 01:00:10:14 01:00:15:00 00:02:06:10 00:02:10:21
|
||||
* FROM CLIP NAME: Jellyfish.jpg
|
||||
|
||||
009 AX V C 00:00:00:00 00:00:30:01 00:02:10:21 00:02:40:22
|
||||
* FROM CLIP NAME: Test rename
|
||||
M2 AX -25.0 00:00:00:00
|
||||
|
||||
010 AX AA C 00:00:00:00 00:00:30:01 00:02:10:21 00:02:40:22
|
||||
* FROM CLIP NAME: Test rename
|
||||
M2 AX -25.0 00:00:00:00
|
||||
|
||||
REM The MIT License (MIT)
|
||||
REM
|
||||
REM Copyright (c) 2013 <simon@simon-hargreaves.com>
|
||||
REM
|
||||
REM Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
REM of this software and associated documentation files (the "Software"), to deal
|
||||
REM in the Software without restriction, including without limitation the rights
|
||||
REM to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
REM copies of the Software, and to permit persons to whom the Software is
|
||||
REM furnished to do so, subject to the following conditions:
|
||||
REM
|
||||
REM The above copyright notice and this permission notice shall be included in
|
||||
REM all copies or substantial portions of the Software.
|
||||
REM
|
||||
REM THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
REM IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
REM FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
REM AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
REM LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
REM OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
REM THE SOFTWARE.
|
||||
REM
|
||||
66
tests/edls/test_25.edl
Executable file
66
tests/edls/test_25.edl
Executable file
@@ -0,0 +1,66 @@
|
||||
TITLE: Sequence 01
|
||||
|
||||
001 AX V C 01:00:00:00 01:00:59:24 00:00:00:00 00:00:59:24
|
||||
* FROM CLIP NAME: Jellyfish.jpg
|
||||
|
||||
002 AX AA C 00:00:00:00 00:01:30:00 00:00:00:00 00:01:30:00
|
||||
* FROM CLIP NAME: N5_final screensaver_mp4.mov
|
||||
|
||||
003 AX V C 00:00:00:00 00:00:30:01 00:00:59:24 00:01:30:00
|
||||
* FROM CLIP NAME: Test rename
|
||||
AUD 3 4
|
||||
|
||||
004 AX V C 00:00:00:00 00:00:24:17 00:01:30:00 00:01:54:17
|
||||
* FROM CLIP NAME: Test rename
|
||||
|
||||
005 AX V C 00:00:24:17 00:00:24:17 00:01:54:17 00:01:54:17
|
||||
005 AX V D 070 00:59:58:21 01:00:05:14 00:01:54:17 00:02:01:10
|
||||
EFFECTS NAME IS CROSS DISSOLVE
|
||||
* FROM CLIP NAME: Test rename
|
||||
* TO CLIP NAME: Jellyfish.jpg
|
||||
|
||||
006 AX AA C 00:00:00:00 00:00:29:01 00:01:30:00 00:01:59:01
|
||||
* FROM CLIP NAME: Test rename
|
||||
|
||||
007 AX AA C 00:00:29:01 00:00:29:01 00:01:59:01 00:01:59:01
|
||||
007 BL AA W001 025 00:00:00:00 00:00:10:20 00:01:59:01 00:02:10:21
|
||||
EFFECTS NAME IS Constant Power
|
||||
* FROM CLIP NAME: Test rename
|
||||
* TO CLIP NAME: BL
|
||||
|
||||
008 AX V C 01:00:00:00 01:00:05:00 00:02:01:10 00:02:06:10
|
||||
* FROM CLIP NAME: Black Video
|
||||
|
||||
009 AX V C 01:00:10:14 01:00:15:00 00:02:06:10 00:02:10:21
|
||||
* FROM CLIP NAME: Jellyfish.jpg
|
||||
|
||||
010 AX V C 00:00:00:00 00:00:30:01 00:02:10:21 00:02:40:22
|
||||
* FROM CLIP NAME: Test rename
|
||||
M2 AX -25.0 00:00:00:00
|
||||
|
||||
011 AX AA C 00:00:00:00 00:00:30:01 00:02:10:21 00:02:40:22
|
||||
* FROM CLIP NAME: Test rename
|
||||
M2 AX -25.0 00:00:00:00
|
||||
|
||||
REM The MIT License (MIT)
|
||||
REM
|
||||
REM Copyright (c) 2013 <simon@simon-hargreaves.com>
|
||||
REM
|
||||
REM Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
REM of this software and associated documentation files (the "Software"), to deal
|
||||
REM in the Software without restriction, including without limitation the rights
|
||||
REM to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
REM copies of the Software, and to permit persons to whom the Software is
|
||||
REM furnished to do so, subject to the following conditions:
|
||||
REM
|
||||
REM The above copyright notice and this permission notice shall be included in
|
||||
REM all copies or substantial portions of the Software.
|
||||
REM
|
||||
REM THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
REM IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
REM FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
REM AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
REM LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
REM OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
REM THE SOFTWARE.
|
||||
REM
|
||||
42
tests/edls/test_edl_cdl.edl
Normal file
42
tests/edls/test_edl_cdl.edl
Normal file
@@ -0,0 +1,42 @@
|
||||
TITLE: test_edl_cdl
|
||||
FCM: NON-DROP FRAME
|
||||
000001 BAAAAAAA_00001_ABCD V C 01:00:00:01 01:00:02:01 01:00:00:00 01:00:02:00
|
||||
*ASC_SOP (0.8111 0.8112 0.8113)(0.2111 0.2112 0.2113)(1.8111 1.8112 1.8113)
|
||||
*ASC_SAT 0.91
|
||||
*Descript:
|
||||
*FROM CLIP NAME: dra_001_0001_v0001
|
||||
*LOC: 1:00:01:00 YELLOW DRA_001_0001
|
||||
000002 BAAAAAAA_00001_ABCD V C 01:00:00:02 01:00:02:02 01:00:02:00 01:00:04:00
|
||||
*ASC_SOP (0.8121 0.8122 0.8123)(0.2121 0.2122 0.2123)(1.8121 1.8122 1.8123)
|
||||
*ASC_SAT 0.82
|
||||
*Descript:
|
||||
*FROM CLIP NAME: dra_001_0002_v0001
|
||||
*LOC: 1:00:03:00 YELLOW DRA_001_0002
|
||||
000003 BAAAAAAA_00001_ABCD V C 01:00:00:03 01:00:02:03 01:00:04:00 01:00:06:00
|
||||
*ASC_SOP (0.8131 0.8132 0.8133)(0.2131 0.2132 0.2133)(1.8131 1.8132 1.8133)
|
||||
*ASC_SAT 0.73
|
||||
*Descript:
|
||||
*FROM CLIP NAME: dra_001_0003_v0001
|
||||
*LOC: 1:00:05:00 YELLOW DRA_001_0003
|
||||
|
||||
REM The MIT License (MIT)
|
||||
REM
|
||||
REM Copyright (c) 2014 Simon Hargreaves
|
||||
REM
|
||||
REM Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
REM of this software and associated documentation files (the "Software"), to deal
|
||||
REM in the Software without restriction, including without limitation the rights
|
||||
REM to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
REM copies of the Software, and to permit persons to whom the Software is
|
||||
REM furnished to do so, subject to the following conditions:
|
||||
REM
|
||||
REM The above copyright notice and this permission notice shall be included in all
|
||||
REM copies or substantial portions of the Software.
|
||||
REM
|
||||
REM THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
REM IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
REM FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
REM AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
REM LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
REM OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
REM SOFTWARE.
|
||||
112
tests/test_parse.py
Normal file
112
tests/test_parse.py
Normal file
@@ -0,0 +1,112 @@
|
||||
from unittest import TestCase
|
||||
|
||||
import pycmx
|
||||
|
||||
class TestParse(TestCase):
|
||||
|
||||
files = ["INS4_R1_010417.edl" ,
|
||||
"INS4_R1_DX_092117.edl",
|
||||
"STP R1 v082517.edl",
|
||||
"ToD_R4_LOCK3.1_030618_Video.edl",
|
||||
"TEST.edl",
|
||||
"test_edl_cdl.edl",
|
||||
"INS4_R1_DX_092117.edl"
|
||||
]
|
||||
|
||||
def test_event_counts(self):
|
||||
|
||||
counts = [ 287, 466, 250 , 376, 120 , 3 , 466 ]
|
||||
|
||||
for fn, count in zip(type(self).files, counts):
|
||||
with open("tests/edls/" + fn ,'r') as f:
|
||||
edl = pycmx.parse_cmx3600(f)
|
||||
actual = len( list( edl.events ))
|
||||
self.assertTrue( actual == count ,
|
||||
"expected %i in file %s but found %i" % (count, fn, actual))
|
||||
|
||||
def test_list_sanity(self):
|
||||
for fn in type(self).files:
|
||||
with open("tests/edls/" + fn ,'r') as f:
|
||||
edl = pycmx.parse_cmx3600(f)
|
||||
self.assertTrue( type(edl.title) is str )
|
||||
self.assertTrue( len(edl.title) > 0 )
|
||||
|
||||
|
||||
def test_event_sanity(self):
|
||||
for fn in type(self).files:
|
||||
path = "tests/edls/" + fn
|
||||
with open(path ,'r') as f:
|
||||
edl = pycmx.parse_cmx3600(f)
|
||||
for index, event in enumerate(edl.events):
|
||||
self.assertTrue( len(event.edits) > 0 )
|
||||
self.assertTrue( event.number == index + 1 )
|
||||
|
||||
|
||||
|
||||
def test_events(self):
|
||||
with open("tests/edls/TEST.edl",'r') as f:
|
||||
edl = pycmx.parse_cmx3600(f)
|
||||
events = list( edl.events )
|
||||
|
||||
self.assertEqual( 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_channel_map(self):
|
||||
with open("tests/edls/TEST.edl",'r') as f:
|
||||
edl = pycmx.parse_cmx3600(f)
|
||||
events = list( edl.events )
|
||||
self.assertFalse( events[0].edits[0].channels.video)
|
||||
self.assertFalse( events[0].edits[0].channels.a1)
|
||||
self.assertTrue( events[0].edits[0].channels.a2)
|
||||
self.assertTrue( events[2].edits[0].channels.get_audio_channel(7) )
|
||||
|
||||
|
||||
def test_multi_edit_events(self):
|
||||
with open("tests/edls/TEST.edl",'r') as f:
|
||||
edl = pycmx.parse_cmx3600(f)
|
||||
events = list( edl.events )
|
||||
|
||||
self.assertEqual( 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)
|
||||
|
||||
def test_line_numbers(self):
|
||||
with open("tests/edls/ToD_R4_LOCK3.1_030618_Video.edl") as f:
|
||||
edl = pycmx.parse_cmx3600(f)
|
||||
|
||||
events = list( edl.events )
|
||||
self.assertEqual( events[0].edits[0].line_number, 2)
|
||||
self.assertEqual( events[14].edits[0].line_number, 45)
|
||||
self.assertEqual( events[180].edits[0].line_number, 544)
|
||||
|
||||
def test_transition_name(self):
|
||||
with open("tests/edls/test_25.edl","r") as f:
|
||||
edl = pycmx.parse_cmx3600(f)
|
||||
events = list(edl.events)
|
||||
self.assertEqual( events[4].edits[1].transition.name , "CROSS DISSOLVE" )
|
||||
|
||||
|
||||
# add test for edit_list.channels
|
||||
|
||||
Reference in New Issue
Block a user