mirror of
https://github.com/iluvcapra/ptulsconv.git
synced 2026-10-01 17:27:27 +00:00
Compare commits
5 Commits
ab19793bd1
...
9c4f6faf2a
| Author | SHA1 | Date | |
|---|---|---|---|
| 9c4f6faf2a | |||
| 754e4d5251 | |||
| 888d9aa5d9 | |||
| bd0b09d1db | |||
| 3c15237ed2 |
@@ -42,6 +42,13 @@ doc = [
|
|||||||
"sphinx-rtd-theme>=3.0.2",
|
"sphinx-rtd-theme>=3.0.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
ignore = [
|
||||||
|
"DTZ005" # datetime created without a tz
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.ruff.lint.per-file-ignores]
|
||||||
|
"reaper/Export Items as Text.py" = ["F821"]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
ptulsconv = "ptulsconv:__main__.main"
|
ptulsconv = "ptulsconv:__main__.main"
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
|
# type: ignore[reportUndefinedVariable]
|
||||||
|
|
||||||
# Export Items as Text.py
|
# Export Items as Text.py
|
||||||
# (c) 2021 Jamie Hardt. All rights reserved.
|
# (c) 2021 Jamie Hardt. All rights reserved.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
item_records = list()
|
item_records = []
|
||||||
|
|
||||||
for i in range(RPR_CountMediaItems(0)):
|
for i in range(RPR_CountMediaItems(0)):
|
||||||
this_item = RPR_GetMediaItem(0, i)
|
this_item = RPR_GetMediaItem(0, i)
|
||||||
|
|
||||||
item_record = {}
|
item_record = {}
|
||||||
item_record["mute"] = (
|
item_record["mute"] = RPR_GetMediaItemInfo_Value(this_item, "B_MUTE_ACTUAL") > 0.0
|
||||||
True if RPR_GetMediaItemInfo_Value(this_item, "B_MUTE_ACTUAL") > 0.0 else False
|
|
||||||
)
|
|
||||||
|
|
||||||
item_record["duration"] = RPR_GetMediaItemInfo_Value(this_item, "D_LENGTH")
|
item_record["duration"] = RPR_GetMediaItemInfo_Value(this_item, "D_LENGTH")
|
||||||
_, item_record["duration_tc"], _, _, _ = RPR_format_timestr_len(
|
_, item_record["duration_tc"], _, _, _ = RPR_format_timestr_len(
|
||||||
@@ -26,9 +26,7 @@ for i in range(RPR_CountMediaItems(0)):
|
|||||||
item_record["position"], "", 128, 5
|
item_record["position"], "", 128, 5
|
||||||
)
|
)
|
||||||
|
|
||||||
item_record["selected"] = (
|
item_record["selected"] = RPR_GetMediaItemInfo_Value(this_item, "B_UISEL") > 0.0
|
||||||
True if RPR_GetMediaItemInfo_Value(this_item, "B_UISEL") > 0.0 else False
|
|
||||||
)
|
|
||||||
_, _, _, item_record["notes"], _ = RPR_GetSetMediaItemInfo_String(
|
_, _, _, item_record["notes"], _ = RPR_GetSetMediaItemInfo_String(
|
||||||
this_item, "P_NOTES", "", False
|
this_item, "P_NOTES", "", False
|
||||||
)
|
)
|
||||||
@@ -54,13 +52,11 @@ for i in range(RPR_CountMediaItems(0)):
|
|||||||
item_record["track_index"] = RPR_GetMediaTrackInfo_Value(
|
item_record["track_index"] = RPR_GetMediaTrackInfo_Value(
|
||||||
item_track, "IP_TRACKNUMBER"
|
item_track, "IP_TRACKNUMBER"
|
||||||
)
|
)
|
||||||
item_record["track_muted"] = (
|
item_record["track_muted"] = RPR_GetMediaTrackInfo_Value(item_track, "B_MUTE") > 0.0
|
||||||
True if RPR_GetMediaTrackInfo_Value(item_track, "B_MUTE") > 0.0 else False
|
|
||||||
)
|
|
||||||
|
|
||||||
item_records = item_records + [item_record]
|
item_records = item_records + [item_record]
|
||||||
|
|
||||||
output = dict()
|
output = {}
|
||||||
output["items"] = item_records
|
output["items"] = item_records
|
||||||
_, output["project_title"], _ = RPR_GetProjectName(0, "", 1024)
|
_, output["project_title"], _ = RPR_GetProjectName(0, "", 1024)
|
||||||
_, _, output["project_author"], _ = RPR_GetSetProjectAuthor(0, False, "", 1024)
|
_, _, output["project_author"], _ = RPR_GetSetProjectAuthor(0, False, "", 1024)
|
||||||
@@ -76,15 +72,14 @@ output_title = output["project_title"]
|
|||||||
if output_title == "":
|
if output_title == "":
|
||||||
output_title = "unsaved project"
|
output_title = "unsaved project"
|
||||||
|
|
||||||
output_file_name = "%s Text Export %s.txt" % (output_title, now.strftime("%Y%m%d_%H%M"))
|
output_file_name = f"{output_title} Text Export {now.strftime('%Y%m%d_%H%M')}.txt"
|
||||||
output_path = output_path + "/" + output_file_name
|
output_path = output_path + "/" + output_file_name
|
||||||
|
|
||||||
with open(output_path, "w") as f:
|
with open(output_path, "w") as f:
|
||||||
json.dump(output, f, allow_nan=True, indent=4)
|
json.dump(output, f, allow_nan=True, indent=4)
|
||||||
|
|
||||||
RPR_ShowMessageBox(
|
RPR_ShowMessageBox(
|
||||||
'Exported text file "%s" to project folder.' % output_file_name,
|
f'Exported text file "{output_file_name}" to project folder. Text Export Complete',
|
||||||
"Text Export Complete",
|
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ def main():
|
|||||||
(options, args) = parser.parse_args(sys.argv)
|
(options, args) = parser.parse_args(sys.argv)
|
||||||
|
|
||||||
print_section_header_style("Startup")
|
print_section_header_style("Startup")
|
||||||
print_status_style("This run started %s" % (datetime.datetime.now().isoformat()))
|
print_status_style(f"This run started {datetime.datetime.now().isoformat()}")
|
||||||
|
|
||||||
if options.show_tags:
|
if options.show_tags:
|
||||||
dump_field_map()
|
dump_field_map()
|
||||||
@@ -124,17 +124,6 @@ def main():
|
|||||||
input_file=args[1], major_mode=major_mode, warnings=options.warnings
|
input_file=args[1], major_mode=major_mode, warnings=options.warnings
|
||||||
)
|
)
|
||||||
|
|
||||||
except FileNotFoundError as e:
|
|
||||||
print_fatal_error("Error trying to read input file")
|
|
||||||
raise e
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
print_fatal_error("Error trying to convert file")
|
|
||||||
print("\033[31m" + e.__repr__() + "\033[0m", file=sys.stderr)
|
|
||||||
print(traceback.format_exc())
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
Useful functions for parsing and working with timecode.
|
Useful functions for parsing and working with timecode.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import math
|
import math
|
||||||
import re
|
import re
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from typing import Optional, SupportsFloat
|
from typing import SupportsFloat
|
||||||
|
|
||||||
|
|
||||||
class TimecodeFormat(
|
class TimecodeFormat(
|
||||||
@@ -16,7 +18,7 @@ class TimecodeFormat(
|
|||||||
A struct reperesenting a timecode datum.
|
A struct reperesenting a timecode datum.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def smpte_to_seconds(self, smpte: str) -> Optional[Fraction]:
|
def smpte_to_seconds(self, smpte: str) -> Fraction | None:
|
||||||
frame_count = smpte_to_frame_count(
|
frame_count = smpte_to_frame_count(
|
||||||
smpte, self.logical_fps, drop_frame_hint=self.drop_frame
|
smpte, self.logical_fps, drop_frame_hint=self.drop_frame
|
||||||
)
|
)
|
||||||
@@ -32,7 +34,7 @@ class TimecodeFormat(
|
|||||||
|
|
||||||
def smpte_to_frame_count(
|
def smpte_to_frame_count(
|
||||||
smpte_rep_string: str, frames_per_logical_second: int, drop_frame_hint=False
|
smpte_rep_string: str, frames_per_logical_second: int, drop_frame_hint=False
|
||||||
) -> Optional[int]:
|
) -> int | None:
|
||||||
"""
|
"""
|
||||||
Convert a string with a SMPTE timecode representation into a frame count.
|
Convert a string with a SMPTE timecode representation into a frame count.
|
||||||
|
|
||||||
@@ -83,7 +85,7 @@ def frame_count_to_smpte(
|
|||||||
frame_count: int,
|
frame_count: int,
|
||||||
frames_per_logical_second: int,
|
frames_per_logical_second: int,
|
||||||
drop_frame: bool = False,
|
drop_frame: bool = False,
|
||||||
fractional_frame: Optional[float] = None,
|
fractional_frame: float | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
assert frames_per_logical_second in [24, 25, 30, 48, 50, 60]
|
assert frames_per_logical_second in [24, 25, 30, 48, 50, 60]
|
||||||
assert fractional_frame is None or fractional_frame < 1.0
|
assert fractional_frame is None or fractional_frame < 1.0
|
||||||
@@ -104,20 +106,21 @@ def frame_count_to_smpte(
|
|||||||
ss, ff = divmod(rem, frames_per_logical_second)
|
ss, ff = divmod(rem, frames_per_logical_second)
|
||||||
|
|
||||||
hh = hh % 24
|
hh = hh % 24
|
||||||
|
|
||||||
|
hh = int(hh)
|
||||||
|
mm = int(mm)
|
||||||
|
ss = int(ss)
|
||||||
|
ff = int(ff)
|
||||||
|
|
||||||
if fractional_frame is not None and fractional_frame > 0:
|
if fractional_frame is not None and fractional_frame > 0:
|
||||||
return "%02i:%02i:%02i%s%02i%s" % (
|
fpart = "{fractional_frame:.3f}"[1:]
|
||||||
hh,
|
return f"{hh:02}:{mm:02}:{ss:02}{separator}{ff:02}{fpart}"
|
||||||
mm,
|
|
||||||
ss,
|
|
||||||
separator,
|
|
||||||
ff,
|
|
||||||
("%.3f" % fractional_frame)[1:],
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
return "%02i:%02i:%02i%s%02i" % (hh, mm, ss, separator, ff)
|
return f"{hh:02}:{mm:02}:{ss:02}{separator}{ff:02}"
|
||||||
|
# "%02i:%02i:%02i%s%02i" % (hh, mm, ss, separator, ff)
|
||||||
|
|
||||||
|
|
||||||
def footage_to_frame_count(footage_string) -> Optional[int]:
|
def footage_to_frame_count(footage_string) -> int | None:
|
||||||
m = re.search(r"(\d+)\+(\d+)(\.\d+)?", footage_string)
|
m = re.search(r"(\d+)\+(\d+)(\.\d+)?", footage_string)
|
||||||
if m is None:
|
if m is None:
|
||||||
return None
|
return None
|
||||||
@@ -131,4 +134,4 @@ def footage_to_frame_count(footage_string) -> Optional[int]:
|
|||||||
|
|
||||||
def frame_count_to_footage(frame_count):
|
def frame_count_to_footage(frame_count):
|
||||||
feet, frm = divmod(frame_count, 16)
|
feet, frm = divmod(frame_count, 16)
|
||||||
return "%i+%02i" % (feet, frm)
|
return f"{feet}+{frm:02}"
|
||||||
|
|||||||
+19
-21
@@ -3,6 +3,8 @@ This module provides the main input document parsing and transform
|
|||||||
implementation.
|
implementation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import csv
|
import csv
|
||||||
import datetime
|
import datetime
|
||||||
import os
|
import os
|
||||||
@@ -11,7 +13,7 @@ from collections.abc import Iterator
|
|||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
from json import JSONEncoder
|
from json import JSONEncoder
|
||||||
from typing import List, Optional
|
from zoneinfo import ZoneInfo
|
||||||
|
|
||||||
import ptsl
|
import ptsl
|
||||||
|
|
||||||
@@ -39,26 +41,25 @@ class FractionEncoder(JSONEncoder):
|
|||||||
as a dict.
|
as a dict.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
force_denominator: Optional[int]
|
force_denominator: int | None
|
||||||
|
|
||||||
def default(self, o):
|
def default(self, o):
|
||||||
""" """
|
|
||||||
if isinstance(o, Fraction):
|
if isinstance(o, Fraction):
|
||||||
return dict(numerator=o.numerator, denominator=o.denominator)
|
return {"numerator": o.numerator, "denominator": o.denominator}
|
||||||
else:
|
else:
|
||||||
return o.__dict__
|
return o.__dict__
|
||||||
|
|
||||||
|
|
||||||
def output_adr_csv(lines: List[ADRLine], time_format: TimecodeFormat):
|
def output_adr_csv(lines: list[ADRLine], time_format: TimecodeFormat):
|
||||||
"""
|
"""
|
||||||
Writes ADR lines as CSV to the current working directory. Creates
|
Writes ADR lines as CSV to the current working directory. Creates
|
||||||
directories for each character number and name pair, and within that
|
directories for each character number and name pair, and within that
|
||||||
directory, creates a CSV file for each reel.
|
directory, creates a CSV file for each reel.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
reels: set[str | None] = set([ln.reel for ln in lines])
|
reels: set[str | None] = {ln.reel for ln in lines}
|
||||||
for n, name in [(n.character_id, n.character_name) for n in lines]:
|
for n, name in [(n.character_id, n.character_name) for n in lines]:
|
||||||
dir_name = "%s_%s" % (n, name)
|
dir_name = f"{n}_{name}"
|
||||||
os.makedirs(dir_name, exist_ok=True)
|
os.makedirs(dir_name, exist_ok=True)
|
||||||
os.chdir(dir_name)
|
os.chdir(dir_name)
|
||||||
for reel in reels:
|
for reel in reels:
|
||||||
@@ -69,11 +70,8 @@ def output_adr_csv(lines: List[ADRLine], time_format: TimecodeFormat):
|
|||||||
if len(these_lines) == 0:
|
if len(these_lines) == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
outfile_name = "%s_%s_%s_%s.csv" % (
|
outfile_name = (
|
||||||
these_lines[0].title,
|
f"{these_lines[0].title}_{n}_{these_lines[0].character_name}_{reel}.csv"
|
||||||
n,
|
|
||||||
these_lines[0].character_name,
|
|
||||||
reel,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
with open(outfile_name, mode="w", newline="") as outfile:
|
with open(outfile_name, mode="w", newline="") as outfile:
|
||||||
@@ -119,13 +117,13 @@ def output_adr_csv(lines: List[ADRLine], time_format: TimecodeFormat):
|
|||||||
os.chdir("..")
|
os.chdir("..")
|
||||||
|
|
||||||
|
|
||||||
def generate_documents(session_tc_format, scenes, adr_lines: List[ADRLine], title):
|
def generate_documents(session_tc_format, scenes, adr_lines: list[ADRLine], title):
|
||||||
"""
|
"""
|
||||||
Create PDF output.
|
Create PDF output.
|
||||||
"""
|
"""
|
||||||
print_section_header_style("Creating PDF Reports")
|
print_section_header_style("Creating PDF Reports")
|
||||||
report_date = datetime.datetime.now()
|
report_date = datetime.datetime.now()
|
||||||
reports_dir = "%s_%s" % (title, report_date.strftime("%Y-%m-%d_%H%M%S"))
|
reports_dir = f"{title}_{report_date.strftime('%Y-%m-%d_%H%M%S')}"
|
||||||
os.makedirs(reports_dir, exist_ok=False)
|
os.makedirs(reports_dir, exist_ok=False)
|
||||||
os.chdir(reports_dir)
|
os.chdir(reports_dir)
|
||||||
|
|
||||||
@@ -155,7 +153,7 @@ def generate_documents(session_tc_format, scenes, adr_lines: List[ADRLine], titl
|
|||||||
|
|
||||||
|
|
||||||
def create_adr_reports(
|
def create_adr_reports(
|
||||||
lines: List[ADRLine], tc_display_format: TimecodeFormat, reel_list: List[str]
|
lines: list[ADRLine], tc_display_format: TimecodeFormat, reel_list: list[str]
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Creates a directory heirarchy and a respective set of ADR reports,
|
Creates a directory heirarchy and a respective set of ADR reports,
|
||||||
@@ -240,18 +238,18 @@ def convert(major_mode, input_file=None, output=sys.stdout, warnings=True):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# TODO: Breakdown by titles
|
# TODO: Breakdown by titles
|
||||||
titles = set([x.title for x in (generic_events + adr_lines)])
|
titles = {x.title for x in (generic_events + adr_lines)}
|
||||||
if len(titles) != 1:
|
if len(titles) != 1:
|
||||||
print_warning(
|
print_warning(
|
||||||
"Multiple titles per export is not supported, "
|
"Multiple titles per export is not supported, "
|
||||||
"found multiple titles: %s Exiting." % titles
|
f"found multiple titles: {titles} Exiting."
|
||||||
)
|
)
|
||||||
exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
title = list(titles)[0]
|
title = next(iter(titles))
|
||||||
|
|
||||||
print_status_style("%i generic events found." % len(generic_events))
|
print_status_style(f"{len(generic_events)} generic events found.")
|
||||||
print_status_style("%i ADR events found." % len(adr_lines))
|
print_status_style(f"{len(adr_lines)} ADR events found.")
|
||||||
|
|
||||||
if warnings:
|
if warnings:
|
||||||
perform_adr_validations(iter(adr_lines))
|
perform_adr_validations(iter(adr_lines))
|
||||||
|
|||||||
@@ -131,7 +131,6 @@ class TagCompiler:
|
|||||||
return effective_tags
|
return effective_tags
|
||||||
|
|
||||||
def parse_data(self) -> Iterator[Intermediate]:
|
def parse_data(self) -> Iterator[Intermediate]:
|
||||||
|
|
||||||
for track, clip, start, finish, _ in self.session.track_clips_timed():
|
for track, clip, start, finish, _ in self.session.track_clips_timed():
|
||||||
if clip.state == "Muted":
|
if clip.state == "Muted":
|
||||||
continue
|
continue
|
||||||
@@ -153,7 +152,6 @@ class TagCompiler:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def apply_appends(parsed: Iterator[Intermediate]) -> Iterator[Intermediate]:
|
def apply_appends(parsed: Iterator[Intermediate]) -> Iterator[Intermediate]:
|
||||||
|
|
||||||
def should_append(a, b):
|
def should_append(a, b):
|
||||||
return b.clip_tag_mode == TagPreModes.APPEND and b.start >= a.finish
|
return b.clip_tag_mode == TagPreModes.APPEND and b.start >= a.finish
|
||||||
|
|
||||||
@@ -177,7 +175,6 @@ class TagCompiler:
|
|||||||
def collect_time_spans(
|
def collect_time_spans(
|
||||||
parsed: Iterator[Intermediate],
|
parsed: Iterator[Intermediate],
|
||||||
) -> Iterator[tuple[Intermediate, tuple[dict, Fraction, Fraction]]]:
|
) -> Iterator[tuple[Intermediate, tuple[dict, Fraction, Fraction]]]:
|
||||||
|
|
||||||
time_spans = []
|
time_spans = []
|
||||||
|
|
||||||
for item in parsed:
|
for item in parsed:
|
||||||
@@ -199,7 +196,6 @@ class TagCompiler:
|
|||||||
def apply_tags(
|
def apply_tags(
|
||||||
self, parsed_with_time_spans
|
self, parsed_with_time_spans
|
||||||
) -> Iterator[tuple[str, str, str, dict, Fraction, Fraction]]:
|
) -> Iterator[tuple[str, str, str, dict, Fraction, Fraction]]:
|
||||||
|
|
||||||
session_parsed = parse_tags(self.session.header.session_name)
|
session_parsed = parse_tags(self.session.header.session_name)
|
||||||
|
|
||||||
for event, time_spans in parsed_with_time_spans:
|
for event, time_spans in parsed_with_time_spans:
|
||||||
@@ -226,13 +222,13 @@ class TagCompiler:
|
|||||||
|
|
||||||
|
|
||||||
def apply_appends(
|
def apply_appends(
|
||||||
source: Iterator, should_append: Callable, do_append: Callable
|
source: Iterator, should_append: Callable, preform_append: Callable
|
||||||
) -> Generator:
|
) -> Generator:
|
||||||
"""
|
"""
|
||||||
:param source:
|
:param source:
|
||||||
:param should_append: Called with two variables a and b, your
|
:param should_append: Called with two variables a and b, your
|
||||||
function should return true if b should be
|
function should return true if b should be
|
||||||
appended to a
|
appended to a
|
||||||
:param do_append: Called with two variables a and b, your function
|
:param do_append: Called with two variables a and b, your function
|
||||||
should return
|
should return
|
||||||
:returns: A Generator
|
:returns: A Generator
|
||||||
@@ -240,7 +236,7 @@ def apply_appends(
|
|||||||
this_element = next(source)
|
this_element = next(source)
|
||||||
for element in source:
|
for element in source:
|
||||||
if should_append(this_element, element):
|
if should_append(this_element, element):
|
||||||
this_element = do_append(this_element, element)
|
this_element = preform_append(this_element, element)
|
||||||
else:
|
else:
|
||||||
yield this_element
|
yield this_element
|
||||||
this_element = element
|
this_element = element
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
"""
|
"""
|
||||||
Methods for converting string reprentations of film footage.
|
Methods for converting string reprentations of film footage.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
|
|
||||||
def footage_to_seconds(footage: str) -> Optional[Fraction]:
|
def footage_to_seconds(footage: str) -> Fraction | None:
|
||||||
"""
|
"""
|
||||||
Converts a string representation of a footage (35mm, 24fps)
|
Converts a string representation of a footage (35mm, 24fps)
|
||||||
into a :class:`Fraction`, this fraction being a some number of
|
into a :class:`Fraction`, this fraction being a some number of
|
||||||
|
|||||||
+18
-10
@@ -1,11 +1,13 @@
|
|||||||
import datetime
|
from __future__ import annotations
|
||||||
|
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import pathlib
|
import pathlib
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from typing import List
|
from datetime import datetime
|
||||||
|
from importlib.metadata import version as module_version
|
||||||
from xml.etree.ElementTree import TreeBuilder, tostring
|
from xml.etree.ElementTree import TreeBuilder, tostring
|
||||||
|
|
||||||
import ptulsconv
|
import ptulsconv
|
||||||
@@ -15,13 +17,16 @@ from ptulsconv.docparser.adr_entity import ADRLine
|
|||||||
|
|
||||||
|
|
||||||
def avid_marker_list(
|
def avid_marker_list(
|
||||||
lines: List[ADRLine],
|
lines: list[ADRLine],
|
||||||
report_date=datetime.datetime.now(),
|
report_date: datetime | None = None,
|
||||||
reel_start_frame=0,
|
reel_start_frame=0,
|
||||||
fps=24,
|
fps=24,
|
||||||
):
|
):
|
||||||
doc = TreeBuilder(element_factory=None)
|
doc = TreeBuilder(element_factory=None)
|
||||||
|
|
||||||
|
if report_date is None:
|
||||||
|
report_date = datetime.now()
|
||||||
|
|
||||||
doc.start("Avid:StreamItems", {"xmlns:Avid": "http://www.avid.com"})
|
doc.start("Avid:StreamItems", {"xmlns:Avid": "http://www.avid.com"})
|
||||||
doc.start("Avid:XMLFileData", {})
|
doc.start("Avid:XMLFileData", {})
|
||||||
doc.start("AvProp", {"name": "DomainMagic", "type": "string"})
|
doc.start("AvProp", {"name": "DomainMagic", "type": "string"})
|
||||||
@@ -57,6 +62,8 @@ def avid_marker_list(
|
|||||||
|
|
||||||
doc.start("List", {"id": "OMFI:ATTR:AttrRefs"})
|
doc.start("List", {"id": "OMFI:ATTR:AttrRefs"})
|
||||||
|
|
||||||
|
assert report_date
|
||||||
|
|
||||||
insert_elem(
|
insert_elem(
|
||||||
"1",
|
"1",
|
||||||
"OMFI:ATTB:IntAttribute",
|
"OMFI:ATTB:IntAttribute",
|
||||||
@@ -75,7 +82,7 @@ def avid_marker_list(
|
|||||||
line.supervisor or "",
|
line.supervisor or "",
|
||||||
)
|
)
|
||||||
|
|
||||||
marker_name = "%s: %s" % (line.cue_number, line.prompt)
|
marker_name = f"{line.cue_number}: {line.prompt}"
|
||||||
insert_elem(
|
insert_elem(
|
||||||
"2", "OMFI:ATTB:StringAttribute", "string", "_ATN_CRM_COM", marker_name
|
"2", "OMFI:ATTB:StringAttribute", "string", "_ATN_CRM_COM", marker_name
|
||||||
)
|
)
|
||||||
@@ -112,7 +119,8 @@ def dump_fmpxml(data, input_file_name, output, adr_field_map):
|
|||||||
doc.data("0")
|
doc.data("0")
|
||||||
doc.end("ERRORCODE")
|
doc.end("ERRORCODE")
|
||||||
|
|
||||||
doc.start("PRODUCT", {"NAME": ptulsconv.__name__, "VERSION": ptulsconv.__version__})
|
version = module_version("ptulsconv")
|
||||||
|
doc.start("PRODUCT", {"NAME": ptulsconv.__name__, "VERSION": f"{version}"})
|
||||||
doc.end("PRODUCT")
|
doc.end("PRODUCT")
|
||||||
|
|
||||||
doc.start(
|
doc.start(
|
||||||
@@ -147,7 +155,7 @@ def dump_fmpxml(data, input_file_name, output, adr_field_map):
|
|||||||
doc.start("COL", {})
|
doc.start("COL", {})
|
||||||
doc.start("DATA", {})
|
doc.start("DATA", {})
|
||||||
for key_attempt in field[0]:
|
for key_attempt in field[0]:
|
||||||
if key_attempt in event.keys():
|
if key_attempt in event:
|
||||||
doc.data(str(event[key_attempt]))
|
doc.data(str(event[key_attempt]))
|
||||||
break
|
break
|
||||||
doc.end("DATA")
|
doc.end("DATA")
|
||||||
@@ -170,7 +178,7 @@ def xform_options():
|
|||||||
|
|
||||||
def dump_xform_options(output=sys.stdout):
|
def dump_xform_options(output=sys.stdout):
|
||||||
print("# Available transforms:", file=output)
|
print("# Available transforms:", file=output)
|
||||||
print("# Transform dir: %s" % xslt_path, file=output)
|
print(f"# Transform dir: {xslt_path}", file=output)
|
||||||
for f in xform_options():
|
for f in xform_options():
|
||||||
base = os.path.basename(f)
|
base = os.path.basename(f)
|
||||||
name, _ = os.path.splitext(base)
|
name, _ = os.path.splitext(base)
|
||||||
@@ -188,14 +196,14 @@ def fmp_transformed_dump(data, input_file, xsl_name, output, adr_field_map):
|
|||||||
dump_fmpxml(data, input_file, pipe, adr_field_map)
|
dump_fmpxml(data, input_file, pipe, adr_field_map)
|
||||||
|
|
||||||
str_data = pipe.getvalue()
|
str_data = pipe.getvalue()
|
||||||
print_status_style("Base XML size %i" % (len(str_data)))
|
print_status_style(f"Base XML size {len(str_data)}")
|
||||||
|
|
||||||
print_status_style("Running xsltproc")
|
print_status_style("Running xsltproc")
|
||||||
|
|
||||||
xsl_path = os.path.join(
|
xsl_path = os.path.join(
|
||||||
pathlib.Path(__file__).parent.absolute(), "xslt", xsl_name + ".xsl"
|
pathlib.Path(__file__).parent.absolute(), "xslt", xsl_name + ".xsl"
|
||||||
)
|
)
|
||||||
print_status_style("Using xsl: %s" % xsl_path)
|
print_status_style(f"Using xsl: {xsl_path}")
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
["xsltproc", xsl_path, "-"],
|
["xsltproc", xsl_path, "-"],
|
||||||
input=str_data,
|
input=str_data,
|
||||||
|
|||||||
Reference in New Issue
Block a user