├── .clang-format ├── .codecov.yml ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml ├── labeler.yml ├── release-drafter.yml ├── scripts │ └── release-branch.sh └── workflows │ ├── docs.yml │ ├── pr-tools.yml │ ├── pypi-publish.yml │ ├── python-package.yml │ ├── release-preview.yml │ └── release-publish.yml ├── .gitignore ├── .gitmodules ├── .readthedocs.yml ├── ADOPTERS.md ├── CMakeLists.txt ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CONTRIBUTORS.md ├── GOVERNANCE.md ├── LICENSE.txt ├── MANIFEST.in ├── Makefile ├── NOTICE.txt ├── OTIO_CLA_Corporate.pdf ├── OTIO_CLA_Individual.pdf ├── OTIO_VERSION.json ├── README.md ├── README_contrib.md ├── docs ├── Makefile ├── _static │ ├── .empty │ ├── OpenTimelineIO@3xDark.png │ ├── OpenTimelineIO@3xLight.png │ ├── OpenTimelineIO@5xDark.png │ ├── OpenTimelineIO@5xLight.png │ ├── OpenTimelineIO_Logo.pdf │ ├── OpenTimelineIO_Logo.svg │ ├── multiple_tracks.png │ ├── nested_compositions.png │ ├── otioview.png │ ├── simple_cut_list.png │ ├── spatial_coords_example1.svg │ ├── spatial_coords_example2.svg │ ├── spatial_coords_example3.svg │ ├── spatial_coords_example4.svg │ ├── spatial_coords_system.svg │ └── transitions.png ├── _templates │ └── autosummary │ │ └── module.rst ├── conf.py ├── cxx │ ├── bridges.md │ ├── cxx.rst │ └── older.md ├── index.rst ├── make.bat ├── python_reference.rst ├── requirements.txt ├── tutorials │ ├── adapters.md │ ├── architecture.md │ ├── contributing.md │ ├── developing-a-new-schema.md │ ├── feature-matrix.rst │ ├── otio-env-variables.md │ ├── otio-file-format-specification.md │ ├── otio-filebundles.md │ ├── otio-plugins.md │ ├── otio-serialized-schema-only-fields.md │ ├── otio-serialized-schema.md │ ├── otio-timeline-structure.md │ ├── quickstart.md │ ├── spatial-coordinates.md │ ├── time-ranges.md │ ├── versioning-schemas.md │ ├── write-a-hookscript.md │ ├── write-a-media-linker.md │ ├── write-a-schemadef.md │ └── write-an-adapter.md └── use-cases │ ├── animation-shot-frame-ranges.md │ ├── conform-new-renders-into-cut.md │ └── shots-added-removed-from-cut.md ├── doxygen ├── Makefile └── config │ └── dox_config ├── examples ├── CMakeLists.txt ├── build_simple_timeline.py ├── conform.cpp ├── conform.py ├── flatten_video_tracks.cpp ├── flatten_video_tracks.py ├── io_perf_test.cpp ├── python_adapters_child_process.cpp ├── python_adapters_embed.cpp ├── sample_plugin │ ├── otio_counter │ │ ├── __init__.py │ │ ├── adapter.py │ │ └── plugin_manifest.json │ └── setup.py ├── shot_detect.py ├── summarize_timing.cpp ├── summarize_timing.py ├── upgrade_downgrade_example.cpp ├── util.cpp └── util.h ├── maintainers ├── bump_version_number.py ├── download_gha_artifact.py ├── fetch_contributors.py ├── freeze_ci_versions.py ├── remove_dev_suffix.py └── verify_license.py ├── pyproject.toml ├── readthedocs-conda.yml ├── setup.cfg ├── setup.py ├── src ├── deps │ └── CMakeLists.txt ├── opentime │ ├── CMakeLists.txt │ ├── OpenTimeConfig.cmake.in │ ├── errorStatus.cpp │ ├── errorStatus.h │ ├── rationalTime.cpp │ ├── rationalTime.h │ ├── stringPrintf.h │ ├── timeRange.cpp │ ├── timeRange.h │ ├── timeTransform.cpp │ ├── timeTransform.h │ └── version.h ├── opentimelineio │ ├── CMakeLists.txt │ ├── CORE_VERSION_MAP.cpp │ ├── CORE_VERSION_MAP.last.cpp │ ├── OpenTimelineIOConfig.cmake.in │ ├── algo │ │ ├── editAlgorithm.cpp │ │ └── editAlgorithm.h │ ├── anyDictionary.h │ ├── anyVector.h │ ├── clip.cpp │ ├── clip.h │ ├── composable.cpp │ ├── composable.h │ ├── composition.cpp │ ├── composition.h │ ├── deserialization.cpp │ ├── deserialization.h │ ├── effect.cpp │ ├── effect.h │ ├── errorStatus.cpp │ ├── errorStatus.h │ ├── externalReference.cpp │ ├── externalReference.h │ ├── freezeFrame.cpp │ ├── freezeFrame.h │ ├── gap.cpp │ ├── gap.h │ ├── generatorReference.cpp │ ├── generatorReference.h │ ├── imageSequenceReference.cpp │ ├── imageSequenceReference.h │ ├── item.cpp │ ├── item.h │ ├── linearTimeWarp.cpp │ ├── linearTimeWarp.h │ ├── marker.cpp │ ├── marker.h │ ├── mediaReference.cpp │ ├── mediaReference.h │ ├── missingReference.cpp │ ├── missingReference.h │ ├── safely_typed_any.cpp │ ├── safely_typed_any.h │ ├── serializableCollection.cpp │ ├── serializableCollection.h │ ├── serializableObject.cpp │ ├── serializableObject.h │ ├── serializableObjectWithMetadata.cpp │ ├── serializableObjectWithMetadata.h │ ├── serialization.cpp │ ├── serialization.h │ ├── stack.cpp │ ├── stack.h │ ├── stackAlgorithm.cpp │ ├── stackAlgorithm.h │ ├── stringUtils.cpp │ ├── stringUtils.h │ ├── timeEffect.cpp │ ├── timeEffect.h │ ├── timeline.cpp │ ├── timeline.h │ ├── track.cpp │ ├── track.h │ ├── trackAlgorithm.cpp │ ├── trackAlgorithm.h │ ├── transition.cpp │ ├── transition.h │ ├── typeRegistry.cpp │ ├── typeRegistry.h │ ├── unknownSchema.cpp │ ├── unknownSchema.h │ ├── vectorIndexing.h │ └── version.h ├── opentimelineview │ ├── __init__.py │ ├── console.py │ ├── details_widget.py │ ├── ruler_widget.py │ ├── settings.py │ ├── timeline_widget.py │ └── track_widgets.py └── py-opentimelineio │ ├── CMakeLists.txt │ ├── opentime-bindings │ ├── CMakeLists.txt │ ├── opentime_bindings.cpp │ ├── opentime_bindings.h │ ├── opentime_rationalTime.cpp │ ├── opentime_timeRange.cpp │ └── opentime_timeTransform.cpp │ ├── opentimelineio-bindings │ ├── CMakeLists.txt │ ├── otio_anyDictionary.cpp │ ├── otio_anyDictionary.h │ ├── otio_anyVector.cpp │ ├── otio_anyVector.h │ ├── otio_bindings.cpp │ ├── otio_bindings.h │ ├── otio_errorStatusHandler.cpp │ ├── otio_errorStatusHandler.h │ ├── otio_imath.cpp │ ├── otio_serializableObjects.cpp │ ├── otio_tests.cpp │ ├── otio_utils.cpp │ └── otio_utils.h │ └── opentimelineio │ ├── __init__.py │ ├── adapters │ ├── __init__.py │ ├── adapter.py │ ├── builtin_adapters.plugin_manifest.json │ ├── file_bundle_utils.py │ ├── otio_json.py │ ├── otiod.py │ └── otioz.py │ ├── algorithms │ ├── __init__.py │ ├── filter.py │ ├── stack_algo.py │ ├── timeline_algo.py │ └── track_algo.py │ ├── console │ ├── __init__.py │ ├── autogen_plugin_documentation.py │ ├── autogen_serialized_datamodel.py │ ├── autogen_version_map.py │ ├── console_utils.py │ ├── otiocat.py │ ├── otioconvert.py │ ├── otiopluginfo.py │ ├── otiostat.py │ └── otiotool.py │ ├── core │ ├── __init__.py │ ├── _core_utils.py │ ├── composable.py │ ├── composition.py │ ├── item.py │ └── mediaReference.py │ ├── exceptions.py │ ├── hooks.py │ ├── media_linker.py │ ├── opentime.py │ ├── plugins │ ├── __init__.py │ ├── manifest.py │ └── python_plugin.py │ ├── schema │ ├── __init__.py │ ├── box2d.py │ ├── clip.py │ ├── effect.py │ ├── external_reference.py │ ├── generator_reference.py │ ├── image_sequence_reference.py │ ├── marker.py │ ├── schemadef.py │ ├── serializable_collection.py │ ├── timeline.py │ ├── transition.py │ └── v2d.py │ ├── schemadef │ └── __init__.py │ ├── test_utils.py │ ├── url_utils.py │ └── versioning.py ├── tests ├── CMakeLists.txt ├── __init__.py ├── baseline_reader.py ├── baselines │ ├── adapter_example.json │ ├── adapter_plugin_manifest.plugin_manifest.json │ ├── custom_adapter_hookscript_example.json │ ├── custom_adapter_hookscript_example.py │ ├── empty_clip.json │ ├── empty_effect.json │ ├── empty_external_reference.json │ ├── empty_gap.json │ ├── empty_generator_reference.json │ ├── empty_marker.json │ ├── empty_missingreference.json │ ├── empty_rationaltime.json │ ├── empty_serializable_collection.json │ ├── empty_stack.json │ ├── empty_timeline.json │ ├── empty_timerange.json │ ├── empty_timetransform.json │ ├── empty_track.json │ ├── empty_transition.json │ ├── example.py │ ├── example_schemadef.py │ ├── hookscript_example.json │ ├── media_linker_example.json │ ├── plugin_module │ │ ├── otio_jsonplugin.egg-info │ │ │ ├── PKG-INFO │ │ │ └── entry_points.txt │ │ ├── otio_jsonplugin │ │ │ ├── __init__.py │ │ │ └── plugin_manifest.json │ │ ├── otio_mockplugin.egg-info │ │ │ ├── PKG-INFO │ │ │ └── entry_points.txt │ │ ├── otio_mockplugin │ │ │ ├── __init__.py │ │ │ └── unusually_named_plugin_manifest.json │ │ ├── otio_override_adapter.egg-info │ │ │ ├── PKG-INFO │ │ │ └── entry_points.txt │ │ └── otio_override_adapter │ │ │ ├── __init__.py │ │ │ ├── adapter.py │ │ │ └── plugin_manifest.json │ ├── post_write_example.py │ ├── post_write_hookscript_example.json │ └── schemadef_example.json ├── consumer │ ├── CMakeLists.txt │ ├── opentime │ │ └── CMakeLists.txt │ └── opentimeline │ │ └── CMakeLists.txt ├── sample_data │ ├── OpenTimelineIO@3xDark.png │ ├── OpenTimelineIO@3xLight.png │ ├── big_int.otio │ ├── clip_example.otio │ ├── generator_reference_test.otio │ ├── multiple_track.otio │ ├── multitrack.otio │ ├── nested_example.otio │ ├── preflattened.otio │ ├── premiere_example.otio │ ├── screening_example.otio │ ├── simple_cut.otio │ ├── transition.otio │ └── transition_test.otio ├── test_adapter_plugin.py ├── test_box2d.py ├── test_builtin_adapters.py ├── test_clip.cpp ├── test_clip.py ├── test_composable.py ├── test_composition.py ├── test_console.py ├── test_core.py ├── test_core_utils.py ├── test_cxx_sdk_bindings.py ├── test_documentation.py ├── test_editAlgorithm.cpp ├── test_effect.py ├── test_examples.py ├── test_filter_algorithms.py ├── test_generator_reference.py ├── test_hooks_plugins.py ├── test_image_sequence_reference.py ├── test_item.py ├── test_json_backend.py ├── test_marker.py ├── test_media_linker.py ├── test_media_reference.py ├── test_multithreading.py ├── test_opentime.cpp ├── test_opentime.py ├── test_otiod.py ├── test_otioz.py ├── test_plugin_detection.py ├── test_schemadef_plugin.py ├── test_serializableCollection.cpp ├── test_serializable_collection.py ├── test_serializable_object.py ├── test_serialization.cpp ├── test_serialized_schema.py ├── test_stack_algo.cpp ├── test_stack_algo.py ├── test_timeline.cpp ├── test_timeline.py ├── test_timeline_algo.py ├── test_track.cpp ├── test_track.py ├── test_track_algo.py ├── test_transition.py ├── test_unknown_schema.py ├── test_url_conversions.py ├── test_v2d.py ├── test_version_manifest.py ├── utils.cpp ├── utils.h └── utils.py └── tsc └── OpenTimelineIO_TSC_Charter.md /.codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | notify: {} 3 | require_ci_to_pass: yes 4 | 5 | coverage: 6 | precision: 2 7 | round: down 8 | range: "70...95" 9 | 10 | status: 11 | project: yes 12 | patch: yes 13 | changes: yes 14 | 15 | comment: 16 | layout: "reach, diff, flags, files, footer" 17 | behavior: default 18 | require_changes: no 19 | 20 | ignore: 21 | - "*aaf2*" 22 | - "*pkg_resources*" 23 | - "*pbr*" 24 | - "*mock*" 25 | - "*PIL*" 26 | - "*funcsigs*" 27 | - "/usr/*" 28 | - "*/deps/*" 29 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.otio linguist-language=JSON 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | --- 2 | labels: triage 3 | --- 4 | 5 | # Required: 6 | ------------ 7 | [ ] I believe this isn't a duplicate topic 8 | [ ] This report is not related to an adapter 9 | 10 | For adapter related issues, please go to the appropriate repository - likely in 11 | the [OpenTimelineIO github organization](https://github.com/OpenTimelineIO/). 12 | For general questions and help please use the 13 | [Academy Software Foundation slack](https://slack.aswf.io/), 14 | [#opentimelineio](https://academysoftwarefdn.slack.com/messages/CMQ9J4BQC). 15 | 16 | ## Select One: 17 | 18 | [ ] Build problem 19 | [ ] Incorrect Functionality or bug 20 | [ ] New feature or functionality 21 | 22 | ## Description 23 | 24 | 25 | 26 | # Optional 27 | ----------- 28 | 29 | ## Environment 30 | 31 | Operating System: 32 | Python version if appropriate: 33 | 34 | ## Reproduction Steps 35 | 36 | ## Log output if appropriate 37 | 38 | ## Sample data and other attachements 39 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Link the Issue(s) this Pull Request is related to.** 2 | 3 | If there is an associated issue, link it in the form: 4 | 5 | ```Fixes #123``` 6 | 7 | Use one line for each Issue. This allows auto-closing the related issue when the fix is merged. 8 | 9 | **Summarize your change.** 10 | 11 | Describe the reason for the change. 12 | 13 | Add a list of changes, and note any that might need special attention during review. 14 | 15 | **Reference associated tests.** 16 | 17 | If no new tests are introduced as part of this PR, note the tests that are providing coverage. 18 | 19 | 23 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | 9 | - package-ecosystem: "pip" 10 | directory: "/" 11 | schedule: 12 | day: "monday" 13 | interval: "weekly" 14 | 15 | - package-ecosystem: "gitsubmodule" 16 | directory: "/" 17 | schedule: 18 | day: "monday" 19 | interval: "weekly" 20 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | # https://github.com/actions/labeler#common-examples 2 | 3 | release-candidate: 4 | - 'CHANGELOG.md' 5 | 6 | submodules: 7 | - any: ['src/deps/**'] 8 | 9 | dependencies: 10 | - any: ['pyproject.toml'] 11 | 12 | ci: 13 | - '.github/**' 14 | 15 | documentation: 16 | - any: ['docs/**'] 17 | 18 | opentime: 19 | - any: ['src/opentime/**'] 20 | 21 | 'time calculations': 22 | - any: ['src/opentime/**'] 23 | 24 | otioview: 25 | - any: ['src/opentimelineview/**'] 26 | 27 | python-bindings: 28 | - any: ['src/py-opentimelineio/**'] 29 | -------------------------------------------------------------------------------- /.github/scripts/release-branch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | # 5 | # entry script to create a release branch in ci 6 | # generates a release branch named with a utc timestamp 7 | # 8 | echo 'CREATING A RELEASE BRANCH' 9 | 10 | # create a release branch locally and remotely 11 | # normalize utc date to YYYY-MM-DD-HH-MM 12 | NEW_BRANCH_NAME="release/$(date -u +%Y-%m-%d-%H-%M)" 13 | echo "NEW BRANCH: $NEW_BRANCH_NAME" 14 | git checkout -b $NEW_BRANCH_NAME 15 | git push origin $NEW_BRANCH_NAME -------------------------------------------------------------------------------- /.github/workflows/pr-tools.yml: -------------------------------------------------------------------------------- 1 | name: Pull Request Tools 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request_target: 6 | types: [ 7 | opened, # pr is created 8 | reopened, # pr is reopened after being closed 9 | synchronize, # pr is updated with new commits 10 | ] 11 | 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.ref }} 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | # label PRs based on the files that were changed 18 | pr-labeler: 19 | name: Label Pull Requests 20 | runs-on: ubuntu-latest 21 | timeout-minutes: 8 22 | permissions: 23 | contents: read 24 | pull-requests: write 25 | steps: 26 | - name: Checkout Repo 27 | uses: actions/checkout@v4 # https://github.com/actions/checkout/tree/main#usage 28 | 29 | # https://github.com/actions/labeler#usage 30 | - uses: actions/labeler@v4 31 | with: 32 | # https://github.com/actions/labeler#inputs 33 | configuration-path: .github/labeler.yml 34 | sync-labels: true # remove labels when matching files are reverted or no longer changed by the PR 35 | dot: true # auto-include paths starting with dot (e.g.; ~/.github) 36 | -------------------------------------------------------------------------------- /.github/workflows/pypi-publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Release to PyPI 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | release: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Debug information 12 | run: | 13 | echo 'sha: ${{ github.sha }}' 14 | echo 'ref: ${{ github.ref }}' 15 | 16 | # This action will download the artifact for workflow runs that 17 | # happen for this actual commit (the commit that the tag points to). 18 | # It also restores the files timestamps. 19 | - name: Download wheels from commit ${{ github.sha }} 20 | uses: dawidd6/action-download-artifact@v8 21 | with: 22 | workflow: python-package.yml 23 | workflow_conclusion: success 24 | commit: ${{ github.sha }} 25 | name_is_regexp: true 26 | name: 'wheel-.*' 27 | path: dist 28 | 29 | - name: Download sdist from commit ${{ github.sha }} 30 | uses: dawidd6/action-download-artifact@v8 31 | with: 32 | workflow: python-package.yml 33 | workflow_conclusion: success 34 | commit: ${{ github.sha }} 35 | name: sdist 36 | path: dist 37 | 38 | - name: Publish distribution 📦 to PyPI 39 | uses: pypa/gh-action-pypi-publish@release/v1 40 | with: 41 | user: __token__ 42 | password: ${{ secrets.PYPI_API_TOKEN }} 43 | -------------------------------------------------------------------------------- /.github/workflows/release-publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Release 2 | # This workflow is called when a new release is published in GitHub. 3 | 4 | 5 | # Cancel other related workflows in-progress 6 | concurrency: 7 | group: release-publish-${{ github.ref }} 8 | cancel-in-progress: true 9 | 10 | on: 11 | release: 12 | types: [published] 13 | 14 | jobs: 15 | load-repo: 16 | name: Download GitHub repo 17 | runs-on: ubuntu-latest 18 | timeout-minutes: 5 19 | steps: 20 | - uses: actions/checkout@v4 21 | 22 | announce-release: 23 | runs-on: ubuntu-latest 24 | name: Announce successful release 25 | needs: [load-repo] 26 | steps: 27 | - name: Convert markdown to slack markdown 28 | # https://github.com/LoveToKnow/slackify-markdown-action 29 | uses: LoveToKnow/slackify-markdown-action@v1.0.0 30 | id: slack-markdown 31 | with: 32 | text: | 33 | ${{ github.ref_name }} New version of OTIO released!. 34 | [Release Notes](https://github.com/AcademySoftwareFoundation/OpenTimelineIO/releases/tag/${{ github.ref_name }}) 35 | 36 | - name: 'Slack Notification to #opentimelineio' 37 | # https://github.com/rtCamp/action-slack-notify 38 | uses: rtCamp/action-slack-notify@v2 39 | env: 40 | SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_RELEASES_URL }} 41 | SLACK_ICON: https://avatars.githubusercontent.com/u/40807682?s=512&v=4 42 | SLACK_LINK_NAMES: true 43 | SLACK_USERNAME: 'OTIO Release Bot' 44 | SLACK_CHANNEL: 'opentimelineio' 45 | SLACK_COLOR: '#5b53ff' 46 | SLACK_TITLE: 'New OTIO version released!' 47 | SLACK_MESSAGE: | 48 | ${{ steps.slack-markdown.outputs.text }} 49 | SLACK_FOOTER: | 50 | Release Published: ${{ github.ref_name }} 51 | MSG_MINIMAL: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.pyc 3 | build* 4 | dist* 5 | *.egg-info 6 | .coverage 7 | coverage.info 8 | .DS_store 9 | htmlcov 10 | .vscode/ 11 | xcuserdata/ 12 | .venv/ 13 | .cache 14 | 15 | # Pycharm metadata 16 | .idea/ 17 | 18 | # These files are generated, don't put them into source control 19 | docs/api 20 | docs/_build 21 | .tox 22 | cpp_cov_html/ 23 | lcov_html_report/ 24 | *.so 25 | *.pyd 26 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "src/deps/pybind11"] 2 | path = src/deps/pybind11 3 | url = https://github.com/pybind/pybind11.git 4 | [submodule "src/deps/rapidjson"] 5 | path = src/deps/rapidjson 6 | url = https://github.com/Tencent/rapidjson.git 7 | [submodule "src/deps/Imath"] 8 | path = src/deps/Imath 9 | url = https://github.com/AcademySoftwareFoundation/Imath 10 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # required by RTD 2 | version: 2 3 | 4 | sphinx: 5 | # Path to your Sphinx configuration file. 6 | configuration: docs/conf.py 7 | 8 | build: 9 | os: "ubuntu-20.04" 10 | tools: 11 | python: "3.10" 12 | 13 | python: 14 | install: 15 | - method: pip 16 | path: . 17 | - requirements: docs/requirements.txt 18 | 19 | submodules: 20 | include: all 21 | recursive: true 22 | -------------------------------------------------------------------------------- /ADOPTERS.md: -------------------------------------------------------------------------------- 1 | # OpenTimelineIO Adopters 2 | 3 | Below is a partial list of organizations and projects that are using OpenTimelineIO. If you would like to be added to this list, please submit a pull request to this file. 4 | 5 | | Name | Description | 6 | |------|------------------------------------------------------------------------------------------------------------------------------------------------| 7 | | [Adobe Premiere Pro](https://www.adobe.com/products/premiere.html) | [Timeline import/export](https://community.adobe.com/t5/premiere-pro-beta-discussions/new-in-beta-otio-import-and-export/td-p/14937493) (beta) | 8 | | [AVID Media Composer](https://www.avid.com/media-composer) | Timeline export (preview) | 9 | | [Black Magic Design DaVinci Resolve](https://www.blackmagicdesign.com/products/davinciresolve/) | Timeline import/export | 10 | | [CineSync](https://www.backlight.co/product/cinesync) | Timeline viewing | | 11 | | [ColorFront Transkoder](https://colorfront.com/index.php?page=SOFTWARE&spage=Transkoder) | Timeline import | 12 | | [Nuke Studio](https://www.foundry.com/products/nuke) | Timeline import/export with full timeline round-tripping | 13 | | [Hiero](https://www.foundry.com/products/nuke-family/hiero) | Timeline import/export | 14 | | [OpenRV](https://github.com/AcademySoftwareFoundation/OpenRV) | Timeline import and viewing | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md README_contrib.md CHANGELOG.md LICENSE.txt NOTICE.txt CMakeLists.txt 2 | recursive-include examples * 3 | recursive-include src * 4 | recursive-include tests * 5 | prune .github 6 | prune docs 7 | prune doxygen 8 | exclude .gitmodules 9 | recursive-exclude src *.git 10 | exclude .readthedocs.yml 11 | exclude readthedocs-conda.yml 12 | exclude .codecov.yml 13 | exclude .gitlab-ci.yml 14 | exclude *.pdf 15 | exclude ADOPTERS.md 16 | exclude CODE_OF_CONDUCT.md 17 | exclude CONTRIBUTING.md 18 | exclude CONTRIBUTORS.md 19 | exclude GOVERNANCE.md 20 | exclude Makefile 21 | exclude */.DS_Store 22 | exclude .clang-format 23 | exclude OTIO_VERSION.json 24 | global-exclude *.pyc 25 | global-exclude *.so 26 | global-exclude *.pyd 27 | 28 | prune maintainers 29 | prune tsc 30 | prune src/deps/pybind11/tools/clang 31 | prune src/deps/rapidjson/thirdparty 32 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | OpenTimelineIO 2 | Copyright Contributors to the OpenTimelineIO project. 3 | All rights reserved. 4 | 5 | This product includes software developed at: 6 | 7 | Pixar (http://www.pixar.com/). 8 | -------------------------------------------------------------------------------- /OTIO_CLA_Corporate.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/OTIO_CLA_Corporate.pdf -------------------------------------------------------------------------------- /OTIO_CLA_Individual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/OTIO_CLA_Individual.pdf -------------------------------------------------------------------------------- /OTIO_VERSION.json: -------------------------------------------------------------------------------- 1 | {"version": ["0", "18", "0"]} -------------------------------------------------------------------------------- /README_contrib.md: -------------------------------------------------------------------------------- 1 | # OpenTimelineIO Contrib Area 2 | 3 | The contrib area was a place to host adapters and application plugins submitted 4 | by the OpenTimelineIO community. Those contributions may have involved challenging external 5 | dependencies, and may not have the same level of support as the core. 6 | 7 | The adapters previously found in the contrib area have been moved to individual 8 | repos within the 9 | [OpenTimelineIO GitHub Organization](https://github.com/OpenTimelineIO/). 10 | 11 | New contributions should be created in standalone repos, and those can later be 12 | migrated to the OTIO GitHub organization after review. 13 | 14 | ## Creating New Contrib Adapters and Plugins 15 | 16 | The best way to get started is to go to the 17 | [otio-plugin-template repo](https://github.com/OpenTimelineIO/otio-plugin-template) 18 | and click "Use this template". This will get you started with plugin boilerplate 19 | and allow you to develop the adapter in your own GitHub account. 20 | 21 | Once you've developed your plugin, please contact the 22 | [OpenTimelineIO team](https://github.com/AcademySoftwareFoundation/OpenTimelineIO) 23 | to talk about next steps for the plugin. 24 | -------------------------------------------------------------------------------- /docs/_static/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/docs/_static/.empty -------------------------------------------------------------------------------- /docs/_static/OpenTimelineIO@3xDark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/docs/_static/OpenTimelineIO@3xDark.png -------------------------------------------------------------------------------- /docs/_static/OpenTimelineIO@3xLight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/docs/_static/OpenTimelineIO@3xLight.png -------------------------------------------------------------------------------- /docs/_static/OpenTimelineIO@5xDark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/docs/_static/OpenTimelineIO@5xDark.png -------------------------------------------------------------------------------- /docs/_static/OpenTimelineIO@5xLight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/docs/_static/OpenTimelineIO@5xLight.png -------------------------------------------------------------------------------- /docs/_static/OpenTimelineIO_Logo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/docs/_static/OpenTimelineIO_Logo.pdf -------------------------------------------------------------------------------- /docs/_static/multiple_tracks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/docs/_static/multiple_tracks.png -------------------------------------------------------------------------------- /docs/_static/nested_compositions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/docs/_static/nested_compositions.png -------------------------------------------------------------------------------- /docs/_static/otioview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/docs/_static/otioview.png -------------------------------------------------------------------------------- /docs/_static/simple_cut_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/docs/_static/simple_cut_list.png -------------------------------------------------------------------------------- /docs/_static/spatial_coords_example1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | (X=0.0, Y=0.0) 24 | X 25 | Y 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | min = (0.0, 0.0) 49 | max = (16.0, 9.0) 50 | 51 | 52 | 53 | (Width=16.0) 54 | 55 | 56 | 57 | (Height=9.0) 58 | 59 | 60 | -------------------------------------------------------------------------------- /docs/_static/spatial_coords_example2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | (X=0.0, Y=0.0) 24 | X 25 | Y 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | min = (-8.0, -4.5) 49 | max = (8.0, 4.5) 50 | 51 | 52 | 53 | (Width=16.0) 54 | 55 | 56 | 57 | (Height=9.0) 58 | 59 | 60 | -------------------------------------------------------------------------------- /docs/_static/spatial_coords_example3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | (X=0.0, Y=0.0) 24 | X 25 | Y 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | min = (-4.5, -4.5) 52 | max = (4.5, 4.5) 53 | 54 | 55 | 56 | (Width=9.0) 57 | 58 | 59 | 60 | (Height=9.0) 61 | 62 | 63 | -------------------------------------------------------------------------------- /docs/_static/spatial_coords_example4.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | (X=0.0, Y=0.0) 24 | X 25 | Y 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | min = (4.0, 2.25) 55 | max = (8.0, 4.5) 56 | 57 | 58 | 59 | (Width=4.0) 60 | 61 | 62 | 63 | (Height=2.25) 64 | 65 | 66 | -------------------------------------------------------------------------------- /docs/_static/spatial_coords_system.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | (X=0.0, Y=0.0) 19 | X 20 | Y 21 | 22 | -------------------------------------------------------------------------------- /docs/_static/transitions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/docs/_static/transitions.png -------------------------------------------------------------------------------- /docs/_templates/autosummary/module.rst: -------------------------------------------------------------------------------- 1 | {{ fullname }} 2 | {{ underline }} 3 | 4 | .. automodule:: {{ fullname }} 5 | :members: 6 | 7 | {% block modules %} 8 | {% if modules %} 9 | .. rubric:: Modules 10 | 11 | .. autosummary:: 12 | :toctree: 13 | :recursive: 14 | {% for item in modules %} 15 | {{ item }} 16 | {%- endfor %} 17 | {% endif %} 18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /docs/cxx/bridges.md: -------------------------------------------------------------------------------- 1 | # Language Bridges 2 | 3 | ## Python 4 | 5 | Since OTIO originated as Python (and has an extensive test suite, in Python), 6 | our starting position is that existing Python code (adapters, plugins, 7 | schemadefs) should continue to work, as currently written, with as few changes 8 | as possible. However, in anticipation of the rewrite of the core in C++, some 9 | changes are were made proactively made to ease this transition. 10 | 11 | For example, the Opentime types (e.g. ``RationalTime``) have value semantics in 12 | C++, but reference semantics in Python, which has actually been a source of 13 | bugs. Recent changes to the Python code have made the Opentime classes 14 | immutable, to ease the transition to them being entirely value types in C++. 15 | 16 | Python code in the `core` or `schema` directories were rewritten, but Python 17 | code outside those modules should required little (or in some cases no) 18 | changes. 19 | 20 | The bridge from C++ to Python (and back) is `pybind11`. Given that existing 21 | code needs to work, clearly, the bridge is implemented so as to make the 22 | reflection of the C++ datastructures, back to Python, utterly "Pythonic." (It 23 | has to be, since we didn't want to break existing code.) 24 | 25 | ## Swift 26 | 27 | The intention is to expose OTIO in Swift with the same care we take with 28 | Python: we want everything to feel utterly Swift-like. Because Swift can gain 29 | automatic API access to non-member functions written in Objective-C++, and 30 | Objective-C++ can directly use the proposed OTIO C++ API, we believe that a 31 | bridge to swift will not require writing an explicit `extern "C"` wrapper 32 | around OTIO C++. We believe that like Python, Swift should be capable of 33 | defining new schemas, and that access to existing and new schemas and their 34 | properties should be done in terms of Swift API's that conform Swift's 35 | sequence/collection protocols, just as Python interfaces do with respect to 36 | Python. 37 | 38 | ## Bridging to C (and other languages) 39 | 40 | Bridging to C (and by extension other languages) would presumably be 41 | accomplished by writing an `extern "C"` wrapper around the OTIO C++ API. This 42 | is of relatively low priority, given that we will have three languages (C++ 43 | itself, Python, and Swift) that do not need this. 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to OpenTimelineIO's documentation! 2 | ================================================== 3 | 4 | Overview 5 | -------- 6 | 7 | OpenTimelineIO (OTIO) is an API and interchange format for editorial cut information. You can think 8 | of it as a modern Edit Decision List (EDL) that also includes an API for reading, writing, and 9 | manipulating editorial data. It also includes a plugin system for translating to/from existing 10 | editorial formats as well as a plugin system for linking to proprietary media storage schemas. 11 | 12 | OTIO supports clips, timing, tracks, transitions, markers, metadata, etc. but not embedded video or 13 | audio. Video and audio media are referenced externally. We encourage 3rd party vendors, animation 14 | studios and visual effects studios to work together as a community to provide adaptors for each 15 | video editing tool and pipeline. 16 | 17 | Links 18 | --------- 19 | `OpenTimelineIO Home Page `_ 20 | 21 | `OpenTimelineIO Discussion Group `_ 22 | 23 | Quick Start 24 | ------------ 25 | .. toctree:: 26 | :maxdepth: 2 27 | :caption: Quick Start 28 | 29 | tutorials/quickstart 30 | tutorials/otio-env-variables 31 | 32 | Tutorials 33 | ------------ 34 | .. toctree:: 35 | :maxdepth: 2 36 | :caption: Tutorials 37 | 38 | tutorials/adapters 39 | tutorials/architecture 40 | tutorials/contributing 41 | tutorials/feature-matrix 42 | tutorials/otio-timeline-structure 43 | tutorials/time-ranges 44 | tutorials/otio-filebundles 45 | tutorials/write-an-adapter 46 | tutorials/write-a-media-linker 47 | tutorials/write-a-hookscript 48 | tutorials/write-a-schemadef 49 | tutorials/spatial-coordinates 50 | tutorials/developing-a-new-schema 51 | tutorials/versioning-schemas 52 | 53 | Use Cases 54 | ------------ 55 | .. toctree:: 56 | :maxdepth: 2 57 | :caption: Use Cases 58 | 59 | use-cases/animation-shot-frame-ranges 60 | use-cases/conform-new-renders-into-cut 61 | use-cases/shots-added-removed-from-cut 62 | 63 | API References 64 | -------------- 65 | 66 | 67 | .. toctree:: 68 | :maxdepth: 3 69 | :caption: API References 70 | 71 | python_reference 72 | 73 | cxx/bridges.md 74 | cxx/cxx.md 75 | cxx/older.md 76 | 77 | Schema Reference 78 | ---------------- 79 | 80 | .. toctree:: 81 | :maxdepth: 2 82 | :caption: Schema Reference 83 | 84 | tutorials/otio-file-format-specification 85 | tutorials/otio-serialized-schema 86 | tutorials/otio-serialized-schema-only-fields 87 | 88 | Autogenerated Plugin Reference 89 | ------------------------------ 90 | 91 | .. toctree:: 92 | :maxdepth: 2 93 | :caption: Plugins Reference 94 | 95 | tutorials/otio-plugins.md 96 | 97 | 98 | Indices and tables 99 | ------------------ 100 | 101 | * :ref:`genindex` 102 | * :ref:`modindex` 103 | * :ref:`search` 104 | -------------------------------------------------------------------------------- /docs/python_reference.rst: -------------------------------------------------------------------------------- 1 | Python 2 | ====== 3 | 4 | .. autosummary:: 5 | :toctree: api/python 6 | :recursive: 7 | 8 | opentimelineio 9 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx==5.3.0 2 | readthedocs-sphinx-ext==2.1.9 # ?? 3 | sphinx-rtd-theme 4 | myst-parser==0.18.1 5 | -------------------------------------------------------------------------------- /docs/tutorials/adapters.md: -------------------------------------------------------------------------------- 1 | # Adapters 2 | 3 | While OpenTimelineIO favors the `.otio` JSON format, Python OpenTimelineIO supports many file formats via adapter plugins. 4 | 5 | ## Built-In Adapters 6 | 7 | The OpenTimelineIO native file format adapters that are present in the `opentimelineio` python package are: 8 | 9 | - [otio_json](https://github.com/AcademySoftwareFoundation/OpenTimelineIO/blob/main/src/py-opentimelineio/opentimelineio/adapters/otio_json.py) - OpenTimelineIO's native file format. 10 | - [otiod](https://github.com/AcademySoftwareFoundation/OpenTimelineIO/blob/main/src/py-opentimelineio/opentimelineio/adapters/otiod.py) - a directory bundle of a `.otio` file along with referenced media. 11 | - [otioz](https://github.com/AcademySoftwareFoundation/OpenTimelineIO/blob/main/src/py-opentimelineio/opentimelineio/adapters/otioz.py) - a zip file bundle of a `.otio` file along with referenced media. 12 | 13 | ## Batteries-Included Adapters 14 | 15 | To also install a curated list of additional useful adapters, use the [OpenTimelineIO-Plugins ](https://pypi.org/project/OpenTimelineIO-Plugins/) python package. In addition to the OpenTimelineIO native adapters, you'll get additional useful adapters including: 16 | 17 | - [AAF](https://github.com/OpenTimelineIO/otio-aaf-adapter) 18 | - [ale](https://github.com/OpenTimelineIO/otio-ale-adapter) 19 | - [burnins](https://github.com/OpenTimelineIO/otio-burnins-adapter) 20 | - [cmx_3600](https://github.com/OpenTimelineIO/otio-cmx3600-adapter) 21 | - [fcp_xml](https://github.com/OpenTimelineIO/otio-fcp-adapter) 22 | - [fcpx_xml](https://github.com/OpenTimelineIO/otio-fcpx-xml-adapter) 23 | - [hls_playlist](https://github.com/OpenTimelineIO/otio-hls-playlist-adapter) 24 | - [maya_sequencer](https://github.com/OpenTimelineIO/otio-maya-sequencer-adapter) 25 | - [svg](https://github.com/OpenTimelineIO/otio-svg-adapter) 26 | - [xges](https://github.com/OpenTimelineIO/otio-xges-adapter) 27 | 28 | These adapters are supported by the broader OpenTimelineIO community. While the OTIO core team consults and sometimes contribute to their development, they may be maintained and supported at varying levels. 29 | 30 | ## Additional Adapters 31 | 32 | Below are some other adapters that may be useful to some users: 33 | 34 | - [kdenlive](https://invent.kde.org/multimedia/kdenlive-opentimelineio) 35 | 36 | ## Custom Adapters 37 | 38 | Adapters are implemented as plugins for OpenTimelineIO and can either be registered via an [environment variable](./otio-env-variables) or by packaging in a Python module with a particular entrypoint defined. For more detail, see the [Writing an OTIO Adapter](./write-an-adapter) tutorial. 39 | 40 | -------------------------------------------------------------------------------- /docs/tutorials/feature-matrix.rst: -------------------------------------------------------------------------------- 1 | Feature Matrix 2 | =============== 3 | 4 | Adapters may or may not support all of the features of OpenTimelineIO or the format they convert to/from. Here is a list of features and which adapters do/don't support those features. 5 | 6 | +-------------------------+------+-------+--------+--------+-------+--------+-------+----------+ 7 | |Feature | OTIO | EDL |FCP7 XML| FCP X | AAF | RV | ALE |GStreamer | 8 | +=========================+======+=======+========+========+=======+========+=======+==========+ 9 | |Single Track of Clips | ✔ | ✔ | ✔ | ✔ | ✔ | W-O | ✔ | ✔ | 10 | +-------------------------+------+-------+--------+--------+-------+--------+-------+----------+ 11 | |Multiple Video Tracks | ✔ | ✖ | ✔ | ✔ | ✔ | W-O | ✔ | ✔ | 12 | +-------------------------+------+-------+--------+--------+-------+--------+-------+----------+ 13 | |Audio Tracks & Clips | ✔ | ✔ | ✔ | ✔ | ✔ | W-O | ✔ | ✔ | 14 | +-------------------------+------+-------+--------+--------+-------+--------+-------+----------+ 15 | |Gap/Filler | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✖ | ✔ | 16 | +-------------------------+------+-------+--------+--------+-------+--------+-------+----------+ 17 | |Markers | ✔ | ✔ | ✔ | ✔ | ✔ | N/A | ✖ | ✔ | 18 | +-------------------------+------+-------+--------+--------+-------+--------+-------+----------+ 19 | |Nesting | ✔ | ✖ | ✔ | ✔ | ✔ | W-O | ✔ | ✔ | 20 | +-------------------------+------+-------+--------+--------+-------+--------+-------+----------+ 21 | |Transitions | ✔ | ✔ | ✖ | ✖ | ✔ | W-O | ✖ | ✔ | 22 | +-------------------------+------+-------+--------+--------+-------+--------+-------+----------+ 23 | |Audio/Video Effects | ✖ | ✖ | ✖ | ✖ | ✖ | N/A | ✖ | ✔ | 24 | +-------------------------+------+-------+--------+--------+-------+--------+-------+----------+ 25 | |Linear Speed Effects | ✔ | ✔ | ✖ | ✖ | R-O | ✖ | ✖ | ✖ | 26 | +-------------------------+------+-------+--------+--------+-------+--------+-------+----------+ 27 | |Fancy Speed Effects | ✖ | ✖ | ✖ | ✖ | ✖ | ✖ | ✖ | ✖ | 28 | +-------------------------+------+-------+--------+--------+-------+--------+-------+----------+ 29 | |Color Decision List | ✔ | ✔ | ✖ | ✖ | ✖ | ✖ | N/A | ✖ | 30 | +-------------------------+------+-------+--------+--------+-------+--------+-------+----------+ 31 | |Image Sequence Reference | ✔ | ✔ | ✖ | ✖ | ✖ | W-O | ✖ | ✔ | 32 | +-------------------------+------+-------+--------+--------+-------+--------+-------+----------+ 33 | 34 | N/A: Not Applicable 35 | W-O: Write Only 36 | R-O: Read Only 37 | -------------------------------------------------------------------------------- /docs/tutorials/otio-env-variables.md: -------------------------------------------------------------------------------- 1 | # Environment Variables 2 | 3 | This document describes the environment variables that can be used to configure 4 | various aspects of OTIO. 5 | 6 | ## Plugin Configuration 7 | 8 | These variables must be set _before_ the OpenTimelineIO python library is imported. They only impact the python library. The C++ library has no environment variables. 9 | 10 | ```{glossary} 11 | 12 | OTIO_PLUGIN_MANIFEST_PATH 13 | A colon (`:`) on POSIX system (or a semicolon (`;`) on Windows) separated string with paths 14 | to `.manifest.json` files that contain OTIO plugin manifests. 15 | See the [tutorial on how to write an adapter plugin](write-an-adapter.md) for additional details. 16 | 17 | OTIO_DEFAULT_MEDIA_LINKER 18 | The name of the default media linker to use after reading a file, if `""` then no 19 | media linker is automatically invoked. 20 | 21 | OTIO_DISABLE_ENTRYPOINTS_PLUGINS 22 | By default, OTIO will use the `importlib.metadata` entry_points mechanism to discover plugins 23 | that have been installed into the current python environment. For users who wish to disable this 24 | behavior, this variable can be set to 1. 25 | 26 | OTIO_DEFAULT_TARGET_VERSION_FAMILY_LABEL 27 | If no downgrade arguments are passed to `write_to_file`/`write_to_string`, use the downgrade manifest 28 | specified by the family/label combination in the variable. Variable is of the form `FAMILY:LABEL`. 29 | Only one tuple of `FAMILY:LABEL` may be specified. 30 | ``` 31 | 32 | ## Unit tests 33 | 34 | These variables only impact unit tests. 35 | 36 | ```{glossary} 37 | 38 | OTIO_DISABLE_SHELLOUT_TESTS 39 | When running the unit tests, skip the console tests that run the otiocat program and check output through the shell. This is desirable in environments where running the commandline tests is not meaningful or problematic. Does not disable the tests that run through python calling mechanisms. 40 | 41 | OTIO_DISABLE_SERIALIZED_SCHEMA_TEST 42 | Skip the unit tests that generate documentation and compare the current state of the schema against the stored one. Useful if the documentation is not available from the test directory. 43 | ``` 44 | -------------------------------------------------------------------------------- /docs/use-cases/conform-new-renders-into-cut.md: -------------------------------------------------------------------------------- 1 | # Conform New Renders Into The Cut 2 | 3 | **Status: Done** 4 | This use case is in active use at several feature film production studios. 5 | 6 | ## Summary 7 | 8 | Artists working on the animation or visual effects for shots in a sequence often want to view their in-progress work in the context of a current cut of the film. This could be accomplished by importing their latest renders into the editing system, but that often involves many steps (e.g. transcoding, cutting the clips into the editing system, etc.) Instead, the artists would like to preview the cut with their latest work spliced in at their desk. 9 | 10 | ## Workflow 11 | * In Editorial: 12 | 1. Export an EDL from the editorial system (Media Composer, Adobe Premiere, Final Cut Pro X, etc.) 13 | 2. Export a QuickTime audio/video mixdown that matches that EDL 14 | 3. Send the EDL+ QuickTime to the animators or visual effects artists 15 | * At the Artist's Desk: 16 | 1. Open the EDL+QuickTime in a video player tool (RV, etc.) 17 | 2. Either: 18 | 2a. Use OpenTimelineIO to convert the EDL to OTIO or 19 | 2b. A plugin in the video player tool uses OpenTimelineIO to read the EDL. 20 | 3. In either case, we link the shots in the timeline to segments of the supplied QuickTime movie. 21 | 3. The artist can now play the sequence and see exactly what the editor saw. 22 | 4. The artist can now relink any or all of the shots to the latest renders (either via OpenTimelineIO or features of the video player tool) 23 | -------------------------------------------------------------------------------- /doxygen/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Doxygen documentation 2 | # 3 | 4 | .PHONY: clean 5 | clean: 6 | rm -rf output/html output/latex output/xml 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(PythonLibs REQUIRED) 2 | 3 | include_directories(${PROJECT_SOURCE_DIR}/src 4 | ${PROJECT_SOURCE_DIR}/src/deps 5 | ${PROJECT_SOURCE_DIR}/src/deps/optional-lite/include 6 | ${PYTHON_INCLUDE_DIRS}) 7 | 8 | list(APPEND examples conform) 9 | list(APPEND examples flatten_video_tracks) 10 | list(APPEND examples summarize_timing) 11 | list(APPEND examples io_perf_test) 12 | list(APPEND examples upgrade_downgrade_example) 13 | if(OTIO_PYTHON_INSTALL) 14 | list(APPEND examples python_adapters_child_process) 15 | list(APPEND examples python_adapters_embed) 16 | endif() 17 | foreach(example ${examples}) 18 | add_executable(${example} ${example}.cpp util.h util.cpp) 19 | target_link_libraries(${example} OTIO::opentimelineio ${PYTHON_LIBRARIES}) 20 | set_target_properties(${example} PROPERTIES FOLDER examples) 21 | endforeach() 22 | -------------------------------------------------------------------------------- /examples/flatten_video_tracks.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # Copyright Contributors to the OpenTimelineIO project 5 | 6 | import opentimelineio as otio 7 | import sys 8 | import copy 9 | 10 | inputpath, outputpath = sys.argv[1:] 11 | 12 | # Read the file 13 | timeline = otio.adapters.read_from_file(inputpath) 14 | video_tracks = timeline.video_tracks() 15 | audio_tracks = timeline.audio_tracks() 16 | 17 | print("Read {} video tracks and {} audio tracks.".format( 18 | len(video_tracks), 19 | len(audio_tracks) 20 | )) 21 | 22 | # Take just the video tracks - and flatten them into one. 23 | # This will trim away any overlapping segments, collapsing everything 24 | # into a single track. 25 | print(f"Flattening {len(video_tracks)} video tracks into one...") 26 | onetrack = otio.algorithms.flatten_stack(video_tracks) 27 | 28 | # Now make a new empty Timeline and put that one Track into it 29 | newtimeline = otio.schema.Timeline(name=f"{timeline.name} Flattened") 30 | newtimeline.tracks[:] = [onetrack] 31 | 32 | # keep the audio track(s) as-is 33 | newtimeline.tracks.extend(copy.deepcopy(audio_tracks)) 34 | 35 | # ...and save it to disk. 36 | print("Saving {} video tracks and {} audio tracks.".format( 37 | len(newtimeline.video_tracks()), 38 | len(newtimeline.audio_tracks()) 39 | )) 40 | otio.adapters.write_to_file(newtimeline, outputpath) 41 | -------------------------------------------------------------------------------- /examples/sample_plugin/otio_counter/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | import importlib.resources 5 | 6 | from opentimelineio.plugins import manifest 7 | 8 | """ 9 | In the ``setup.py`` the top-level module was provided as the entry point. When 10 | OTIO loads a plugin, it will look for ``plugin_manifest.json`` in the package 11 | and register the plugins declared. 12 | 13 | If you wish to programmatically generate the manifest, you may return a 14 | :class:`Manifest` instance from your entry point's ``plugin_manifest`` 15 | function. 16 | 17 | For example purposes, this simply deserializes it from the json file included 18 | in the package. 19 | 20 | Below is an example of what the manifest json might look like (also included 21 | as a file in this package). 22 | 23 | .. codeblock:: JSON 24 | 25 | { 26 | "OTIO_SCHEMA" : "PluginManifest.1", 27 | "adapters": [ 28 | { 29 | "OTIO_SCHEMA": "Adapter.1", 30 | "name": "track_counter", 31 | "filepath": "adapter.py", 32 | "suffixes": ["count"] 33 | } 34 | ] 35 | } 36 | 37 | 38 | While this example shows an adapter, you may also define Media Linker plugins 39 | as below. 40 | 41 | .. codeblock:: JSON 42 | 43 | { 44 | "OTIO_SCHEMA" : "MediaLinker.1", 45 | "name" : "linker_example", 46 | "filepath" : "linker.py" 47 | } 48 | 49 | """ 50 | 51 | 52 | def plugin_manifest(): 53 | """ 54 | If, for some reason, the Manifest needs to be generated at runtime, it can 55 | be done here. This function takes precedence over ``plugin_manifest.json`` 56 | automatic discovery. 57 | 58 | Note the example implemenation's behavior is identical to the default when 59 | this function isn't defined. In most cases ``plugin_manifest.json`` should 60 | be sufficient and the ``__init__.py`` file can be left empty. 61 | """ 62 | 63 | # XXX: note, this doesn't get called. For an example of this working, 64 | # see the mockplugin unit test. 65 | 66 | filepath = importlib.resources.files(__package__) / "plugin_manifest.json" 67 | return manifest.manifest_from_string( 68 | filepath.read_text() 69 | ) 70 | -------------------------------------------------------------------------------- /examples/sample_plugin/otio_counter/adapter.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | import opentimelineio as otio 4 | 5 | """ 6 | This is the implementation of the contrived example adapter that simply writes 7 | the number of tracks in the timeline to a file, or will read an integer from a 8 | file and create a timeline with that number of tracks. 9 | 10 | This would be where your plugin implementation would be. 11 | """ 12 | 13 | 14 | def write_to_string(input_otio): 15 | return f'{len(input_otio.tracks)}' 16 | 17 | 18 | def read_from_string(input_str): 19 | t = otio.schema.Timeline() 20 | 21 | for i in range(int(input_str)): 22 | t.tracks.append(otio.schema.Track()) 23 | 24 | return t 25 | -------------------------------------------------------------------------------- /examples/sample_plugin/otio_counter/plugin_manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "PluginManifest.1", 3 | "adapters": [ 4 | { 5 | "OTIO_SCHEMA": "Adapter.1", 6 | "name": "track_counter", 7 | "filepath": "adapter.py", 8 | "suffixes": ["count"] 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /examples/sample_plugin/setup.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | from setuptools import setup 4 | 5 | """ 6 | This is an example of how to an OpenTimelineIO plugin installable as a separate 7 | python package. 8 | 9 | For the most part, the module can be built like any other python module, the 10 | one exception is that it must expose an ``opentimelineio.plugins`` entry point 11 | to allow OTIO to discover it. 12 | 13 | The entry point defined below can be read as: 14 | 1. Declaring this module provides for the entry point group 15 | ``opentimelineio.plugins``. 16 | 2. Declaring that for the ``opentimelineio.plugins`` group, this module 17 | provides a plugin named ``track_counter`` and the module that should be 18 | loaded for that plugin is the ``otio_counter`` module. 19 | 20 | For more information about python plugins, see the python packaging guide: 21 | https://packaging.python.org/guides/creating-and-discovering-plugins/#using-package-metadata 22 | """ 23 | 24 | setup( 25 | name='otio_counter', 26 | entry_points={ 27 | 'opentimelineio.plugins': 'track_counter = otio_counter' 28 | }, 29 | packages=['otio_counter'], 30 | package_data={ 31 | 'otio_counter': [ 32 | 'plugin_manifest.json', 33 | ], 34 | }, 35 | keywords='plugin OpenTimelineIO sample', 36 | platforms='any', 37 | version='1.0.0', 38 | description='Adapter writes number of tracks to file.', 39 | license='Modified Apache 2.0 License', 40 | author='Contributors to the OpenTimelineIO project', 41 | author_email='otio-discussion@lists.aswf.io', 42 | url='http://opentimeline.io', 43 | ) 44 | -------------------------------------------------------------------------------- /examples/util.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace examples { 11 | 12 | // Normalize path (change '\' path delimiters to '/'). 13 | std::string normalize_path(std::string const&); 14 | 15 | // Get the absolute path. 16 | std::string absolute(std::string const&); 17 | 18 | // Create a temporary directory. 19 | std::string create_temp_dir(); 20 | 21 | // Get a list of files from a directory. 22 | std::vector glob(std::string const& path, std::string const& pattern); 23 | 24 | // Print an error to std::cerr. 25 | void print_error(opentimelineio::OPENTIMELINEIO_VERSION::ErrorStatus const&); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /maintainers/remove_dev_suffix.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # Copyright Contributors to the OpenTimelineIO project 5 | 6 | __doc__ = """Strip or add the .dev1 suffix, part of the release process""" 7 | 8 | import argparse 9 | import sys 10 | 11 | TARGET_FILES = [ 12 | "setup.py" 13 | ] 14 | 15 | 16 | def _parsed_args(): 17 | parser = argparse.ArgumentParser( 18 | description='Fetch a list of contributors for a given GitHub repo.' 19 | ) 20 | 21 | op_grp = parser.add_mutually_exclusive_group(required=True) 22 | op_grp.add_argument( 23 | "-a", 24 | "--add", 25 | default=False, 26 | action="store_true", 27 | help="add the dev1 suffix to the version" 28 | ) 29 | op_grp.add_argument( 30 | "-r", 31 | "--remove", 32 | default=False, 33 | action="store_true", 34 | help="remove the dev1 suffix to the version" 35 | ) 36 | parser.add_argument( 37 | "-d", 38 | "--dryrun", 39 | default=False, 40 | action="store_true", 41 | help="Perform actions but modify no files on disk." 42 | ) 43 | return parser.parse_args() 44 | 45 | 46 | def _target_version(): 47 | import bump_version_number 48 | return ".".join(bump_version_number.version()) 49 | 50 | 51 | def main(): 52 | args = _parsed_args() 53 | 54 | version = _target_version() 55 | 56 | for fp in TARGET_FILES: 57 | with open(fp) as fi: 58 | content = fi.read() 59 | 60 | if args.add: 61 | modified = add_suffix(content, version) 62 | elif args.remove: 63 | modified = remove_suffix(content, version) 64 | 65 | if modified and not args.dryrun: 66 | with open(fp, 'w') as fo: 67 | fo.write(modified) 68 | print(f"Wrote modified {fp}.") 69 | 70 | 71 | def add_suffix(content, version): 72 | if version not in content: 73 | sys.stderr.write( 74 | "Version {} not found, suffix may have already been " 75 | "added.\n".format(version) 76 | ) 77 | return False 78 | 79 | print("adding suffix, version will be: {}".format(version + ".dev1")) 80 | return content.replace(version, version + ".dev1") 81 | 82 | 83 | def remove_suffix(content, version): 84 | if version + '.dev1' not in content: 85 | sys.stderr.write( 86 | "Version+Suffix {} not found, suffix may have already been " 87 | "removed.\n".format(version + '.dev1') 88 | ) 89 | return False 90 | 91 | print(f"removing suffix, version will be: {version}") 92 | return content.replace(version + '.dev1', version) 93 | 94 | 95 | if __name__ == "__main__": 96 | main() 97 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools", 4 | "wheel", 5 | "cmake>=3.12", 6 | ] 7 | build-backend = "setuptools.build_meta" 8 | 9 | [tool.cibuildwheel.linux] 10 | archs = ["x86_64", "aarch64"] 11 | 12 | [tool.cibuildwheel.windows] 13 | archs = ["AMD64"] 14 | -------------------------------------------------------------------------------- /readthedocs-conda.yml: -------------------------------------------------------------------------------- 1 | # YAML file for configuring the Conda environment in read the docs. 2 | name: opentimelineio-readthedocs 3 | 4 | dependencies: 5 | - cmake 6 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Python Distribution 3 | ############################################################################### 4 | [metadata] 5 | description_file = README.md 6 | 7 | ############################################################################### 8 | # flake8 9 | ############################################################################### 10 | [flake8] 11 | exclude = 12 | .tox 13 | *.egg 14 | build 15 | venv 16 | __pycache__ 17 | docs 18 | dist 19 | .git 20 | deps 21 | .venv 22 | select = E,W,F 23 | max-line-length = 88 24 | # @TODO: for now, ignoring both line continuation before OR after binary 25 | # operators. The pep8 style seems to have adopted the W504 style as 26 | # correct, which we've been doing conventionally but not 100% uniformly. 27 | # At some point in the future, we should remove W504 from this list and 28 | # conform all the continuation to be the same. 29 | ignore = 30 | W503 31 | W504 32 | 33 | 34 | ############################################################################### 35 | # Check-Manifest 36 | ############################################################################### 37 | [check-manifest] 38 | ignore = 39 | tests* 40 | requirements* 41 | ignore-bad-ideas = 42 | *.egg-info 43 | *egg-info/* 44 | 45 | 46 | ############################################################################### 47 | # Python Coverage 48 | ############################################################################### 49 | [coverage:run] 50 | branch = True 51 | source = 52 | opentimelineio 53 | opentimelineio_contrib 54 | ./tests 55 | 56 | [coverage:paths] 57 | otio = 58 | src/py-opentimelineio/opentimelineio 59 | *site-packages/opentimelineio 60 | 61 | [coverage:report] 62 | include =* 63 | # Regexes for lines to exclude from consideration 64 | omit = 65 | *aaf2* 66 | *pkg_resources* 67 | *pbr* 68 | *mock* 69 | *PIL* 70 | *funcsigs* 71 | 72 | exclude_lines = 73 | # Have to re-enable the standard pragma 74 | pragma: no cover 75 | 76 | # Don't complain if tests don't hit defensive assertion code: 77 | # raise AssertionError 78 | # raise NotImplementedError 79 | 80 | # # Don't complain if non-runnable code isn't run: 81 | # if 0: 82 | # if __name__ == .__main__.: 83 | ignore_errors = True 84 | show_missing = True 85 | 86 | [coverage:html] 87 | directory = coverage_html_report 88 | -------------------------------------------------------------------------------- /src/deps/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #----- Other dependencies 5 | 6 | # detect if the submodules haven't been updated 7 | set(DEPS_SUBMODULES pybind11) 8 | 9 | if(NOT OTIO_FIND_RAPIDJSON) 10 | set(DEPS_SUBMODULES ${DEPS_SUBMODULES} rapidjson) 11 | endif() 12 | 13 | foreach(submodule IN LISTS DEPS_SUBMODULES) 14 | file(GLOB SUBMOD_CONTENTS ${submodule}) 15 | list(LENGTH SUBMOD_CONTENTS SUBMOD_CONTENT_LEN) 16 | if(SUBMOD_CONTENT_LEN EQUAL 0) 17 | message( 18 | FATAL_ERROR "Error: the submodule ${submodule} is empty. You may \ 19 | need to install git and run: 'git submodule update' to remedy this." 20 | ) 21 | endif() 22 | endforeach() 23 | 24 | if(OTIO_PYTHON_INSTALL) 25 | add_subdirectory(pybind11) 26 | endif() 27 | 28 | if(NOT OTIO_FIND_IMATH) 29 | # preserve BUILD_SHARED_LIBS options for this project, but set it off for Imath 30 | option(BUILD_SHARED_LIBS "Build shared libraries" ON) 31 | set(BUILD_SHARED_LIBS OFF) 32 | 33 | # If we do not want Imath to install headers and CMake files use the EXCLUDE_FROM_ALL option 34 | if(OTIO_CXX_INSTALL AND OTIO_DEPENDENCIES_INSTALL) 35 | add_subdirectory(Imath) 36 | else() 37 | add_subdirectory(Imath EXCLUDE_FROM_ALL) 38 | endif() 39 | endif() 40 | 41 | -------------------------------------------------------------------------------- /src/opentime/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # opentime/CMakeLists.txt 3 | 4 | set(OPENTIME_HEADER_FILES 5 | errorStatus.h 6 | rationalTime.h 7 | stringPrintf.h 8 | timeRange.h 9 | timeTransform.h 10 | version.h) 11 | 12 | add_library(opentime ${OTIO_SHARED_OR_STATIC_LIB} 13 | errorStatus.cpp 14 | rationalTime.cpp 15 | ${OPENTIME_HEADER_FILES}) 16 | 17 | add_library(OTIO::opentime ALIAS opentime) 18 | 19 | target_include_directories(opentime PRIVATE "${PROJECT_SOURCE_DIR}/src") 20 | 21 | set_target_properties(opentime PROPERTIES 22 | DEBUG_POSTFIX "${OTIO_DEBUG_POSTFIX}" 23 | LIBRARY_OUTPUT_NAME "opentime" 24 | POSITION_INDEPENDENT_CODE TRUE 25 | WINDOWS_EXPORT_ALL_SYMBOLS true) 26 | 27 | if(BUILD_SHARED_LIBS) 28 | set_target_properties(opentime PROPERTIES 29 | SOVERSION ${OTIO_SOVERSION} 30 | VERSION ${OTIO_VERSION}) 31 | endif() 32 | 33 | if(APPLE) 34 | set_target_properties(opentime PROPERTIES 35 | INSTALL_NAME_DIR "@loader_path" 36 | MACOSX_RPATH ON) 37 | endif() 38 | 39 | target_compile_options(opentime PRIVATE 40 | $<$,$,$>: 41 | -Wall> 42 | $<$: /W4> 43 | $<$: /EHsc> 44 | ) 45 | 46 | if(OTIO_CXX_INSTALL) 47 | install(FILES ${OPENTIME_HEADER_FILES} 48 | DESTINATION "${OTIO_RESOLVED_CXX_INSTALL_DIR}/include/opentime") 49 | 50 | install(TARGETS opentime 51 | EXPORT OpenTimeTargets 52 | INCLUDES DESTINATION "${OTIO_RESOLVED_CXX_INSTALL_DIR}/include" 53 | ARCHIVE DESTINATION "${OTIO_RESOLVED_CXX_DYLIB_INSTALL_DIR}" 54 | LIBRARY DESTINATION "${OTIO_RESOLVED_CXX_DYLIB_INSTALL_DIR}" 55 | RUNTIME DESTINATION "${OTIO_RESOLVED_CXX_DYLIB_INSTALL_DIR}") 56 | 57 | install(EXPORT OpenTimeTargets 58 | DESTINATION "${OTIO_RESOLVED_CXX_INSTALL_DIR}/share/opentime" 59 | NAMESPACE OTIO:: ) 60 | 61 | include(CMakePackageConfigHelpers) 62 | configure_package_config_file( 63 | ${CMAKE_CURRENT_SOURCE_DIR}/OpenTimeConfig.cmake.in 64 | ${CMAKE_CURRENT_BINARY_DIR}/OpenTimeConfig.cmake 65 | INSTALL_DESTINATION 66 | ${OTIO_RESOLVED_CXX_INSTALL_DIR}/share/opentime 67 | NO_SET_AND_CHECK_MACRO 68 | NO_CHECK_REQUIRED_COMPONENTS_MACRO 69 | ) 70 | 71 | install( 72 | FILES 73 | ${CMAKE_CURRENT_BINARY_DIR}/OpenTimeConfig.cmake 74 | DESTINATION 75 | ${OTIO_RESOLVED_CXX_INSTALL_DIR}/share/opentime 76 | ) 77 | endif() 78 | 79 | -------------------------------------------------------------------------------- /src/opentime/OpenTimeConfig.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | include("${CMAKE_CURRENT_LIST_DIR}/OpenTimeTargets.cmake") 4 | -------------------------------------------------------------------------------- /src/opentime/errorStatus.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentime/errorStatus.h" 5 | 6 | namespace opentime { namespace OPENTIME_VERSION { 7 | 8 | std::string 9 | ErrorStatus::outcome_to_string(Outcome o) 10 | { 11 | switch (o) 12 | { 13 | case OK: 14 | return std::string(); 15 | case INVALID_TIMECODE_RATE: 16 | return "SMPTE timecode does not support this rate"; 17 | case INVALID_TIMECODE_STRING: 18 | return "string is not a SMPTE timecode string"; 19 | case TIMECODE_RATE_MISMATCH: 20 | return "timecode specifies a frame higher than its rate"; 21 | case INVALID_TIME_STRING: 22 | return "invalid time string"; 23 | case NEGATIVE_VALUE: 24 | return "value cannot be negative here"; 25 | case INVALID_RATE_FOR_DROP_FRAME_TIMECODE: 26 | return "rate is not valid for drop frame timecode"; 27 | default: 28 | return "unknown/illegal ErrorStatus::Outcome code"; 29 | }; 30 | } 31 | 32 | }} // namespace opentime::OPENTIME_VERSION 33 | -------------------------------------------------------------------------------- /src/opentime/errorStatus.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentime/version.h" 7 | #include 8 | 9 | namespace opentime { namespace OPENTIME_VERSION { 10 | 11 | /// @brief This struct represents the return status of a function. 12 | struct ErrorStatus 13 | { 14 | /// @brief This enumeration represents the possible outcomes. 15 | enum Outcome 16 | { 17 | OK = 0, 18 | INVALID_TIMECODE_RATE, 19 | INVALID_TIMECODE_STRING, 20 | INVALID_TIME_STRING, 21 | TIMECODE_RATE_MISMATCH, 22 | NEGATIVE_VALUE, 23 | INVALID_RATE_FOR_DROP_FRAME_TIMECODE, 24 | }; 25 | 26 | /// @brief Construct a new status with no error. 27 | ErrorStatus() 28 | : outcome{ OK } 29 | {} 30 | 31 | /// @brief Construct a new status with the given outcome. 32 | ErrorStatus(Outcome in_outcome) 33 | : outcome{ in_outcome } 34 | , details{ outcome_to_string(in_outcome) } 35 | {} 36 | 37 | /// @brief Construct a new status with the given outcome and details. 38 | ErrorStatus(Outcome in_outcome, std::string const& in_details) 39 | : outcome{ in_outcome } 40 | , details{ in_details } 41 | {} 42 | 43 | /// @brief The outcome of the function. 44 | Outcome outcome; 45 | 46 | /// @brief A human readable string that provides details about the outcome. 47 | std::string details; 48 | 49 | ///! @brief Return a human readable string for the given outcome. 50 | static std::string outcome_to_string(Outcome); 51 | }; 52 | 53 | ///! @brief Check whether the given ErrorStatus is an error. 54 | constexpr bool 55 | is_error(const ErrorStatus& es) noexcept 56 | { 57 | return ErrorStatus::Outcome::OK != es.outcome; 58 | } 59 | 60 | ///! @brief Check whether the given ErrorStatus is non-null and an error. 61 | constexpr bool 62 | is_error(const ErrorStatus* es) noexcept 63 | { 64 | return es && ErrorStatus::Outcome::OK != es->outcome; 65 | } 66 | 67 | }} // namespace opentime::OPENTIME_VERSION 68 | -------------------------------------------------------------------------------- /src/opentime/stringPrintf.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentime/version.h" 7 | #include 8 | #include 9 | #include 10 | 11 | namespace opentime { namespace OPENTIME_VERSION { 12 | 13 | /// @brief This provides printf style functionality for std::string. 14 | template 15 | std::string 16 | string_printf(char const* format, Args... args) 17 | { 18 | char buffer[4096]; 19 | size_t size = snprintf(buffer, sizeof(buffer), format, args...) + 1; 20 | if (size < sizeof(buffer)) 21 | { 22 | return std::string(buffer); 23 | } 24 | 25 | std::unique_ptr buf(new char[size]); 26 | std::snprintf(buf.get(), size, format, args...); 27 | return std::string(buf.get()); 28 | } 29 | 30 | }} // namespace opentime::OPENTIME_VERSION 31 | -------------------------------------------------------------------------------- /src/opentime/timeRange.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentime/timeRange.h" 5 | -------------------------------------------------------------------------------- /src/opentime/timeTransform.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentime/timeTransform.h" 5 | -------------------------------------------------------------------------------- /src/opentime/version.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #define OPENTIME_VERSION v1_0 7 | 8 | namespace opentime { 9 | namespace OPENTIME_VERSION { 10 | } 11 | 12 | using namespace OPENTIME_VERSION; 13 | } // namespace opentime 14 | -------------------------------------------------------------------------------- /src/opentimelineio/OpenTimelineIOConfig.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | include(CMakeFindDependencyMacro) 4 | find_dependency(OpenTime) 5 | find_dependency(Imath) 6 | 7 | include("${CMAKE_CURRENT_LIST_DIR}/OpenTimelineIOTargets.cmake") 8 | -------------------------------------------------------------------------------- /src/opentimelineio/composable.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/composable.h" 5 | #include "opentimelineio/composition.h" 6 | 7 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 8 | 9 | Composable::Composable(std::string const& name, AnyDictionary const& metadata) 10 | : Parent(name, metadata) 11 | , _parent(nullptr) 12 | {} 13 | 14 | Composable::~Composable() 15 | {} 16 | 17 | bool 18 | Composable::visible() const 19 | { 20 | return true; 21 | } 22 | 23 | bool 24 | Composable::overlapping() const 25 | { 26 | return false; 27 | } 28 | 29 | bool 30 | Composable::_set_parent(Composition* new_parent) noexcept 31 | { 32 | if (new_parent && _parent) 33 | { 34 | return false; 35 | } 36 | 37 | _parent = new_parent; 38 | return true; 39 | } 40 | 41 | Composable* 42 | Composable::_highest_ancestor() noexcept 43 | { 44 | Composable* c = this; 45 | for (; c->_parent; c = c->_parent) 46 | { 47 | /* empty */ 48 | } 49 | return c; 50 | } 51 | 52 | bool 53 | Composable::read_from(Reader& reader) 54 | { 55 | return Parent::read_from(reader); 56 | } 57 | 58 | void 59 | Composable::write_to(Writer& writer) const 60 | { 61 | Parent::write_to(writer); 62 | } 63 | 64 | RationalTime 65 | Composable::duration(ErrorStatus* error_status) const 66 | { 67 | if (error_status) 68 | { 69 | *error_status = ErrorStatus( 70 | ErrorStatus::OBJECT_WITHOUT_DURATION, 71 | "Cannot determine duration from this kind of object", 72 | this); 73 | } 74 | return RationalTime(); 75 | } 76 | 77 | std::optional 78 | Composable::available_image_bounds(ErrorStatus* error_status) const 79 | { 80 | *error_status = ErrorStatus::NOT_IMPLEMENTED; 81 | return std::optional(); 82 | } 83 | 84 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 85 | -------------------------------------------------------------------------------- /src/opentimelineio/composable.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/serializableObjectWithMetadata.h" 7 | #include "opentimelineio/version.h" 8 | 9 | #include 10 | 11 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 12 | 13 | class Composition; 14 | 15 | /// @brief An object that can be composed within a Composition (such as a Track or Stack). 16 | class Composable : public SerializableObjectWithMetadata 17 | { 18 | public: 19 | /// @brief This struct provides the Composable schema. 20 | struct Schema 21 | { 22 | static auto constexpr name = "Composable"; 23 | static int constexpr version = 1; 24 | }; 25 | 26 | using Parent = SerializableObjectWithMetadata; 27 | 28 | /// @brief Create a new composable. 29 | /// 30 | /// @param name The name of the composable. 31 | /// @param metadata The metadata for the clip. 32 | Composable( 33 | std::string const& name = std::string(), 34 | AnyDictionary const& metadata = AnyDictionary()); 35 | 36 | /// @brief Return whether the composable is visible. 37 | virtual bool visible() const; 38 | 39 | /// @brief Return whether the composable is overlapping another item. 40 | virtual bool overlapping() const; 41 | 42 | /// @brief Return the parent composition. 43 | Composition* parent() const { return _parent; } 44 | 45 | /// @brief Return the duration of the composable. 46 | virtual RationalTime duration(ErrorStatus* error_status = nullptr) const; 47 | 48 | /// @brief Return the available image bounds. 49 | virtual std::optional 50 | available_image_bounds(ErrorStatus* error_status) const; 51 | 52 | protected: 53 | bool _set_parent(Composition*) noexcept; 54 | Composable* _highest_ancestor() noexcept; 55 | 56 | Composable const* _highest_ancestor() const noexcept 57 | { 58 | return const_cast(this)->_highest_ancestor(); 59 | } 60 | 61 | virtual ~Composable(); 62 | 63 | bool read_from(Reader&) override; 64 | void write_to(Writer&) const override; 65 | 66 | private: 67 | Composition* _parent; 68 | friend class Composition; 69 | }; 70 | 71 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 72 | -------------------------------------------------------------------------------- /src/opentimelineio/deserialization.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/serializableObject.h" 7 | #include "opentimelineio/version.h" 8 | 9 | #include 10 | #include 11 | 12 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 13 | 14 | /// @brief Deserialize JSON data from a string. 15 | bool deserialize_json_from_string( 16 | std::string const& input, 17 | std::any* destination, 18 | ErrorStatus* error_status = nullptr); 19 | 20 | /// @brief Deserialize JSON data from a file. 21 | bool deserialize_json_from_file( 22 | std::string const& file_name, 23 | std::any* destination, 24 | ErrorStatus* error_status = nullptr); 25 | 26 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 27 | -------------------------------------------------------------------------------- /src/opentimelineio/effect.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/effect.h" 5 | #include "opentimelineio/missingReference.h" 6 | 7 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 8 | 9 | Effect::Effect( 10 | std::string const& name, 11 | std::string const& effect_name, 12 | AnyDictionary const& metadata, 13 | bool enabled) 14 | : Parent(name, metadata) 15 | , _effect_name(effect_name) 16 | , _enabled(enabled) 17 | {} 18 | 19 | Effect::~Effect() 20 | {} 21 | 22 | bool 23 | Effect::read_from(Reader& reader) 24 | { 25 | return reader.read("effect_name", &_effect_name) 26 | && reader.read_if_present("enabled", &_enabled) 27 | && Parent::read_from(reader); 28 | } 29 | 30 | void 31 | Effect::write_to(Writer& writer) const 32 | { 33 | Parent::write_to(writer); 34 | writer.write("effect_name", _effect_name); 35 | writer.write("enabled", _enabled); 36 | } 37 | 38 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 39 | -------------------------------------------------------------------------------- /src/opentimelineio/effect.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/serializableObjectWithMetadata.h" 7 | #include "opentimelineio/version.h" 8 | 9 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 10 | 11 | /// @brief An effect that can be applied to an item, such as an image or audio filter. 12 | class Effect : public SerializableObjectWithMetadata 13 | { 14 | public: 15 | /// @brief This struct provides the Effect schema. 16 | struct Schema 17 | { 18 | static auto constexpr name = "Effect"; 19 | static int constexpr version = 1; 20 | }; 21 | 22 | using Parent = SerializableObjectWithMetadata; 23 | 24 | /// @brief Create a new effect. 25 | /// 26 | /// @param name The name of the effect object. 27 | /// @param name The name of the effect. 28 | /// @param metadata The metadata for the clip. 29 | /// @param enabled Whether the effect is enabled. 30 | Effect( 31 | std::string const& name = std::string(), 32 | std::string const& effect_name = std::string(), 33 | AnyDictionary const& metadata = AnyDictionary(), 34 | bool enabled = true); 35 | 36 | /// @brief Return the effect name. 37 | std::string effect_name() const noexcept { return _effect_name; } 38 | 39 | /// @brief Set the effect name. 40 | void set_effect_name(std::string const& effect_name) 41 | { 42 | _effect_name = effect_name; 43 | } 44 | 45 | /// @brief Return whether the effect is enabed. 46 | bool enabled() const { return _enabled; }; 47 | 48 | /// @brief Set whether the effect is enabled. 49 | void set_enabled(bool enabled) { _enabled = enabled; } 50 | 51 | protected: 52 | virtual ~Effect(); 53 | 54 | bool read_from(Reader&) override; 55 | void write_to(Writer&) const override; 56 | 57 | private: 58 | std::string _effect_name; 59 | bool _enabled; 60 | }; 61 | 62 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 63 | -------------------------------------------------------------------------------- /src/opentimelineio/externalReference.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/externalReference.h" 5 | 6 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 7 | 8 | ExternalReference::ExternalReference( 9 | std::string const& target_url, 10 | std::optional const& available_range, 11 | AnyDictionary const& metadata, 12 | std::optional const& available_image_bounds) 13 | : Parent(std::string(), available_range, metadata, available_image_bounds) 14 | , _target_url(target_url) 15 | {} 16 | 17 | ExternalReference::~ExternalReference() 18 | {} 19 | 20 | bool 21 | ExternalReference::read_from(Reader& reader) 22 | { 23 | return reader.read("target_url", &_target_url) && Parent::read_from(reader); 24 | } 25 | 26 | void 27 | ExternalReference::write_to(Writer& writer) const 28 | { 29 | Parent::write_to(writer); 30 | writer.write("target_url", _target_url); 31 | } 32 | 33 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 34 | -------------------------------------------------------------------------------- /src/opentimelineio/externalReference.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/mediaReference.h" 7 | #include "opentimelineio/version.h" 8 | 9 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 10 | 11 | /// @brief A reference to a media file. 12 | class ExternalReference final : public MediaReference 13 | { 14 | public: 15 | /// @brief This struct provides the ExternalReference schema. 16 | struct Schema 17 | { 18 | static auto constexpr name = "ExternalReference"; 19 | static int constexpr version = 1; 20 | }; 21 | 22 | using Parent = MediaReference; 23 | 24 | /// @brief Create a new external reference. 25 | /// 26 | /// @param target_url The URL to the media. 27 | /// @param available_range The available range of the media. 28 | /// @param metadata The metadata for the media. 29 | /// @param available_image_bounds The spatial bounds of the media. 30 | ExternalReference( 31 | std::string const& target_url = std::string(), 32 | std::optional const& available_range = std::nullopt, 33 | AnyDictionary const& metadata = AnyDictionary(), 34 | std::optional const& available_image_bounds = 35 | std::nullopt); 36 | 37 | /// @brief Return the media file URL. 38 | std::string target_url() const noexcept { return _target_url; } 39 | 40 | /// @brief Set the media file URL. 41 | void set_target_url(std::string const& target_url) 42 | { 43 | _target_url = target_url; 44 | } 45 | 46 | protected: 47 | virtual ~ExternalReference(); 48 | 49 | bool read_from(Reader&) override; 50 | void write_to(Writer&) const override; 51 | 52 | private: 53 | std::string _target_url; 54 | }; 55 | 56 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 57 | -------------------------------------------------------------------------------- /src/opentimelineio/freezeFrame.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/freezeFrame.h" 5 | 6 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 7 | 8 | FreezeFrame::FreezeFrame(std::string const& name, AnyDictionary const& metadata) 9 | : Parent(name, "FreezeFrame", 0.0, metadata) 10 | {} 11 | 12 | FreezeFrame::~FreezeFrame() 13 | {} 14 | 15 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 16 | -------------------------------------------------------------------------------- /src/opentimelineio/freezeFrame.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/linearTimeWarp.h" 7 | #include "opentimelineio/version.h" 8 | 9 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 10 | 11 | /// @brief Hold the first frame of the clip for the duration of the clip. 12 | class FreezeFrame : public LinearTimeWarp 13 | { 14 | public: 15 | /// @brief This struct provides the FreezeFrame schema. 16 | struct Schema 17 | { 18 | static auto constexpr name = "FreezeFrame"; 19 | static int constexpr version = 1; 20 | }; 21 | 22 | using Parent = LinearTimeWarp; 23 | 24 | /// @brief Create a new freeze frame time effect. 25 | /// 26 | /// @param name The name of the time effect. 27 | /// @param metadata The metadata for the time effect. 28 | FreezeFrame( 29 | std::string const& name = std::string(), 30 | AnyDictionary const& metadata = AnyDictionary()); 31 | 32 | protected: 33 | virtual ~FreezeFrame(); 34 | }; 35 | 36 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 37 | -------------------------------------------------------------------------------- /src/opentimelineio/gap.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/gap.h" 5 | 6 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 7 | 8 | Gap::Gap( 9 | TimeRange const& source_range, 10 | std::string const& name, 11 | std::vector const& effects, 12 | std::vector const& markers, 13 | AnyDictionary const& metadata) 14 | : Parent(name, source_range, metadata, effects, markers) 15 | {} 16 | 17 | Gap::Gap( 18 | RationalTime duration, 19 | std::string const& name, 20 | std::vector const& effects, 21 | std::vector const& markers, 22 | AnyDictionary const& metadata) 23 | : Parent( 24 | name, 25 | TimeRange(RationalTime(0, duration.rate()), duration), 26 | metadata, 27 | effects, 28 | markers) 29 | {} 30 | 31 | Gap::~Gap() 32 | {} 33 | 34 | bool 35 | Gap::visible() const 36 | { 37 | return false; 38 | } 39 | 40 | bool 41 | Gap::read_from(Reader& reader) 42 | { 43 | return Parent::read_from(reader); 44 | } 45 | 46 | void 47 | Gap::write_to(Writer& writer) const 48 | { 49 | Parent::write_to(writer); 50 | } 51 | 52 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 53 | -------------------------------------------------------------------------------- /src/opentimelineio/gap.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/item.h" 7 | #include "opentimelineio/mediaReference.h" 8 | #include "opentimelineio/version.h" 9 | 10 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 11 | 12 | /// @brief An empty item within a timeline. 13 | class Gap : public Item 14 | { 15 | public: 16 | /// @brief This struct provides the Gap schema. 17 | struct Schema 18 | { 19 | static auto constexpr name = "Gap"; 20 | static int constexpr version = 1; 21 | }; 22 | 23 | using Parent = Item; 24 | 25 | /// @brief Create a new gap. 26 | /// 27 | /// @param source_range The source range of the gap. 28 | /// @param name The name of the gap. 29 | /// @param effects The list of effects for the gap. Note that the 30 | /// the gap keeps a retainer to each effect. 31 | /// @param markers The list of markers for the gap. Note that the 32 | /// the gap keeps a retainer to each marker. 33 | /// @param metadata The metadata for the gap. 34 | Gap(TimeRange const& source_range = TimeRange(), 35 | std::string const& name = std::string(), 36 | std::vector const& effects = std::vector(), 37 | std::vector const& markers = std::vector(), 38 | AnyDictionary const& metadata = AnyDictionary()); 39 | 40 | /// @brief Create a new gap. 41 | /// 42 | /// @param duration The duration of the gap. 43 | /// @param name The name of the gap. 44 | /// @param effects The list of effects for the gap. Note that the 45 | /// the gap keeps a retainer to each effect. 46 | /// @param markers The list of markers for the gap. Note that the 47 | /// the gap keeps a retainer to each marker. 48 | /// @param metadata The metadata for the gap. 49 | Gap(RationalTime duration, 50 | std::string const& name = std::string(), 51 | std::vector const& effects = std::vector(), 52 | std::vector const& markers = std::vector(), 53 | AnyDictionary const& metadata = AnyDictionary()); 54 | 55 | bool visible() const override; 56 | 57 | protected: 58 | virtual ~Gap(); 59 | 60 | bool read_from(Reader&) override; 61 | void write_to(Writer&) const override; 62 | }; 63 | 64 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 65 | -------------------------------------------------------------------------------- /src/opentimelineio/generatorReference.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/generatorReference.h" 5 | 6 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 7 | 8 | GeneratorReference::GeneratorReference( 9 | std::string const& name, 10 | std::string const& generator_kind, 11 | std::optional const& available_range, 12 | AnyDictionary const& parameters, 13 | AnyDictionary const& metadata, 14 | std::optional const& available_image_bounds) 15 | : Parent(name, available_range, metadata, available_image_bounds) 16 | , _generator_kind(generator_kind) 17 | , _parameters(parameters) 18 | {} 19 | 20 | GeneratorReference::~GeneratorReference() 21 | {} 22 | 23 | bool 24 | GeneratorReference::read_from(Reader& reader) 25 | { 26 | return reader.read("generator_kind", &_generator_kind) 27 | && reader.read("parameters", &_parameters) 28 | && Parent::read_from(reader); 29 | } 30 | 31 | void 32 | GeneratorReference::write_to(Writer& writer) const 33 | { 34 | Parent::write_to(writer); 35 | writer.write("generator_kind", _generator_kind); 36 | writer.write("parameters", _parameters); 37 | } 38 | 39 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 40 | -------------------------------------------------------------------------------- /src/opentimelineio/generatorReference.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/mediaReference.h" 7 | #include "opentimelineio/version.h" 8 | 9 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 10 | 11 | /// @brief A reference to dynamically generated media. 12 | class GeneratorReference final : public MediaReference 13 | { 14 | public: 15 | /// @brief This struct provides the GeneratorReference schema. 16 | struct Schema 17 | { 18 | static auto constexpr name = "GeneratorReference"; 19 | static int constexpr version = 1; 20 | }; 21 | 22 | using Parent = MediaReference; 23 | 24 | /// @brief Create a new generator reference. 25 | /// 26 | /// @param name The name of the generator. 27 | /// @param generator_kind The kind of generator. 28 | /// @param available_range The available range of the generator. 29 | /// @param parameters The parameters used to configure the generator. 30 | /// @param metadata The metadata for the generator. 31 | /// @param available_image_bounds The spatial bounds of the generator. 32 | GeneratorReference( 33 | std::string const& name = std::string(), 34 | std::string const& generator_kind = std::string(), 35 | std::optional const& available_range = std::nullopt, 36 | AnyDictionary const& parameters = AnyDictionary(), 37 | AnyDictionary const& metadata = AnyDictionary(), 38 | std::optional const& available_image_bounds = 39 | std::nullopt); 40 | 41 | /// @brief Return the kind of generator. 42 | std::string generator_kind() const noexcept { return _generator_kind; } 43 | 44 | /// @brief Set the kind of generator. 45 | void set_generator_kind(std::string const& generator_kind) 46 | { 47 | _generator_kind = generator_kind; 48 | } 49 | 50 | /// @brief Modify the generator parameters. 51 | AnyDictionary& parameters() noexcept { return _parameters; } 52 | 53 | /// @brief Return the generator parameters. 54 | AnyDictionary parameters() const noexcept { return _parameters; } 55 | 56 | protected: 57 | virtual ~GeneratorReference(); 58 | 59 | bool read_from(Reader&) override; 60 | void write_to(Writer&) const override; 61 | 62 | private: 63 | std::string _generator_kind; 64 | AnyDictionary _parameters; 65 | }; 66 | 67 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 68 | -------------------------------------------------------------------------------- /src/opentimelineio/linearTimeWarp.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/linearTimeWarp.h" 5 | 6 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 7 | 8 | LinearTimeWarp::LinearTimeWarp( 9 | std::string const& name, 10 | std::string const& effect_name, 11 | double time_scalar, 12 | AnyDictionary const& metadata) 13 | : Parent(name, effect_name, metadata) 14 | , _time_scalar(time_scalar) 15 | {} 16 | 17 | LinearTimeWarp::~LinearTimeWarp() 18 | {} 19 | 20 | bool 21 | LinearTimeWarp::read_from(Reader& reader) 22 | { 23 | return reader.read("time_scalar", &_time_scalar) 24 | && Parent::read_from(reader); 25 | } 26 | 27 | void 28 | LinearTimeWarp::write_to(Writer& writer) const 29 | { 30 | Parent::write_to(writer); 31 | writer.write("time_scalar", _time_scalar); 32 | } 33 | 34 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 35 | -------------------------------------------------------------------------------- /src/opentimelineio/linearTimeWarp.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/timeEffect.h" 7 | #include "opentimelineio/version.h" 8 | 9 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 10 | 11 | /// @brief A time warp that applies a linear speed up or slow down across the entire clip. 12 | class LinearTimeWarp : public TimeEffect 13 | { 14 | public: 15 | /// @brief This struct provides the LinearTimeWarp schema. 16 | struct Schema 17 | { 18 | static auto constexpr name = "LinearTimeWarp"; 19 | static int constexpr version = 1; 20 | }; 21 | 22 | using Parent = TimeEffect; 23 | 24 | /// @brief Create a new linear time warp effect. 25 | /// 26 | /// @param name The name of the time effect object. 27 | /// @param effect_name The name of the time effect. 28 | /// @param time_scalar The amount to scale the time. 29 | /// @param metadata The metadata for the time effect. 30 | LinearTimeWarp( 31 | std::string const& name = std::string(), 32 | std::string const& effect_name = std::string(), 33 | double time_scalar = 1, 34 | AnyDictionary const& metadata = AnyDictionary()); 35 | 36 | /// @brief Return the amount to scale the time. 37 | double time_scalar() const noexcept { return _time_scalar; } 38 | 39 | /// @brief Set the amount to scale the time. 40 | void set_time_scalar(double time_scalar) noexcept 41 | { 42 | _time_scalar = time_scalar; 43 | } 44 | 45 | protected: 46 | virtual ~LinearTimeWarp(); 47 | 48 | bool read_from(Reader&) override; 49 | void write_to(Writer&) const override; 50 | 51 | private: 52 | double _time_scalar; 53 | }; 54 | 55 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 56 | -------------------------------------------------------------------------------- /src/opentimelineio/marker.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/marker.h" 5 | #include "opentimelineio/missingReference.h" 6 | 7 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 8 | 9 | Marker::Marker( 10 | std::string const& name, 11 | TimeRange const& marked_range, 12 | std::string const& color, 13 | AnyDictionary const& metadata, 14 | std::string const& comment) 15 | : Parent(name, metadata) 16 | , _color(color) 17 | , _marked_range(marked_range) 18 | , _comment(comment) 19 | {} 20 | 21 | Marker::~Marker() 22 | {} 23 | 24 | bool 25 | Marker::read_from(Reader& reader) 26 | { 27 | return reader.read_if_present("color", &_color) 28 | && reader.read("marked_range", &_marked_range) 29 | && reader.read_if_present("comment", &_comment) 30 | && Parent::read_from(reader); 31 | } 32 | 33 | void 34 | Marker::write_to(Writer& writer) const 35 | { 36 | Parent::write_to(writer); 37 | writer.write("color", _color); 38 | writer.write("marked_range", _marked_range); 39 | writer.write("comment", _comment); 40 | } 41 | 42 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 43 | -------------------------------------------------------------------------------- /src/opentimelineio/mediaReference.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/mediaReference.h" 5 | 6 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 7 | 8 | MediaReference::MediaReference( 9 | std::string const& name, 10 | std::optional const& available_range, 11 | AnyDictionary const& metadata, 12 | std::optional const& available_image_bounds) 13 | : Parent(name, metadata) 14 | , _available_range(available_range) 15 | , _available_image_bounds(available_image_bounds) 16 | {} 17 | 18 | MediaReference::~MediaReference() 19 | {} 20 | 21 | bool 22 | MediaReference::is_missing_reference() const 23 | { 24 | return false; 25 | } 26 | 27 | bool 28 | MediaReference::read_from(Reader& reader) 29 | { 30 | return reader.read_if_present("available_range", &_available_range) 31 | && reader.read_if_present( 32 | "available_image_bounds", 33 | &_available_image_bounds) 34 | && Parent::read_from(reader); 35 | } 36 | 37 | void 38 | MediaReference::write_to(Writer& writer) const 39 | { 40 | Parent::write_to(writer); 41 | writer.write("available_range", _available_range); 42 | writer.write("available_image_bounds", _available_image_bounds); 43 | } 44 | 45 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 46 | -------------------------------------------------------------------------------- /src/opentimelineio/mediaReference.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/serializableObjectWithMetadata.h" 7 | #include "opentimelineio/version.h" 8 | 9 | #include 10 | 11 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 12 | 13 | using namespace opentime; 14 | 15 | /// @brief A reference to a piece of media, for example a movie on a clip. 16 | class MediaReference : public SerializableObjectWithMetadata 17 | { 18 | public: 19 | /// @brief This struct provides the MediaReference schema. 20 | struct Schema 21 | { 22 | static auto constexpr name = "MediaReference"; 23 | static int constexpr version = 1; 24 | }; 25 | 26 | using Parent = SerializableObjectWithMetadata; 27 | 28 | /// @brief Create a new media reference. 29 | /// 30 | /// @param name The name of the media reference. 31 | /// @param available_range The available range of the media reference. 32 | /// @param metadata The metadata for the media reference. 33 | /// @param available_image_bounds The spatial bounds of the media reference. 34 | MediaReference( 35 | std::string const& name = std::string(), 36 | std::optional const& available_range = std::nullopt, 37 | AnyDictionary const& metadata = AnyDictionary(), 38 | std::optional const& available_image_bounds = 39 | std::nullopt); 40 | 41 | /// @brief Return the available range of the media reference. 42 | std::optional available_range() const noexcept 43 | { 44 | return _available_range; 45 | } 46 | 47 | /// @brief Set the available range of the media reference. 48 | void set_available_range(std::optional const& available_range) 49 | { 50 | _available_range = available_range; 51 | } 52 | 53 | /// @brief Return whether the reference is missing. 54 | virtual bool is_missing_reference() const; 55 | 56 | /// @brief Return the spatial bounds of the media reference. 57 | std::optional available_image_bounds() const 58 | { 59 | return _available_image_bounds; 60 | } 61 | 62 | /// @brief Set the spatial bounds of the media reference. 63 | void set_available_image_bounds( 64 | std::optional const& available_image_bounds) 65 | { 66 | _available_image_bounds = available_image_bounds; 67 | } 68 | 69 | protected: 70 | virtual ~MediaReference(); 71 | 72 | bool read_from(Reader&) override; 73 | void write_to(Writer&) const override; 74 | 75 | private: 76 | std::optional _available_range; 77 | std::optional _available_image_bounds; 78 | }; 79 | 80 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 81 | -------------------------------------------------------------------------------- /src/opentimelineio/missingReference.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/missingReference.h" 5 | 6 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 7 | 8 | MissingReference::MissingReference( 9 | std::string const& name, 10 | std::optional const& available_range, 11 | AnyDictionary const& metadata, 12 | std::optional const& available_image_bounds) 13 | : Parent(name, available_range, metadata, available_image_bounds) 14 | {} 15 | 16 | MissingReference::~MissingReference() 17 | {} 18 | 19 | bool 20 | MissingReference::is_missing_reference() const 21 | { 22 | return true; 23 | } 24 | 25 | bool 26 | MissingReference::read_from(Reader& reader) 27 | { 28 | return Parent::read_from(reader); 29 | } 30 | 31 | void 32 | MissingReference::write_to(Writer& writer) const 33 | { 34 | Parent::write_to(writer); 35 | } 36 | 37 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 38 | -------------------------------------------------------------------------------- /src/opentimelineio/missingReference.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/mediaReference.h" 7 | #include "opentimelineio/version.h" 8 | 9 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 10 | 11 | /// @brief Represents media for which a concrete reference is missing. 12 | /// 13 | /// Note that a missing reference may have useful metadata, even if the 14 | /// location of the media is not known. 15 | class MissingReference final : public MediaReference 16 | { 17 | public: 18 | /// @brief This struct provides the MissingReference schema. 19 | struct Schema 20 | { 21 | static auto constexpr name = "MissingReference"; 22 | static int constexpr version = 1; 23 | }; 24 | 25 | using Parent = MediaReference; 26 | 27 | /// @brief Create a new missing reference. 28 | /// 29 | /// @param name The name of the missing reference. 30 | /// @param available_range The available range of the missing reference. 31 | /// @param metadata The metadata for the missing reference. 32 | /// @param available_image_bounds The spatial bounds for the missing reference. 33 | MissingReference( 34 | std::string const& name = std::string(), 35 | std::optional const& available_range = std::nullopt, 36 | AnyDictionary const& metadata = AnyDictionary(), 37 | std::optional const& available_image_bounds = 38 | std::nullopt); 39 | 40 | bool is_missing_reference() const override; 41 | 42 | protected: 43 | virtual ~MissingReference(); 44 | 45 | bool read_from(Reader&) override; 46 | void write_to(Writer&) const override; 47 | }; 48 | 49 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 50 | -------------------------------------------------------------------------------- /src/opentimelineio/serializableObjectWithMetadata.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/serializableObjectWithMetadata.h" 5 | 6 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 7 | 8 | SerializableObjectWithMetadata::SerializableObjectWithMetadata( 9 | std::string const& name, 10 | AnyDictionary const& metadata) 11 | : _name(name) 12 | , _metadata(metadata) 13 | {} 14 | 15 | SerializableObjectWithMetadata::~SerializableObjectWithMetadata() 16 | {} 17 | 18 | bool 19 | SerializableObjectWithMetadata::read_from(Reader& reader) 20 | { 21 | return reader.read_if_present("metadata", &_metadata) 22 | && reader.read_if_present("name", &_name) 23 | && SerializableObject::read_from(reader); 24 | } 25 | 26 | void 27 | SerializableObjectWithMetadata::write_to(Writer& writer) const 28 | { 29 | SerializableObject::write_to(writer); 30 | writer.write("metadata", _metadata); 31 | writer.write("name", _name); 32 | } 33 | 34 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 35 | -------------------------------------------------------------------------------- /src/opentimelineio/serializableObjectWithMetadata.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/serializableObject.h" 7 | #include "opentimelineio/version.h" 8 | 9 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 10 | 11 | /// @brief A serializable object with metadata. 12 | class SerializableObjectWithMetadata : public SerializableObject 13 | { 14 | public: 15 | /// @brief This struct provides the SerializableObjectWithMetadata schema. 16 | struct Schema 17 | { 18 | static auto constexpr name = "SerializableObjectWithMetadata"; 19 | static int constexpr version = 1; 20 | }; 21 | 22 | using Parent = SerializableObject; 23 | 24 | /// @brief Create a new serializable object. 25 | /// 26 | /// @param name The object name. 27 | /// @param metadata The metadata for the object. 28 | SerializableObjectWithMetadata( 29 | std::string const& name = std::string(), 30 | AnyDictionary const& metadata = AnyDictionary()); 31 | 32 | /// @brief Return the object name. 33 | std::string name() const noexcept { return _name; } 34 | 35 | /// @brief Set the object name. 36 | void set_name(std::string const& name) { _name = name; } 37 | 38 | /// @brief Modify the object metadata. 39 | AnyDictionary& metadata() noexcept { return _metadata; } 40 | 41 | /// @brief Return the object metadata. 42 | AnyDictionary metadata() const noexcept { return _metadata; } 43 | 44 | protected: 45 | virtual ~SerializableObjectWithMetadata(); 46 | 47 | bool read_from(Reader&) override; 48 | void write_to(Writer&) const override; 49 | 50 | private: 51 | std::string _name; 52 | AnyDictionary _metadata; 53 | }; 54 | 55 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 56 | -------------------------------------------------------------------------------- /src/opentimelineio/serialization.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/errorStatus.h" 7 | #include "opentimelineio/typeRegistry.h" 8 | #include "opentimelineio/version.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 15 | 16 | /// @brief Serialize JSON data to a string. 17 | std::string serialize_json_to_string( 18 | const std::any& value, 19 | const schema_version_map* schema_version_targets = nullptr, 20 | ErrorStatus* error_status = nullptr, 21 | int indent = 4); 22 | 23 | /// @brief Serialize JSON data to a file. 24 | bool serialize_json_to_file( 25 | const std::any& value, 26 | std::string const& file_name, 27 | const schema_version_map* schema_version_targets = nullptr, 28 | ErrorStatus* error_status = nullptr, 29 | int indent = 4); 30 | 31 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 32 | -------------------------------------------------------------------------------- /src/opentimelineio/stackAlgorithm.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/stack.h" 7 | #include "opentimelineio/track.h" 8 | #include "opentimelineio/version.h" 9 | 10 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 11 | 12 | /// @brief Flatten a stack down to a single track. 13 | Track* flatten_stack(Stack* in_stack, ErrorStatus* error_status = nullptr); 14 | 15 | /// @brief Flatten a list of tracks down to a single track. 16 | Track* flatten_stack( 17 | std::vector const& tracks, 18 | ErrorStatus* error_status = nullptr); 19 | 20 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 21 | -------------------------------------------------------------------------------- /src/opentimelineio/stringUtils.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/serializableObject.h" 5 | #include 6 | #include 7 | #include 8 | 9 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 10 | 11 | std::string 12 | type_name_for_error_message(std::type_info const& t) 13 | { 14 | if (t == typeid(std::string)) 15 | { 16 | return "string"; 17 | } 18 | if (t == typeid(void)) 19 | { 20 | return "None"; 21 | } 22 | 23 | return t.name(); 24 | } 25 | 26 | std::string 27 | type_name_for_error_message(std::any const& a) 28 | { 29 | return type_name_for_error_message(a.type()); 30 | } 31 | 32 | std::string 33 | type_name_for_error_message(SerializableObject* so) 34 | { 35 | return type_name_for_error_message(typeid(*so)); 36 | } 37 | 38 | void 39 | fatal_error(std::string const& errMsg) 40 | { 41 | fprintf(stderr, "Fatal error: %s\n", errMsg.c_str()); 42 | exit(-1); 43 | } 44 | 45 | bool 46 | split_schema_string( 47 | std::string const& schema_and_version, 48 | std::string* schema_name, 49 | int* schema_version) 50 | { 51 | size_t index = schema_and_version.rfind('.'); 52 | if (index == std::string::npos) 53 | { 54 | return false; 55 | } 56 | 57 | *schema_name = schema_and_version.substr(0, index); 58 | try 59 | { 60 | *schema_version = std::stoi(schema_and_version.substr(index + 1)); 61 | return true; 62 | } 63 | catch (...) 64 | { 65 | return false; 66 | } 67 | } 68 | 69 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 70 | -------------------------------------------------------------------------------- /src/opentimelineio/stringUtils.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentime/stringPrintf.h" 7 | #include "opentimelineio/version.h" 8 | using opentime::string_printf; 9 | 10 | #include 11 | #include 12 | 13 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 14 | 15 | /// @name String Utilities 16 | ///@{ 17 | 18 | void fatal_error(std::string const& errMsg); 19 | 20 | std::string type_name_for_error_message(std::type_info const&); 21 | std::string type_name_for_error_message(std::any const& a); 22 | std::string type_name_for_error_message(class SerializableObject*); 23 | 24 | template 25 | std::string 26 | type_name_for_error_message() 27 | { 28 | return type_name_for_error_message(typeid(T)); 29 | } 30 | 31 | bool split_schema_string( 32 | std::string const& schema_and_version, 33 | std::string* schema_name, 34 | int* schema_version); 35 | 36 | ///@} 37 | 38 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 39 | -------------------------------------------------------------------------------- /src/opentimelineio/timeEffect.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/timeEffect.h" 5 | 6 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 7 | 8 | TimeEffect::TimeEffect( 9 | std::string const& name, 10 | std::string const& effect_name, 11 | AnyDictionary const& metadata) 12 | : Parent(name, effect_name, metadata) 13 | {} 14 | 15 | TimeEffect::~TimeEffect() 16 | {} 17 | 18 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 19 | -------------------------------------------------------------------------------- /src/opentimelineio/timeEffect.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/effect.h" 7 | #include "opentimelineio/version.h" 8 | 9 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 10 | 11 | /// @brief Base class for all effects that alter the timing of an item. 12 | class TimeEffect : public Effect 13 | { 14 | public: 15 | /// @brief This struct provides the TimeEffect schema. 16 | struct Schema 17 | { 18 | static auto constexpr name = "TimeEffect"; 19 | static int constexpr version = 1; 20 | }; 21 | 22 | using Parent = Effect; 23 | 24 | /// @brief Create a new time effect. 25 | /// 26 | /// @param name The name of the object. 27 | /// @param effect_name The time effect name. 28 | /// @param metadata The metadata for the time effect. 29 | TimeEffect( 30 | std::string const& name = std::string(), 31 | std::string const& effect_name = std::string(), 32 | AnyDictionary const& metadata = AnyDictionary()); 33 | 34 | protected: 35 | virtual ~TimeEffect(); 36 | }; 37 | 38 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 39 | -------------------------------------------------------------------------------- /src/opentimelineio/timeline.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/timeline.h" 5 | #include "opentimelineio/clip.h" 6 | 7 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 8 | 9 | Timeline::Timeline( 10 | std::string const& name, 11 | std::optional global_start_time, 12 | AnyDictionary const& metadata) 13 | : SerializableObjectWithMetadata(name, metadata) 14 | , _global_start_time(global_start_time) 15 | , _tracks(new Stack("tracks")) 16 | {} 17 | 18 | Timeline::~Timeline() 19 | {} 20 | 21 | void 22 | Timeline::set_tracks(Stack* stack) 23 | { 24 | _tracks = stack ? stack : new Stack("tracks"); 25 | } 26 | 27 | bool 28 | Timeline::read_from(Reader& reader) 29 | { 30 | return reader.read("tracks", &_tracks) 31 | && reader.read_if_present("global_start_time", &_global_start_time) 32 | && Parent::read_from(reader); 33 | } 34 | 35 | void 36 | Timeline::write_to(Writer& writer) const 37 | { 38 | Parent::write_to(writer); 39 | writer.write("global_start_time", _global_start_time); 40 | writer.write("tracks", _tracks); 41 | } 42 | 43 | std::vector 44 | Timeline::video_tracks() const 45 | { 46 | std::vector result; 47 | for (auto c: _tracks->children()) 48 | { 49 | if (auto t = dynamic_retainer_cast(c)) 50 | { 51 | if (t->kind() == Track::Kind::video) 52 | { 53 | result.push_back(t); 54 | } 55 | } 56 | } 57 | return result; 58 | } 59 | 60 | std::vector 61 | Timeline::audio_tracks() const 62 | { 63 | std::vector result; 64 | for (auto c: _tracks->children()) 65 | { 66 | if (auto t = dynamic_retainer_cast(c)) 67 | { 68 | if (t->kind() == Track::Kind::audio) 69 | { 70 | result.push_back(t); 71 | } 72 | } 73 | } 74 | return result; 75 | } 76 | 77 | std::vector> 78 | Timeline::find_clips( 79 | ErrorStatus* error_status, 80 | std::optional const& search_range, 81 | bool shallow_search) const 82 | { 83 | return _tracks.value->find_clips( 84 | error_status, 85 | search_range, 86 | shallow_search); 87 | } 88 | 89 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 90 | -------------------------------------------------------------------------------- /src/opentimelineio/trackAlgorithm.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/track.h" 7 | #include "opentimelineio/version.h" 8 | 9 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 10 | 11 | /// @brief Trim the track to the given range. 12 | Track* track_trimmed_to_range( 13 | Track* in_track, 14 | TimeRange trim_range, 15 | ErrorStatus* error_status = nullptr); 16 | 17 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 18 | -------------------------------------------------------------------------------- /src/opentimelineio/transition.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/transition.h" 5 | #include "opentimelineio/composition.h" 6 | 7 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 8 | 9 | Transition::Transition( 10 | std::string const& name, 11 | std::string const& transition_type, 12 | RationalTime in_offset, 13 | RationalTime out_offset, 14 | AnyDictionary const& metadata) 15 | : Parent(name, metadata) 16 | , _transition_type(transition_type) 17 | , _in_offset(in_offset) 18 | , _out_offset(out_offset) 19 | {} 20 | 21 | Transition::~Transition() 22 | {} 23 | 24 | bool 25 | Transition::overlapping() const 26 | { 27 | return true; 28 | } 29 | 30 | bool 31 | Transition::read_from(Reader& reader) 32 | { 33 | return reader.read("in_offset", &_in_offset) 34 | && reader.read("out_offset", &_out_offset) 35 | && reader.read("transition_type", &_transition_type) 36 | && Parent::read_from(reader); 37 | } 38 | 39 | void 40 | Transition::write_to(Writer& writer) const 41 | { 42 | Parent::write_to(writer); 43 | writer.write("in_offset", _in_offset); 44 | writer.write("out_offset", _out_offset); 45 | writer.write("transition_type", _transition_type); 46 | } 47 | 48 | RationalTime 49 | Transition::duration(ErrorStatus* /* error_status */) const 50 | { 51 | return _in_offset + _out_offset; 52 | } 53 | 54 | std::optional 55 | Transition::range_in_parent(ErrorStatus* error_status) const 56 | { 57 | if (!parent()) 58 | { 59 | if (error_status) 60 | { 61 | *error_status = ErrorStatus( 62 | ErrorStatus::NOT_A_CHILD, 63 | "cannot compute range in parent because item has no parent", 64 | this); 65 | } 66 | } 67 | 68 | return parent()->range_of_child(this, error_status); 69 | } 70 | 71 | std::optional 72 | Transition::trimmed_range_in_parent(ErrorStatus* error_status) const 73 | { 74 | if (!parent()) 75 | { 76 | if (error_status) 77 | { 78 | *error_status = ErrorStatus( 79 | ErrorStatus::NOT_A_CHILD, 80 | "cannot compute trimmed range in parent because item has no parent", 81 | this); 82 | } 83 | } 84 | 85 | return parent()->trimmed_range_of_child(this, error_status); 86 | } 87 | 88 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 89 | -------------------------------------------------------------------------------- /src/opentimelineio/unknownSchema.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "opentimelineio/unknownSchema.h" 5 | 6 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 7 | 8 | UnknownSchema::UnknownSchema( 9 | std::string const& original_schema_name, 10 | int original_schema_version) 11 | : _original_schema_name(original_schema_name) 12 | , _original_schema_version(original_schema_version) 13 | {} 14 | 15 | UnknownSchema::~UnknownSchema() 16 | {} 17 | 18 | bool 19 | UnknownSchema::read_from(Reader& reader) 20 | { 21 | _data.swap(reader._dict); 22 | _data.erase("OTIO_SCHEMA"); 23 | return true; 24 | } 25 | 26 | void 27 | UnknownSchema::write_to(Writer& writer) const 28 | { 29 | for (auto e: _data) 30 | { 31 | writer.write(e.first, e.second); 32 | } 33 | } 34 | 35 | std::string 36 | UnknownSchema::_schema_name_for_reference() const 37 | { 38 | return _original_schema_name; 39 | } 40 | 41 | bool 42 | UnknownSchema::is_unknown_schema() const 43 | { 44 | return true; 45 | } 46 | 47 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 48 | -------------------------------------------------------------------------------- /src/opentimelineio/unknownSchema.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/serializableObject.h" 7 | #include "opentimelineio/version.h" 8 | 9 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 10 | 11 | /// @brief An unknown schema. 12 | class UnknownSchema : public SerializableObject 13 | { 14 | public: 15 | /// @brief This struct provides the UnknownSchema schema. 16 | struct Schema 17 | { 18 | static auto constexpr name = "UnknownSchema"; 19 | static int constexpr version = 1; 20 | }; 21 | 22 | /// @brief Create a new unknown schema. 23 | /// 24 | /// @param original_schema_name The original schema name. 25 | /// @param original_schema_version The original schema version. 26 | UnknownSchema( 27 | std::string const& original_schema_name, 28 | int original_schema_version); 29 | 30 | /// @brief Return the original schema name. 31 | std::string original_schema_name() const noexcept 32 | { 33 | return _original_schema_name; 34 | } 35 | 36 | /// @brief Return the original schema version. 37 | int original_schema_version() const noexcept 38 | { 39 | return _original_schema_version; 40 | } 41 | 42 | bool read_from(Reader&) override; 43 | void write_to(Writer&) const override; 44 | 45 | bool is_unknown_schema() const override; 46 | 47 | protected: 48 | virtual ~UnknownSchema(); 49 | 50 | std::string _schema_name_for_reference() const override; 51 | 52 | private: 53 | std::string _original_schema_name; 54 | int _original_schema_version; 55 | 56 | AnyDictionary _data; 57 | 58 | friend class TypeRegistry; 59 | friend class SerializableObject::Writer; 60 | }; 61 | 62 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 63 | -------------------------------------------------------------------------------- /src/opentimelineio/vectorIndexing.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include "opentimelineio/version.h" 7 | 8 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 9 | 10 | /// @brief Return the adjusted vector index. 11 | template 12 | constexpr int 13 | adjusted_vector_index(int index, V const& vec) noexcept 14 | { 15 | return index < 0 ? int(vec.size()) + index : index; 16 | } 17 | 18 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 19 | -------------------------------------------------------------------------------- /src/opentimelineio/version.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #define OPENTIMELINEIO_VERSION v1_0 7 | 8 | #include "opentime/rationalTime.h" 9 | #include "opentime/timeRange.h" 10 | #include "opentime/timeTransform.h" 11 | #include "opentime/version.h" 12 | 13 | namespace opentimelineio { namespace OPENTIMELINEIO_VERSION { 14 | using opentime::RationalTime; 15 | using opentime::TimeRange; 16 | using opentime::TimeTransform; 17 | }} // namespace opentimelineio::OPENTIMELINEIO_VERSION 18 | 19 | /// @brief Convenience macro for the full namespace of OpenTimelineIO API. 20 | /// 21 | /// This can be used in place of the full namespace, e.g.: 22 | /// 23 | /// OTIO_NS::Track* track = new OTIO_NS::Track; 24 | /// 25 | /// 26 | #define OTIO_NS opentimelineio::OPENTIMELINEIO_VERSION 27 | -------------------------------------------------------------------------------- /src/opentimelineview/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | # flake8: noqa 5 | 6 | from . import ( 7 | details_widget, 8 | timeline_widget, 9 | ) 10 | -------------------------------------------------------------------------------- /src/opentimelineview/settings.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | VIEW_STYLESHEET = """ 5 | QMainWindow { 6 | background-color: rgb(27, 27, 27); 7 | } 8 | 9 | QScrollBar:horizontal { 10 | background: rgb(21, 21, 21); 11 | height: 15px; 12 | margin: 0px 20px 0 20px; 13 | } 14 | 15 | QScrollBar::handle:horizontal { 16 | background: rgb(255, 83, 112); 17 | min-width: 20px; 18 | } 19 | 20 | QScrollBar::add-line:horizontal { 21 | background: rgb(33, 33, 33); 22 | width: 20px; 23 | subcontrol-position: right; 24 | subcontrol-origin: margin; 25 | } 26 | 27 | QScrollBar::sub-line:horizontal { 28 | background: rgb(33, 33, 33); 29 | width: 20px; 30 | subcontrol-position: left; 31 | subcontrol-origin: margin; 32 | } 33 | 34 | QScrollBar:left-arrow:horizontal, QScrollBar::right-arrow:horizontal { 35 | width: 3px; 36 | height: 3px; 37 | background: transparent; 38 | } 39 | 40 | QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { 41 | background: none; 42 | } 43 | 44 | QScrollBar:vertical { 45 | background: rgb(21, 21, 21); 46 | width: 15px; 47 | margin: 22px 0 22px 0; 48 | } 49 | 50 | QScrollBar::handle:vertical { 51 | background: rgb(255, 83, 112); 52 | min-height: 20px; 53 | } 54 | 55 | QScrollBar::add-line:vertical { 56 | background: rgb(33, 33, 33); 57 | height: 20px; 58 | subcontrol-position: bottom; 59 | subcontrol-origin: margin; 60 | } 61 | 62 | QScrollBar::sub-line:vertical { 63 | background: rgb(33, 33, 33); 64 | height: 20px; 65 | subcontrol-position: top; 66 | subcontrol-origin: margin; 67 | } 68 | 69 | QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical { 70 | width: 3px; 71 | height: 3px; 72 | background: transparent; 73 | } 74 | 75 | QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { 76 | background: none; 77 | } 78 | """ 79 | -------------------------------------------------------------------------------- /src/py-opentimelineio/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # py-opentimelineio/CMakeLists.txt 3 | 4 | add_subdirectory(opentime-bindings) 5 | add_subdirectory(opentimelineio-bindings) 6 | 7 | if(OTIO_INSTALL_PYTHON_MODULES) 8 | # Install pure-python OTIO packages to match PyPI wheel structure 9 | install(DIRECTORY "${PROJECT_SOURCE_DIR}/src/py-opentimelineio/opentimelineio/" 10 | DESTINATION "${OTIO_RESOLVED_PYTHON_INSTALL_DIR}/opentimelineio") 11 | 12 | if(OTIO_INSTALL_COMMANDLINE_TOOLS) 13 | install(DIRECTORY "${PROJECT_SOURCE_DIR}/src/opentimelineview" 14 | DESTINATION "${OTIO_RESOLVED_PYTHON_INSTALL_DIR}") 15 | endif() 16 | 17 | endif() 18 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentime-bindings/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # py-opentimelineio/opentime-bindings/CMakeLists.txt 3 | 4 | pybind11_add_module(_opentime 5 | opentime_bindings.cpp 6 | opentime_rationalTime.cpp 7 | opentime_timeRange.cpp 8 | opentime_timeTransform.cpp 9 | opentime_bindings.h) 10 | 11 | target_include_directories(_opentime 12 | PRIVATE pybind11/include 13 | PRIVATE "${PROJECT_SOURCE_DIR}/src" 14 | PRIVATE "${PROJECT_SOURCE_DIR}/src/deps" 15 | PRIVATE "${PROJECT_SOURCE_DIR}/src/deps/optional-lite/include") 16 | 17 | target_link_libraries(_opentime PUBLIC opentimelineio opentime) 18 | 19 | set_target_properties(_opentime PROPERTIES 20 | LIBRARY_OUTPUT_NAME "_opentime" 21 | DEBUG_POSTFIX "${OTIO_DEBUG_POSTFIX}") 22 | 23 | # The version of pybind11 we are currently using generates an overwhelming number of 24 | # compiler warnings; until we update pybind11, suprress the warnings: 25 | target_compile_options(_opentime PRIVATE 26 | $<$,$,$>: 27 | -Wno-range-loop-analysis> 28 | $<$,$,$>: 29 | -Wno-unused-value> 30 | $<$: /EHsc> 31 | ) 32 | 33 | if(APPLE) 34 | set_target_properties(_opentime PROPERTIES 35 | INSTALL_NAME_DIR "@loader_path" 36 | MACOSX_RPATH ON) 37 | elseif(UNIX) 38 | set_target_properties(_opentime PROPERTIES 39 | INSTALL_RPATH "$ORIGIN" 40 | INSTALL_RPATH_USE_LINK_PATH OFF) 41 | endif() 42 | 43 | install(TARGETS _opentime 44 | ARCHIVE DESTINATION "${OTIO_RESOLVED_CXX_DYLIB_INSTALL_DIR}" 45 | LIBRARY DESTINATION "${OTIO_RESOLVED_CXX_DYLIB_INSTALL_DIR}" 46 | RUNTIME DESTINATION "${OTIO_RESOLVED_CXX_DYLIB_INSTALL_DIR}") 47 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentime-bindings/opentime_bindings.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include 5 | #include "opentime_bindings.h" 6 | 7 | PYBIND11_MODULE(_opentime, m) { 8 | m.doc() = "Bindings to C++ OTIO implementation"; 9 | opentime_rationalTime_bindings(m); 10 | opentime_timeRange_bindings(m); 11 | opentime_timeTransform_bindings(m); 12 | } 13 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentime-bindings/opentime_bindings.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #ifndef OTIO_OPENTIME_BINDINGS_H 5 | #define OTIO_OPENTIME_BINDINGS_H 6 | 7 | #include 8 | #include 9 | #include "opentime/rationalTime.h" 10 | 11 | void opentime_rationalTime_bindings(pybind11::module); 12 | void opentime_timeRange_bindings(pybind11::module); 13 | void opentime_timeTransform_bindings(pybind11::module); 14 | 15 | std::string opentime_python_str(opentime::RationalTime rt); 16 | std::string opentime_python_repr(opentime::RationalTime rt); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentime-bindings/opentime_timeTransform.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include 5 | #include 6 | 7 | #include "opentime_bindings.h" 8 | #include "opentime/timeTransform.h" 9 | #include "opentimelineio/stringUtils.h" 10 | 11 | namespace py = pybind11; 12 | using namespace pybind11::literals; 13 | using namespace opentime; 14 | 15 | 16 | void opentime_timeTransform_bindings(py::module m) { 17 | py::class_(m, "TimeTransform", R"docstring(1D transform for :class:`~RationalTime`. Has offset and scale.)docstring") 18 | .def(py::init(), 19 | "offset"_a = RationalTime(), "scale"_a = 1, "rate"_a = -1) 20 | .def_property_readonly("offset", &TimeTransform::offset) 21 | .def_property_readonly("scale", &TimeTransform::scale) 22 | .def_property_readonly("rate", &TimeTransform::rate) 23 | .def("applied_to", (TimeRange (TimeTransform::*)(TimeRange) const) &TimeTransform::applied_to, "other"_a) 24 | .def("applied_to", (TimeTransform (TimeTransform::*)(TimeTransform) const) &TimeTransform::applied_to, "other"_a) 25 | .def("applied_to", (RationalTime (TimeTransform::*)(RationalTime) const) &TimeTransform::applied_to, "other"_a) 26 | .def("__copy__", [](TimeTransform const& tt) { 27 | return tt; 28 | }) 29 | .def("__deepcopy__", [](TimeTransform const& tt, py::dict memo) { 30 | return tt; 31 | }, "memo"_a) 32 | .def(py::self == py::self) 33 | .def(py::self != py::self) 34 | .def("__str__", [](TimeTransform tt) { 35 | return string_printf("TimeTransform(%s, %g, %g)", 36 | opentime_python_str(tt.offset()).c_str(), 37 | tt.scale(), tt.rate()); 38 | 39 | }) 40 | .def("__repr__", [](TimeTransform tt) { 41 | return string_printf("otio.opentime.TimeTransform(offset=%s, scale=%g, rate=%g)", 42 | opentime_python_repr(tt.offset()).c_str(), tt.scale(), tt.rate()); 43 | }) 44 | ; 45 | } 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio-bindings/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # py-opentimelineio/opentimelineio-bindings/CMakeLists.txt 3 | 4 | set(_OTIO_HEADER_FILES 5 | otio_errorStatusHandler.h 6 | otio_anyDictionary.h 7 | otio_bindings.h 8 | otio_utils.h) 9 | 10 | pybind11_add_module(_otio 11 | otio_errorStatusHandler.cpp 12 | otio_anyDictionary.cpp 13 | otio_anyVector.cpp 14 | otio_bindings.cpp 15 | otio_imath.cpp 16 | otio_tests.cpp 17 | otio_serializableObjects.cpp 18 | otio_utils.cpp 19 | ${_OTIO_HEADER_FILES}) 20 | 21 | target_include_directories(_otio 22 | PRIVATE pybind11/include 23 | PRIVATE "${PROJECT_SOURCE_DIR}/src" 24 | PRIVATE "${PROJECT_SOURCE_DIR}/src/deps" 25 | PRIVATE "${PROJECT_SOURCE_DIR}/src/deps/optional-lite/include" 26 | ) 27 | 28 | target_link_libraries(_otio PUBLIC opentimelineio opentime) 29 | 30 | # The version of pybind11 we are currently using generates an overwhelming number of 31 | # compiler warnings; until we update pybind11, suprress the warnings: 32 | target_compile_options(_otio PRIVATE 33 | $<$,$,$>: 34 | -Wno-range-loop-analysis> 35 | $<$,$,$>: 36 | -Wno-unused-value> 37 | $<$: /EHsc> 38 | ) 39 | 40 | set_target_properties(_otio PROPERTIES 41 | LIBRARY_OUTPUT_NAME "_otio" 42 | DEBUG_POSTFIX "${OTIO_DEBUG_POSTFIX}") 43 | 44 | if(APPLE) 45 | set_target_properties(_otio PROPERTIES 46 | INSTALL_NAME_DIR "@loader_path" 47 | MACOSX_RPATH ON) 48 | elseif(UNIX) 49 | set_target_properties(_otio PROPERTIES 50 | INSTALL_RPATH "$ORIGIN" 51 | INSTALL_RPATH_USE_LINK_PATH OFF) 52 | endif() 53 | 54 | install(TARGETS _otio 55 | ARCHIVE DESTINATION "${OTIO_RESOLVED_CXX_DYLIB_INSTALL_DIR}" 56 | LIBRARY DESTINATION "${OTIO_RESOLVED_CXX_DYLIB_INSTALL_DIR}" 57 | RUNTIME DESTINATION "${OTIO_RESOLVED_CXX_DYLIB_INSTALL_DIR}") 58 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio-bindings/otio_anyDictionary.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include 5 | #include 6 | 7 | namespace py = pybind11; 8 | using namespace pybind11::literals; 9 | 10 | #include "otio_bindings.h" 11 | #include "otio_anyDictionary.h" 12 | #include "otio_anyVector.h" 13 | #include "opentime/rationalTime.h" 14 | #include "opentime/timeRange.h" 15 | #include "opentime/timeTransform.h" 16 | #include "opentimelineio/serializableObject.h" 17 | #include "opentimelineio/stringUtils.h" 18 | 19 | void otio_any_dictionary_bindings(py::module m) { 20 | py::class_(m, "AnyDictionaryIterator") 21 | .def("__iter__", &AnyDictionaryProxy::Iterator::iter) 22 | .def("__next__", &AnyDictionaryProxy::Iterator::next); 23 | 24 | py::class_(m, "AnyDictionary") 25 | .def(py::init<>()) 26 | .def("__getitem__", &AnyDictionaryProxy::get_item, "key"_a) 27 | .def("__internal_setitem__", &AnyDictionaryProxy::set_item, "key"_a, "item"_a) 28 | .def("__delitem__", &AnyDictionaryProxy::del_item, "key"_a) 29 | .def("__len__", &AnyDictionaryProxy::len) 30 | .def("__iter__", &AnyDictionaryProxy::iter, py::return_value_policy::reference_internal); 31 | } 32 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio-bindings/otio_anyVector.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include 5 | #include 6 | 7 | namespace py = pybind11; 8 | using namespace pybind11::literals; 9 | 10 | #include "otio_utils.h" 11 | #include "otio_anyVector.h" 12 | #include "opentime/rationalTime.h" 13 | #include "opentimelineio/stringUtils.h" 14 | 15 | void otio_any_vector_bindings(py::module m) { 16 | py::class_(m, "AnyVectorIterator") 17 | .def("__iter__", &AnyVectorProxy::Iterator::iter) 18 | .def("__next__", &AnyVectorProxy::Iterator::next); 19 | 20 | py::class_(m, "AnyVector") 21 | .def(py::init<>()) 22 | .def("__internal_getitem__", &AnyVectorProxy::get_item, "index"_a) 23 | .def("__internal_setitem__", &AnyVectorProxy::set_item, "index"_a, "item"_a) 24 | .def("__internal_delitem__", &AnyVectorProxy::del_item, "index"_a) 25 | .def("__len__", &AnyVectorProxy::len) 26 | .def("__internal_insert", &AnyVectorProxy::insert) 27 | .def("__iter__", &AnyVectorProxy::iter, py::return_value_policy::reference_internal); 28 | } 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio-bindings/otio_bindings.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include 7 | 8 | void otio_exception_bindings(pybind11::module); 9 | void otio_any_dictionary_bindings(pybind11::module); 10 | void otio_any_vector_bindings(pybind11::module); 11 | void otio_imath_bindings(pybind11::module); 12 | void otio_serializable_object_bindings(pybind11::module); 13 | void otio_tests_bindings(pybind11::module); 14 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio-bindings/otio_errorStatusHandler.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | 6 | #include 7 | #include "opentimelineio/errorStatus.h" 8 | 9 | using namespace opentimelineio::OPENTIMELINEIO_VERSION; 10 | 11 | struct ErrorStatusHandler { 12 | operator ErrorStatus* () { 13 | return &error_status; 14 | } 15 | 16 | ~ErrorStatusHandler() noexcept(false); 17 | 18 | std::string details(); 19 | std::string full_details(); 20 | 21 | ErrorStatus error_status; 22 | }; 23 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | """An editorial interchange format and library. 5 | 6 | see: http://opentimeline.io 7 | 8 | .. moduleauthor:: Contributors to the OpenTimelineIO project 9 | """ 10 | 11 | # flake8: noqa 12 | 13 | # in dependency hierarchy 14 | from . import ( 15 | opentime, 16 | exceptions, 17 | core, 18 | schema, 19 | schemadef, 20 | plugins, 21 | media_linker, 22 | adapters, 23 | hooks, 24 | algorithms, 25 | url_utils, 26 | versioning, 27 | ) 28 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/adapters/builtin_adapters.plugin_manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "PluginManifest.1", 3 | "adapters": [ 4 | { 5 | "OTIO_SCHEMA" : "Adapter.1", 6 | "name" : "otio_json", 7 | "filepath" : "otio_json.py", 8 | "suffixes" : ["otio"] 9 | }, 10 | { 11 | "OTIO_SCHEMA" : "Adapter.1", 12 | "name" : "otioz", 13 | "filepath" : "otioz.py", 14 | "suffixes" : ["otioz"] 15 | }, 16 | { 17 | "OTIO_SCHEMA" : "Adapter.1", 18 | "name" : "otiod", 19 | "filepath" : "otiod.py", 20 | "suffixes" : ["otiod"] 21 | } 22 | ], 23 | "hooks": { 24 | "post_adapter_read" : [], 25 | "post_media_linker" : [], 26 | "pre_adapter_write" : [], 27 | "post_adapter_write" : [] 28 | }, 29 | "version_manifests": { 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/algorithms/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | """Algorithms for OTIO objects.""" 5 | 6 | # flake8: noqa 7 | from .track_algo import ( 8 | track_trimmed_to_range, 9 | track_with_expanded_transitions 10 | ) 11 | 12 | from .stack_algo import ( 13 | flatten_stack, 14 | top_clip_at_time, 15 | ) 16 | 17 | from .filter import ( 18 | filtered_composition, 19 | filtered_with_sequence_context 20 | ) 21 | from .timeline_algo import ( 22 | timeline_trimmed_to_range 23 | ) 24 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/algorithms/stack_algo.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | __doc__ = """ Algorithms for stack objects. """ 5 | 6 | from .. import ( 7 | schema, 8 | opentime, 9 | _otio, 10 | ) 11 | 12 | 13 | def top_clip_at_time(in_stack, t): 14 | """Return the topmost visible child that overlaps with time ``t``. 15 | 16 | Example:: 17 | 18 | tr1: G1, A, G2 19 | tr2: [B------] 20 | G1, and G2 are gaps, A and B are clips. 21 | 22 | If ``t`` is within ``A``, ``A`` will be returned. If ``t`` is within ``G1`` or 23 | ``G2``, ``B`` will be returned. 24 | 25 | :param Stack in_stack: Stack 26 | :param RationalTime t: Time 27 | :returns: Top clip 28 | :rtype: Clip 29 | """ 30 | 31 | # ensure that it only runs on stacks 32 | if not isinstance(in_stack, schema.Stack): 33 | raise ValueError( 34 | "Argument in_stack must be of type otio.schema.Stack, " 35 | "not: '{}'".format( 36 | type(in_stack) 37 | ) 38 | ) 39 | 40 | # build a range to use the `find_clips`method. 41 | search_range = opentime.TimeRange( 42 | start_time=t, 43 | # 0 duration so we are just sampling a point in time. 44 | # XXX Should this duration be equal to the length of one sample? 45 | # opentime.RationalTime(1, rate)? 46 | duration=opentime.RationalTime(0, t.rate) 47 | ) 48 | 49 | # walk through the children of the stack in reverse order. 50 | for track in reversed(in_stack): 51 | valid_results = [] 52 | if hasattr(track, "find_clips"): 53 | valid_results = list( 54 | c for c in track.find_clips(search_range, shallow_search=True) 55 | if c.visible() 56 | ) 57 | 58 | # XXX doesn't handle nested tracks/stacks at the moment 59 | 60 | for result in valid_results: 61 | return result 62 | 63 | return None 64 | 65 | 66 | flatten_stack = _otio.flatten_stack 67 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/algorithms/timeline_algo.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | """Algorithms for timeline objects.""" 5 | 6 | import copy 7 | 8 | from . import ( 9 | track_algo 10 | ) 11 | 12 | 13 | def timeline_trimmed_to_range(in_timeline, trim_range): 14 | """ 15 | Returns a new timeline that is a copy of the in_timeline, but with items 16 | outside the trim_range removed and items on the ends trimmed to the 17 | trim_range. 18 | 19 | .. note:: the timeline is never expanded, only shortened. 20 | 21 | Please note that you could do nearly the same thing non-destructively by 22 | just setting the :py:class:`.Track`\'s source_range but sometimes you want to 23 | really cut away the stuff outside and that's what this function is meant for. 24 | 25 | :param Timeline in_timeline: Timeline to trim 26 | :param TimeRange trim_range: 27 | :returnd: New trimmed timeline 28 | :rtype: Timeline 29 | """ 30 | new_timeline = copy.deepcopy(in_timeline) 31 | 32 | for track_num, child_track in enumerate(in_timeline.tracks): 33 | # @TODO: put the trim_range into the space of the tracks 34 | # new_range = new_timeline.tracks.transformed_time_range( 35 | # trim_range, 36 | # child_track 37 | # ) 38 | 39 | # trim the track and assign it to the new stack. 40 | new_timeline.tracks[track_num] = track_algo.track_trimmed_to_range( 41 | child_track, 42 | trim_range 43 | ) 44 | 45 | return new_timeline 46 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/console/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | """Console scripts for OpenTimelineIO 5 | 6 | .. moduleauthor:: Contributors to the OpenTimelineIO project 7 | """ 8 | 9 | # flake8: noqa 10 | 11 | # in dependency hierarchy 12 | from . import ( 13 | otioconvert, 14 | otiocat, 15 | otiostat, 16 | otiotool, 17 | console_utils, 18 | autogen_serialized_datamodel, 19 | otiopluginfo, 20 | ) 21 | 22 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/console/console_utils.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | import ast 5 | 6 | from .. import ( 7 | media_linker, 8 | ) 9 | 10 | """Utilities for OpenTimelineIO commandline modules.""" 11 | 12 | 13 | def arg_list_to_map(arg_list, label): 14 | """ 15 | Convert an argument of the form -A foo=bar from the parsed result to a map. 16 | """ 17 | 18 | argument_map = {} 19 | for pair in arg_list: 20 | if '=' not in pair: 21 | raise ValueError( 22 | "error: {} arguments must be in the form key=value" 23 | " got: {}".format(label, pair) 24 | ) 25 | 26 | key, val = pair.split('=', 1) # only split on the 1st '=' 27 | try: 28 | # Sometimes we need to pass a bool, int, list, etc. 29 | parsed_value = ast.literal_eval(val) 30 | except (ValueError, SyntaxError): 31 | # Fall back to a simple string 32 | parsed_value = val 33 | argument_map[key] = parsed_value 34 | 35 | return argument_map 36 | 37 | 38 | def media_linker_name(ml_name_arg): 39 | """ 40 | Parse commandline arguments for the media linker, which can be not set 41 | (fall back to default), "" or "none" (don't link media) or the name of a 42 | media linker to use. 43 | """ 44 | if ml_name_arg.lower() == 'default': 45 | media_linker_name = media_linker.MediaLinkingPolicy.ForceDefaultLinker 46 | elif ml_name_arg.lower() in ['none', '']: 47 | media_linker_name = media_linker.MediaLinkingPolicy.DoNotLinkMedia 48 | else: 49 | media_linker_name = ml_name_arg 50 | 51 | return media_linker_name 52 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/core/composable.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from . _core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.Composable) 9 | def __repr__(self): 10 | return ( 11 | "otio.{}(" 12 | "name={}, " 13 | "metadata={}" 14 | ")".format( 15 | "core.Composable", 16 | repr(str(self.name)), 17 | repr(self.metadata) 18 | ) 19 | ) 20 | 21 | 22 | @add_method(_otio.Composable) 23 | def __str__(self): 24 | return "{}({}, {})".format( 25 | "Composable", 26 | str(self.name), 27 | str(self.metadata) 28 | ) 29 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/core/composition.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from . _core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.Composition) 9 | def __str__(self): 10 | return "{}({}, {}, {}, {})".format( 11 | self.__class__.__name__, 12 | str(self.name), 13 | str(list(self)), 14 | str(self.source_range), 15 | str(self.metadata) 16 | ) 17 | 18 | 19 | @add_method(_otio.Composition) 20 | def __repr__(self): 21 | return ( 22 | "otio.{}.{}(" 23 | "name={}, " 24 | "children={}, " 25 | "source_range={}, " 26 | "metadata={}" 27 | ")".format( 28 | "core" if self.__class__ is _otio.Composition else "schema", 29 | self.__class__.__name__, 30 | repr(self.name), 31 | repr(list(self)), 32 | repr(self.source_range), 33 | repr(self.metadata) 34 | ) 35 | ) 36 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/core/item.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from . _core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.Item) 9 | def __str__(self): 10 | return "{}({}, {}, {}, {}, {}, {})".format( 11 | self.__class__.__name__, 12 | self.name, 13 | str(self.source_range), 14 | str(self.effects), 15 | str(self.markers), 16 | str(self.enabled), 17 | str(self.metadata) 18 | ) 19 | 20 | 21 | @add_method(_otio.Item) 22 | def __repr__(self): 23 | return ( 24 | "otio.{}.{}(" 25 | "name={}, " 26 | "source_range={}, " 27 | "effects={}, " 28 | "markers={}, " 29 | "enabled={}, " 30 | "metadata={}" 31 | ")".format( 32 | "core" if self.__class__ is _otio.Item else "schema", 33 | self.__class__.__name__, 34 | repr(self.name), 35 | repr(self.source_range), 36 | repr(self.effects), 37 | repr(self.markers), 38 | repr(self.enabled), 39 | repr(self.metadata) 40 | ) 41 | ) 42 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/core/mediaReference.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from . _core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.MediaReference) 9 | def __str__(self): 10 | return "{}({}, {}, {}, {})".format( 11 | self.__class__.__name__, 12 | repr(self.name), 13 | repr(self.available_range), 14 | repr(self.available_image_bounds), 15 | repr(self.metadata) 16 | ) 17 | 18 | 19 | @add_method(_otio.MediaReference) 20 | def __repr__(self): 21 | return ( 22 | "otio.{}.{}(" 23 | "name={}," 24 | " available_range={}," 25 | " available_image_bounds={}," 26 | " metadata={}" 27 | ")" 28 | ).format( 29 | "core" if self.__class__ is _otio.MediaReference else "schema", 30 | self.__class__.__name__, 31 | repr(self.name), 32 | repr(self.available_range), 33 | repr(self.available_image_bounds), 34 | repr(self.metadata) 35 | ) 36 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/exceptions.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | """Exception classes for OpenTimelineIO""" 5 | from . _otio import ( # noqa 6 | OTIOError, 7 | NotAChildError, 8 | UnsupportedSchemaError, 9 | CannotComputeAvailableRangeError 10 | ) 11 | 12 | __all__ = [ 13 | 'OTIOError', 14 | 'NotAChildError', 15 | 'CannotComputeAvailableRangeError', 16 | 'UnsupportedSchemaError', 17 | 'CouldNotReadFileError', 18 | 'NoKnownAdapterForExtensionError', 19 | 'ReadingNotSupportedError', 20 | 'WritingNotSupportedError', 21 | 'NotSupportedError', 22 | 'InvalidSerializableLabelError', 23 | 'AdapterDoesntSupportFunctionError', 24 | 'InstancingNotAllowedError', 25 | 'TransitionFollowingATransitionError', 26 | 'MisconfiguredPluginError', 27 | 'CannotTrimTransitionsError', 28 | 'NoDefaultMediaLinkerError' 29 | ] 30 | 31 | 32 | class CouldNotReadFileError(OTIOError): 33 | pass 34 | 35 | 36 | class NoKnownAdapterForExtensionError(OTIOError): 37 | pass 38 | 39 | 40 | class ReadingNotSupportedError(OTIOError): 41 | pass 42 | 43 | 44 | class WritingNotSupportedError(OTIOError): 45 | pass 46 | 47 | 48 | class NotSupportedError(OTIOError): 49 | pass 50 | 51 | 52 | class InvalidSerializableLabelError(OTIOError): 53 | pass 54 | 55 | 56 | class AdapterDoesntSupportFunctionError(OTIOError): 57 | pass 58 | 59 | 60 | class InstancingNotAllowedError(OTIOError): 61 | pass 62 | 63 | 64 | class TransitionFollowingATransitionError(OTIOError): 65 | pass 66 | 67 | 68 | class MisconfiguredPluginError(OTIOError): 69 | pass 70 | 71 | 72 | class CannotTrimTransitionsError(OTIOError): 73 | pass 74 | 75 | 76 | class NoDefaultMediaLinkerError(OTIOError): 77 | pass 78 | 79 | 80 | class InvalidEnvironmentVariableError(OTIOError): 81 | pass 82 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/opentime.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from . _opentime import ( # noqa 5 | RationalTime, 6 | TimeRange, 7 | TimeTransform, 8 | ) 9 | 10 | __all__ = [ 11 | 'RationalTime', 12 | 'TimeRange', 13 | 'TimeTransform', 14 | 'from_frames', 15 | 'from_timecode', 16 | 'from_time_string', 17 | 'from_seconds', 18 | 'to_timecode', 19 | 'to_nearest_timecode', 20 | 'to_frames', 21 | 'to_seconds', 22 | 'to_time_string', 23 | 'range_from_start_end_time', 24 | 'range_from_start_end_time_inclusive', 25 | 'duration_from_start_end_time', 26 | 'duration_from_start_end_time_inclusive', 27 | ] 28 | 29 | from_frames = RationalTime.from_frames 30 | from_timecode = RationalTime.from_timecode 31 | from_time_string = RationalTime.from_time_string 32 | from_seconds = RationalTime.from_seconds 33 | 34 | range_from_start_end_time = TimeRange.range_from_start_end_time 35 | range_from_start_end_time_inclusive = TimeRange.range_from_start_end_time_inclusive 36 | duration_from_start_end_time = RationalTime.duration_from_start_end_time 37 | duration_from_start_end_time_inclusive = ( 38 | RationalTime.duration_from_start_end_time_inclusive 39 | ) 40 | 41 | 42 | def to_timecode(rt, rate=None, drop_frame=None): 43 | """Convert a :class:`~RationalTime` into a timecode string.""" 44 | return ( 45 | rt.to_timecode() 46 | if rate is None and drop_frame is None 47 | else rt.to_timecode(rate, drop_frame) 48 | ) 49 | 50 | 51 | def to_nearest_timecode(rt, rate=None, drop_frame=None): 52 | """Convert a :class:`~RationalTime` into a timecode string.""" 53 | return ( 54 | rt.to_nearest_timecode() 55 | if rate is None and drop_frame is None 56 | else rt.to_nearest_timecode(rate, drop_frame) 57 | ) 58 | 59 | 60 | def to_frames(rt, rate=None): 61 | """Turn a :class:`~RationalTime` into a frame number.""" 62 | return rt.to_frames() if rate is None else rt.to_frames(rate) 63 | 64 | 65 | def to_seconds(rt): 66 | """Convert a :class:`~RationalTime` into float seconds""" 67 | return rt.to_seconds() 68 | 69 | 70 | def to_time_string(rt): 71 | """ 72 | Convert this timecode to time as used by ffmpeg, formatted as 73 | ``hh:mm:ss`` where ss is an integer or decimal number. 74 | """ 75 | return rt.to_time_string() 76 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/plugins/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | """Plugin system for OTIO""" 5 | 6 | # flake8: noqa 7 | 8 | from .python_plugin import ( 9 | plugin_info_map, 10 | PythonPlugin, 11 | ) 12 | 13 | from .manifest import ( 14 | manifest_from_file, 15 | ActiveManifest, 16 | ) 17 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/schema/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | # flake8: noqa 5 | 6 | """User facing classes.""" 7 | 8 | from .. _otio import ( 9 | Box2d, 10 | Clip, 11 | Effect, 12 | TimeEffect, 13 | LinearTimeWarp, 14 | ExternalReference, 15 | FreezeFrame, 16 | Gap, 17 | GeneratorReference, 18 | ImageSequenceReference, 19 | Marker, 20 | MissingReference, 21 | SerializableCollection, 22 | Stack, 23 | Timeline, 24 | Track, 25 | Transition, 26 | V2d, 27 | ) 28 | 29 | MarkerColor = Marker.Color 30 | TrackKind = Track.Kind 31 | TransitionTypes = Transition.Type 32 | NeighborGapPolicy = Track.NeighborGapPolicy 33 | 34 | from . schemadef import ( 35 | SchemaDef 36 | ) 37 | 38 | from . import ( 39 | box2d, 40 | clip, 41 | effect, 42 | external_reference, 43 | generator_reference, 44 | image_sequence_reference, 45 | marker, 46 | serializable_collection, 47 | timeline, 48 | transition, 49 | v2d, 50 | ) 51 | 52 | def timeline_from_clips(clips): 53 | """Convenience for making a single track timeline from a list of clips.""" 54 | 55 | trck = Track(children=clips) 56 | return Timeline(tracks=[trck]) 57 | 58 | __all__ = [ 59 | 'Box2d', 60 | 'Clip', 61 | 'Effect', 62 | 'TimeEffect', 63 | 'LinearTimeWarp', 64 | 'ExternalReference', 65 | 'FreezeFrame', 66 | 'Gap', 67 | 'GeneratorReference', 68 | 'ImageSequenceReference', 69 | 'Marker', 70 | 'MissingReference', 71 | 'SerializableCollection', 72 | 'Stack', 73 | 'Timeline', 74 | 'Transition', 75 | 'SchemaDef', 76 | 'timeline_from_clips', 77 | 'V2d' 78 | ] 79 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/schema/box2d.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from .. core._core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.Box2d) 9 | def __str__(self): 10 | return 'Box2d({}, {})'.format( 11 | self.min, 12 | self.max 13 | ) 14 | 15 | 16 | @add_method(_otio.Box2d) 17 | def __repr__(self): 18 | return ( 19 | 'otio.schema.Box2d(' 20 | 'min={}, ' 21 | 'max={}' 22 | ')'.format( 23 | repr(self.min), 24 | repr(self.max), 25 | ) 26 | ) 27 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/schema/clip.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from .. core._core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.Clip) 9 | def __str__(self): 10 | return 'Clip("{}", {}, {}, {}, {}, {})'.format( 11 | self.name, 12 | self.media_reference, 13 | self.source_range, 14 | self.metadata, 15 | self.effects, 16 | self.markers 17 | ) 18 | 19 | 20 | @add_method(_otio.Clip) 21 | def __repr__(self): 22 | return ( 23 | 'otio.schema.Clip(' 24 | 'name={}, ' 25 | 'media_reference={}, ' 26 | 'source_range={}, ' 27 | 'metadata={}, ' 28 | 'effects={}, ' 29 | 'markers={}' 30 | ')'.format( 31 | repr(self.name), 32 | repr(self.media_reference), 33 | repr(self.source_range), 34 | repr(self.metadata), 35 | repr(self.effects), 36 | repr(self.markers) 37 | ) 38 | ) 39 | 40 | 41 | @add_method(_otio.Clip) 42 | def find_clips(self, search_range=None): 43 | yield self 44 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/schema/effect.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from .. core._core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.Effect) 9 | def __str__(self): 10 | return ( 11 | "Effect(" 12 | "{}, " 13 | "{}, " 14 | "{}, " 15 | "{}" 16 | ")".format( 17 | str(self.name), 18 | str(self.effect_name), 19 | str(self.metadata), 20 | str(self.enabled) 21 | ) 22 | ) 23 | 24 | 25 | @add_method(_otio.Effect) 26 | def __repr__(self): 27 | return ( 28 | "otio.schema.Effect(" 29 | "name={}, " 30 | "effect_name={}, " 31 | "metadata={}, " 32 | "enabled={}" 33 | ")".format( 34 | repr(self.name), 35 | repr(self.effect_name), 36 | repr(self.metadata), 37 | repr(self.enabled) 38 | ) 39 | ) 40 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/schema/external_reference.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from .. core._core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.ExternalReference) 9 | def __str__(self): 10 | return f'ExternalReference("{str(self.target_url)}")' 11 | 12 | 13 | @add_method(_otio.ExternalReference) 14 | def __repr__(self): 15 | return 'otio.schema.ExternalReference(target_url={})'.format( 16 | repr(str(self.target_url)) 17 | ) 18 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/schema/generator_reference.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from .. core._core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.GeneratorReference) 9 | def __str__(self): 10 | return 'GeneratorReference("{}", "{}", {}, {}, {})'.format( 11 | self.name, 12 | self.generator_kind, 13 | self.parameters, 14 | self.available_image_bounds, 15 | self.metadata 16 | ) 17 | 18 | 19 | @add_method(_otio.GeneratorReference) 20 | def __repr__(self): 21 | return ( 22 | 'otio.schema.GeneratorReference(' 23 | 'name={}, ' 24 | 'generator_kind={}, ' 25 | 'parameters={}, ' 26 | 'available_image_bounds={}, ' 27 | 'metadata={}' 28 | ')'.format( 29 | repr(self.name), 30 | repr(self.generator_kind), 31 | repr(self.parameters), 32 | repr(self.available_image_bounds), 33 | repr(self.metadata), 34 | ) 35 | ) 36 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/schema/image_sequence_reference.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from .. core._core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.ImageSequenceReference) 9 | def __str__(self): 10 | return ( 11 | 'ImageSequenceReference(' 12 | '"{}", "{}", "{}", {}, {}, {}, {}, {}, {}, {}, {})' .format( 13 | self.target_url_base, 14 | self.name_prefix, 15 | self.name_suffix, 16 | self.start_frame, 17 | self.frame_step, 18 | self.rate, 19 | self.frame_zero_padding, 20 | self.missing_frame_policy, 21 | self.available_range, 22 | self.available_image_bounds, 23 | self.metadata, 24 | ) 25 | ) 26 | 27 | 28 | @add_method(_otio.ImageSequenceReference) 29 | def __repr__(self): 30 | return ( 31 | 'ImageSequenceReference(' 32 | 'target_url_base={}, ' 33 | 'name_prefix={}, ' 34 | 'name_suffix={}, ' 35 | 'start_frame={}, ' 36 | 'frame_step={}, ' 37 | 'rate={}, ' 38 | 'frame_zero_padding={}, ' 39 | 'missing_frame_policy={}, ' 40 | 'available_range={}, ' 41 | 'available_image_bounds={}, ' 42 | 'metadata={}' 43 | ')' .format( 44 | repr(self.target_url_base), 45 | repr(self.name_prefix), 46 | repr(self.name_suffix), 47 | repr(self.start_frame), 48 | repr(self.frame_step), 49 | repr(self.rate), 50 | repr(self.frame_zero_padding), 51 | repr(self.missing_frame_policy), 52 | repr(self.available_range), 53 | repr(self.available_image_bounds), 54 | repr(self.metadata), 55 | ) 56 | ) 57 | 58 | 59 | @add_method(_otio.ImageSequenceReference) 60 | def frame_range_for_time_range(self, time_range): 61 | """Returns first and last frame numbers for 62 | the given time range in the reference. 63 | 64 | :rtype: tuple[int] 65 | :raises ValueError: if the provided time range is outside the available range. 66 | """ 67 | return ( 68 | self.frame_for_time(time_range.start_time), 69 | self.frame_for_time(time_range.end_time_inclusive()) 70 | ) 71 | 72 | 73 | @add_method(_otio.ImageSequenceReference) 74 | def abstract_target_url(self, symbol): 75 | """ 76 | Generates a target url for a frame where ``symbol`` is used in place 77 | of the frame number. This is often used to generate wildcard target urls. 78 | """ 79 | if not self.target_url_base.endswith("/"): 80 | base = self.target_url_base + "/" 81 | else: 82 | base = self.target_url_base 83 | 84 | return "{}{}{}{}".format( 85 | base, self.name_prefix, symbol, self.name_suffix 86 | ) 87 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/schema/marker.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from .. core._core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.Marker) 9 | def __str__(self): 10 | return "Marker({}, {}, {})".format( 11 | str(self.name), 12 | str(self.marked_range), 13 | str(self.metadata), 14 | ) 15 | 16 | 17 | @add_method(_otio.Marker) 18 | def __repr__(self): 19 | return ( 20 | "otio.schema.Marker(" 21 | "name={}, " 22 | "marked_range={}, " 23 | "metadata={}" 24 | ")".format( 25 | repr(self.name), 26 | repr(self.marked_range), 27 | repr(self.metadata), 28 | ) 29 | ) 30 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/schema/serializable_collection.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from .. core._core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.SerializableCollection) 9 | def __str__(self): 10 | return "SerializableCollection({}, {}, {})".format( 11 | str(self.name), 12 | str(list(self)), 13 | str(self.metadata) 14 | ) 15 | 16 | 17 | @add_method(_otio.SerializableCollection) 18 | def __repr__(self): 19 | return ( 20 | "otio.{}(" 21 | "name={}, " 22 | "children={}, " 23 | "metadata={}" 24 | ")".format( 25 | "schema.SerializableCollection", 26 | repr(self.name), 27 | repr(list(self)), 28 | repr(self.metadata) 29 | ) 30 | ) 31 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/schema/timeline.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from .. core._core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.Timeline) 9 | def __str__(self): 10 | return f'Timeline("{str(self.name)}", {str(self.tracks)})' 11 | 12 | 13 | @add_method(_otio.Timeline) 14 | def __repr__(self): 15 | return ( 16 | "otio.schema.Timeline(name={}, tracks={})".format( 17 | repr(self.name), 18 | repr(self.tracks) 19 | ) 20 | ) 21 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/schema/transition.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from .. core._core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.Transition) 9 | def __str__(self): 10 | return 'Transition("{}", "{}", {}, {}, {})'.format( 11 | self.name, 12 | self.transition_type, 13 | self.in_offset, 14 | self.out_offset, 15 | self.metadata 16 | ) 17 | 18 | 19 | @add_method(_otio.Transition) 20 | def __repr__(self): 21 | return ( 22 | 'otio.schema.Transition(' 23 | 'name={}, ' 24 | 'transition_type={}, ' 25 | 'in_offset={}, ' 26 | 'out_offset={}, ' 27 | 'metadata={}' 28 | ')'.format( 29 | repr(self.name), 30 | repr(self.transition_type), 31 | repr(self.in_offset), 32 | repr(self.out_offset), 33 | repr(self.metadata), 34 | ) 35 | ) 36 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/schema/v2d.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from .. core._core_utils import add_method 5 | from .. import _otio 6 | 7 | 8 | @add_method(_otio.V2d) 9 | def __str__(self): 10 | return 'V2d({}, {})'.format( 11 | self.x, 12 | self.y 13 | ) 14 | 15 | 16 | @add_method(_otio.V2d) 17 | def __repr__(self): 18 | return ( 19 | 'otio.schema.V2d(' 20 | 'x={}, ' 21 | 'y={}' 22 | ')'.format( 23 | repr(self.x), 24 | repr(self.y), 25 | ) 26 | ) 27 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/schemadef/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | def _add_schemadef_module(name, mod): 5 | """Insert a new module name and module object into schemadef namespace.""" 6 | ns = globals() # the namespace dict of the schemadef package 7 | ns[name] = mod 8 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/test_utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # Copyright Contributors to the OpenTimelineIO project 5 | 6 | """Utility assertions for OTIO Unit tests.""" 7 | 8 | import re 9 | 10 | from . import ( 11 | adapters 12 | ) 13 | 14 | 15 | class OTIOAssertions: 16 | def assertJsonEqual(self, known, test_result): 17 | """Convert to json and compare that (more readable).""" 18 | self.maxDiff = None 19 | 20 | known_str = adapters.write_to_string(known, 'otio_json') 21 | test_str = adapters.write_to_string(test_result, 'otio_json') 22 | 23 | def strip_trailing_decimal_zero(s): 24 | return re.sub(r'"(value|rate)": (\d+)\.0', r'"\1": \2', s) 25 | 26 | self.assertMultiLineEqual( 27 | strip_trailing_decimal_zero(known_str), 28 | strip_trailing_decimal_zero(test_str) 29 | ) 30 | 31 | def assertIsOTIOEquivalentTo(self, known, test_result): 32 | """Test using the 'is equivalent to' method on SerializableObject""" 33 | 34 | self.assertTrue(known.is_equivalent_to(test_result)) 35 | -------------------------------------------------------------------------------- /src/py-opentimelineio/opentimelineio/versioning.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | """Tools for fetching the family->label->schema:version maps""" 5 | 6 | import copy 7 | 8 | from . import ( 9 | core, 10 | plugins 11 | ) 12 | 13 | 14 | def full_map(): 15 | """Return the full map of schema version sets, including core and plugins. 16 | Organized as follows: 17 | 18 | .. code-block:: python 19 | 20 | { 21 | "FAMILY_NAME": { 22 | "LABEL": { 23 | "SchemaName": schemaversion, 24 | "Clip": 2, 25 | "Timeline": 3, 26 | ... 27 | } 28 | } 29 | } 30 | 31 | 32 | The "OTIO_CORE" family is always provided and represents the built in 33 | schemas defined in the C++ core. 34 | IE: 35 | 36 | .. code-block:: python 37 | 38 | { 39 | "OTIO_CORE": { 40 | "0.15.0": { 41 | "Clip": 2, 42 | ... 43 | } 44 | } 45 | } 46 | 47 | :returns: full map of schema version sets, including core and plugins 48 | :rtype: dict[str, dict[str, dict[str, int]]] 49 | """ 50 | 51 | result = copy.deepcopy(plugins.ActiveManifest().version_manifests) 52 | result.update( 53 | { 54 | "OTIO_CORE": core.release_to_schema_version_map(), 55 | } 56 | ) 57 | return result 58 | 59 | 60 | def fetch_map(family, label): 61 | """Fetch the version map for the given family and label. OpenTimelineIO 62 | includes a built in family called "OTIO_CORE", this is compiled into the 63 | C++ core and represents the core interchange schemas of OpenTimelineIO. 64 | 65 | Users may define more family/label/schema:version mappings by way of the 66 | version manifest plugins. 67 | 68 | Returns a dictionary mapping Schema name to schema version, like: 69 | 70 | .. code-block:: python 71 | 72 | { 73 | "Clip": 2, 74 | "Timeline": 1, 75 | ... 76 | } 77 | 78 | :param str family: family of labels (ie: "OTIO_CORE") 79 | :param str label: label of schema-version map (ie: "0.15.0") 80 | :returns: a dictionary mapping Schema name to schema version 81 | :rtype: dict[str, int] 82 | """ 83 | 84 | if family == "OTIO_CORE": 85 | src = core.release_to_schema_version_map() 86 | else: 87 | src = plugins.ActiveManifest().version_manifests[family] 88 | 89 | return copy.deepcopy(src[label]) 90 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${PROJECT_SOURCE_DIR}/src 2 | ${PROJECT_SOURCE_DIR}/src/deps 3 | ${PROJECT_SOURCE_DIR}/src/deps/optional-lite/include 4 | ${PROJECT_SOURCE_DIR}/src/tests) 5 | 6 | list(APPEND tests_opentime test_opentime) 7 | foreach(test ${tests_opentime}) 8 | add_executable(${test} utils.h utils.cpp ${test}.cpp) 9 | target_link_libraries(${test} opentime) 10 | set_target_properties(${test} PROPERTIES FOLDER tests) 11 | add_test(NAME ${test} 12 | COMMAND ${test} 13 | # Set the pwd to the source directory so we can load the samples 14 | # like the python tests do 15 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 16 | endforeach() 17 | 18 | list(APPEND tests_opentimelineio test_clip test_serialization test_serializableCollection test_stack_algo test_timeline test_track test_editAlgorithm) 19 | foreach(test ${tests_opentimelineio}) 20 | add_executable(${test} utils.h utils.cpp ${test}.cpp) 21 | 22 | target_link_libraries(${test} opentimelineio) 23 | set_target_properties(${test} PROPERTIES FOLDER tests) 24 | add_test(NAME ${test} 25 | COMMAND ${test} 26 | # Set the pwd to the source directory so we can load the samples 27 | # like the python tests do 28 | WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 29 | endforeach() 30 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | -------------------------------------------------------------------------------- /tests/baseline_reader.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | """Utilities for reading baseline json.""" 5 | 6 | import os 7 | import json 8 | 9 | MODPATH = os.path.dirname(__file__) 10 | 11 | 12 | def test_hook(dct): 13 | if "FROM_TEST_FILE" in dct: 14 | # fetch the baseline 15 | result = json_from_file_as_string( 16 | os.path.join( 17 | MODPATH, 18 | "baselines", 19 | str(dct["FROM_TEST_FILE"]) 20 | ) 21 | ) 22 | 23 | # allow you to overlay values onto the baseline in the test, if they 24 | # store non-default for the baseline values. 25 | del dct["FROM_TEST_FILE"] 26 | result.update(dct) 27 | return result 28 | 29 | return dct 30 | 31 | 32 | def json_from_string(jsonstr): 33 | return json.loads(jsonstr, object_hook=test_hook) 34 | 35 | 36 | def json_from_file_as_string(fpath): 37 | with open(fpath) as fo: 38 | return json_from_string(fo.read()) 39 | 40 | 41 | def path_to_baseline_directory(): 42 | return os.path.join(MODPATH, "baselines") 43 | 44 | 45 | def path_to_baseline(name): 46 | return os.path.join(path_to_baseline_directory(), f"{name}.json") 47 | 48 | 49 | def json_baseline(name): 50 | return json_from_file_as_string(path_to_baseline(name)) 51 | 52 | 53 | def json_baseline_as_string(name): 54 | return json.dumps(json_baseline(name)) 55 | -------------------------------------------------------------------------------- /tests/baselines/adapter_example.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "Adapter.1", 3 | "name" : "example", 4 | "filepath" : "example.py", 5 | "suffixes" : ["example"] 6 | } 7 | -------------------------------------------------------------------------------- /tests/baselines/adapter_plugin_manifest.plugin_manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "PluginManifest.1", 3 | "adapters" : [ 4 | { 5 | "FROM_TEST_FILE" : "adapter_example.json" 6 | } 7 | ], 8 | "media_linkers" : [ 9 | { 10 | "FROM_TEST_FILE" : "media_linker_example.json" 11 | } 12 | ], 13 | "hook_scripts" : [ 14 | { 15 | "FROM_TEST_FILE" : "hookscript_example.json" 16 | }, 17 | { 18 | "FROM_TEST_FILE" : "post_write_hookscript_example.json" 19 | }, 20 | { 21 | "FROM_TEST_FILE" : "custom_adapter_hookscript_example.json" 22 | } 23 | ], 24 | "hooks" : { 25 | "pre_adapter_write" : ["example hook", "example hook"], 26 | "post_adapter_read" : [], 27 | "post_adapter_write" : ["post write example hook"], 28 | "post_media_linker" : ["example hook"], 29 | "custom_adapter_hook": ["custom adapter hook"] 30 | }, 31 | "version_manifests" : { 32 | "TEST_FAMILY_NAME": { 33 | "TEST_LABEL": { 34 | "ExampleSchema":2, 35 | "EnvVarTestSchema":1, 36 | "Clip": 1 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/baselines/custom_adapter_hookscript_example.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "HookScript.1", 3 | "name" : "custom adapter hook", 4 | "filepath" : "custom_adapter_hookscript_example.py" 5 | } 6 | -------------------------------------------------------------------------------- /tests/baselines/custom_adapter_hookscript_example.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | """This file is here to support the test_adapter_plugin unittest, specifically adapters 5 | that implement their own hooks. 6 | If you want to learn how to write your own adapter plugin, please read: 7 | https://opentimelineio.readthedocs.io/en/latest/tutorials/write-an-adapter.html 8 | """ 9 | 10 | 11 | def hook_function(in_timeline, argument_map=None): 12 | in_timeline.metadata["custom_hook"] = dict(argument_map) 13 | return in_timeline 14 | -------------------------------------------------------------------------------- /tests/baselines/empty_clip.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "Clip.2", 3 | "metadata" : {}, 4 | "name" : "test_clip", 5 | "source_range" : null, 6 | "markers" : [], 7 | "enabled" : true, 8 | "effects" : [], 9 | "active_media_reference_key": "DEFAULT_MEDIA", 10 | "media_references" : { 11 | "DEFAULT_MEDIA" : { 12 | "FROM_TEST_FILE" : "empty_missingreference.json" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/baselines/empty_effect.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "Effect.1", 3 | "name" : "", 4 | "effect_name" : "", 5 | "metadata" : {}, 6 | "enabled" : true 7 | } 8 | -------------------------------------------------------------------------------- /tests/baselines/empty_external_reference.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "ExternalReference.1", 3 | "available_range" : null, 4 | "available_image_bounds" : null, 5 | "metadata" : {}, 6 | "name" : "", 7 | "target_url" : "foo.bar" 8 | } 9 | -------------------------------------------------------------------------------- /tests/baselines/empty_gap.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "Gap.1", 3 | "metadata" : {}, 4 | "name" : "", 5 | "markers" : [], 6 | "enabled" : true, 7 | "effects" : [], 8 | "source_range" : { 9 | "FROM_TEST_FILE" : "empty_timerange.json" 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /tests/baselines/empty_generator_reference.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "GeneratorReference.1", 3 | "available_range" : null, 4 | "available_image_bounds" : null, 5 | "generator_kind" : "", 6 | "metadata" : {}, 7 | "parameters" : {}, 8 | "name" : "" 9 | } 10 | -------------------------------------------------------------------------------- /tests/baselines/empty_marker.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "Marker.2", 3 | "metadata" : {}, 4 | "name" : "", 5 | "color" : "RED", 6 | "comment" : "", 7 | "marked_range" : { 8 | "FROM_TEST_FILE" : "empty_timerange.json" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/baselines/empty_missingreference.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "MissingReference.1", 3 | "available_range" : null, 4 | "available_image_bounds" : null, 5 | "metadata" : {}, 6 | "name" : "" 7 | } 8 | -------------------------------------------------------------------------------- /tests/baselines/empty_rationaltime.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "RationalTime.1", 3 | "rate" : 1.0, 4 | "value" : 0.0 5 | } 6 | -------------------------------------------------------------------------------- /tests/baselines/empty_serializable_collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "SerializableCollection.1", 3 | "metadata" : { 4 | "foo":"bar" 5 | }, 6 | "name" : "test", 7 | "children" : [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/baselines/empty_stack.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "Stack.1", 3 | "metadata" : { 4 | "comments" : "adding some stuff to metadata to try out", 5 | "a number" : 1.0 6 | }, 7 | "name" : "tracks", 8 | "source_range": null, 9 | "children" : [], 10 | "markers" : [], 11 | "enabled" : true, 12 | "effects" : [] 13 | } 14 | -------------------------------------------------------------------------------- /tests/baselines/empty_timeline.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "Timeline.1", 3 | "global_start_time" : null, 4 | "metadata" : { 5 | "comments" : "adding some stuff to metadata to try out", 6 | "a number" : 1.0 7 | }, 8 | "name" : "Example Timeline", 9 | "tracks" : { 10 | "FROM_TEST_FILE" : "empty_stack.json" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/baselines/empty_timerange.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "TimeRange.1", 3 | "start_time" : { 4 | "FROM_TEST_FILE" : "empty_rationaltime.json" 5 | }, 6 | "duration" : { 7 | "FROM_TEST_FILE" : "empty_rationaltime.json" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/baselines/empty_timetransform.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "TimeTransform.1", 3 | "offset" : { 4 | "FROM_TEST_FILE" : "empty_rationaltime.json" 5 | }, 6 | "scale" : 1.0, 7 | "rate" : -1.0 8 | } 9 | -------------------------------------------------------------------------------- /tests/baselines/empty_track.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "Track.1", 3 | "metadata" : { 4 | "comments" : "adding some stuff to metadata to try out", 5 | "a number" : 1.0 6 | }, 7 | "name" : "test_track", 8 | "source_range": null, 9 | "children" : [], 10 | "markers" : [], 11 | "enabled" : true, 12 | "effects" : [], 13 | "kind" : "Video" 14 | } 15 | -------------------------------------------------------------------------------- /tests/baselines/empty_transition.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA": "Transition.1", 3 | "metadata": {}, 4 | "name": "", 5 | "transition_type": "", 6 | "in_offset": { 7 | "FROM_TEST_FILE" : "empty_rationaltime.json" 8 | }, 9 | "out_offset": { 10 | "FROM_TEST_FILE" : "empty_rationaltime.json" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/baselines/example.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | """This file is here to support the test_adapter_plugin unittest. 5 | If you want to learn how to write your own adapter plugin, please read: 6 | https://opentimelineio.readthedocs.io/en/latest/tutorials/write-an-adapter.html 7 | """ 8 | 9 | 10 | # `hook_function_argument_map` is only a required argument for adapters that implement 11 | # custom hooks. 12 | def read_from_file(filepath, suffix="", hook_function_argument_map=None): 13 | import opentimelineio as otio 14 | 15 | fake_tl = otio.schema.Timeline(name=filepath + str(suffix)) 16 | fake_tl.tracks.append(otio.schema.Track()) 17 | fake_tl.tracks[0].append(otio.schema.Clip(name=filepath + "_clip")) 18 | 19 | if (hook_function_argument_map and 20 | hook_function_argument_map.get("run_custom_hook", False)): 21 | return otio.hooks.run(hook="custom_adapter_hook", tl=fake_tl, 22 | extra_args=hook_function_argument_map) 23 | 24 | return fake_tl 25 | 26 | 27 | # `hook_function_argument_map` is only a required argument for adapters that implement 28 | # custom hooks. 29 | def read_from_string(input_str, suffix="", hook_function_argument_map=None): 30 | tl = read_from_file(input_str, suffix, hook_function_argument_map) 31 | return tl 32 | 33 | 34 | # this is only required for adapters that implement custom hooks 35 | def adapter_hook_names(): 36 | return ["custom_adapter_hook"] 37 | 38 | 39 | # in practice, these will be in separate plugins, but for simplicity in the 40 | # unit tests, we put this in the same file as the example adapter. 41 | def link_media_reference(in_clip, media_linker_argument_map): 42 | import opentimelineio as otio 43 | 44 | d = {'from_test_linker': True} 45 | d.update(media_linker_argument_map) 46 | return otio.schema.MissingReference( 47 | name=in_clip.name + "_tweaked", 48 | metadata=d 49 | ) 50 | 51 | 52 | # same thing for this hookscript 53 | def hook_function(in_timeline, argument_map=None): 54 | in_timeline.name = "hook ran and did stuff" 55 | in_timeline.metadata.update(argument_map) 56 | return in_timeline 57 | -------------------------------------------------------------------------------- /tests/baselines/example_schemadef.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | """This file is here to support the test_schemadef_plugin unittest. 5 | If you want to learn how to write your own SchemaDef plugin, please read: 6 | https://opentimelineio.readthedocs.io/en/latest/tutorials/write-a-schemadef.html 7 | """ 8 | 9 | import opentimelineio as otio 10 | 11 | 12 | @otio.core.register_type 13 | class exampleSchemaDef(otio.core.SerializableObject): 14 | """Example of a SchemaDef plugin class for testing.""" 15 | 16 | _serializable_label = "exampleSchemaDef.1" 17 | _name = "exampleSchemaDef" 18 | 19 | def __init__( 20 | self, 21 | exampleArg=None, 22 | ): 23 | otio.core.SerializableObject.__init__(self) 24 | self.exampleArg = exampleArg 25 | 26 | exampleArg = otio.core.serializable_field( 27 | "exampleArg", 28 | doc=( 29 | "example of an arg passed to the exampleSchemaDef" 30 | ) 31 | ) 32 | 33 | def __str__(self): 34 | return 'exampleSchemaDef({})'.format( 35 | repr(self.exampleArg) 36 | ) 37 | 38 | def __repr__(self): 39 | return \ 40 | 'otio.schemadef.example_schemadef.exampleSchemaDef(exampleArg={})'.format( 41 | repr(self.exampleArg) 42 | ) 43 | -------------------------------------------------------------------------------- /tests/baselines/hookscript_example.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "HookScript.1", 3 | "name" : "example hook", 4 | "filepath" : "example.py" 5 | } 6 | -------------------------------------------------------------------------------- /tests/baselines/media_linker_example.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "MediaLinker.1", 3 | "name" : "example", 4 | "filepath" : "example.py" 5 | } 6 | -------------------------------------------------------------------------------- /tests/baselines/plugin_module/otio_jsonplugin.egg-info/PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 1.0 2 | Name: otio-jsonplugin 3 | Version: 1.0.0 4 | Summary: Dummy plugin used for testing. 5 | Home-page: http://opentimeline.io 6 | Author: Contributors to the OpenTimelineIO project 7 | Author-email: otio-discussion@lists.aswf.io 8 | License: Modified Apache 2.0 License 9 | Description-Content-Type: UNKNOWN 10 | Description: UNKNOWN 11 | Platform: any 12 | -------------------------------------------------------------------------------- /tests/baselines/plugin_module/otio_jsonplugin.egg-info/entry_points.txt: -------------------------------------------------------------------------------- 1 | [opentimelineio.plugins] 2 | mock_plugin = otio_jsonplugin 3 | 4 | -------------------------------------------------------------------------------- /tests/baselines/plugin_module/otio_jsonplugin/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/tests/baselines/plugin_module/otio_jsonplugin/__init__.py -------------------------------------------------------------------------------- /tests/baselines/plugin_module/otio_jsonplugin/plugin_manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "PluginManifest.1", 3 | "adapters": [ 4 | { 5 | "OTIO_SCHEMA": "Adapter.1", 6 | "name": "mock_adapter_json", 7 | "filepath": "adapter.py", 8 | "suffixes": ["mockadapter"] 9 | } 10 | ], 11 | "media_linkers": [ 12 | { 13 | "OTIO_SCHEMA" : "MediaLinker.1", 14 | "name" : "mock_linker_json", 15 | "filepath" : "linker.py" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tests/baselines/plugin_module/otio_mockplugin.egg-info/PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 1.0 2 | Name: otio-mockplugin 3 | Version: 1.0.0 4 | Summary: Dummy plugin used for testing. 5 | Home-page: http://opentimeline.io 6 | Author: Contributors to the OpenTimelineIO project 7 | Author-email: otio-discussion@lists.aswf.io 8 | License: Modified Apache 2.0 License 9 | Description-Content-Type: UNKNOWN 10 | Description: UNKNOWN 11 | Platform: any 12 | -------------------------------------------------------------------------------- /tests/baselines/plugin_module/otio_mockplugin.egg-info/entry_points.txt: -------------------------------------------------------------------------------- 1 | [opentimelineio.plugins] 2 | mock_plugin = otio_mockplugin 3 | 4 | -------------------------------------------------------------------------------- /tests/baselines/plugin_module/otio_mockplugin/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | from importlib import resources 5 | 6 | from opentimelineio.plugins import manifest 7 | 8 | """An example plugin package that generates its package manifest on demand. 9 | 10 | If you create a plugin that doesn't have a plugin_manifest.json, OTIO will 11 | attempt to call the plugin_manifest() function from the __init__.py directory. 12 | 13 | This would allow you to programmatically generate a manifest rather than have 14 | it be static on disk, allowing you to switch features on or off or do some 15 | template substitution or any other kind of procedural processing. 16 | 17 | This unit test uses a very simple example that just reads the manifest from 18 | a non-standard json file path. 19 | """ 20 | 21 | 22 | def plugin_manifest(): 23 | filepath = ( 24 | resources.files(__package__) 25 | / "unusually_named_plugin_manifest.json" 26 | ) 27 | 28 | return manifest.manifest_from_string( 29 | filepath.read_text() 30 | ) 31 | -------------------------------------------------------------------------------- /tests/baselines/plugin_module/otio_mockplugin/unusually_named_plugin_manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "PluginManifest.1", 3 | "adapters": [ 4 | { 5 | "OTIO_SCHEMA": "Adapter.1", 6 | "name": "mock_adapter", 7 | "filepath": "adapter.py", 8 | "suffixes": ["mockadapter"] 9 | } 10 | ], 11 | "media_linkers": [ 12 | { 13 | "OTIO_SCHEMA" : "MediaLinker.1", 14 | "name" : "mock_linker", 15 | "filepath" : "linker.py" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tests/baselines/plugin_module/otio_override_adapter.egg-info/PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 1.0 2 | Name: otio-override-adapter 3 | Version: 1.0.0 4 | Summary: Dummy Adapter used for testing. 5 | Home-page: http://opentimeline.io 6 | Author: Contributors to the OpenTimelineIO project 7 | Author-email: otio-discussion@lists.aswf.io 8 | License: Modified Apache 2.0 License 9 | Description-Content-Type: UNKNOWN 10 | Description: UNKNOWN 11 | Platform: any 12 | -------------------------------------------------------------------------------- /tests/baselines/plugin_module/otio_override_adapter.egg-info/entry_points.txt: -------------------------------------------------------------------------------- 1 | [opentimelineio.plugins] 2 | mock_plugin = otio_override_adapter 3 | 4 | -------------------------------------------------------------------------------- /tests/baselines/plugin_module/otio_override_adapter/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/tests/baselines/plugin_module/otio_override_adapter/__init__.py -------------------------------------------------------------------------------- /tests/baselines/plugin_module/otio_override_adapter/adapter.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/tests/baselines/plugin_module/otio_override_adapter/adapter.py -------------------------------------------------------------------------------- /tests/baselines/plugin_module/otio_override_adapter/plugin_manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "PluginManifest.1", 3 | "adapters": [ 4 | { 5 | "OTIO_SCHEMA" : "Adapter.1", 6 | "name" : "otiod", 7 | "filepath" : "adapter.py", 8 | "suffixes" : ["otiod"] 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /tests/baselines/post_write_example.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | import os 5 | 6 | """This file is here to support the test_adapter_plugin unittest. 7 | If you want to learn how to write your own adapter plugin, please read: 8 | https://opentimelineio.readthedocs.io/en/latest/tutorials/write-an-adapter.html 9 | """ 10 | 11 | 12 | def hook_function(in_timeline, argument_map=None): 13 | filepath = argument_map.get('_filepath') 14 | argument_map.update({'filesize': os.path.getsize(filepath)}) 15 | in_timeline.metadata.update(argument_map) 16 | 17 | return in_timeline 18 | -------------------------------------------------------------------------------- /tests/baselines/post_write_hookscript_example.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "HookScript.1", 3 | "name" : "post write example hook", 4 | "filepath" : "post_write_example.py" 5 | } 6 | -------------------------------------------------------------------------------- /tests/baselines/schemadef_example.json: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA" : "PluginManifest.1", 3 | "schemadefs": [ 4 | { 5 | "OTIO_SCHEMA" : "SchemaDef.1", 6 | "name" : "example_schemadef", 7 | "filepath" : "example_schemadef.py" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /tests/consumer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.18.2 FATAL_ERROR) 2 | 3 | project(consumer_tests) 4 | 5 | add_subdirectory(opentime) 6 | add_subdirectory(opentimeline) 7 | -------------------------------------------------------------------------------- /tests/consumer/opentime/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(OpenTime REQUIRED) 2 | message(STATUS "Found OpenTime successfully at '${OpenTime_DIR}'") 3 | -------------------------------------------------------------------------------- /tests/consumer/opentimeline/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(OpenTimelineIO REQUIRED) 2 | message(STATUS "Found OpenTimelineIO successfully at '${OpenTimelineIO_DIR}'") 3 | -------------------------------------------------------------------------------- /tests/sample_data/OpenTimelineIO@3xDark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/tests/sample_data/OpenTimelineIO@3xDark.png -------------------------------------------------------------------------------- /tests/sample_data/OpenTimelineIO@3xLight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AcademySoftwareFoundation/OpenTimelineIO/8405a575dcde826d0170270b833b4e9a14d612fc/tests/sample_data/OpenTimelineIO@3xLight.png -------------------------------------------------------------------------------- /tests/sample_data/generator_reference_test.otio: -------------------------------------------------------------------------------- 1 | { 2 | "OTIO_SCHEMA": "Timeline.1", 3 | "metadata": {}, 4 | "name": "transition_test", 5 | "tracks": { 6 | "OTIO_SCHEMA": "Stack.1", 7 | "children": [ 8 | { 9 | "OTIO_SCHEMA": "Sequence.1", 10 | "children": [ 11 | { 12 | "OTIO_SCHEMA": "Clip.1", 13 | "effects": [], 14 | "markers": [], 15 | "enabled": true, 16 | "media_reference": { 17 | "OTIO_SCHEMA" : "GeneratorReference.1", 18 | "available_range" : { 19 | "OTIO_SCHEMA": "TimeRange.1", 20 | "duration": { 21 | "OTIO_SCHEMA": "RationalTime.1", 22 | "rate": 24, 23 | "value": 50 24 | }, 25 | "start_time": { 26 | "OTIO_SCHEMA": "RationalTime.1", 27 | "rate": 24, 28 | "value": 0.0 29 | } 30 | }, 31 | "generator_kind" : "SMPTEBars", 32 | "metadata" : {}, 33 | "parameters" : {}, 34 | "name" : "bars" 35 | }, 36 | "metadata": {}, 37 | "name": "C", 38 | "source_range": { 39 | "OTIO_SCHEMA": "TimeRange.1", 40 | "duration": { 41 | "OTIO_SCHEMA": "RationalTime.1", 42 | "rate": 24, 43 | "value": 50 44 | }, 45 | "start_time": { 46 | "OTIO_SCHEMA": "RationalTime.1", 47 | "rate": 24, 48 | "value": 0.0 49 | } 50 | } 51 | 52 | } 53 | ], 54 | "effects": [], 55 | "kind": "Video", 56 | "markers": [], 57 | "enabled": true, 58 | "metadata": {}, 59 | "name": "Sequence1", 60 | "source_range": null 61 | } 62 | ], 63 | "effects": [], 64 | "markers": [], 65 | "enabled": true, 66 | "metadata": {}, 67 | "name": "tracks", 68 | "source_range": null 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/test_composable.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | """Test harness for Composable.""" 5 | 6 | import unittest 7 | 8 | import opentimelineio as otio 9 | import opentimelineio.test_utils as otio_test_utils 10 | 11 | 12 | class ComposableTests(unittest.TestCase, otio_test_utils.OTIOAssertions): 13 | def test_constructor(self): 14 | seqi = otio.core.Composable( 15 | name="test", 16 | metadata={"foo": "bar"} 17 | ) 18 | self.assertEqual(seqi.name, "test") 19 | self.assertEqual(seqi.metadata, {'foo': 'bar'}) 20 | 21 | def test_serialize(self): 22 | b = otio.schema.Box2d( 23 | otio.schema.V2d(0.0, 0.0), otio.schema.V2d(16.0, 9.0)) 24 | seqi = otio.core.Composable( 25 | name="test", 26 | metadata={"box": b} 27 | ) 28 | encoded = otio.adapters.otio_json.write_to_string(seqi) 29 | decoded = otio.adapters.otio_json.read_from_string(encoded) 30 | self.assertIsOTIOEquivalentTo(seqi, decoded) 31 | 32 | def test_stringify(self): 33 | seqi = otio.core.Composable() 34 | self.assertMultiLineEqual( 35 | str(seqi), 36 | "Composable(" 37 | "{}, " 38 | "{}" 39 | ")".format( 40 | str(seqi.name), 41 | str(seqi.metadata), 42 | ) 43 | ) 44 | 45 | self.assertMultiLineEqual( 46 | repr(seqi), 47 | "otio.core.Composable(" 48 | "name={}, " 49 | "metadata={}" 50 | ")".format( 51 | repr(seqi.name), 52 | repr(seqi.metadata), 53 | ) 54 | ) 55 | 56 | def test_metadata(self): 57 | seqi = otio.core.Composable() 58 | seqi.metadata["foo"] = "bar" 59 | encoded = otio.adapters.otio_json.write_to_string(seqi) 60 | decoded = otio.adapters.otio_json.read_from_string(encoded) 61 | self.assertIsOTIOEquivalentTo(seqi, decoded) 62 | self.assertEqual(decoded.metadata["foo"], seqi.metadata["foo"]) 63 | 64 | 65 | if __name__ == '__main__': 66 | unittest.main() 67 | -------------------------------------------------------------------------------- /tests/test_core.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | import sys 5 | import shutil 6 | import tempfile 7 | import unittest 8 | 9 | import opentimelineio as otio 10 | 11 | 12 | class TestCoreFunctions(unittest.TestCase): 13 | def setUp(self): 14 | self.tmpDir = tempfile.mkdtemp() 15 | 16 | def tearDown(self): 17 | shutil.rmtree(self.tmpDir) 18 | 19 | def test_deserialize_json_from_file_errors(self): 20 | """Verify the bindings return the correct errors based on the errno""" 21 | 22 | with self.assertRaises(FileNotFoundError) as exc: 23 | otio.core.deserialize_json_from_file('non-existent-file-here') 24 | self.assertIsInstance(exc.exception, FileNotFoundError) 25 | 26 | @unittest.skipUnless( 27 | not sys.platform.startswith("win"), 28 | "requires non Windows system" 29 | ) 30 | def test_serialize_json_to_file_errors_non_windows(self): 31 | """Verify the bindings return the correct errors based on the errno""" 32 | 33 | with self.assertRaises(IsADirectoryError) as exc: 34 | otio.core.serialize_json_to_file({}, self.tmpDir) 35 | self.assertIsInstance(exc.exception, IsADirectoryError) 36 | 37 | @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") 38 | def test_serialize_json_to_file_errors_windows(self): 39 | """Verify the bindings return the correct errors based on the errno""" 40 | 41 | with self.assertRaises(PermissionError) as exc: 42 | otio.core.serialize_json_to_file({}, self.tmpDir) 43 | self.assertIsInstance(exc.exception, PermissionError) 44 | -------------------------------------------------------------------------------- /tests/test_cxx_sdk_bindings.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | import unittest 5 | 6 | import opentimelineio as otio 7 | 8 | 9 | class CxxSDKTests(unittest.TestCase): 10 | def test_cpp_big_ints(self): 11 | self.assertTrue(otio._otio._testing.test_big_uint()) 12 | 13 | 14 | if __name__ == '__main__': 15 | unittest.main() 16 | -------------------------------------------------------------------------------- /tests/test_examples.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | """Unit tests for the 'examples'""" 5 | import unittest 6 | import sys 7 | import os 8 | import subprocess 9 | 10 | 11 | import tempfile 12 | 13 | import opentimelineio as otio 14 | 15 | 16 | class BuildSimpleTimelineExampleTest(unittest.TestCase): 17 | """use the build_simple_timeline.py example to generate timelines""" 18 | 19 | def test_duration(self): 20 | with tempfile.TemporaryDirectory() as temp_dir: 21 | temp_file = os.path.join(temp_dir, "test_basic.otio") 22 | 23 | examples_path = os.path.join( 24 | os.path.dirname(os.path.dirname(__file__)), 25 | "examples", 26 | "build_simple_timeline.py", 27 | ) 28 | 29 | subprocess.check_call( 30 | [sys.executable, examples_path, temp_file], 31 | stdout=subprocess.PIPE 32 | ) 33 | known = otio.adapters.read_from_file(temp_file) 34 | 35 | # TODO: add checks against a couple of the adapters. 36 | # This used to include .edl and .xml 37 | for suffix in [".otio"]: 38 | this_test_file = temp_file.replace(".otio", suffix) 39 | subprocess.check_call( 40 | [sys.executable, examples_path, this_test_file], 41 | stdout=subprocess.PIPE 42 | ) 43 | test_result = otio.adapters.read_from_file(this_test_file) 44 | self.assertEqual(known.duration(), test_result.duration()) 45 | 46 | 47 | if __name__ == '__main__': 48 | unittest.main() 49 | -------------------------------------------------------------------------------- /tests/test_multithreading.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | import unittest 5 | import threading 6 | import weakref 7 | 8 | import opentimelineio as otio 9 | import opentimelineio.test_utils as otio_test_utils 10 | 11 | 12 | class MultithreadingTests(unittest.TestCase, otio_test_utils.OTIOAssertions): 13 | def test1(self): 14 | self.sc = otio.schema.SerializableCollection() 15 | child = otio.core.SerializableObject() 16 | child.extra = 17 17 | wc = weakref.ref(child) 18 | self.assertEqual(wc() is not None, True) 19 | self.sc.append(child) 20 | del child 21 | 22 | threads = [] 23 | for i in range(5): 24 | t = threading.Thread(target=self.bash_retainers1) 25 | t.daemon = True 26 | t.start() 27 | threads.append(t) 28 | 29 | for t in threads: 30 | t.join() 31 | 32 | self.assertEqual(self.sc[0].extra, 17) 33 | self.sc.pop() 34 | self.assertEqual(wc() is None, True) 35 | 36 | def bash_retainers1(self): 37 | otio._otio._testing.bash_retainers1(self.sc) 38 | 39 | def test2(self): 40 | sc = otio.schema.SerializableCollection() 41 | child = otio.core.SerializableObject() 42 | sc.append(child) 43 | self.materialized = False 44 | 45 | self.sc = sc.clone() 46 | self.lock = threading.Lock() 47 | # self.sc[0] has not been given out to Python yet 48 | 49 | threads = [] 50 | for i in range(5): 51 | t = threading.Thread(target=self.bash_retainers2) 52 | t.daemon = True 53 | t.start() 54 | threads.append(t) 55 | 56 | for t in threads: 57 | t.join() 58 | 59 | self.assertEqual(self.wc() is not None, True) 60 | self.assertEqual(self.wc().extra, 37) 61 | del self.sc 62 | self.assertEqual(self.wc() is None, True) 63 | 64 | def test3(self): 65 | t = threading.Thread(target=self.gil_scoping) 66 | t.daemon = True 67 | t.start() 68 | t.join() 69 | 70 | def test4(self): 71 | self.gil_scoping() 72 | 73 | def gil_scoping(self): 74 | otio._otio._testing.gil_scoping() 75 | 76 | def materialize(self): 77 | with self.lock: 78 | if not self.materialized: 79 | self.materialized = True 80 | child = self.sc[0] 81 | self.wc = weakref.ref(child) 82 | self.assertEqual(self.wc() is not None, True) 83 | child.extra = 37 84 | del child 85 | 86 | def bash_retainers2(self): 87 | otio._otio._testing.bash_retainers2(self.sc, self.materialize) 88 | 89 | 90 | if __name__ == '__main__': 91 | unittest.main() 92 | -------------------------------------------------------------------------------- /tests/test_unknown_schema.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | import unittest 5 | 6 | import opentimelineio as otio 7 | import opentimelineio.test_utils as otio_test_utils 8 | 9 | has_undefined_schema = """ 10 | { 11 | "OTIO_SCHEMA": "Clip.1", 12 | "effects": [], 13 | "markers": [], 14 | "media_reference": { 15 | "OTIO_SCHEMA": "ExternalReference.1", 16 | "available_range": { 17 | "OTIO_SCHEMA": "TimeRange.1", 18 | "duration": { 19 | "OTIO_SCHEMA": "RationalTime.1", 20 | "rate": 24, 21 | "value": 140 22 | }, 23 | "start_time": { 24 | "OTIO_SCHEMA": "RationalTime.1", 25 | "rate": 24, 26 | "value": 91 27 | } 28 | }, 29 | "metadata": { 30 | "stuff": { 31 | "OTIO_SCHEMA": "MyOwnDangSchema.3", 32 | "some_data": 895, 33 | "howlongami": { 34 | "OTIO_SCHEMA": "RationalTime.1", 35 | "rate": 30, 36 | "value": 100 37 | } 38 | } 39 | }, 40 | "name": null, 41 | "target_url": "/usr/tmp/some_media.mov" 42 | }, 43 | "metadata": {}, 44 | "name": null, 45 | "source_range": null 46 | } 47 | """ 48 | 49 | 50 | class UnknownSchemaTests(unittest.TestCase, otio_test_utils.OTIOAssertions): 51 | def setUp(self): 52 | # make an OTIO data structure containing an undefined schema object 53 | self.orig = otio.adapters.otio_json.read_from_string(has_undefined_schema) 54 | 55 | def test_serialize_deserialize(self): 56 | serialized = otio.adapters.otio_json.write_to_string(self.orig) 57 | test_otio = otio.adapters.otio_json.read_from_string(serialized) 58 | 59 | self.assertIsOTIOEquivalentTo(self.orig, test_otio) 60 | 61 | def test_is_unknown_schema(self): 62 | self.assertFalse(self.orig.is_unknown_schema) 63 | unknown = self.orig.media_reference.metadata["stuff"] 64 | self.assertTrue(unknown.is_unknown_schema) 65 | 66 | 67 | if __name__ == '__main__': 68 | unittest.main() 69 | -------------------------------------------------------------------------------- /tests/utils.cpp: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #include "utils.h" 5 | 6 | #include 7 | #include 8 | 9 | void 10 | assertTrue(bool value) 11 | { 12 | assert(value); 13 | } 14 | 15 | void 16 | assertFalse(bool value) 17 | { 18 | assert(!value); 19 | } 20 | 21 | void 22 | Tests::add_test(std::string const& name, std::function const& test) 23 | { 24 | _tests.push_back(std::make_pair(name, test)); 25 | } 26 | 27 | void 28 | Tests::run(int argc, char** argv) 29 | { 30 | std::vector filter; 31 | for (int arg = 1; arg < argc; ++arg) 32 | { 33 | filter.push_back(argv[arg]); 34 | } 35 | 36 | for (auto const& test: _tests) 37 | { 38 | bool run_test = true; 39 | if (!filter.empty()) 40 | { 41 | const auto filter_it = 42 | std::find(filter.begin(), filter.end(), test.first); 43 | run_test = filter_it != filter.end(); 44 | } 45 | 46 | std::cout << (run_test ? "Running" : "Skipping") << " test " 47 | << test.first << std::endl; 48 | if (run_test) 49 | { 50 | test.second(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tests/utils.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright Contributors to the OpenTimelineIO project 3 | 4 | #pragma once 5 | #undef NDEBUG 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | void assertTrue(bool value); 16 | void assertFalse(bool value); 17 | 18 | template 19 | inline void 20 | assertEqual(T const& a, T const& b) 21 | { 22 | assert(a == b); 23 | } 24 | 25 | // We are not testing values outside of one million seconds. 26 | // At one million second, and double precision, the smallest 27 | // resolvable number that can be added to one million and return 28 | // a new value one million + epsilon is 5.82077e-11. 29 | // 30 | // This was calculated by searching iteratively for epsilon 31 | // around 1,000,000, with epsilon starting from 1 and halved 32 | // at every iteration, until epsilon when added to 1,000,000 33 | // resulted in 1,000,000. 34 | constexpr double double_epsilon = 5.82077e-11; 35 | 36 | inline void 37 | assertEqual(double a, double b) 38 | { 39 | assert(std::abs(a - b) <= double_epsilon); 40 | } 41 | 42 | inline void 43 | assertEqual(const char* a, const char* b) 44 | { 45 | assert(a != nullptr); 46 | assert(b != nullptr); 47 | assert(strcmp(a, b) == 0); 48 | } 49 | 50 | inline void 51 | assertEqual(const void* a, const void* b) 52 | { 53 | assert(a == b); 54 | } 55 | 56 | template 57 | inline void 58 | assertNotEqual(T const& a, T const& b) 59 | { 60 | assert(a != b); 61 | } 62 | 63 | inline void 64 | assertNotEqual(double a, double b) 65 | { 66 | assert(std::abs(a - b) > double_epsilon); 67 | } 68 | 69 | inline void 70 | assertNotNull(const void* a) 71 | { 72 | assert(a != nullptr); 73 | } 74 | 75 | class Tests 76 | { 77 | public: 78 | void 79 | add_test(std::string const& name, std::function const& test); 80 | 81 | void run(int argc, char** argv); 82 | 83 | private: 84 | std::vector>> _tests; 85 | }; 86 | -------------------------------------------------------------------------------- /tests/utils.py: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | # Copyright Contributors to the OpenTimelineIO project 3 | 4 | """Reusable utilities for tests.""" 5 | 6 | # import built-in modules 7 | import os 8 | import tempfile 9 | 10 | # import local modules 11 | import opentimelineio as otio 12 | from tests import baseline_reader 13 | 14 | 15 | MANIFEST_PATH = "adapter_plugin_manifest.plugin_manifest" 16 | 17 | 18 | def create_manifest(): 19 | """Create a temporary manifest.""" 20 | full_baseline = baseline_reader.json_baseline_as_string(MANIFEST_PATH) 21 | 22 | temp_dir = tempfile.mkdtemp(prefix='test_otio_manifest') 23 | man_path = os.path.join(temp_dir, 'manifest') 24 | with open(man_path, 'w') as fo: 25 | fo.write(full_baseline) 26 | man = otio.plugins.manifest_from_file(man_path) 27 | man._update_plugin_source(baseline_reader.path_to_baseline(MANIFEST_PATH)) 28 | return man 29 | 30 | 31 | def remove_manifest(manifest): 32 | """Remove the manifest source files.""" 33 | for file_path in manifest.source_files: 34 | # don't accidentally blow away python 35 | if not file_path.endswith('.py'): 36 | os.remove(file_path) 37 | --------------------------------------------------------------------------------