[![Build Status](https://travis-ci.com/iluvcapra/pycmx.svg?branch=master)](https://travis-ci.com/iluvcapra/pycmx)
[![Documentation Status](https://readthedocs.org/projects/pycmx/badge/?version=latest)](https://pycmx.readthedocs.io/en/latest/?badge=latest) ![](https://img.shields.io/github/license/iluvcapra/pycmx.svg) ![](https://img.shields.io/pypi/pyversions/pycmx.svg) [![](https://img.shields.io/pypi/v/pycmx.svg)](https://pypi.org/project/pycmx/) ![](https://img.shields.io/pypi/wheel/pycmx.svg)


# 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 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
>>> with open("tests/edls/TEST.edl") as f
... 	edl = pycmx.parse_cmx3600(f)
...
>>> edl.title
'DC7 R1_v8.2'
```

### Reading Events and Edits

`EditList.events` is a generator...

```
>>> events = list( edl.events )  
>>> len(events)
120
>>> events[43].number 
'044'
```

...and events contain 1...n edits.

```
>>> 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'
```

### Acessing Transitions and Enabled Channels

```           
>>> 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
```

## Should I Use This?

At this time, this is (at best) beta software. I feel like the interface is 
about where where I'd like it to be but more testing is required.

Contributions are welcome and will make this module production-ready all the
faster! Please reach out or file a ticket! 
