Single mechanical restructure commit: - root Cargo.toml = oakapp bin + workspace; one cargo build produces oakapp, oak-cli, oak-worker, liboakengine.dylib - app/rust/src -> src/ (app at repo root, no rust/ nesting) - src/<mod>/rust -> crates/oak<mod>; src/oakcore-rs -> crates/oakcore; src/bindings/oakotio -> crates/oakotio; src/engine/rust -> crates/oakengine (keeps cdylib+staticlib+rlib) - public C headers include/<mod>/ -> crates/oakengine/include/<mod>/ - OFX SDK headers vendored into crates/oakplugin/ofx/ (HostSupport gone) - legacy deleted: old src/ C++ modules, engine/, core/, ffmpeg_bridge/, app/ (Qt), cli/worker C++, root CMakeLists, third_party/KDDockWidgets submodule, otio-install, all build-* output (~40GB) - oakstorage kept but excluded from the workspace (skeleton w/ todos); gpui excluded (own workspace) - verified: cargo build green, cargo test --workspace 1845/0 (with the documented OCIO_RS_* env override for the homebrew OCIO)
271 lines
11 KiB
Rust
271 lines
11 KiB
Rust
// Oak Video Editor - Non-Linear Video Editor
|
|
// Copyright (C) 2026 Oak Team
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
// Oak Video Editor - Non-Linear Video Editor
|
|
// Copyright (C) 2026 Oak Team
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
//! oakrender C ABI imports. The task module reaches the render side through
|
|
//! `include/render/cancelatom.h` (task cancellation), `include/render/ticket.h`
|
|
//! (frame/audio render tickets), `include/render/copier.h` (export project
|
|
//! copy) and `include/render/color.h` (color processor). Signatures mirror
|
|
//! the headers verbatim.
|
|
//!
|
|
//! Resolution is at link time (the crate's existing pattern, see
|
|
//! `bridge/codec.rs`): the symbols are satisfied by the real `liboakrender`
|
|
//! when it is linked into the same binary (the app links the module dylibs;
|
|
//! the `real-oakrender` integration test links the oakrender crate directly),
|
|
//! and by the `#[no_mangle]` stubs in `tests/common/mod.rs` in plain
|
|
//! `cargo test`. The real-oakrender ticket contract — in particular the
|
|
//! 2-argument `oakrender_ticket_finished_fn` — is verified by
|
|
//! `tests/render_real_integration_test.rs` against the actual exports.
|
|
|
|
use std::ffi::{c_char, c_int, c_void};
|
|
|
|
use crate::bridge::codec::OakFrame;
|
|
use crate::bridge::common::{OakAudioParams, OakColorTransform, OakVideoParams};
|
|
use crate::bridge::node::{OakNodeColorManager, OakNodeNode, OakNodeProject};
|
|
use crate::handle::CHandle;
|
|
|
|
/// Mirror of `OakCancelAtom` (`include/render/cancelatom.h`).
|
|
pub type OakCancelAtom = oakrender::ffi::OakCancelAtom;
|
|
|
|
|
|
|
|
/// Mirror of `OakRenderTicket` (`include/render/ticket.h`).
|
|
pub type OakRenderTicket = oakrender::ffi::OakRenderTicket;
|
|
|
|
|
|
/// Mirror of `OakRenderCache` (`include/render/cache.h`).
|
|
pub type OakRenderCache = oakrender::ffi::OakRenderCache;
|
|
|
|
|
|
|
|
/// Mirror of `OakRenderProjectCopier` (`include/render/copier.h`).
|
|
pub type OakRenderProjectCopier = oakrender::ffi::OakRenderProjectCopier;
|
|
|
|
|
|
/// Mirror of `OakColorProcessor` (`include/render/color.h`).
|
|
pub type OakColorProcessor = oakrender::ffi::OakColorProcessor;
|
|
|
|
|
|
|
|
/// Mirror of `oakrender_ticket_finished_fn` (`include/render/ticket.h`).
|
|
///
|
|
/// Two arguments — `(ticket, userdata)` — mirroring the header verbatim and
|
|
/// matching the oakrender implementation (`src/render/rust/src/ffi.rs`).
|
|
/// The ticket is a borrowed copy of the submitter's handle (the submitter
|
|
/// keeps ownership and releases it); cancelled tickets fire with a NULL
|
|
/// result observed through `oakrender_ticket_get_frame`.
|
|
pub type OakRenderTicketFinishedFn = unsafe extern "C" fn(ticket: OakRenderTicket, userdata: *mut c_void);
|
|
|
|
/// Mirror of `oakrender_video_ticket_params` (`include/render/ticket.h`).
|
|
pub type OakRenderVideoTicketParams = oakrender::ffi::OakVideoTicketParams;
|
|
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_cancelatom_init() -> OakCancelAtom {
|
|
unsafe { oakrender::ffi::cancelatom::oakrender_cancelatom_init() }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_cancelatom_free(atom: *mut OakCancelAtom) {
|
|
unsafe { oakrender::ffi::cancelatom::oakrender_cancelatom_free(atom) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_cancelatom_cancel(atom: OakCancelAtom) -> c_int {
|
|
unsafe { oakrender::ffi::cancelatom::oakrender_cancelatom_cancel(atom) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_cancelatom_is_cancelled(atom: OakCancelAtom, cancelled: *mut c_int) -> c_int {
|
|
unsafe { oakrender::ffi::cancelatom::oakrender_cancelatom_is_cancelled(atom, cancelled) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_cancelatom_heard_cancel(atom: OakCancelAtom, heard: *mut c_int) -> c_int {
|
|
unsafe { oakrender::ffi::cancelatom::oakrender_cancelatom_heard_cancel(atom, heard) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_ticket_render_frame(
|
|
params: *const OakRenderVideoTicketParams,
|
|
cb: Option<OakRenderTicketFinishedFn>,
|
|
userdata: *mut c_void,
|
|
) -> OakRenderTicket {
|
|
unsafe { oakrender::ffi::ticket::oakrender_ticket_render_frame(params, cb, userdata) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_ticket_render_audio(
|
|
output_node: OakNodeNode,
|
|
in_num: i64,
|
|
in_den: i64,
|
|
out_num: i64,
|
|
out_den: i64,
|
|
params: *const OakAudioParams,
|
|
mode: c_int,
|
|
cb: Option<OakRenderTicketFinishedFn>,
|
|
userdata: *mut c_void,
|
|
) -> OakRenderTicket {
|
|
unsafe { oakrender::ffi::ticket::oakrender_ticket_render_audio(output_node, in_num, in_den, out_num, out_den, params, mode, cb, userdata) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_ticket_is_finished(ticket: OakRenderTicket) -> c_int {
|
|
unsafe { oakrender::ffi::ticket::oakrender_ticket_is_finished(ticket) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_ticket_wait(ticket: OakRenderTicket) -> c_int {
|
|
unsafe { oakrender::ffi::ticket::oakrender_ticket_wait(ticket) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_ticket_cancel(ticket: OakRenderTicket) -> c_int {
|
|
unsafe { oakrender::ffi::ticket::oakrender_ticket_cancel(ticket) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_ticket_get_type(ticket: OakRenderTicket) -> c_int {
|
|
unsafe { oakrender::ffi::ticket::oakrender_ticket_get_type(ticket) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_ticket_get_frame(ticket: OakRenderTicket, out: *mut OakFrame) -> c_int {
|
|
unsafe { oakrender::ffi::ticket::oakrender_ticket_get_frame(ticket, out) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_ticket_get_time(ticket: OakRenderTicket, out_num: *mut i64, out_den: *mut i64) -> c_int {
|
|
unsafe { oakrender::ffi::ticket::oakrender_ticket_get_time(ticket, out_num, out_den) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_ticket_get_range(
|
|
ticket: OakRenderTicket,
|
|
in_num: *mut i64,
|
|
in_den: *mut i64,
|
|
out_num: *mut i64,
|
|
out_den: *mut i64,
|
|
) -> c_int {
|
|
unsafe { oakrender::ffi::ticket::oakrender_ticket_get_range(ticket, in_num, in_den, out_num, out_den) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_ticket_get_samples(ticket: OakRenderTicket, out: *mut *mut std::ffi::c_void) -> c_int {
|
|
unsafe { oakrender::ffi::ticket::oakrender_ticket_get_samples(ticket, out) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_ticket_free(ticket: *mut OakRenderTicket) {
|
|
unsafe { oakrender::ffi::ticket::oakrender_ticket_free(ticket) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_project_copier_create() -> OakRenderProjectCopier {
|
|
unsafe { oakrender::ffi::copier::oakrender_project_copier_create() }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_project_copier_free(copier: *mut OakRenderProjectCopier) {
|
|
unsafe { oakrender::ffi::copier::oakrender_project_copier_free(copier) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_project_copier_set_project(
|
|
copier: OakRenderProjectCopier,
|
|
project: OakNodeProject,
|
|
) -> c_int {
|
|
unsafe { oakrender::ffi::copier::oakrender_project_copier_set_project(copier, project) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_project_copier_get_copy(
|
|
copier: OakRenderProjectCopier,
|
|
original: OakNodeNode,
|
|
) -> OakNodeNode {
|
|
unsafe { oakrender::ffi::copier::oakrender_project_copier_get_copy(copier, original) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_project_copier_get_copied_project(
|
|
copier: OakRenderProjectCopier,
|
|
) -> OakNodeProject {
|
|
unsafe { oakrender::ffi::copier::oakrender_project_copier_get_copied_project(copier) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_color_processor_create(
|
|
src_space: *const c_char,
|
|
dst_transform: *const c_char,
|
|
direction: c_int,
|
|
) -> OakColorProcessor {
|
|
unsafe { oakrender::ffi::color::oakrender_color_processor_create(src_space, dst_transform, direction) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_color_processor_free(processor: *mut OakColorProcessor) {
|
|
unsafe { oakrender::ffi::color::oakrender_color_processor_free(processor) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_color_processor_is_valid(processor: OakColorProcessor) -> c_int {
|
|
unsafe { oakrender::ffi::color::oakrender_color_processor_is_valid(processor) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_codec_frame_free(frame: *mut crate::bridge::codec::OakFrame) {
|
|
unsafe { oakrender::ffi::renderer::oakrender_codec_frame_free(frame) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_manager_set_aggressive_gc(enabled: c_int) -> c_int {
|
|
unsafe { oakrender::ffi::ticket::oakrender_manager_set_aggressive_gc(enabled) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_cache_get_invalidated_ranges(
|
|
cache: OakRenderCache,
|
|
in_num: i64,
|
|
in_den: i64,
|
|
out_num: i64,
|
|
out_den: i64,
|
|
flat: *mut i64,
|
|
flat_size: c_int,
|
|
) -> c_int {
|
|
unsafe { oakrender::ffi::cache::oakrender_cache_get_invalidated_ranges(cache, in_num, in_den, out_num, out_den, flat, flat_size) }
|
|
}
|
|
|
|
/// Direct call into the `oakrender` crate (single-lib unification).
|
|
pub fn oakrender_cache_free(cache: *mut OakRenderCache) {
|
|
unsafe { oakrender::ffi::cache::oakrender_cache_free(cache) }
|
|
}
|
|
|