def __exit__(self, *ext: Any): cur_atom = _GlobalKronContext.get_ctx().atoms[self._atom_idx] cur_layers = _GlobalKronContext.get_ctx().layers max_to: sec = sec(0) atom_fitted_layer_indices: list[int] = [] for layer_idx in cur_atom.layer_indices: cur_layer = cur_layers[layer_idx] if isinstance(cur_layer._duration, sec): # resolve -1 duration if cur_layer.kind in ["VIDEO", "AUDIO"] and cur_layer._duration == sec(-1): layer_src: str = cast('HasMediaField', cur_layer).media.src if layer_src in g_resource_map: cur_layer.duration = g_resource_map[layer_src] else: cur_layer.duration = get_duration(layer_src) g_resource_map[layer_src] = cur_layer.duration elif cur_layer.duration == NOT_FIXED_SEC: cur_layer.duration = cur_layer._duration layer_to = cur_layer.atom_offset + cur_layer.duration if layer_to > max_to: max_to = layer_to else: atom_fitted_layer_indices.append(layer_idx) cur_atom._duration = max_to # resolve atom fitted layers for at_layer_idx in atom_fitted_layer_indices: cur_layers[at_layer_idx].duration = cur_atom._duration return False
class LayerField: uuid: UUID = UUID('') atom_uuid: UUID = UUID('') kind: LayerKind = 'LAYER' key: str = '' duration: sec = NOT_FIXED_SEC _duration: sec | 'tp.Type[root]' | 'UnitHandle' = sec(5) atom_offset: sec = sec(0)
def __post_init__(self): self._duration = sec(-1) self.video = VideoLocalField() self.media = MediaField(self._req_src) self.transform = TransformField() self.tex = TextureField() self.shader = ShaderField()
def duration( self: '_TLayerTrait', duration: sec | float | 'UnitHandle' | 'tp.Type[root]' ) -> '_TLayerTrait': if (cur_layer := peek_entry(self._idx)): _duration = sec(duration) if isinstance(duration, (int, float)) else duration tp.cast(LayerField, cur_layer)._duration = _duration
def get_duration(url: str) -> sec: if not _API: raise Exception('API is null') duration = _AKFraction() _API.akprobe_get_duration(duration, url.encode('utf-8')) return sec(duration.num, duration.den)
class AtomEntry: uuid: UUID layer_indices: list[int] = field(default_factory=list, init=False) bg_color: str = "#000000" # "#rrggbb" _duration: sec = field(default=sec(0), init=False)
class TransformField: pos: tuple[int, int] = (0, 0) z: float = 0.0 layer_size: tuple[int, int] = (-1, -1) rotation: sec = sec(0)
def offset(self: '_TLayerTrait', offset: sec | float) -> '_TLayerTrait': if (cur_layer := peek_entry(self._idx)): cur_layer.atom_offset = sec(offset)
def start(self, start: sec | float) -> 'MediaTrait': if (cur_layer := peek_entry(self._idx)): tp.cast(HasMediaField, cur_layer).media.start = sec(start)
class MediaField: src: str gain: float = 1.0 start: sec = sec(0) # temporary
def rotate(self, degrees: int | float | sec) -> 'TransformTrait': if (cur_layer := peek_entry(self._idx)): tp.cast(HasTransformField, cur_layer).transform.rotation = sec(degrees)