refactor(engine): single-lib phase 1 — direct Rust calls across the facade
- unify CHandle in oakcore-rs (all crates re-export it) - facade bridge: 618/624 externs converted to direct module calls - signature-drift fixes surfaced by direct calls (videoparams, seconds, sync estimate, POD unification) - dead node<->render call sites removed; cancelatom -> oakcommon - node bridge/undo -> oakundo direct calls - docs/zh/plans/riir/single-lib.md: design + live status
This commit is contained in:
@@ -54,47 +54,13 @@ pub struct RefBox<T: ?Sized> {
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
/// `#[repr(C)]` mirror of the public handle structs
|
||||
/// (`{ctx, addref, release, abi_version}`).
|
||||
///
|
||||
/// Handles cross the C ABI by value (the C caller copies the 4-field
|
||||
/// struct), so the type is `Copy`/`Clone` — the oaknode crate only derives
|
||||
/// `Clone`, but `Copy` matches the C semantics exactly and lets exports and
|
||||
/// tests pass the same handle around freely. No `Drop`: releasing goes
|
||||
/// through the explicit `free_*`/`release` path, never on scope exit.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CHandle {
|
||||
/// Opaque box pointer.
|
||||
pub ctx: *mut std::ffi::c_void,
|
||||
/// Atomic increment.
|
||||
pub addref: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// Atomic decrement; destroys at zero.
|
||||
pub release: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// ABI version.
|
||||
pub abi_version: u32,
|
||||
}
|
||||
|
||||
// Handles are passed by value across the C ABI and used from the caller's
|
||||
// thread; the objects behind them synchronize their own state.
|
||||
unsafe impl Send for CHandle {}
|
||||
|
||||
impl CHandle {
|
||||
/// The empty handle.
|
||||
pub fn null() -> Self {
|
||||
CHandle {
|
||||
ctx: std::ptr::null_mut(),
|
||||
addref: None,
|
||||
release: None,
|
||||
abi_version: OAKAUDIO_ABI_VERSION,
|
||||
}
|
||||
}
|
||||
|
||||
/// True when the handle carries no object.
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ctx.is_null()
|
||||
}
|
||||
}
|
||||
/// The shared ABI value-handle type (single-lib unification, see
|
||||
/// `docs/zh/plans/riir/single-lib.md`): one canonical
|
||||
/// `{ctx, addref, release, abi_version}` type in `oakcore-rs`, re-exported
|
||||
/// here so the crate's `ffi.rs` signatures and handle scaffolding stay
|
||||
/// source-compatible. It is `Clone + Copy` (handles cross the C ABI by
|
||||
/// value) and `Send + Sync` (refcounted, shared across threads).
|
||||
pub use oakcore_rs::handle::CHandle;
|
||||
|
||||
/// `// CPP-PARITY: src/audio/c_api/refcounted.h` (`ref_counted_addref`).
|
||||
unsafe extern "C" fn owned_addref<T: Send + 'static>(ctx: *mut std::ffi::c_void) {
|
||||
|
||||
@@ -93,7 +93,8 @@ fn manager_singleton_and_alive_count() {
|
||||
unsafe { oakaudio_manager_destroy_instance() };
|
||||
let none = unsafe { oakaudio_manager_instance() };
|
||||
assert!(none.ctx.is_null());
|
||||
assert_eq!(none.abi_version, oakaudio::handle::OAKAUDIO_ABI_VERSION);
|
||||
// The empty instance handle is the shared `null()` (no ABI version).
|
||||
assert_eq!(none.abi_version, 0);
|
||||
|
||||
unsafe { oakaudio_manager_create_instance() };
|
||||
let m1 = unsafe { oakaudio_manager_instance() };
|
||||
|
||||
@@ -79,7 +79,8 @@ fn borrowed_release() {
|
||||
fn null_and_guard_ok() {
|
||||
let null = CHandle::null();
|
||||
assert!(null.is_null());
|
||||
assert_eq!(null.abi_version, oakaudio::handle::OAKAUDIO_ABI_VERSION);
|
||||
// The shared `null()` stamps no ABI version (single-lib unification).
|
||||
assert_eq!(null.abi_version, 0);
|
||||
|
||||
assert_eq!(guard(|| Ok(())), OAKAUDIO_OK);
|
||||
|
||||
|
||||
@@ -46,38 +46,12 @@ pub struct RefBox<T: ?Sized> {
|
||||
|
||||
/// `#[repr(C)]` mirror of the public handle structs
|
||||
/// (`{ctx, addref, release, abi_version}`).
|
||||
///
|
||||
/// Handles are `Copy`: passing one by value copies the struct, not the
|
||||
/// reference count — exactly the by-value convention the C ABI documents.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[repr(C)]
|
||||
pub struct CHandle {
|
||||
/// Opaque box pointer.
|
||||
pub ctx: *mut std::ffi::c_void,
|
||||
/// Atomic increment.
|
||||
pub addref: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// Atomic decrement; destroys at zero.
|
||||
pub release: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// ABI version.
|
||||
pub abi_version: u32,
|
||||
}
|
||||
|
||||
impl CHandle {
|
||||
/// The empty handle.
|
||||
pub fn null() -> Self {
|
||||
CHandle {
|
||||
ctx: ptr::null_mut(),
|
||||
addref: None,
|
||||
release: None,
|
||||
abi_version: OAKCODEC_ABI_VERSION,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether this is an empty (null) handle.
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ctx.is_null()
|
||||
}
|
||||
}
|
||||
/// The shared ABI value-handle type (single-lib unification, see
|
||||
/// `docs/zh/plans/riir/single-lib.md`): one canonical
|
||||
/// `{ctx, addref, release, abi_version}` type in `oakcore-rs`, re-exported
|
||||
/// here so the crate's `ffi.rs` signatures and handle scaffolding stay
|
||||
/// source-compatible.
|
||||
pub use oakcore_rs::handle::CHandle;
|
||||
|
||||
/// Increment the reference count of a boxed `RefBox<T>`.
|
||||
///
|
||||
@@ -293,6 +267,8 @@ mod tests {
|
||||
fn null_handle_helpers() {
|
||||
let h = CHandle::null();
|
||||
assert!(h.is_null());
|
||||
assert_eq!(h.abi_version, OAKCODEC_ABI_VERSION);
|
||||
// The shared `null()` stamps no ABI version (single-lib
|
||||
// unification; `make_owned` stamps the crate version).
|
||||
assert_eq!(h.abi_version, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
// 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/>.
|
||||
|
||||
//! The cancellation primitive (`olive::CancelAtom`): a thread-safe cancel
|
||||
//! flag shared between a render/encode caller and its worker.
|
||||
//!
|
||||
//! Single-lib unification (see `docs/zh/plans/riir/single-lib.md`): moved
|
||||
//! here from the oakrender crate so the oakcodec crate can use it without
|
||||
//! depending on oakrender (the oaknode/oakcodec/oakrender call cycle).
|
||||
|
||||
use std::sync::{Mutex, MutexGuard};
|
||||
|
||||
/// A cancellation atom (C++ `CancelAtom`). Reading a set flag also records
|
||||
/// that a consumer heard the cancellation.
|
||||
#[derive(Default)]
|
||||
pub struct CancelAtom {
|
||||
state: Mutex<AtomState>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct AtomState {
|
||||
cancelled: bool,
|
||||
heard: bool,
|
||||
}
|
||||
|
||||
fn lock(m: &Mutex<AtomState>) -> MutexGuard<'_, AtomState> {
|
||||
m.lock().unwrap_or_else(|e| e.into_inner())
|
||||
}
|
||||
|
||||
impl CancelAtom {
|
||||
/// A not-cancelled atom.
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Set the cancel flag (C++ `CancelAtom::cancel()`).
|
||||
pub fn cancel(&self) {
|
||||
lock(&self.state).cancelled = true;
|
||||
}
|
||||
|
||||
/// Read the cancel flag; reading a set flag records that the
|
||||
/// cancellation was heard (C++ `is_cancelled()`).
|
||||
pub fn is_cancelled(&self) -> bool {
|
||||
let mut s = lock(&self.state);
|
||||
if s.cancelled {
|
||||
s.heard = true;
|
||||
}
|
||||
s.cancelled
|
||||
}
|
||||
|
||||
/// Whether any consumer has observed the cancel flag through
|
||||
/// [`CancelAtom::is_cancelled`] (C++ `heard_cancel()`).
|
||||
pub fn heard_cancel(&self) -> bool {
|
||||
lock(&self.state).heard
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn fresh_atom_is_not_cancelled() {
|
||||
let a = CancelAtom::new();
|
||||
assert!(!a.is_cancelled());
|
||||
assert!(!a.heard_cancel());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancel_sets_flag_and_reading_marks_heard() {
|
||||
let a = CancelAtom::new();
|
||||
a.cancel();
|
||||
assert!(!a.heard_cancel(), "not heard until read");
|
||||
assert!(a.is_cancelled());
|
||||
assert!(a.heard_cancel(), "reading a set flag marks it heard");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repeated_cancel_is_idempotent() {
|
||||
let a = CancelAtom::new();
|
||||
a.cancel();
|
||||
a.cancel();
|
||||
assert!(a.is_cancelled());
|
||||
}
|
||||
}
|
||||
@@ -920,3 +920,16 @@ mod tests {
|
||||
let _ = std::fs::remove_dir_all(&b);
|
||||
}
|
||||
}
|
||||
|
||||
/// The default disk cache directory (C++ `DiskManager::
|
||||
/// get_default_disk_cache_path`): `<configuration location>/mediacache`.
|
||||
///
|
||||
/// Single-lib unification: this used to live in the oakrender crate's
|
||||
/// `bridge::common` fallback (see `docs/zh/plans/riir/single-lib.md`);
|
||||
/// oaknode and oakrender both call it directly now.
|
||||
pub fn default_disk_cache_path() -> String {
|
||||
Path::new(&FileFunctions::new().get_configuration_location().unwrap_or_default())
|
||||
.join("mediacache")
|
||||
.to_string_lossy()
|
||||
.into_owned()
|
||||
}
|
||||
|
||||
@@ -59,36 +59,12 @@ pub struct RefBox<T: Sized> {
|
||||
pub refs: AtomicU32,
|
||||
}
|
||||
|
||||
/// `#[repr(C)]` mirror of the public handle structs
|
||||
/// (`{ctx, addref, release, abi_version}`).
|
||||
#[repr(C)]
|
||||
pub struct CHandle {
|
||||
/// Opaque box pointer.
|
||||
pub ctx: *mut std::ffi::c_void,
|
||||
/// Atomic increment.
|
||||
pub addref: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// Atomic decrement; destroys at zero.
|
||||
pub release: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// ABI version.
|
||||
pub abi_version: u32,
|
||||
}
|
||||
|
||||
impl CHandle {
|
||||
/// The empty handle.
|
||||
pub fn null() -> Self {
|
||||
Self {
|
||||
ctx: std::ptr::null_mut(),
|
||||
addref: None,
|
||||
release: None,
|
||||
abi_version: OAKCOMMON_ABI_VERSION,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether this is an empty handle (`ctx == NULL`).
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ctx.is_null()
|
||||
}
|
||||
}
|
||||
/// The shared ABI value-handle type (single-lib unification, see
|
||||
/// `docs/zh/plans/riir/single-lib.md`): one canonical
|
||||
/// `{ctx, addref, release, abi_version}` type in `oakcore-rs`, re-exported
|
||||
/// here so the crate's `ffi.rs` signatures and handle scaffolding stay
|
||||
/// source-compatible.
|
||||
pub use oakcore_rs::handle::CHandle;
|
||||
|
||||
/// addref thunk: atomically increments the count. Shared by owned and
|
||||
/// borrowed boxes — for a borrowed handle addref only extends the life of
|
||||
@@ -260,7 +236,9 @@ mod tests {
|
||||
assert!(h.ctx.is_null());
|
||||
assert!(h.addref.is_none());
|
||||
assert!(h.release.is_none());
|
||||
assert_eq!(h.abi_version, OAKCOMMON_ABI_VERSION);
|
||||
// The shared `null()` stamps no ABI version (single-lib
|
||||
// unification; `make_owned` stamps the crate version).
|
||||
assert_eq!(h.abi_version, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
pub mod colortransform;
|
||||
pub mod commandlineparser;
|
||||
pub mod cancelatom;
|
||||
pub mod configstore;
|
||||
pub mod debug;
|
||||
pub mod error;
|
||||
|
||||
@@ -126,7 +126,8 @@ fn init_output_null_yields_null_handle() {
|
||||
assert!(h.ctx.is_null());
|
||||
assert!(h.addref.is_none());
|
||||
assert!(h.release.is_none());
|
||||
assert_eq!(h.abi_version, OAKCOMMON_ABI_VERSION);
|
||||
// The shared `null()` stamps no ABI version (single-lib unification).
|
||||
assert_eq!(h.abi_version, 0);
|
||||
}
|
||||
|
||||
/// An empty output name is a valid value: the transform is still an output
|
||||
@@ -189,7 +190,8 @@ fn init_display_null_any_arg_yields_null_handle() {
|
||||
assert!(h.ctx.is_null());
|
||||
assert!(h.addref.is_none());
|
||||
assert!(h.release.is_none());
|
||||
assert_eq!(h.abi_version, OAKCOMMON_ABI_VERSION);
|
||||
// The shared `null()` stamps no ABI version (single-lib unification).
|
||||
assert_eq!(h.abi_version, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Generated
+4
@@ -806,7 +806,9 @@ dependencies = [
|
||||
name = "oaknode"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"oakcommon",
|
||||
"oakcore-rs",
|
||||
"oakundo",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -824,12 +826,14 @@ name = "oakplugin"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"oakcore-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oakrender"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"oakcommon",
|
||||
"oakcore-rs",
|
||||
"ocio-rs",
|
||||
"wgpu",
|
||||
|
||||
@@ -327,10 +327,6 @@ pub unsafe extern "C" fn oakengine_audio_estimate_stretch_and_offset(
|
||||
confidence: 0.0,
|
||||
valid: 0,
|
||||
};
|
||||
// The module's rate search is fixed-step; the engine's range
|
||||
// parameters are not part of its C ABI (documented deviation:
|
||||
// the module searches its own default range).
|
||||
let _ = (min_rate, max_rate, rate_step);
|
||||
Error::from_module(a::oakaudio_sync_estimate_stretch_and_offset(
|
||||
reference,
|
||||
reference_len,
|
||||
@@ -340,6 +336,9 @@ pub unsafe extern "C" fn oakengine_audio_estimate_stretch_and_offset(
|
||||
candidate_valid,
|
||||
window_samples,
|
||||
max_offset_windows,
|
||||
min_rate,
|
||||
max_rate,
|
||||
rate_step,
|
||||
&mut result,
|
||||
))?;
|
||||
(*out).rate = result.rate;
|
||||
|
||||
+277
-170
@@ -14,6 +14,33 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! oakaudio C ABI bridge: direct Rust calls into the `oakaudio` crate.
|
||||
//!
|
||||
//! Single-lib unification (see `docs/zh/plans/riir/single-lib.md`): every
|
||||
//! call below is a compile-time Rust call into `oakaudio`'s `ffi` (the
|
||||
//! `#[no_mangle]` exports stay in the dylib for the external C ABI;
|
||||
//! internal callers bypass them). Handles cross as the shared
|
||||
//! [`crate::handle::CHandle`]. Exceptions that keep an `extern "C"`
|
||||
//! declaration (resolved at link time against the sibling crate in the
|
||||
//! same dylib) are the host `oakcore_*` symbols and the encoding-params
|
||||
//! C ABI POD crossings (the facade keeps its own POD mirrors there).
|
||||
|
||||
// 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/>.
|
||||
|
||||
//! oakaudio C ABI imports, mirroring the oakaudio crate's exports
|
||||
//! (`src/audio/rust/src/ffi.rs`; headers `include/audio/*.h`), plus the
|
||||
//! liboakcore `oakcore_audioparams_*` readers used to convert the
|
||||
@@ -23,182 +50,21 @@ use std::ffi::{c_char, c_double, c_int, c_void};
|
||||
|
||||
use crate::handle::CHandle;
|
||||
|
||||
/// `oakaudio_sync_offset_result` mirror — `oak_audio_waveform_offset`.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct OffsetResult {
|
||||
/// Offset of the candidate relative to the reference, in samples.
|
||||
pub offset_samples: i64,
|
||||
/// Normalized correlation confidence in `[0, 1]`.
|
||||
pub confidence: c_double,
|
||||
/// Whether an offset could be determined.
|
||||
pub valid: c_int,
|
||||
}
|
||||
/// `oakaudio_offsetresult` C ABI POD. Single-lib unification: aliases
|
||||
/// the oakaudio crate's struct (identical layout).
|
||||
pub type OffsetResult = oakaudio::ffi::sync::OffsetResult;
|
||||
|
||||
/// `oakaudio_stretch_offset_result` mirror — `oak_audio_waveform_stretch_offset`.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct StretchOffsetResult {
|
||||
/// Playback rate aligning the candidate (`> 1` = speed up).
|
||||
pub rate: c_double,
|
||||
/// Offset in samples.
|
||||
pub offset_samples: i64,
|
||||
/// Normalized correlation confidence in `[0, 1]`.
|
||||
pub confidence: c_double,
|
||||
/// Whether a rate+offset could be determined.
|
||||
pub valid: c_int,
|
||||
}
|
||||
|
||||
/// `oakaudio_sync_source_clip` mirror — `oak_audio_sync_source_clip`.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct SourceClip {
|
||||
/// Source start time numerator (seconds).
|
||||
pub source_start_time_num: i64,
|
||||
/// Source start time denominator (seconds).
|
||||
pub source_start_time_den: i64,
|
||||
/// Media in point numerator (seconds).
|
||||
pub media_in_num: i64,
|
||||
/// Media in point denominator (seconds).
|
||||
pub media_in_den: i64,
|
||||
/// Whether `source_start_time` is set.
|
||||
pub has_source_start_time: c_int,
|
||||
}
|
||||
/// `oakaudio_stretchoffsetresult` C ABI POD. Single-lib unification: aliases
|
||||
/// the oakaudio crate's struct (identical layout).
|
||||
pub type StretchOffsetResult = oakaudio::ffi::sync::StretchOffsetResult;
|
||||
|
||||
extern "C" {
|
||||
// ---- manager.h --------------------------------------------------------
|
||||
/// `oakaudio_manager_create_instance` — create the singleton.
|
||||
pub fn oakaudio_manager_create_instance() -> c_int;
|
||||
/// `oakaudio_manager_destroy_instance` — destroy the singleton.
|
||||
pub fn oakaudio_manager_destroy_instance();
|
||||
/// `oakaudio_manager_instance` — borrowed handle (empty when none).
|
||||
pub fn oakaudio_manager_instance() -> CHandle;
|
||||
/// `oakaudio_manager_free` — release a manager handle.
|
||||
pub fn oakaudio_manager_free(_self: *mut CHandle);
|
||||
/// `oakaudio_manager_set_output_notify_interval`.
|
||||
pub fn oakaudio_manager_set_output_notify_interval(_self: CHandle, bytes: i64) -> c_int;
|
||||
/// `oakaudio_manager_push_to_output`.
|
||||
pub fn oakaudio_manager_push_to_output(
|
||||
_self: CHandle,
|
||||
rate: c_int,
|
||||
layout: u64,
|
||||
format: c_int,
|
||||
samples: *const c_char,
|
||||
samples_size: i64,
|
||||
error_buf: *mut c_char,
|
||||
error_buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakaudio_manager_clear_buffered_output`.
|
||||
pub fn oakaudio_manager_clear_buffered_output(_self: CHandle) -> c_int;
|
||||
/// `oakaudio_manager_stop_output`.
|
||||
pub fn oakaudio_manager_stop_output(_self: CHandle) -> c_int;
|
||||
/// `oakaudio_manager_reset_output_clock`.
|
||||
pub fn oakaudio_manager_reset_output_clock(_self: CHandle) -> c_int;
|
||||
/// `oakaudio_manager_get_output_device` — module returns the device as
|
||||
/// `c_int`; the facade widens to the engine's int64_t.
|
||||
pub fn oakaudio_manager_get_output_device(_self: CHandle) -> c_int;
|
||||
/// `oakaudio_manager_set_output_device`.
|
||||
pub fn oakaudio_manager_set_output_device(_self: CHandle, device: c_int) -> c_int;
|
||||
/// `oakaudio_manager_get_input_device`.
|
||||
pub fn oakaudio_manager_get_input_device(_self: CHandle) -> c_int;
|
||||
/// `oakaudio_manager_set_input_device`.
|
||||
pub fn oakaudio_manager_set_input_device(_self: CHandle, device: c_int) -> c_int;
|
||||
/// `oakaudio_manager_hard_reset`.
|
||||
pub fn oakaudio_manager_hard_reset(_self: CHandle) -> c_int;
|
||||
/// `oakaudio_manager_start_recording`.
|
||||
pub fn oakaudio_manager_start_recording(
|
||||
_self: CHandle,
|
||||
params: *const EncodingParams,
|
||||
error_buf: *mut c_char,
|
||||
error_buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakaudio_manager_stop_recording`.
|
||||
pub fn oakaudio_manager_stop_recording(_self: CHandle) -> c_int;
|
||||
/// `oakaudio_manager_seconds`.
|
||||
pub fn oakaudio_manager_seconds(_self: CHandle) -> i64;
|
||||
|
||||
// ---- processor.h ------------------------------------------------------
|
||||
/// `oakaudio_processor_init` — new processor, refcount 1.
|
||||
pub fn oakaudio_processor_init() -> CHandle;
|
||||
/// `oakaudio_processor_free` — NULL/empty no-op.
|
||||
pub fn oakaudio_processor_free(_self: *mut CHandle);
|
||||
/// `oakaudio_processor_open`.
|
||||
pub fn oakaudio_processor_open(
|
||||
_self: CHandle,
|
||||
in_rate: c_int,
|
||||
in_layout: u64,
|
||||
in_format: c_int,
|
||||
out_rate: c_int,
|
||||
out_layout: u64,
|
||||
out_format: c_int,
|
||||
speed: c_double,
|
||||
) -> c_int;
|
||||
/// `oakaudio_processor_close`.
|
||||
pub fn oakaudio_processor_close(_self: CHandle) -> c_int;
|
||||
/// `oakaudio_processor_is_open`.
|
||||
pub fn oakaudio_processor_is_open(_self: CHandle) -> c_int;
|
||||
/// `oakaudio_sourceclip` C ABI POD. Single-lib unification: aliases
|
||||
/// the oakaudio crate's struct (identical layout).
|
||||
pub type SourceClip = oakaudio::ffi::sync::SourceClip;
|
||||
|
||||
// ---- sync.h -----------------------------------------------------------
|
||||
/// `oakaudio_sync_estimate_envelope_offset`.
|
||||
pub fn oakaudio_sync_estimate_envelope_offset(
|
||||
reference: *const c_double,
|
||||
reference_len: c_int,
|
||||
candidate: *const c_double,
|
||||
candidate_len: c_int,
|
||||
reference_valid: *const u8,
|
||||
candidate_valid: *const u8,
|
||||
window_samples: u64,
|
||||
max_offset_windows: i64,
|
||||
out: *mut OffsetResult,
|
||||
) -> c_int;
|
||||
/// `oakaudio_sync_estimate_stretch_and_offset`.
|
||||
pub fn oakaudio_sync_estimate_stretch_and_offset(
|
||||
reference: *const c_double,
|
||||
reference_len: c_int,
|
||||
candidate: *const c_double,
|
||||
candidate_len: c_int,
|
||||
reference_valid: *const u8,
|
||||
candidate_valid: *const u8,
|
||||
window_samples: u64,
|
||||
max_offset_windows: i64,
|
||||
out: *mut StretchOffsetResult,
|
||||
) -> c_int;
|
||||
/// `oakaudio_sync_place_by_source_time`.
|
||||
pub fn oakaudio_sync_place_by_source_time(
|
||||
reference: *const SourceClip,
|
||||
candidate: *const SourceClip,
|
||||
reference_timeline_in_num: i64,
|
||||
reference_timeline_in_den: i64,
|
||||
out_num: *mut i64,
|
||||
out_den: *mut i64,
|
||||
out_valid: *mut c_int,
|
||||
) -> c_int;
|
||||
/// `oakaudio_sync_place_by_waveform_offset`.
|
||||
pub fn oakaudio_sync_place_by_waveform_offset(
|
||||
reference_timeline_in_num: i64,
|
||||
reference_timeline_in_den: i64,
|
||||
candidate_offset_samples: i64,
|
||||
sample_rate: c_int,
|
||||
out_num: *mut i64,
|
||||
out_den: *mut i64,
|
||||
out_valid: *mut c_int,
|
||||
) -> c_int;
|
||||
|
||||
// ---- liboakcore (oakcore_audioparams_*) --------------------------------
|
||||
/// `oakcore_audioparams_create` — new owned params (release with
|
||||
/// [`oakcore_audioparams_free`]).
|
||||
pub fn oakcore_audioparams_create(sample_rate: c_int, channel_layout: u64, format: c_int) -> *mut c_void;
|
||||
/// `oakcore_audioparams_free` — release params created by
|
||||
/// [`oakcore_audioparams_create`] (or returned by the oaknode sequence
|
||||
/// audio-params getter).
|
||||
pub fn oakcore_audioparams_free(params: *mut c_void);
|
||||
/// `oakcore_audioparams_sample_rate` — borrowed params reader.
|
||||
pub fn oakcore_audioparams_sample_rate(params: *const c_void) -> c_int;
|
||||
/// `oakcore_audioparams_channel_layout` — borrowed params reader.
|
||||
pub fn oakcore_audioparams_channel_layout(params: *const c_void) -> u64;
|
||||
/// `oakcore_audioparams_format` — borrowed params reader.
|
||||
pub fn oakcore_audioparams_format(params: *const c_void) -> c_int;
|
||||
}
|
||||
|
||||
/// Opaque mirror of the oakaudio recording-params POD
|
||||
/// (`include/audio/manager.h`). The facade passes the engine's
|
||||
@@ -208,3 +74,244 @@ extern "C" {
|
||||
pub struct EncodingParams {
|
||||
_opaque: [u8; 0],
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn oakcore_audioparams_create(sample_rate: c_int, channel_layout: u64, format: c_int) -> *mut c_void;
|
||||
pub fn oakcore_audioparams_free(params: *mut c_void);
|
||||
pub fn oakcore_audioparams_sample_rate(params: *const c_void) -> c_int;
|
||||
pub fn oakcore_audioparams_channel_layout(params: *const c_void) -> u64;
|
||||
pub fn oakcore_audioparams_format(params: *const c_void) -> c_int;
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_create_instance() -> c_int {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_create_instance() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_destroy_instance() {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_destroy_instance() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_instance() -> CHandle {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_instance() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_free(_self: *mut CHandle) {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_free(_self) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_set_output_notify_interval(_self: CHandle, bytes: i64) -> c_int {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_set_output_notify_interval(_self, bytes) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_push_to_output(
|
||||
_self: CHandle,
|
||||
rate: c_int,
|
||||
layout: u64,
|
||||
format: c_int,
|
||||
samples: *const c_char,
|
||||
samples_size: i64,
|
||||
error_buf: *mut c_char,
|
||||
error_buf_size: c_int,
|
||||
) -> c_int {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_push_to_output(_self, rate, layout, format, samples, samples_size, error_buf, error_buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_clear_buffered_output(_self: CHandle) -> c_int {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_clear_buffered_output(_self) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_stop_output(_self: CHandle) -> c_int {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_stop_output(_self) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_reset_output_clock(_self: CHandle) -> c_int {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_reset_output_clock(_self) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_get_output_device(_self: CHandle) -> c_int {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_get_output_device(_self) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_set_output_device(_self: CHandle, device: c_int) -> c_int {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_set_output_device(_self, device) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_get_input_device(_self: CHandle) -> c_int {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_get_input_device(_self) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_set_input_device(_self: CHandle, device: c_int) -> c_int {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_set_input_device(_self, device) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_hard_reset(_self: CHandle) -> c_int {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_hard_reset(_self) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
/// `oakaudio_manager_start_recording` — crosses the encoding-params C ABI
|
||||
/// POD (the facade keeps its own opaque mirror; the module's
|
||||
/// `oakaudio::bridge::codec::EncodingParams`). Kept as a link-time
|
||||
/// `extern "C"` declaration against the frozen module C ABI.
|
||||
pub fn oakaudio_manager_start_recording(
|
||||
_self: CHandle,
|
||||
params: *const EncodingParams,
|
||||
error_buf: *mut c_char,
|
||||
error_buf_size: c_int,
|
||||
) -> c_int {
|
||||
unsafe { oakaudio_start_recording_extern(_self, params, error_buf, error_buf_size) }
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "oakaudio_manager_start_recording"]
|
||||
pub fn oakaudio_start_recording_extern(
|
||||
_self: CHandle,
|
||||
params: *const EncodingParams,
|
||||
error_buf: *mut c_char,
|
||||
error_buf_size: c_int,
|
||||
) -> c_int;
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_stop_recording(_self: CHandle) -> c_int {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_stop_recording(_self) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_manager_seconds(_self: CHandle, out: *mut c_double) -> c_int {
|
||||
unsafe { oakaudio::ffi::manager::oakaudio_manager_seconds(_self, out) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_processor_init() -> CHandle {
|
||||
unsafe { oakaudio::ffi::processor::oakaudio_processor_init() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_processor_free(_self: *mut CHandle) {
|
||||
unsafe { oakaudio::ffi::processor::oakaudio_processor_free(_self) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_processor_open(
|
||||
_self: CHandle,
|
||||
in_rate: c_int,
|
||||
in_layout: u64,
|
||||
in_format: c_int,
|
||||
out_rate: c_int,
|
||||
out_layout: u64,
|
||||
out_format: c_int,
|
||||
speed: c_double,
|
||||
) -> c_int {
|
||||
unsafe { oakaudio::ffi::processor::oakaudio_processor_open(_self, in_rate, in_layout, in_format, out_rate, out_layout, out_format, speed) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_processor_close(_self: CHandle) -> c_int {
|
||||
unsafe { oakaudio::ffi::processor::oakaudio_processor_close(_self) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_processor_is_open(_self: CHandle) -> c_int {
|
||||
unsafe { oakaudio::ffi::processor::oakaudio_processor_is_open(_self) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_sync_estimate_envelope_offset(
|
||||
reference: *const c_double,
|
||||
reference_len: c_int,
|
||||
candidate: *const c_double,
|
||||
candidate_len: c_int,
|
||||
reference_valid: *const u8,
|
||||
candidate_valid: *const u8,
|
||||
window_samples: u64,
|
||||
max_offset_windows: i64,
|
||||
out: *mut OffsetResult,
|
||||
) -> c_int {
|
||||
unsafe { oakaudio::ffi::sync::oakaudio_sync_estimate_envelope_offset(reference, reference_len, candidate, candidate_len, reference_valid, candidate_valid, window_samples, max_offset_windows, out) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_sync_estimate_stretch_and_offset(
|
||||
reference: *const c_double,
|
||||
reference_len: c_int,
|
||||
candidate: *const c_double,
|
||||
candidate_len: c_int,
|
||||
reference_valid: *const u8,
|
||||
candidate_valid: *const u8,
|
||||
window_samples: u64,
|
||||
max_offset_windows: i64,
|
||||
min_rate: c_double,
|
||||
max_rate: c_double,
|
||||
rate_step: c_double,
|
||||
out: *mut StretchOffsetResult,
|
||||
) -> c_int {
|
||||
unsafe { oakaudio::ffi::sync::oakaudio_sync_estimate_stretch_and_offset(reference, reference_len, candidate, candidate_len, reference_valid, candidate_valid, window_samples, max_offset_windows, min_rate, max_rate, rate_step, out) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_sync_place_by_source_time(
|
||||
reference: *const SourceClip,
|
||||
candidate: *const SourceClip,
|
||||
reference_timeline_in_num: i64,
|
||||
reference_timeline_in_den: i64,
|
||||
out_num: *mut i64,
|
||||
out_den: *mut i64,
|
||||
out_valid: *mut c_int,
|
||||
) -> c_int {
|
||||
unsafe { oakaudio::ffi::sync::oakaudio_sync_place_by_source_time(reference, candidate, reference_timeline_in_num, reference_timeline_in_den, out_num, out_den, out_valid) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakaudio` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakaudio_sync_place_by_waveform_offset(
|
||||
reference_timeline_in_num: i64,
|
||||
reference_timeline_in_den: i64,
|
||||
candidate_offset_samples: i64,
|
||||
sample_rate: c_int,
|
||||
out_num: *mut i64,
|
||||
out_den: *mut i64,
|
||||
out_valid: *mut c_int,
|
||||
) -> c_int {
|
||||
unsafe { oakaudio::ffi::sync::oakaudio_sync_place_by_waveform_offset(reference_timeline_in_num, reference_timeline_in_den, candidate_offset_samples, sample_rate, out_num, out_den, out_valid) }
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,33 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! oakcodec C ABI bridge: direct Rust calls into the `oakcodec` crate.
|
||||
//!
|
||||
//! Single-lib unification (see `docs/zh/plans/riir/single-lib.md`): every
|
||||
//! call below is a compile-time Rust call into `oakcodec`'s `ffi` (the
|
||||
//! `#[no_mangle]` exports stay in the dylib for the external C ABI;
|
||||
//! internal callers bypass them). Handles cross as the shared
|
||||
//! [`crate::handle::CHandle`]. Exceptions that keep an `extern "C"`
|
||||
//! declaration (resolved at link time against the sibling crate in the
|
||||
//! same dylib) are the host `oakcore_*` symbols and the encoding-params
|
||||
//! C ABI POD crossings (the facade keeps its own POD mirrors there).
|
||||
|
||||
// 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/>.
|
||||
|
||||
//! oakcodec C ABI imports, mirroring the oakcodec crate's exports
|
||||
//! (`src/codec/rust/src/ffi/{format,encoder}.rs`; headers
|
||||
//! `include/codec/{format,encoder}.h`). Also carries the
|
||||
@@ -117,76 +144,171 @@ impl EncodingParamsPOD {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
// ---- include/codec/format.h (encoding metadata) ------------------------
|
||||
/// `oakcodec_encoding_format_count`.
|
||||
pub fn oakcodec_encoding_format_count() -> c_int;
|
||||
/// `oakcodec_encoding_format_name` (two-stage string).
|
||||
pub fn oakcodec_encoding_format_name(format: c_int, buf: *mut c_char, buf_size: c_int) -> c_int;
|
||||
/// `oakcodec_encoding_format_extension` (two-stage string).
|
||||
pub fn oakcodec_encoding_format_extension(
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_format_count() -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_format_count() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_format_name(format: c_int, buf: *mut c_char, buf_size: c_int) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_format_name(format, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_format_extension(
|
||||
format: c_int,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcodec_encoding_format_video_codec_count`.
|
||||
pub fn oakcodec_encoding_format_video_codec_count(format: c_int) -> c_int;
|
||||
/// `oakcodec_encoding_format_video_codec_at`.
|
||||
pub fn oakcodec_encoding_format_video_codec_at(format: c_int, index: c_int) -> c_int;
|
||||
/// `oakcodec_encoding_format_audio_codec_count`.
|
||||
pub fn oakcodec_encoding_format_audio_codec_count(format: c_int) -> c_int;
|
||||
/// `oakcodec_encoding_format_audio_codec_at`.
|
||||
pub fn oakcodec_encoding_format_audio_codec_at(format: c_int, index: c_int) -> c_int;
|
||||
/// `oakcodec_encoding_format_subtitle_codec_count`.
|
||||
pub fn oakcodec_encoding_format_subtitle_codec_count(format: c_int) -> c_int;
|
||||
/// `oakcodec_encoding_format_subtitle_codec_at`.
|
||||
pub fn oakcodec_encoding_format_subtitle_codec_at(format: c_int, index: c_int) -> c_int;
|
||||
/// `oakcodec_encoding_codec_name` (two-stage string).
|
||||
pub fn oakcodec_encoding_codec_name(codec: c_int, buf: *mut c_char, buf_size: c_int) -> c_int;
|
||||
/// `oakcodec_encoding_codec_is_still_image`.
|
||||
pub fn oakcodec_encoding_codec_is_still_image(codec: c_int) -> c_int;
|
||||
/// `oakcodec_encoding_codec_is_lossless`.
|
||||
pub fn oakcodec_encoding_codec_is_lossless(codec: c_int) -> c_int;
|
||||
/// `oakcodec_encoding_pix_fmt_count`.
|
||||
pub fn oakcodec_encoding_pix_fmt_count(format: c_int, codec: c_int) -> c_int;
|
||||
/// `oakcodec_encoding_pix_fmt_at` (two-stage string).
|
||||
pub fn oakcodec_encoding_pix_fmt_at(
|
||||
) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_format_extension(format, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_format_video_codec_count(format: c_int) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_format_video_codec_count(format) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_format_video_codec_at(format: c_int, index: c_int) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_format_video_codec_at(format, index) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_format_audio_codec_count(format: c_int) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_format_audio_codec_count(format) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_format_audio_codec_at(format: c_int, index: c_int) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_format_audio_codec_at(format, index) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_format_subtitle_codec_count(format: c_int) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_format_subtitle_codec_count(format) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_format_subtitle_codec_at(format: c_int, index: c_int) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_format_subtitle_codec_at(format, index) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_codec_name(codec: c_int, buf: *mut c_char, buf_size: c_int) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_codec_name(codec, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_codec_is_still_image(codec: c_int) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_codec_is_still_image(codec) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_codec_is_lossless(codec: c_int) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_codec_is_lossless(codec) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_pix_fmt_count(format: c_int, codec: c_int) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_pix_fmt_count(format, codec) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_pix_fmt_at(
|
||||
format: c_int,
|
||||
codec: c_int,
|
||||
index: c_int,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcodec_encoding_pix_fmt_index`.
|
||||
pub fn oakcodec_encoding_pix_fmt_index(codec: c_int, pix_fmt: *const c_char) -> c_int;
|
||||
/// `oakcodec_encoding_sample_format_count`.
|
||||
pub fn oakcodec_encoding_sample_format_count(format: c_int, codec: c_int) -> c_int;
|
||||
/// `oakcodec_encoding_sample_format_at`.
|
||||
pub fn oakcodec_encoding_sample_format_at(format: c_int, codec: c_int, index: c_int) -> c_int;
|
||||
/// `oakcodec_encoding_filename_contains_digit_placeholder` (0 for NULL).
|
||||
pub fn oakcodec_encoding_filename_contains_digit_placeholder(filename: *const c_char) -> c_int;
|
||||
/// `oakcodec_encoding_image_sequence_digit_count` (0 when none).
|
||||
pub fn oakcodec_encoding_image_sequence_digit_count(filename: *const c_char) -> c_int;
|
||||
/// `oakcodec_encoding_filename_remove_digit_placeholder` (two-stage).
|
||||
pub fn oakcodec_encoding_filename_remove_digit_placeholder(
|
||||
) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_pix_fmt_at(format, codec, index, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_pix_fmt_index(codec: c_int, pix_fmt: *const c_char) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_pix_fmt_index(codec, pix_fmt) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_sample_format_count(format: c_int, codec: c_int) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_sample_format_count(format, codec) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_sample_format_at(format: c_int, codec: c_int, index: c_int) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_sample_format_at(format, codec, index) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_filename_contains_digit_placeholder(filename: *const c_char) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_filename_contains_digit_placeholder(filename) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_image_sequence_digit_count(filename: *const c_char) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_image_sequence_digit_count(filename) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_filename_remove_digit_placeholder(
|
||||
filename: *const c_char,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcodec_encoding_generate_matrix` — writes 16 `f64` (the engine
|
||||
/// surface uses `f32`; the facade converts).
|
||||
pub fn oakcodec_encoding_generate_matrix(
|
||||
) -> c_int {
|
||||
unsafe { oakcodec::ffi::format::oakcodec_encoding_filename_remove_digit_placeholder(filename, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoding_generate_matrix(
|
||||
method: c_int,
|
||||
src_width: c_int,
|
||||
src_height: c_int,
|
||||
dst_width: c_int,
|
||||
dst_height: c_int,
|
||||
out_matrix: *mut f64,
|
||||
) -> c_int;
|
||||
|
||||
// ---- include/codec/encoder.h -------------------------------------------
|
||||
/// `oakcodec_encoder_init` — encoder over a params POD (refcount 1).
|
||||
pub fn oakcodec_encoder_init(params: *const EncodingParamsPOD) -> CHandle;
|
||||
/// `oakcodec_encoder_free` — NULL/empty no-op.
|
||||
pub fn oakcodec_encoder_free(encoder: *mut CHandle);
|
||||
) -> c_int {
|
||||
unsafe { oakcodec::ffi::encoder::oakcodec_encoding_generate_matrix(method, src_width, src_height, dst_width, dst_height, out_matrix) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
/// `oakcodec_encoder_init` — crosses the encoding-params C ABI POD
|
||||
/// (`oakcodec_encoding_params`; the facade keeps its own POD mirror).
|
||||
/// Kept as a link-time `extern "C"` declaration against the frozen module
|
||||
/// C ABI.
|
||||
pub fn oakcodec_encoder_init(params: *const EncodingParamsPOD) -> CHandle {
|
||||
unsafe { oakcodec_encoder_init_extern(params) }
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "oakcodec_encoder_init"]
|
||||
pub fn oakcodec_encoder_init_extern(params: *const EncodingParamsPOD) -> CHandle;
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcodec` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcodec_encoder_free(encoder: *mut CHandle) {
|
||||
unsafe { oakcodec::ffi::encoder::oakcodec_encoder_free(encoder) }
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,33 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! oakcommon C ABI bridge: direct Rust calls into the `oakcommon` crate.
|
||||
//!
|
||||
//! Single-lib unification (see `docs/zh/plans/riir/single-lib.md`): every
|
||||
//! call below is a compile-time Rust call into `oakcommon`'s `ffi` (the
|
||||
//! `#[no_mangle]` exports stay in the dylib for the external C ABI;
|
||||
//! internal callers bypass them). Handles cross as the shared
|
||||
//! [`crate::handle::CHandle`]. Exceptions that keep an `extern "C"`
|
||||
//! declaration (resolved at link time against the sibling crate in the
|
||||
//! same dylib) are the host `oakcore_*` symbols and the encoding-params
|
||||
//! C ABI POD crossings (the facade keeps its own POD mirrors there).
|
||||
|
||||
// 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/>.
|
||||
|
||||
//! oakcommon C ABI imports, mirroring the oakcommon crate's exports
|
||||
//! (`src/common/rust/src/ffi.rs`; headers `include/common/*.h`). Only the
|
||||
//! families the facade wraps: config, videoparams, colortransform, xml
|
||||
@@ -27,316 +54,686 @@ use crate::handle::CHandle;
|
||||
pub type ConfigErrorHandler =
|
||||
Option<unsafe extern "C" fn(title: *const c_char, message: *const c_char, userdata: *mut c_void)>;
|
||||
|
||||
extern "C" {
|
||||
// ---- config.h -------------------------------------------------------
|
||||
/// `oakcommon_config_load` — reset to defaults, then read config.ini.
|
||||
pub fn oakcommon_config_load() -> c_int;
|
||||
/// `oakcommon_config_save` — write config.ini (temp file + rename).
|
||||
pub fn oakcommon_config_save() -> c_int;
|
||||
/// `oakcommon_config_reset_defaults` — drop custom keys.
|
||||
pub fn oakcommon_config_reset_defaults() -> c_int;
|
||||
/// `oakcommon_config_set` — set a string entry.
|
||||
pub fn oakcommon_config_set(group: *const c_char, key: *const c_char, value: *const c_char);
|
||||
/// `oakcommon_config_get` — read an entry as string (two-stage).
|
||||
pub fn oakcommon_config_get(
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_load() -> c_int {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_load() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_save() -> c_int {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_save() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_reset_defaults() -> c_int {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_reset_defaults() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_set(group: *const c_char, key: *const c_char, value: *const c_char) {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_set(group, key, value) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_get(
|
||||
group: *const c_char,
|
||||
key: *const c_char,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_config_get_int` — INT entry with fallback.
|
||||
pub fn oakcommon_config_get_int(group: *const c_char, key: *const c_char, fallback: c_int) -> c_int;
|
||||
/// `oakcommon_config_get_int64` — INT64 entry with fallback.
|
||||
pub fn oakcommon_config_get_int64(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_get(group, key, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_get_int(group: *const c_char, key: *const c_char, fallback: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_get_int(group, key, fallback) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_get_int64(
|
||||
group: *const c_char,
|
||||
key: *const c_char,
|
||||
fallback: i64,
|
||||
) -> i64;
|
||||
/// `oakcommon_config_get_double` — DOUBLE entry with fallback.
|
||||
pub fn oakcommon_config_get_double(group: *const c_char, key: *const c_char, fallback: f64) -> f64;
|
||||
/// `oakcommon_config_get_bool` — BOOL entry with fallback.
|
||||
pub fn oakcommon_config_get_bool(group: *const c_char, key: *const c_char, fallback: c_int) -> c_int;
|
||||
/// `oakcommon_config_set_int` — set an INT entry.
|
||||
pub fn oakcommon_config_set_int(group: *const c_char, key: *const c_char, value: c_int);
|
||||
/// `oakcommon_config_set_int64` — set an INT64 entry.
|
||||
pub fn oakcommon_config_set_int64(group: *const c_char, key: *const c_char, value: i64);
|
||||
/// `oakcommon_config_set_double` — set a DOUBLE entry.
|
||||
pub fn oakcommon_config_set_double(group: *const c_char, key: *const c_char, value: f64);
|
||||
/// `oakcommon_config_set_bool` — set a BOOL entry.
|
||||
pub fn oakcommon_config_set_bool(group: *const c_char, key: *const c_char, value: c_int);
|
||||
/// `oakcommon_config_entry_type` — the entry's declared type.
|
||||
pub fn oakcommon_config_entry_type(group: *const c_char, key: *const c_char) -> c_int;
|
||||
/// `oakcommon_config_set_error_handler` — install the UI error handler.
|
||||
pub fn oakcommon_config_set_error_handler(handler: ConfigErrorHandler, userdata: *mut c_void) -> c_int;
|
||||
) -> i64 {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_get_int64(group, key, fallback) }
|
||||
}
|
||||
|
||||
// ---- videoparams.h --------------------------------------------------
|
||||
/// `oakcommon_videoparams_init` — default video params, refcount 1.
|
||||
pub fn oakcommon_videoparams_init() -> CHandle;
|
||||
/// `oakcommon_videoparams_init_basic` — width/height/frame-rate params.
|
||||
pub fn oakcommon_videoparams_init_basic(
|
||||
width: c_int,
|
||||
height: c_int,
|
||||
time_base_num: c_int,
|
||||
time_base_den: c_int,
|
||||
) -> CHandle;
|
||||
/// `oakcommon_videoparams_init_with_time_base` — params + time base.
|
||||
pub fn oakcommon_videoparams_init_with_time_base(
|
||||
width: c_int,
|
||||
height: c_int,
|
||||
time_base_num: c_int,
|
||||
time_base_den: c_int,
|
||||
) -> CHandle;
|
||||
/// `oakcommon_videoparams_free` — NULL/empty no-op; clears `params->ctx`.
|
||||
pub fn oakcommon_videoparams_free(params: *mut CHandle);
|
||||
/// `oakcommon_videoparams_get_width`.
|
||||
pub fn oakcommon_videoparams_get_width(params: CHandle, width: *mut c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_set_width`.
|
||||
pub fn oakcommon_videoparams_set_width(params: CHandle, width: c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_get_height`.
|
||||
pub fn oakcommon_videoparams_get_height(params: CHandle, height: *mut c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_set_height`.
|
||||
pub fn oakcommon_videoparams_set_height(params: CHandle, height: c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_get_time_base`.
|
||||
pub fn oakcommon_videoparams_get_time_base(
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_get_double(group: *const c_char, key: *const c_char, fallback: f64) -> f64 {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_get_double(group, key, fallback) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_get_bool(group: *const c_char, key: *const c_char, fallback: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_get_bool(group, key, fallback) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_set_int(group: *const c_char, key: *const c_char, value: c_int) {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_set_int(group, key, value) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_set_int64(group: *const c_char, key: *const c_char, value: i64) {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_set_int64(group, key, value) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_set_double(group: *const c_char, key: *const c_char, value: f64) {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_set_double(group, key, value) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_set_bool(group: *const c_char, key: *const c_char, value: c_int) {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_set_bool(group, key, value) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_entry_type(group: *const c_char, key: *const c_char) -> c_int {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_entry_type(group, key) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_config_set_error_handler(handler: ConfigErrorHandler, userdata: *mut c_void) -> c_int {
|
||||
unsafe { oakcommon::ffi::config::oakcommon_config_set_error_handler(handler, userdata) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_init() -> CHandle {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_init() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_init_basic(
|
||||
width: c_int,
|
||||
height: c_int,
|
||||
pixel_format: c_int,
|
||||
nb_channels: c_int,
|
||||
pixel_aspect_num: c_int,
|
||||
pixel_aspect_den: c_int,
|
||||
interlacing: c_int,
|
||||
divider: c_int,
|
||||
) -> CHandle {
|
||||
unsafe {
|
||||
oakcommon::ffi::videoparams::oakcommon_videoparams_init_basic(
|
||||
width, height, pixel_format, nb_channels, pixel_aspect_num, pixel_aspect_den,
|
||||
interlacing, divider,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_init_with_time_base(
|
||||
width: c_int,
|
||||
height: c_int,
|
||||
time_base_num: c_int,
|
||||
time_base_den: c_int,
|
||||
pixel_format: c_int,
|
||||
nb_channels: c_int,
|
||||
pixel_aspect_num: c_int,
|
||||
pixel_aspect_den: c_int,
|
||||
interlacing: c_int,
|
||||
divider: c_int,
|
||||
) -> CHandle {
|
||||
unsafe {
|
||||
oakcommon::ffi::videoparams::oakcommon_videoparams_init_with_time_base(
|
||||
width, height, time_base_num, time_base_den, pixel_format, nb_channels,
|
||||
pixel_aspect_num, pixel_aspect_den, interlacing, divider,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_free(params: *mut CHandle) {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_free(params) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_width(params: CHandle, width: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_width(params, width) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_set_width(params: CHandle, width: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_set_width(params, width) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_height(params: CHandle, height: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_height(params, height) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_set_height(params: CHandle, height: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_set_height(params, height) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_time_base(
|
||||
params: CHandle,
|
||||
numerator: *mut c_int,
|
||||
denominator: *mut c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_videoparams_set_time_base`.
|
||||
pub fn oakcommon_videoparams_set_time_base(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_time_base(params, numerator, denominator) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_set_time_base(
|
||||
params: CHandle,
|
||||
numerator: c_int,
|
||||
denominator: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_videoparams_get_frame_rate`.
|
||||
pub fn oakcommon_videoparams_get_frame_rate(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_set_time_base(params, numerator, denominator) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_frame_rate(
|
||||
params: CHandle,
|
||||
numerator: *mut c_int,
|
||||
denominator: *mut c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_videoparams_set_frame_rate`.
|
||||
pub fn oakcommon_videoparams_set_frame_rate(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_frame_rate(params, numerator, denominator) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_set_frame_rate(
|
||||
params: CHandle,
|
||||
numerator: c_int,
|
||||
denominator: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_videoparams_get_pixel_aspect_ratio`.
|
||||
pub fn oakcommon_videoparams_get_pixel_aspect_ratio(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_set_frame_rate(params, numerator, denominator) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_pixel_aspect_ratio(
|
||||
params: CHandle,
|
||||
numerator: *mut c_int,
|
||||
denominator: *mut c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_videoparams_set_pixel_aspect_ratio`.
|
||||
pub fn oakcommon_videoparams_set_pixel_aspect_ratio(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_pixel_aspect_ratio(params, numerator, denominator) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_set_pixel_aspect_ratio(
|
||||
params: CHandle,
|
||||
numerator: c_int,
|
||||
denominator: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_videoparams_get_format`.
|
||||
pub fn oakcommon_videoparams_get_format(params: CHandle, format: *mut c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_set_format`.
|
||||
pub fn oakcommon_videoparams_set_format(params: CHandle, format: c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_get_interlacing`.
|
||||
pub fn oakcommon_videoparams_get_interlacing(params: CHandle, interlacing: *mut c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_set_interlacing`.
|
||||
pub fn oakcommon_videoparams_set_interlacing(params: CHandle, interlacing: c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_get_divider`.
|
||||
pub fn oakcommon_videoparams_get_divider(params: CHandle, divider: *mut c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_set_divider`.
|
||||
pub fn oakcommon_videoparams_set_divider(params: CHandle, divider: c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_get_video_type`.
|
||||
pub fn oakcommon_videoparams_get_video_type(params: CHandle, type_: *mut c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_set_video_type`.
|
||||
pub fn oakcommon_videoparams_set_video_type(params: CHandle, type_: c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_get_premultiplied_alpha`.
|
||||
pub fn oakcommon_videoparams_get_premultiplied_alpha(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_set_pixel_aspect_ratio(params, numerator, denominator) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_format(params: CHandle, format: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_format(params, format) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_set_format(params: CHandle, format: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_set_format(params, format) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_interlacing(params: CHandle, interlacing: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_interlacing(params, interlacing) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_set_interlacing(params: CHandle, interlacing: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_set_interlacing(params, interlacing) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_divider(params: CHandle, divider: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_divider(params, divider) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_set_divider(params: CHandle, divider: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_set_divider(params, divider) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_video_type(params: CHandle, type_: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_video_type(params, type_) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_set_video_type(params: CHandle, type_: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_set_video_type(params, type_) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_premultiplied_alpha(
|
||||
params: CHandle,
|
||||
premultiplied: *mut c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_videoparams_set_premultiplied_alpha`.
|
||||
pub fn oakcommon_videoparams_set_premultiplied_alpha(params: CHandle, premultiplied: c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_get_color_range`.
|
||||
pub fn oakcommon_videoparams_get_color_range(params: CHandle, color_range: *mut c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_set_color_range`.
|
||||
pub fn oakcommon_videoparams_set_color_range(params: CHandle, color_range: c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_get_is_valid`.
|
||||
pub fn oakcommon_videoparams_get_is_valid(params: CHandle, valid: *mut c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_get_effective_width` — divider-scaled width.
|
||||
pub fn oakcommon_videoparams_get_effective_width(params: CHandle, width: *mut c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_get_effective_height` — divider-scaled height.
|
||||
pub fn oakcommon_videoparams_get_effective_height(params: CHandle, height: *mut c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_get_bytes_per_pixel` — with the params' format.
|
||||
pub fn oakcommon_videoparams_get_bytes_per_pixel(params: CHandle, bytes: *mut c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_equals` — user-facing field equality.
|
||||
pub fn oakcommon_videoparams_equals(a: CHandle, b: CHandle, out_equal: *mut c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_format_is_float` — 1 when the format is float.
|
||||
pub fn oakcommon_videoparams_format_is_float(pixel_format: c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_get_format_name` — display name (two-stage).
|
||||
pub fn oakcommon_videoparams_get_format_name(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_premultiplied_alpha(params, premultiplied) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_set_premultiplied_alpha(params: CHandle, premultiplied: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_set_premultiplied_alpha(params, premultiplied) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_color_range(params: CHandle, color_range: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_color_range(params, color_range) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_set_color_range(params: CHandle, color_range: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_set_color_range(params, color_range) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_is_valid(params: CHandle, valid: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_is_valid(params, valid) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_effective_width(params: CHandle, width: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_effective_width(params, width) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_effective_height(params: CHandle, height: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_effective_height(params, height) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_bytes_per_pixel(params: CHandle, bytes: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_bytes_per_pixel(params, bytes) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_equals(a: CHandle, b: CHandle, out_equal: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_equals(a, b, out_equal) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_format_is_float(pixel_format: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_format_is_float(pixel_format) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_format_name(
|
||||
pixel_format: c_int,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_videoparams_frame_rate_to_string` — label (two-stage).
|
||||
pub fn oakcommon_videoparams_frame_rate_to_string(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_format_name(pixel_format, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_frame_rate_to_string(
|
||||
numerator: c_int,
|
||||
denominator: c_int,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_videoparams_get_name_for_divider` — label (two-stage).
|
||||
pub fn oakcommon_videoparams_get_name_for_divider(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_frame_rate_to_string(numerator, denominator, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_name_for_divider(
|
||||
divider: c_int,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_videoparams_get_scaled_dimension` — size at a divider.
|
||||
pub fn oakcommon_videoparams_get_scaled_dimension(dimension: c_int, divider: c_int) -> c_int;
|
||||
/// `oakcommon_videoparams_generate_auto_divider` — best divider for size.
|
||||
pub fn oakcommon_videoparams_generate_auto_divider(width: i64, height: i64) -> c_int;
|
||||
/// `oakcommon_videoparams_get_divider_for_target_resolution`.
|
||||
pub fn oakcommon_videoparams_get_divider_for_target_resolution(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_name_for_divider(divider, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_scaled_dimension(dimension: c_int, divider: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_scaled_dimension(dimension, divider) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_generate_auto_divider(width: i64, height: i64) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_generate_auto_divider(width, height) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_divider_for_target_resolution(
|
||||
src_width: c_int,
|
||||
src_height: c_int,
|
||||
target_width: c_int,
|
||||
target_height: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_videoparams_get_bytes_per_channel_for_format`.
|
||||
pub fn oakcommon_videoparams_get_bytes_per_channel_for_format(
|
||||
pixel_format: c_int,
|
||||
bytes: *mut c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_videoparams_get_bytes_per_pixel_for_format`.
|
||||
pub fn oakcommon_videoparams_get_bytes_per_pixel_for_format(
|
||||
pixel_format: c_int,
|
||||
bytes: *mut c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_videoparams_static_get_bytes_per_pixel`.
|
||||
pub fn oakcommon_videoparams_static_get_bytes_per_pixel(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_divider_for_target_resolution(src_width, src_height, target_width, target_height) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_bytes_per_channel_for_format(pixel_format: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_bytes_per_channel_for_format(pixel_format) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_bytes_per_pixel_for_format(
|
||||
pixel_format: c_int,
|
||||
channels: c_int,
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_bytes_per_pixel_for_format(pixel_format, channels) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_static_get_bytes_per_pixel(
|
||||
pixel_format: c_int,
|
||||
channels: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_videoparams_get_buffer_size`.
|
||||
pub fn oakcommon_videoparams_get_buffer_size(params: CHandle, bytes: *mut i64) -> c_int;
|
||||
/// `oakcommon_videoparams_get_time_in_timebase_units`.
|
||||
pub fn oakcommon_videoparams_get_time_in_timebase_units(
|
||||
params: CHandle,
|
||||
time_num: i64,
|
||||
time_den: i64,
|
||||
out: *mut i64,
|
||||
) -> c_int;
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_static_get_bytes_per_pixel(pixel_format, channels) }
|
||||
}
|
||||
|
||||
// ---- colortransform.h -----------------------------------------------
|
||||
/// `oakcommon_colortransform_init_output` — output color space transform.
|
||||
pub fn oakcommon_colortransform_init_output(output: *const c_char) -> CHandle;
|
||||
/// `oakcommon_colortransform_init_display` — display/view/look transform.
|
||||
pub fn oakcommon_colortransform_init_display(
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_buffer_size(params: CHandle, size: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_buffer_size(params, size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_videoparams_get_time_in_timebase_units(
|
||||
params: CHandle,
|
||||
time_num: c_int,
|
||||
time_den: c_int,
|
||||
timestamp: *mut i64,
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::videoparams::oakcommon_videoparams_get_time_in_timebase_units(params, time_num, time_den, timestamp) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_colortransform_init_output(output: *const c_char) -> CHandle {
|
||||
unsafe { oakcommon::ffi::colortransform::oakcommon_colortransform_init_output(output) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_colortransform_init_display(
|
||||
display: *const c_char,
|
||||
view: *const c_char,
|
||||
look: *const c_char,
|
||||
) -> CHandle;
|
||||
/// `oakcommon_colortransform_free` — NULL/empty no-op.
|
||||
pub fn oakcommon_colortransform_free(transform: *mut CHandle);
|
||||
/// `oakcommon_colortransform_is_display` — 1 for a display transform.
|
||||
pub fn oakcommon_colortransform_is_display(transform: CHandle) -> c_int;
|
||||
/// `oakcommon_colortransform_get_display` (two-stage string).
|
||||
pub fn oakcommon_colortransform_get_display(
|
||||
transform: CHandle,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_colortransform_get_output` (two-stage string).
|
||||
pub fn oakcommon_colortransform_get_output(
|
||||
transform: CHandle,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_colortransform_get_view` (two-stage string).
|
||||
pub fn oakcommon_colortransform_get_view(
|
||||
transform: CHandle,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_colortransform_get_look` (two-stage string).
|
||||
pub fn oakcommon_colortransform_get_look(
|
||||
transform: CHandle,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
) -> CHandle {
|
||||
unsafe { oakcommon::ffi::colortransform::oakcommon_colortransform_init_display(display, view, look) }
|
||||
}
|
||||
|
||||
// ---- xmlutils.h -----------------------------------------------------
|
||||
/// `oakcommon_xml_reader_init` — reader over a NUL-terminated document.
|
||||
pub fn oakcommon_xml_reader_init(data: *const c_char) -> CHandle;
|
||||
/// `oakcommon_xml_reader_free` — NULL/empty no-op.
|
||||
pub fn oakcommon_xml_reader_free(reader: *mut CHandle);
|
||||
/// `oakcommon_xml_reader_read_next_start_element` — found 1/0 in `found`.
|
||||
pub fn oakcommon_xml_reader_read_next_start_element(reader: CHandle, found: *mut c_int) -> c_int;
|
||||
/// `oakcommon_xml_reader_name` (two-stage string).
|
||||
pub fn oakcommon_xml_reader_name(reader: CHandle, buf: *mut c_char, buf_size: c_int) -> c_int;
|
||||
/// `oakcommon_xml_reader_read_element_text` (two-stage string).
|
||||
pub fn oakcommon_xml_reader_read_element_text(
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_colortransform_free(transform: *mut CHandle) {
|
||||
unsafe { oakcommon::ffi::colortransform::oakcommon_colortransform_free(transform) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_colortransform_is_display(transform: CHandle) -> c_int {
|
||||
unsafe { oakcommon::ffi::colortransform::oakcommon_colortransform_is_display(transform) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_colortransform_get_display(
|
||||
transform: CHandle,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::colortransform::oakcommon_colortransform_get_display(transform, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_colortransform_get_output(
|
||||
transform: CHandle,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::colortransform::oakcommon_colortransform_get_output(transform, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_colortransform_get_view(
|
||||
transform: CHandle,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::colortransform::oakcommon_colortransform_get_view(transform, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_colortransform_get_look(
|
||||
transform: CHandle,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::colortransform::oakcommon_colortransform_get_look(transform, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_reader_init(data: *const c_char) -> CHandle {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_reader_init(data) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_reader_free(reader: *mut CHandle) {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_reader_free(reader) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_reader_read_next_start_element(reader: CHandle, found: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_reader_read_next_start_element(reader, found) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_reader_name(reader: CHandle, buf: *mut c_char, buf_size: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_reader_name(reader, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_reader_read_element_text(
|
||||
reader: CHandle,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_xml_reader_skip_current_element`.
|
||||
pub fn oakcommon_xml_reader_skip_current_element(reader: CHandle) -> c_int;
|
||||
/// `oakcommon_xml_reader_attribute_count`.
|
||||
pub fn oakcommon_xml_reader_attribute_count(reader: CHandle, count: *mut c_int) -> c_int;
|
||||
/// `oakcommon_xml_reader_attribute_name` (two-stage string).
|
||||
pub fn oakcommon_xml_reader_attribute_name(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_reader_read_element_text(reader, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_reader_skip_current_element(reader: CHandle) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_reader_skip_current_element(reader) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_reader_attribute_count(reader: CHandle, count: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_reader_attribute_count(reader, count) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_reader_attribute_name(
|
||||
reader: CHandle,
|
||||
index: c_int,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_xml_reader_attribute_value` (two-stage string).
|
||||
pub fn oakcommon_xml_reader_attribute_value(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_reader_attribute_name(reader, index, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_reader_attribute_value(
|
||||
reader: CHandle,
|
||||
index: c_int,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakcommon_xml_reader_has_error`.
|
||||
pub fn oakcommon_xml_reader_has_error(reader: CHandle, has_error: *mut c_int) -> c_int;
|
||||
/// `oakcommon_xml_writer_init` — fresh writer.
|
||||
pub fn oakcommon_xml_writer_init() -> CHandle;
|
||||
/// `oakcommon_xml_writer_free` — NULL/empty no-op.
|
||||
pub fn oakcommon_xml_writer_free(writer: *mut CHandle);
|
||||
/// `oakcommon_xml_writer_write_start_element`.
|
||||
pub fn oakcommon_xml_writer_write_start_element(writer: CHandle, name: *const c_char) -> c_int;
|
||||
/// `oakcommon_xml_writer_write_attribute`.
|
||||
pub fn oakcommon_xml_writer_write_attribute(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_reader_attribute_value(reader, index, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_reader_has_error(reader: CHandle, has_error: *mut c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_reader_has_error(reader, has_error) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_writer_init() -> CHandle {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_writer_init() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_writer_free(writer: *mut CHandle) {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_writer_free(writer) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_writer_write_start_element(writer: CHandle, name: *const c_char) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_writer_write_start_element(writer, name) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_writer_write_attribute(
|
||||
writer: CHandle,
|
||||
name: *const c_char,
|
||||
value: *const c_char,
|
||||
) -> c_int;
|
||||
/// `oakcommon_xml_writer_write_characters`.
|
||||
pub fn oakcommon_xml_writer_write_characters(writer: CHandle, text: *const c_char) -> c_int;
|
||||
/// `oakcommon_xml_writer_write_text_element`.
|
||||
pub fn oakcommon_xml_writer_write_text_element(
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_writer_write_attribute(writer, name, value) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_writer_write_characters(writer: CHandle, text: *const c_char) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_writer_write_characters(writer, text) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_writer_write_text_element(
|
||||
writer: CHandle,
|
||||
name: *const c_char,
|
||||
text: *const c_char,
|
||||
) -> c_int;
|
||||
/// `oakcommon_xml_writer_write_end_element`.
|
||||
pub fn oakcommon_xml_writer_write_end_element(writer: CHandle) -> c_int;
|
||||
/// `oakcommon_xml_writer_write_end_document`.
|
||||
pub fn oakcommon_xml_writer_write_end_document(writer: CHandle) -> c_int;
|
||||
/// `oakcommon_xml_writer_output` (two-stage string).
|
||||
pub fn oakcommon_xml_writer_output(writer: CHandle, buf: *mut c_char, buf_size: c_int) -> c_int;
|
||||
|
||||
// ---- decibel helpers -------------------------------------------------
|
||||
/// `oakcommon_decibel_from_linear` — linear amplitude to decibels.
|
||||
pub fn oakcommon_decibel_from_linear(linear: f64, out_db: *mut f64) -> c_int;
|
||||
/// `oakcommon_decibel_to_linear` — decibels to linear amplitude.
|
||||
pub fn oakcommon_decibel_to_linear(db: f64, out_linear: *mut f64) -> c_int;
|
||||
/// `oakcommon_decibel_from_logarithmic` — slider position to decibels.
|
||||
pub fn oakcommon_decibel_from_logarithmic(logarithmic: f64, out_db: *mut f64) -> c_int;
|
||||
/// `oakcommon_decibel_to_logarithmic` — decibels to slider position.
|
||||
pub fn oakcommon_decibel_to_logarithmic(db: f64, out_logarithmic: *mut f64) -> c_int;
|
||||
/// `oakcommon_decibel_linear_to_logarithmic`.
|
||||
pub fn oakcommon_decibel_linear_to_logarithmic(linear: f64, out_logarithmic: *mut f64) -> c_int;
|
||||
/// `oakcommon_decibel_logarithmic_to_linear`.
|
||||
pub fn oakcommon_decibel_logarithmic_to_linear(logarithmic: f64, out_linear: *mut f64) -> c_int;
|
||||
) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_writer_write_text_element(writer, name, text) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_writer_write_end_element(writer: CHandle) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_writer_write_end_element(writer) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_writer_write_end_document(writer: CHandle) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_writer_write_end_document(writer) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_xml_writer_output(writer: CHandle, buf: *mut c_char, buf_size: c_int) -> c_int {
|
||||
unsafe { oakcommon::ffi::xmlutils::oakcommon_xml_writer_output(writer, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_decibel_from_linear(linear: f64, out_db: *mut f64) -> c_int {
|
||||
unsafe { oakcommon::ffi::misc::oakcommon_decibel_from_linear(linear, out_db) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_decibel_to_linear(db: f64, out_linear: *mut f64) -> c_int {
|
||||
unsafe { oakcommon::ffi::misc::oakcommon_decibel_to_linear(db, out_linear) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_decibel_from_logarithmic(logarithmic: f64, out_db: *mut f64) -> c_int {
|
||||
unsafe { oakcommon::ffi::misc::oakcommon_decibel_from_logarithmic(logarithmic, out_db) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_decibel_to_logarithmic(db: f64, out_logarithmic: *mut f64) -> c_int {
|
||||
unsafe { oakcommon::ffi::misc::oakcommon_decibel_to_logarithmic(db, out_logarithmic) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_decibel_linear_to_logarithmic(linear: f64, out_logarithmic: *mut f64) -> c_int {
|
||||
unsafe { oakcommon::ffi::misc::oakcommon_decibel_linear_to_logarithmic(linear, out_logarithmic) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakcommon` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakcommon_decibel_logarithmic_to_linear(logarithmic: f64, out_linear: *mut f64) -> c_int {
|
||||
unsafe { oakcommon::ffi::misc::oakcommon_decibel_logarithmic_to_linear(logarithmic, out_linear) }
|
||||
}
|
||||
|
||||
|
||||
+2138
-749
File diff suppressed because it is too large
Load Diff
@@ -14,21 +14,65 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! oakplugin C ABI bridge: direct Rust calls into the `oakplugin` crate.
|
||||
//!
|
||||
//! Single-lib unification (see `docs/zh/plans/riir/single-lib.md`): every
|
||||
//! call below is a compile-time Rust call into `oakplugin`'s `ffi` (the
|
||||
//! `#[no_mangle]` exports stay in the dylib for the external C ABI;
|
||||
//! internal callers bypass them). Handles cross as the shared
|
||||
//! [`crate::handle::CHandle`]. Exceptions that keep an `extern "C"`
|
||||
//! declaration (resolved at link time against the sibling crate in the
|
||||
//! same dylib) are the host `oakcore_*` symbols and the encoding-params
|
||||
//! C ABI POD crossings (the facade keeps its own POD mirrors there).
|
||||
|
||||
// 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/>.
|
||||
|
||||
//! oakplugin C ABI imports, mirroring the oakplugin crate's exports
|
||||
//! (`src/plugin/rust/src/ffi.rs`; headers `include/plugin/*.h`).
|
||||
|
||||
use std::ffi::{c_char, c_int};
|
||||
|
||||
extern "C" {
|
||||
/// `oakplugin_host_scan` — scan bundle directories (NULL/0 uses the
|
||||
/// default path set).
|
||||
pub fn oakplugin_host_scan(bundle_dirs: *const *const c_char, dir_count: c_int) -> c_int;
|
||||
/// `oakplugin_host_init` — initialize the OFX host (idempotent).
|
||||
pub fn oakplugin_host_init() -> c_int;
|
||||
/// `oakplugin_host_plugin_count` — number of discovered plugins.
|
||||
pub fn oakplugin_host_plugin_count() -> c_int;
|
||||
/// `oakplugin_host_plugin_id_at` — plugin id at index (two-stage).
|
||||
pub fn oakplugin_host_plugin_id_at(index: c_int, buf: *mut c_char, buf_size: c_int) -> c_int;
|
||||
/// `oakplugin_host_plugin_label` — label for an id (two-stage).
|
||||
pub fn oakplugin_host_plugin_label(plugin_id: *const c_char, buf: *mut c_char, buf_size: c_int) -> c_int;
|
||||
/// Direct call into the `oakplugin` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakplugin_host_scan(bundle_dirs: *const *const c_char, dir_count: c_int) -> c_int {
|
||||
unsafe { oakplugin::ffi::oakplugin_host_scan(bundle_dirs, dir_count) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakplugin` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakplugin_host_init() -> c_int {
|
||||
unsafe { oakplugin::ffi::oakplugin_host_init() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakplugin` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakplugin_host_plugin_count() -> c_int {
|
||||
unsafe { oakplugin::ffi::oakplugin_host_plugin_count() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakplugin` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakplugin_host_plugin_id_at(index: c_int, buf: *mut c_char, buf_size: c_int) -> c_int {
|
||||
unsafe { oakplugin::ffi::oakplugin_host_plugin_id_at(index, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakplugin` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakplugin_host_plugin_label(plugin_id: *const c_char, buf: *mut c_char, buf_size: c_int) -> c_int {
|
||||
unsafe { oakplugin::ffi::oakplugin_host_plugin_label(plugin_id, buf, buf_size) }
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,33 @@
|
||||
// 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 bridge: direct Rust calls into the `oakrender` crate.
|
||||
//!
|
||||
//! Single-lib unification (see `docs/zh/plans/riir/single-lib.md`): every
|
||||
//! call below is a compile-time Rust call into `oakrender`'s `ffi` (the
|
||||
//! `#[no_mangle]` exports stay in the dylib for the external C ABI;
|
||||
//! internal callers bypass them). Handles cross as the shared
|
||||
//! [`crate::handle::CHandle`]. Exceptions that keep an `extern "C"`
|
||||
//! declaration (resolved at link time against the sibling crate in the
|
||||
//! same dylib) are the host `oakcore_*` symbols and the encoding-params
|
||||
//! C ABI POD crossings (the facade keeps its own POD mirrors there).
|
||||
|
||||
// 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, mirroring the oakrender crate's exports
|
||||
//! (`src/render/rust/src/ffi.rs`; headers `include/render/*.h`).
|
||||
|
||||
@@ -21,110 +48,84 @@ use std::ffi::{c_char, c_double, c_int, c_void};
|
||||
|
||||
use crate::handle::CHandle;
|
||||
|
||||
/// `include/render/ticket.h` — video render ticket params mirror. All
|
||||
/// handle fields are [`CHandle`] (borrowed unless noted).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct OakVideoTicketParams {
|
||||
/// Connected texture output node (borrowed).
|
||||
pub output_node: CHandle,
|
||||
/// By-value oakcommon video-params handle.
|
||||
pub video_params: CHandle,
|
||||
/// Borrowed oakcore audio-params handle, may be null.
|
||||
pub audio_params: *const c_void,
|
||||
/// Frame timestamp numerator.
|
||||
pub time_num: i64,
|
||||
/// Frame timestamp denominator.
|
||||
pub time_den: i64,
|
||||
/// Borrowed color manager, empty ctx = null.
|
||||
pub color_manager: CHandle,
|
||||
/// RenderMode::Mode as int.
|
||||
pub mode: c_int,
|
||||
/// 0/0 = off.
|
||||
pub force_width: c_int,
|
||||
/// 0/0 = off.
|
||||
pub force_height: c_int,
|
||||
/// Used when has_force_matrix != 0.
|
||||
pub force_matrix: [c_double; 16],
|
||||
/// 0/1.
|
||||
pub has_force_matrix: c_int,
|
||||
/// PixelFormat as int, -1 = off.
|
||||
pub force_format: c_int,
|
||||
/// 0 = off.
|
||||
pub force_channel_count: c_int,
|
||||
/// Borrowed; empty ctx = none.
|
||||
pub force_color_output: CHandle,
|
||||
/// By value; empty ctx = default.
|
||||
pub force_color_transform: CHandle,
|
||||
/// Borrowed frame cache; empty ctx = none.
|
||||
pub cache: CHandle,
|
||||
}
|
||||
/// `include/render/ticket.h` — video render ticket params. Single-lib
|
||||
/// unification: aliases the oakrender crate's POD (same `repr(C)`
|
||||
/// layout; all handle fields are the shared [`CHandle`]).
|
||||
pub type OakVideoTicketParams = oakrender::ffi::OakVideoTicketParams;
|
||||
|
||||
|
||||
/// `include/render/renderer.h` — frame video-params POD returned by
|
||||
/// `oakrender_codec_frame_get_params`.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct OakRenderVideoParams {
|
||||
/// Width.
|
||||
pub width: c_int,
|
||||
/// Height.
|
||||
pub height: c_int,
|
||||
/// Frame duration numerator.
|
||||
pub time_base_num: c_int,
|
||||
/// Frame duration denominator.
|
||||
pub time_base_den: c_int,
|
||||
/// PixelFormat as int.
|
||||
pub format: c_int,
|
||||
/// Pixel aspect numerator.
|
||||
pub pixel_aspect_num: c_int,
|
||||
/// Pixel aspect denominator.
|
||||
pub pixel_aspect_den: c_int,
|
||||
/// Interlacing as int.
|
||||
pub interlacing: c_int,
|
||||
/// Color range as int.
|
||||
pub color_range: c_int,
|
||||
/// Preview divider.
|
||||
pub divider: c_int,
|
||||
/// Video type.
|
||||
pub video_type: c_int,
|
||||
/// Premultiplied alpha 0/1.
|
||||
pub premultiplied_alpha: c_int,
|
||||
/// `oakrender_codec_frame_get_params`. Single-lib unification: aliases
|
||||
/// the oakrender crate's POD.
|
||||
pub type OakRenderVideoParams = oakrender::ffi::OakRenderVideoParams;
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_display_renderer_create_dynamic(backend_id: *const c_char) -> CHandle {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_display_renderer_create_dynamic(backend_id) }
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
// ---- display renderer --------------------------------------------------
|
||||
/// `oakrender_display_renderer_create_dynamic` — named backend
|
||||
/// ("opengl", "vulkan", "metal", "auto", ...).
|
||||
pub fn oakrender_display_renderer_create_dynamic(backend_id: *const c_char) -> CHandle;
|
||||
/// `oakrender_display_renderer_create_opengl` — direct OpenGL renderer.
|
||||
pub fn oakrender_display_renderer_create_opengl() -> CHandle;
|
||||
/// `oakrender_display_renderer_init` — NULL gl_context uses the
|
||||
/// backend's default device/context path.
|
||||
pub fn oakrender_display_renderer_init(renderer: CHandle, gl_context: *mut c_void) -> c_int;
|
||||
/// `oakrender_display_renderer_destroy` — NULL/empty no-op.
|
||||
pub fn oakrender_display_renderer_destroy(renderer: *mut CHandle);
|
||||
/// `oakrender_display_renderer_is_open_gl` — 1/0.
|
||||
pub fn oakrender_display_renderer_is_open_gl(renderer: CHandle) -> c_int;
|
||||
/// `oakrender_display_renderer_is_vulkan` — 1/0.
|
||||
pub fn oakrender_display_renderer_is_vulkan(renderer: CHandle) -> c_int;
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_display_renderer_create_opengl() -> CHandle {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_display_renderer_create_opengl() }
|
||||
}
|
||||
|
||||
// ---- render manager -----------------------------------------------------
|
||||
/// `oakrender_manager_set_aggressive_gc`.
|
||||
pub fn oakrender_manager_set_aggressive_gc(enabled: c_int) -> c_int;
|
||||
/// `oakrender_set_cacher_multicam` — NULL clears.
|
||||
pub fn oakrender_set_cacher_multicam(multicam_or_null: CHandle) -> c_int;
|
||||
/// `oakrender_set_display_color_processor` — NULL clears.
|
||||
pub fn oakrender_set_display_color_processor(p_or_null: CHandle) -> c_int;
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_display_renderer_init(renderer: CHandle, gl_context: *mut c_void) -> c_int {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_display_renderer_init(renderer, gl_context) }
|
||||
}
|
||||
|
||||
// ---- render tickets -----------------------------------------------------
|
||||
/// `oakrender_ticket_render_frame`.
|
||||
pub fn oakrender_ticket_render_frame(
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_display_renderer_destroy(renderer: *mut CHandle) {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_display_renderer_destroy(renderer) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_display_renderer_is_open_gl(renderer: CHandle) -> c_int {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_display_renderer_is_open_gl(renderer) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_display_renderer_is_vulkan(renderer: CHandle) -> c_int {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_display_renderer_is_vulkan(renderer) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
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; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_set_cacher_multicam(multicam_or_null: CHandle) -> c_int {
|
||||
unsafe { oakrender::ffi::manager::oakrender_set_cacher_multicam(multicam_or_null) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_set_display_color_processor(p_or_null: CHandle) -> c_int {
|
||||
unsafe { oakrender::ffi::manager::oakrender_set_display_color_processor(p_or_null) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_ticket_render_frame(
|
||||
params: *const OakVideoTicketParams,
|
||||
cb: Option<unsafe extern "C" fn(CHandle, *mut c_void)>,
|
||||
userdata: *mut c_void,
|
||||
) -> CHandle;
|
||||
/// `oakrender_ticket_render_audio`.
|
||||
pub fn oakrender_ticket_render_audio(
|
||||
) -> CHandle {
|
||||
unsafe { oakrender::ffi::ticket::oakrender_ticket_render_frame(params, cb, userdata) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_ticket_render_audio(
|
||||
output_node: CHandle,
|
||||
in_num: i64,
|
||||
in_den: i64,
|
||||
@@ -134,61 +135,141 @@ extern "C" {
|
||||
mode: c_int,
|
||||
cb: Option<unsafe extern "C" fn(CHandle, *mut c_void)>,
|
||||
userdata: *mut c_void,
|
||||
) -> CHandle;
|
||||
/// `oakrender_ticket_wait` — block until finished.
|
||||
pub fn oakrender_ticket_wait(ticket: CHandle) -> c_int;
|
||||
/// `oakrender_ticket_cancel`.
|
||||
pub fn oakrender_ticket_cancel(ticket: CHandle) -> c_int;
|
||||
/// `oakrender_ticket_get_frame` — `*out` receives an owned copy.
|
||||
pub fn oakrender_ticket_get_frame(ticket: CHandle, out: *mut CHandle) -> c_int;
|
||||
/// `oakrender_ticket_get_samples` — audio not implemented in the crate.
|
||||
pub fn oakrender_ticket_get_samples(ticket: CHandle, out: *mut *mut c_void) -> c_int;
|
||||
/// `oakrender_ticket_free` — NULL/empty no-op.
|
||||
pub fn oakrender_ticket_free(ticket: *mut CHandle);
|
||||
) -> CHandle {
|
||||
unsafe {
|
||||
oakrender::ffi::ticket::oakrender_ticket_render_audio(
|
||||
output_node, in_num, in_den, out_num, out_den, params as *const CHandle, mode, cb,
|
||||
userdata,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ---- codec frame --------------------------------------------------------
|
||||
/// `oakrender_codec_frame_create` — refcount 1.
|
||||
pub fn oakrender_codec_frame_create() -> CHandle;
|
||||
/// `oakrender_codec_frame_retain` — addref, return copy.
|
||||
pub fn oakrender_codec_frame_retain(frame: CHandle) -> CHandle;
|
||||
/// `oakrender_codec_frame_free` — NULL/empty no-op.
|
||||
pub fn oakrender_codec_frame_free(frame: *mut CHandle);
|
||||
/// `oakrender_codec_frame_width`.
|
||||
pub fn oakrender_codec_frame_width(frame: CHandle) -> c_int;
|
||||
/// `oakrender_codec_frame_height`.
|
||||
pub fn oakrender_codec_frame_height(frame: CHandle) -> c_int;
|
||||
/// `oakrender_codec_frame_linesize_bytes`.
|
||||
pub fn oakrender_codec_frame_linesize_bytes(frame: CHandle) -> c_int;
|
||||
/// `oakrender_codec_frame_data` — borrowed.
|
||||
pub fn oakrender_codec_frame_data(frame: CHandle) -> *mut c_void;
|
||||
/// `oakrender_codec_frame_const_data` — borrowed.
|
||||
pub fn oakrender_codec_frame_const_data(frame: CHandle) -> *const c_void;
|
||||
/// `oakrender_codec_frame_is_allocated`.
|
||||
pub fn oakrender_codec_frame_is_allocated(frame: CHandle) -> c_int;
|
||||
/// `oakrender_codec_frame_get_params` — fills the params POD.
|
||||
pub fn oakrender_codec_frame_get_params(frame: CHandle, out: *mut OakRenderVideoParams) -> c_int;
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_ticket_wait(ticket: CHandle) -> c_int {
|
||||
unsafe { oakrender::ffi::ticket::oakrender_ticket_wait(ticket) }
|
||||
}
|
||||
|
||||
// ---- color processor ----------------------------------------------------
|
||||
/// `oakrender_color_processor_create`.
|
||||
pub fn oakrender_color_processor_create(
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_ticket_cancel(ticket: CHandle) -> c_int {
|
||||
unsafe { oakrender::ffi::ticket::oakrender_ticket_cancel(ticket) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_ticket_get_frame(ticket: CHandle, out: *mut CHandle) -> c_int {
|
||||
unsafe { oakrender::ffi::ticket::oakrender_ticket_get_frame(ticket, out) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_ticket_get_samples(ticket: CHandle, out: *mut *mut c_void) -> c_int {
|
||||
unsafe { oakrender::ffi::ticket::oakrender_ticket_get_samples(ticket, out) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_ticket_free(ticket: *mut CHandle) {
|
||||
unsafe { oakrender::ffi::ticket::oakrender_ticket_free(ticket) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_codec_frame_create() -> CHandle {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_codec_frame_create() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_codec_frame_retain(frame: CHandle) -> CHandle {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_codec_frame_retain(frame) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_codec_frame_free(frame: *mut CHandle) {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_codec_frame_free(frame) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_codec_frame_width(frame: CHandle) -> c_int {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_codec_frame_width(frame) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_codec_frame_height(frame: CHandle) -> c_int {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_codec_frame_height(frame) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_codec_frame_linesize_bytes(frame: CHandle) -> c_int {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_codec_frame_linesize_bytes(frame) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_codec_frame_data(frame: CHandle) -> *mut c_void {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_codec_frame_data(frame) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_codec_frame_const_data(frame: CHandle) -> *const c_void {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_codec_frame_const_data(frame) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_codec_frame_is_allocated(frame: CHandle) -> c_int {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_codec_frame_is_allocated(frame) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_codec_frame_get_params(frame: CHandle, out: *mut OakRenderVideoParams) -> c_int {
|
||||
unsafe { oakrender::ffi::renderer::oakrender_codec_frame_get_params(frame, out) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_color_processor_create(
|
||||
src_space: *const c_char,
|
||||
dst_transform: *const c_char,
|
||||
direction: c_int,
|
||||
) -> CHandle;
|
||||
/// `oakrender_color_processor_free` — NULL/empty no-op.
|
||||
pub fn oakrender_color_processor_free(processor: *mut CHandle);
|
||||
/// `oakrender_color_processor_is_valid`.
|
||||
pub fn oakrender_color_processor_is_valid(processor: CHandle) -> c_int;
|
||||
/// `oakrender_color_processor_create_transform` — manager + input +
|
||||
/// oakcommon colortransform handle + direction.
|
||||
pub fn oakrender_color_processor_create_transform(
|
||||
) -> CHandle {
|
||||
unsafe { oakrender::ffi::color::oakrender_color_processor_create(src_space, dst_transform, direction) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_color_processor_free(processor: *mut CHandle) {
|
||||
unsafe { oakrender::ffi::color::oakrender_color_processor_free(processor) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_color_processor_is_valid(processor: CHandle) -> c_int {
|
||||
unsafe { oakrender::ffi::color::oakrender_color_processor_is_valid(processor) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_color_processor_create_transform(
|
||||
manager: CHandle,
|
||||
input: *const c_char,
|
||||
dest: CHandle,
|
||||
direction: c_int,
|
||||
) -> CHandle;
|
||||
/// `oakrender_color_processor_convert` — single RGBA color.
|
||||
pub fn oakrender_color_processor_convert(
|
||||
) -> CHandle {
|
||||
unsafe { oakrender::ffi::color::oakrender_color_processor_create_transform(manager, input, dest, direction) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_color_processor_convert(
|
||||
processor: CHandle,
|
||||
ir: c_double,
|
||||
ig: c_double,
|
||||
@@ -198,19 +279,37 @@ extern "C" {
|
||||
out_g: *mut c_double,
|
||||
out_b: *mut c_double,
|
||||
out_a: *mut c_double,
|
||||
) -> c_int;
|
||||
|
||||
// ---- color manager ------------------------------------------------------
|
||||
/// `oakrender_color_manager_set_up_default_config`.
|
||||
pub fn oakrender_color_manager_set_up_default_config() -> c_int;
|
||||
/// `oakrender_color_manager_get_config` (two-stage).
|
||||
pub fn oakrender_color_manager_get_config(buf: *mut c_char, n: c_int) -> c_int;
|
||||
|
||||
// ---- LUT extension enumeration ------------------------------------------
|
||||
/// `oakrender_lut_is_supported_extension`.
|
||||
pub fn oakrender_lut_is_supported_extension(extension: *const c_char) -> c_int;
|
||||
/// `oakrender_lut_supported_extensions_count`.
|
||||
pub fn oakrender_lut_supported_extensions_count() -> c_int;
|
||||
/// `oakrender_lut_supported_extension_at` (two-stage).
|
||||
pub fn oakrender_lut_supported_extension_at(i: c_int, buf: *mut c_char, n: c_int) -> c_int;
|
||||
) -> c_int {
|
||||
unsafe { oakrender::ffi::color::oakrender_color_processor_convert(processor, ir, ig, ib, ia, out_r, out_g, out_b, out_a) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_color_manager_set_up_default_config() -> c_int {
|
||||
unsafe { oakrender::ffi::color::oakrender_color_manager_set_up_default_config() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_color_manager_get_config(buf: *mut c_char, n: c_int) -> c_int {
|
||||
unsafe { oakrender::ffi::color::oakrender_color_manager_get_config(buf, n) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_lut_is_supported_extension(extension: *const c_char) -> c_int {
|
||||
unsafe { oakrender::ffi::color::oakrender_lut_is_supported_extension(extension) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_lut_supported_extensions_count() -> c_int {
|
||||
unsafe { oakrender::ffi::color::oakrender_lut_supported_extensions_count() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakrender` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakrender_lut_supported_extension_at(i: c_int, buf: *mut c_char, n: c_int) -> c_int {
|
||||
unsafe { oakrender::ffi::color::oakrender_lut_supported_extension_at(i, buf, n) }
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,33 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! oaktask C ABI bridge: direct Rust calls into the `oaktask` crate.
|
||||
//!
|
||||
//! Single-lib unification (see `docs/zh/plans/riir/single-lib.md`): every
|
||||
//! call below is a compile-time Rust call into `oaktask`'s `ffi` (the
|
||||
//! `#[no_mangle]` exports stay in the dylib for the external C ABI;
|
||||
//! internal callers bypass them). Handles cross as the shared
|
||||
//! [`crate::handle::CHandle`]. Exceptions that keep an `extern "C"`
|
||||
//! declaration (resolved at link time against the sibling crate in the
|
||||
//! same dylib) are the host `oakcore_*` symbols and the encoding-params
|
||||
//! C ABI POD crossings (the facade keeps its own POD mirrors there).
|
||||
|
||||
// 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/>.
|
||||
|
||||
//! oaktask C ABI imports, mirroring the oaktask crate's exports
|
||||
//! (`src/task/rust/src/ffi/{manager,task,project}.rs`; headers
|
||||
//! `include/task/*.h`).
|
||||
@@ -41,81 +68,217 @@ pub type OakTaskOtioImportConfirmFn =
|
||||
pub type OakTaskImageSequenceConfirmFn =
|
||||
unsafe extern "C" fn(filename: *const c_char, userdata: *mut c_void) -> c_int;
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_manager_init() -> c_int {
|
||||
unsafe { oaktask::ffi::manager::oaktask_manager_init() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_manager_shutdown() {
|
||||
unsafe { oaktask::ffi::manager::oaktask_manager_shutdown() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_register_codec_submitter() -> c_int {
|
||||
unsafe { oaktask::ffi::manager::oaktask_register_codec_submitter() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_manager_count() -> c_int {
|
||||
unsafe { oaktask::ffi::manager::oaktask_manager_count() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_manager_at(i: c_int) -> CHandle {
|
||||
unsafe { oaktask::ffi::manager::oaktask_manager_at(i) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_manager_delete_finished() {
|
||||
unsafe { oaktask::ffi::manager::oaktask_manager_delete_finished() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_task_free(t: *mut CHandle) {
|
||||
unsafe { oaktask::ffi::task::oaktask_task_free(t) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_task_start_sync(t: CHandle) -> c_int {
|
||||
unsafe { oaktask::ffi::task::oaktask_task_start_sync(t) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_task_start(t: CHandle) -> c_int {
|
||||
unsafe { oaktask::ffi::task::oaktask_task_start(t) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_task_cancel(t: CHandle) -> c_int {
|
||||
unsafe { oaktask::ffi::task::oaktask_task_cancel(t) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_task_wait(t: CHandle) -> c_int {
|
||||
unsafe { oaktask::ffi::task::oaktask_task_wait(t) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_task_is_finished(t: CHandle) -> c_int {
|
||||
unsafe { oaktask::ffi::task::oaktask_task_is_finished(t) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_task_succeeded(t: CHandle) -> c_int {
|
||||
unsafe { oaktask::ffi::task::oaktask_task_succeeded(t) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_task_title(t: CHandle, buf: *mut c_char, buf_size: c_int) -> c_int {
|
||||
unsafe { oaktask::ffi::task::oaktask_task_title(t, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_task_error(t: CHandle, buf: *mut c_char, buf_size: c_int) -> c_int {
|
||||
unsafe { oaktask::ffi::task::oaktask_task_error(t, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_task_subscribe(t: CHandle, cb: Option<OakTaskEventFn>, userdata: *mut c_void) -> i64 {
|
||||
unsafe { oaktask::ffi::task::oaktask_task_subscribe(t, cb, userdata) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_debug_alive_count() -> c_int {
|
||||
unsafe { oaktask::ffi::task::oaktask_debug_alive_count() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_create_project_load(filename: *const c_char) -> CHandle {
|
||||
unsafe { oaktask::ffi::project::oaktask_create_project_load(filename) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_load_take_project(t: CHandle) -> CHandle {
|
||||
unsafe { oaktask::ffi::project::oaktask_load_take_project(t) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_create_project_save(project: CHandle, filename_or_null: *const c_char, use_compression: c_int) -> CHandle {
|
||||
unsafe { oaktask::ffi::project::oaktask_create_project_save(project, filename_or_null, use_compression) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_create_project_import(folder: CHandle, project: CHandle, urls: *const *const c_char, url_count: c_int) -> CHandle {
|
||||
unsafe { oaktask::ffi::project::oaktask_create_project_import(folder, project, urls, url_count) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_import_take_command(t: CHandle) -> CHandle {
|
||||
unsafe { oaktask::ffi::project::oaktask_import_take_command(t) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_import_footage_count(t: CHandle) -> c_int {
|
||||
unsafe { oaktask::ffi::project::oaktask_import_footage_count(t) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_import_footage_at(t: CHandle, index: c_int) -> CHandle {
|
||||
unsafe { oaktask::ffi::project::oaktask_import_footage_at(t, index) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_import_invalid_count(t: CHandle) -> c_int {
|
||||
unsafe { oaktask::ffi::project::oaktask_import_invalid_count(t) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_import_invalid_at(t: CHandle, index: c_int, buf: *mut c_char, buf_size: c_int) -> c_int {
|
||||
unsafe { oaktask::ffi::project::oaktask_import_invalid_at(t, index, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_create_project_load_otio(filename: *const c_char) -> CHandle {
|
||||
unsafe { oaktask::ffi::project::oaktask_create_project_load_otio(filename) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_load_otio_take_project(t: CHandle) -> CHandle {
|
||||
unsafe { oaktask::ffi::project::oaktask_load_otio_take_project(t) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_create_project_save_otio(project: CHandle, filename: *const c_char) -> CHandle {
|
||||
unsafe { oaktask::ffi::project::oaktask_create_project_save_otio(project, filename) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_load_otio_set_confirm_cb(cb: Option<OakTaskOtioImportConfirmFn>, userdata: *mut c_void) {
|
||||
unsafe { oaktask::ffi::project::oaktask_load_otio_set_confirm_cb(cb, userdata) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_create_precache(footage: CHandle, index: c_int, sequence: CHandle) -> CHandle {
|
||||
unsafe { oaktask::ffi::project::oaktask_create_precache(footage, index, sequence) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
/// `oaktask_create_export` — crosses the encoding-params C ABI POD
|
||||
/// (the facade keeps its own POD mirror). Kept as a link-time
|
||||
/// `extern "C"` declaration against the frozen module C ABI.
|
||||
pub fn oaktask_create_export(
|
||||
viewer: CHandle,
|
||||
color_manager: CHandle,
|
||||
params: *const crate::bridge::codec::EncodingParamsPOD,
|
||||
) -> CHandle {
|
||||
unsafe { oaktask_create_export_extern(viewer, color_manager, params) }
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
// ---- include/task/manager.h ---------------------------------------------
|
||||
/// `oaktask_manager_init` — start the global task manager.
|
||||
pub fn oaktask_manager_init() -> c_int;
|
||||
/// `oaktask_manager_shutdown`.
|
||||
pub fn oaktask_manager_shutdown();
|
||||
/// `oaktask_register_codec_submitter`.
|
||||
pub fn oaktask_register_codec_submitter() -> c_int;
|
||||
/// `oaktask_manager_count` — running plus failed-but-kept tasks.
|
||||
pub fn oaktask_manager_count() -> c_int;
|
||||
/// `oaktask_manager_at` — borrowed task handle at index.
|
||||
pub fn oaktask_manager_at(i: c_int) -> CHandle;
|
||||
/// `oaktask_manager_delete_finished`.
|
||||
pub fn oaktask_manager_delete_finished();
|
||||
|
||||
// ---- include/task/task.h -------------------------------------------------
|
||||
/// `oaktask_task_free` — release one reference; NULL/empty no-op.
|
||||
pub fn oaktask_task_free(t: *mut CHandle);
|
||||
/// `oaktask_task_start_sync` — run in the calling thread; 1 = succeeded.
|
||||
pub fn oaktask_task_start_sync(t: CHandle) -> c_int;
|
||||
/// `oaktask_task_start` — run on the task manager (transfers ownership).
|
||||
pub fn oaktask_task_start(t: CHandle) -> c_int;
|
||||
/// `oaktask_task_cancel`.
|
||||
pub fn oaktask_task_cancel(t: CHandle) -> c_int;
|
||||
/// `oaktask_task_wait` — wait for an asynchronously started task.
|
||||
pub fn oaktask_task_wait(t: CHandle) -> c_int;
|
||||
/// `oaktask_task_is_finished`.
|
||||
pub fn oaktask_task_is_finished(t: CHandle) -> c_int;
|
||||
/// `oaktask_task_succeeded`.
|
||||
pub fn oaktask_task_succeeded(t: CHandle) -> c_int;
|
||||
/// `oaktask_task_title` (two-stage string).
|
||||
pub fn oaktask_task_title(t: CHandle, buf: *mut c_char, buf_size: c_int) -> c_int;
|
||||
/// `oaktask_task_error` (two-stage string).
|
||||
pub fn oaktask_task_error(t: CHandle, buf: *mut c_char, buf_size: c_int) -> c_int;
|
||||
/// `oaktask_task_subscribe` — subscription id >= 0 or a negative code.
|
||||
pub fn oaktask_task_subscribe(t: CHandle, cb: Option<OakTaskEventFn>, userdata: *mut c_void) -> i64;
|
||||
/// `oaktask_debug_alive_count`.
|
||||
pub fn oaktask_debug_alive_count() -> c_int;
|
||||
|
||||
// ---- include/task/project.h ----------------------------------------------
|
||||
/// `oaktask_create_project_load` — owned `ProjectLoadTask`.
|
||||
pub fn oaktask_create_project_load(filename: *const c_char) -> CHandle;
|
||||
/// `oaktask_load_take_project` — ownership transfer of the loaded project.
|
||||
pub fn oaktask_load_take_project(t: CHandle) -> CHandle;
|
||||
/// `oaktask_create_project_save` — owned `ProjectSaveTask`.
|
||||
pub fn oaktask_create_project_save(project: CHandle, filename_or_null: *const c_char, use_compression: c_int) -> CHandle;
|
||||
/// `oaktask_create_project_import` — owned `ProjectImportTask`.
|
||||
pub fn oaktask_create_project_import(folder: CHandle, project: CHandle, urls: *const *const c_char, url_count: c_int) -> CHandle;
|
||||
/// `oaktask_import_take_command` — ownership transfer of the undo command.
|
||||
pub fn oaktask_import_take_command(t: CHandle) -> CHandle;
|
||||
/// `oaktask_import_footage_count`.
|
||||
pub fn oaktask_import_footage_count(t: CHandle) -> c_int;
|
||||
/// `oaktask_import_footage_at` — addref'd footage handle.
|
||||
pub fn oaktask_import_footage_at(t: CHandle, index: c_int) -> CHandle;
|
||||
/// `oaktask_import_invalid_count`.
|
||||
pub fn oaktask_import_invalid_count(t: CHandle) -> c_int;
|
||||
/// `oaktask_import_invalid_at` (two-stage string).
|
||||
pub fn oaktask_import_invalid_at(t: CHandle, index: c_int, buf: *mut c_char, buf_size: c_int) -> c_int;
|
||||
/// `oaktask_create_project_load_otio` — owned `LoadOTIOTask`.
|
||||
pub fn oaktask_create_project_load_otio(filename: *const c_char) -> CHandle;
|
||||
/// `oaktask_load_otio_take_project` — ownership transfer.
|
||||
pub fn oaktask_load_otio_take_project(t: CHandle) -> CHandle;
|
||||
/// `oaktask_create_project_save_otio` — owned `SaveOTIOTask`.
|
||||
pub fn oaktask_create_project_save_otio(project: CHandle, filename: *const c_char) -> CHandle;
|
||||
/// `oaktask_load_otio_set_confirm_cb` — install/clear the confirm callback.
|
||||
pub fn oaktask_load_otio_set_confirm_cb(cb: Option<OakTaskOtioImportConfirmFn>, userdata: *mut c_void);
|
||||
/// `oaktask_create_precache` — owned `PreCacheTask`.
|
||||
pub fn oaktask_create_precache(footage: CHandle, index: c_int, sequence: CHandle) -> CHandle;
|
||||
/// `oaktask_create_export` — owned `ExportTask`; `params` is the
|
||||
/// encoding-params POD (facade's `EncodingParamsPOD`).
|
||||
pub fn oaktask_create_export(
|
||||
#[link_name = "oaktask_create_export"]
|
||||
pub fn oaktask_create_export_extern(
|
||||
viewer: CHandle,
|
||||
color_manager: CHandle,
|
||||
params: *const crate::bridge::codec::EncodingParamsPOD,
|
||||
) -> CHandle;
|
||||
/// `oaktask_import_set_image_sequence_confirm_cb` — install/clear.
|
||||
pub fn oaktask_import_set_image_sequence_confirm_cb(cb: Option<OakTaskImageSequenceConfirmFn>, userdata: *mut c_void);
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktask` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktask_import_set_image_sequence_confirm_cb(cb: Option<OakTaskImageSequenceConfirmFn>, userdata: *mut c_void) {
|
||||
unsafe { oaktask::ffi::project::oaktask_import_set_image_sequence_confirm_cb(cb, userdata) }
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,33 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! oaktimeline C ABI bridge: direct Rust calls into the `oaktimeline` crate.
|
||||
//!
|
||||
//! Single-lib unification (see `docs/zh/plans/riir/single-lib.md`): every
|
||||
//! call below is a compile-time Rust call into `oaktimeline`'s `ffi` (the
|
||||
//! `#[no_mangle]` exports stay in the dylib for the external C ABI;
|
||||
//! internal callers bypass them). Handles cross as the shared
|
||||
//! [`crate::handle::CHandle`]. Exceptions that keep an `extern "C"`
|
||||
//! declaration (resolved at link time against the sibling crate in the
|
||||
//! same dylib) are the host `oakcore_*` symbols and the encoding-params
|
||||
//! C ABI POD crossings (the facade keeps its own POD mirrors there).
|
||||
|
||||
// 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/>.
|
||||
|
||||
//! oaktimeline C ABI imports, mirroring the oaktimeline crate's exports
|
||||
//! (`src/timeline/rust/src/ffi.rs`; headers `include/timeline/*.h`).
|
||||
//!
|
||||
@@ -30,15 +57,28 @@ use crate::handle::CHandle;
|
||||
// oaktimeline_marker_list_create / free / of / add / count / at /
|
||||
// add_command / remove_at_command / set_time_command /
|
||||
// set_props_command / list_load / list_save.
|
||||
extern "C" {
|
||||
/// `oaktimeline_marker_list_create` — new owning list, refcount 1.
|
||||
pub fn oaktimeline_marker_list_create() -> CHandle;
|
||||
/// `oaktimeline_marker_list_of` — borrowed list of a viewer node.
|
||||
pub fn oaktimeline_marker_list_of(owner: CHandle) -> CHandle;
|
||||
/// `oaktimeline_marker_list_free` — NULL/empty no-op; clears `list->ctx`.
|
||||
pub fn oaktimeline_marker_list_free(list: *mut CHandle);
|
||||
/// `oaktimeline_marker_add` — append a marker directly (no command).
|
||||
pub fn oaktimeline_marker_add(
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_marker_list_create() -> CHandle {
|
||||
unsafe { oaktimeline::ffi::marker::oaktimeline_marker_list_create() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_marker_list_of(owner: CHandle) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::marker::oaktimeline_marker_list_of(owner) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_marker_list_free(list: *mut CHandle) {
|
||||
unsafe { oaktimeline::ffi::marker::oaktimeline_marker_list_free(list) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_marker_add(
|
||||
list: CHandle,
|
||||
in_num: c_int,
|
||||
in_den: c_int,
|
||||
@@ -46,11 +86,19 @@ extern "C" {
|
||||
out_den: c_int,
|
||||
name: *const c_char,
|
||||
color: c_int,
|
||||
) -> c_int;
|
||||
/// `oaktimeline_marker_count` — number of markers.
|
||||
pub fn oaktimeline_marker_count(list: CHandle, out_count: *mut c_int) -> c_int;
|
||||
/// `oaktimeline_marker_at` — marker at index; name two-stage.
|
||||
pub fn oaktimeline_marker_at(
|
||||
) -> c_int {
|
||||
unsafe { oaktimeline::ffi::marker::oaktimeline_marker_add(list, in_num, in_den, out_num, out_den, name, color) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_marker_count(list: CHandle, out_count: *mut c_int) -> c_int {
|
||||
unsafe { oaktimeline::ffi::marker::oaktimeline_marker_count(list, out_count) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_marker_at(
|
||||
list: CHandle,
|
||||
index: c_int,
|
||||
in_num: *mut c_int,
|
||||
@@ -60,68 +108,118 @@ extern "C" {
|
||||
color: *mut c_int,
|
||||
name_buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oaktimeline_marker_add_command` — owned `MarkerAddCommand`.
|
||||
pub fn oaktimeline_marker_add_command(
|
||||
list: CHandle,
|
||||
in_num: c_int,
|
||||
in_den: c_int,
|
||||
out_num: c_int,
|
||||
out_den: c_int,
|
||||
name: *const c_char,
|
||||
color: c_int,
|
||||
) -> CHandle;
|
||||
/// `oaktimeline_marker_remove_at_command` — owned `MarkerRemoveCommand`.
|
||||
pub fn oaktimeline_marker_remove_at_command(list: CHandle, index: c_int) -> CHandle;
|
||||
/// `oaktimeline_marker_set_time_command` — owned `MarkerChangeTimeCommand`.
|
||||
pub fn oaktimeline_marker_set_time_command(
|
||||
list: CHandle,
|
||||
index: c_int,
|
||||
in_num: c_int,
|
||||
in_den: c_int,
|
||||
out_num: c_int,
|
||||
out_den: c_int,
|
||||
) -> CHandle;
|
||||
/// `oaktimeline_marker_set_props_command` — owned color/name command.
|
||||
pub fn oaktimeline_marker_set_props_command(
|
||||
list: CHandle,
|
||||
index: c_int,
|
||||
color: c_int,
|
||||
name: *const c_char,
|
||||
) -> CHandle;
|
||||
/// `oaktimeline_marker_list_load` — read from an oakcommon reader.
|
||||
pub fn oaktimeline_marker_list_load(list: CHandle, reader: CHandle) -> c_int;
|
||||
/// `oaktimeline_marker_list_save` — write to an oakcommon writer.
|
||||
pub fn oaktimeline_marker_list_save(list: CHandle, writer: CHandle) -> c_int;
|
||||
) -> c_int {
|
||||
unsafe { oaktimeline::ffi::marker::oaktimeline_marker_at(list, index, in_num, in_den, out_num, out_den, color, name_buf, buf_size) }
|
||||
}
|
||||
|
||||
// ---- include/timeline/workarea.h ----------------------------------------
|
||||
/// `oaktimeline_workarea_create` — new owning work area, refcount 1.
|
||||
pub fn oaktimeline_workarea_create() -> CHandle;
|
||||
/// `oaktimeline_workarea_of` — borrowed work area of a viewer node.
|
||||
pub fn oaktimeline_workarea_of(owner: CHandle) -> CHandle;
|
||||
/// `oaktimeline_workarea_free` — NULL/empty no-op; clears `w->ctx`.
|
||||
pub fn oaktimeline_workarea_free(w: *mut CHandle);
|
||||
/// `oaktimeline_workarea_set_enabled` — live.
|
||||
pub fn oaktimeline_workarea_set_enabled(w: CHandle, enabled: c_int) -> c_int;
|
||||
/// `oaktimeline_workarea_get` — state out; params may be NULL.
|
||||
pub fn oaktimeline_workarea_get(
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_marker_add_command(
|
||||
list: CHandle,
|
||||
in_num: c_int,
|
||||
in_den: c_int,
|
||||
out_num: c_int,
|
||||
out_den: c_int,
|
||||
name: *const c_char,
|
||||
color: c_int,
|
||||
) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::marker::oaktimeline_marker_add_command(list, in_num, in_den, out_num, out_den, name, color) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_marker_remove_at_command(list: CHandle, index: c_int) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::marker::oaktimeline_marker_remove_at_command(list, index) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_marker_set_time_command(
|
||||
list: CHandle,
|
||||
index: c_int,
|
||||
in_num: c_int,
|
||||
in_den: c_int,
|
||||
out_num: c_int,
|
||||
out_den: c_int,
|
||||
) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::marker::oaktimeline_marker_set_time_command(list, index, in_num, in_den, out_num, out_den) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_marker_set_props_command(
|
||||
list: CHandle,
|
||||
index: c_int,
|
||||
color: c_int,
|
||||
name: *const c_char,
|
||||
) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::marker::oaktimeline_marker_set_props_command(list, index, color, name) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_marker_list_load(list: CHandle, reader: CHandle) -> c_int {
|
||||
unsafe { oaktimeline::ffi::marker::oaktimeline_marker_list_load(list, reader) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_marker_list_save(list: CHandle, writer: CHandle) -> c_int {
|
||||
unsafe { oaktimeline::ffi::marker::oaktimeline_marker_list_save(list, writer) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_workarea_create() -> CHandle {
|
||||
unsafe { oaktimeline::ffi::workarea::oaktimeline_workarea_create() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_workarea_of(owner: CHandle) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::workarea::oaktimeline_workarea_of(owner) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_workarea_free(w: *mut CHandle) {
|
||||
unsafe { oaktimeline::ffi::workarea::oaktimeline_workarea_free(w) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_workarea_set_enabled(w: CHandle, enabled: c_int) -> c_int {
|
||||
unsafe { oaktimeline::ffi::workarea::oaktimeline_workarea_set_enabled(w, enabled) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_workarea_get(
|
||||
w: CHandle,
|
||||
in_num: *mut c_int,
|
||||
in_den: *mut c_int,
|
||||
out_num: *mut c_int,
|
||||
out_den: *mut c_int,
|
||||
enabled: *mut c_int,
|
||||
) -> c_int;
|
||||
/// `oaktimeline_workarea_set_range` — live.
|
||||
pub fn oaktimeline_workarea_set_range(
|
||||
) -> c_int {
|
||||
unsafe { oaktimeline::ffi::workarea::oaktimeline_workarea_get(w, in_num, in_den, out_num, out_den, enabled) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_workarea_set_range(
|
||||
w: CHandle,
|
||||
in_num: c_int,
|
||||
in_den: c_int,
|
||||
out_num: c_int,
|
||||
out_den: c_int,
|
||||
) -> c_int;
|
||||
/// `oaktimeline_workarea_set_range_command` — owned command, old range from caller.
|
||||
pub fn oaktimeline_workarea_set_range_command(
|
||||
) -> c_int {
|
||||
unsafe { oaktimeline::ffi::workarea::oaktimeline_workarea_set_range(w, in_num, in_den, out_num, out_den) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_workarea_set_range_command(
|
||||
w: CHandle,
|
||||
in_num: c_int,
|
||||
in_den: c_int,
|
||||
@@ -131,57 +229,102 @@ extern "C" {
|
||||
old_in_den: c_int,
|
||||
old_out_num: c_int,
|
||||
old_out_den: c_int,
|
||||
) -> CHandle;
|
||||
/// `oaktimeline_workarea_set_enabled_command` — owned command.
|
||||
pub fn oaktimeline_workarea_set_enabled_command(w: CHandle, enabled: c_int) -> CHandle;
|
||||
/// `oaktimeline_workarea_reset` — the reset sentinel range.
|
||||
pub fn oaktimeline_workarea_reset(
|
||||
) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::workarea::oaktimeline_workarea_set_range_command(w, in_num, in_den, out_num, out_den, old_in_num, old_in_den, old_out_num, old_out_den) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_workarea_set_enabled_command(w: CHandle, enabled: c_int) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::workarea::oaktimeline_workarea_set_enabled_command(w, enabled) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_workarea_reset(
|
||||
in_num: *mut c_int,
|
||||
in_den: *mut c_int,
|
||||
out_num: *mut c_int,
|
||||
out_den: *mut c_int,
|
||||
) -> c_int;
|
||||
/// `oaktimeline_workarea_load` — read from an oakcommon reader.
|
||||
pub fn oaktimeline_workarea_load(w: CHandle, reader: CHandle) -> c_int;
|
||||
/// `oaktimeline_workarea_save` — write to an oakcommon writer.
|
||||
pub fn oaktimeline_workarea_save(w: CHandle, writer: CHandle) -> c_int;
|
||||
) -> c_int {
|
||||
unsafe { oaktimeline::ffi::workarea::oaktimeline_workarea_reset(in_num, in_den, out_num, out_den) }
|
||||
}
|
||||
|
||||
// ---- include/timeline/edit.h --------------------------------------------
|
||||
/// `oaktimeline_add_track_command` — owned `TimelineAddTrackCommand`.
|
||||
pub fn oaktimeline_add_track_command(list: CHandle) -> CHandle;
|
||||
/// `oaktimeline_remove_track_command` — owned `TimelineRemoveTrackCommand`.
|
||||
pub fn oaktimeline_remove_track_command(track: CHandle) -> CHandle;
|
||||
/// `oaktimeline_place_block_command` — owned `TrackPlaceBlockCommand`.
|
||||
pub fn oaktimeline_place_block_command(
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_workarea_load(w: CHandle, reader: CHandle) -> c_int {
|
||||
unsafe { oaktimeline::ffi::workarea::oaktimeline_workarea_load(w, reader) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_workarea_save(w: CHandle, writer: CHandle) -> c_int {
|
||||
unsafe { oaktimeline::ffi::workarea::oaktimeline_workarea_save(w, writer) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_add_track_command(list: CHandle) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::edit::oaktimeline_add_track_command(list) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_remove_track_command(track: CHandle) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::edit::oaktimeline_remove_track_command(track) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_place_block_command(
|
||||
list: CHandle,
|
||||
track_index: c_int,
|
||||
block: CHandle,
|
||||
in_num: i64,
|
||||
in_den: i64,
|
||||
) -> CHandle;
|
||||
/// `oaktimeline_replace_block_with_gap_command` — owned command.
|
||||
pub fn oaktimeline_replace_block_with_gap_command(track: CHandle, block: CHandle) -> CHandle;
|
||||
/// `oaktimeline_trim_command` — owned `BlockTrimCommand`; `mode` is an
|
||||
/// `OakTimelineMovementMode` value.
|
||||
pub fn oaktimeline_trim_command(
|
||||
) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::edit::oaktimeline_place_block_command(list, track_index, block, in_num, in_den) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_replace_block_with_gap_command(track: CHandle, block: CHandle) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::edit::oaktimeline_replace_block_with_gap_command(track, block) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_trim_command(
|
||||
track: CHandle,
|
||||
block: CHandle,
|
||||
new_length_num: i64,
|
||||
new_length_den: i64,
|
||||
mode: c_int,
|
||||
) -> CHandle;
|
||||
/// `oaktimeline_split_command` — owned `BlockSplitCommand` (one point).
|
||||
pub fn oaktimeline_split_command(blocks: *const CHandle, count: c_int, point_num: i64, point_den: i64) -> CHandle;
|
||||
/// `oaktimeline_split_preserving_links_command` — owned command.
|
||||
pub fn oaktimeline_split_preserving_links_command(
|
||||
) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::edit::oaktimeline_trim_command(track, block, new_length_num, new_length_den, mode) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_split_command(blocks: *const CHandle, count: c_int, point_num: i64, point_den: i64) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::edit::oaktimeline_split_command(blocks, count, point_num, point_den) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_split_preserving_links_command(
|
||||
blocks: *const CHandle,
|
||||
count: c_int,
|
||||
point_nums: *const i64,
|
||||
point_dens: *const i64,
|
||||
time_count: c_int,
|
||||
) -> CHandle;
|
||||
/// `oaktimeline_ripple_delete_gaps_command` — owned command.
|
||||
pub fn oaktimeline_ripple_delete_gaps_command(
|
||||
) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::edit::oaktimeline_split_preserving_links_command(blocks, count, point_nums, point_dens, time_count) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_ripple_delete_gaps_command(
|
||||
sequence: CHandle,
|
||||
in_nums: *const i64,
|
||||
in_dens: *const i64,
|
||||
@@ -189,9 +332,13 @@ extern "C" {
|
||||
out_dens: *const i64,
|
||||
tracks: *const CHandle,
|
||||
range_count: c_int,
|
||||
) -> CHandle;
|
||||
/// `oaktimeline_slide_command` — owned `TrackSlideCommand`.
|
||||
pub fn oaktimeline_slide_command(
|
||||
) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::edit::oaktimeline_ripple_delete_gaps_command(sequence, in_nums, in_dens, out_nums, out_dens, tracks, range_count) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_slide_command(
|
||||
track: CHandle,
|
||||
blocks: *const CHandle,
|
||||
block_count: c_int,
|
||||
@@ -199,22 +346,31 @@ extern "C" {
|
||||
out_adjacent: CHandle,
|
||||
movement_num: i64,
|
||||
movement_den: i64,
|
||||
) -> CHandle;
|
||||
/// `oaktimeline_ripple_remove_area_command` — owned
|
||||
/// `TrackRippleRemoveAreaCommand`.
|
||||
pub fn oaktimeline_ripple_remove_area_command(
|
||||
) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::edit::oaktimeline_slide_command(track, blocks, block_count, in_adjacent, out_adjacent, movement_num, movement_den) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_ripple_remove_area_command(
|
||||
track: CHandle,
|
||||
in_num: i64,
|
||||
in_den: i64,
|
||||
out_num: i64,
|
||||
out_den: i64,
|
||||
) -> CHandle;
|
||||
/// `oaktimeline_insert_gaps_command` — owned `TrackListInsertGaps`.
|
||||
pub fn oaktimeline_insert_gaps_command(
|
||||
) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::edit::oaktimeline_ripple_remove_area_command(track, in_num, in_den, out_num, out_den) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oaktimeline` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oaktimeline_insert_gaps_command(
|
||||
list: CHandle,
|
||||
point_num: i64,
|
||||
point_den: i64,
|
||||
length_num: i64,
|
||||
length_den: i64,
|
||||
) -> CHandle;
|
||||
) -> CHandle {
|
||||
unsafe { oaktimeline::ffi::edit::oaktimeline_insert_gaps_command(list, point_num, point_den, length_num, length_den) }
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,33 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! oakundo C ABI bridge: direct Rust calls into the `oakundo` crate.
|
||||
//!
|
||||
//! Single-lib unification (see `docs/zh/plans/riir/single-lib.md`): every
|
||||
//! call below is a compile-time Rust call into `oakundo`'s `ffi` (the
|
||||
//! `#[no_mangle]` exports stay in the dylib for the external C ABI;
|
||||
//! internal callers bypass them). Handles cross as the shared
|
||||
//! [`crate::handle::CHandle`]. Exceptions that keep an `extern "C"`
|
||||
//! declaration (resolved at link time against the sibling crate in the
|
||||
//! same dylib) are the host `oakcore_*` symbols and the encoding-params
|
||||
//! C ABI POD crossings (the facade keeps its own POD mirrors there).
|
||||
|
||||
// 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/>.
|
||||
|
||||
//! oakundo C ABI imports, mirroring the oakundo crate's exports
|
||||
//! (`src/undo/rust/src/ffi.rs`; headers `include/undo/*.h`).
|
||||
|
||||
@@ -21,82 +48,161 @@ use std::ffi::{c_char, c_int};
|
||||
|
||||
use crate::handle::CHandle;
|
||||
|
||||
extern "C" {
|
||||
/// `oakundo_command_init` — vtable-backed command, refcount 1.
|
||||
pub fn oakundo_command_init(
|
||||
|
||||
/// `include/undo/undocommand.h` — callback table backing a
|
||||
/// caller-defined undo command. Single-lib unification: aliases the
|
||||
/// oakundo crate's vtable POD.
|
||||
pub type OakUndoCommandVtable = oakundo::undocommand::OakUndoCommandVtable;
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_command_init(
|
||||
vtable: *const OakUndoCommandVtable,
|
||||
userdata: *mut std::ffi::c_void,
|
||||
) -> CHandle;
|
||||
/// `oakundo_command_init_multi` — empty multi command, refcount 1.
|
||||
pub fn oakundo_command_init_multi() -> CHandle;
|
||||
/// `oakundo_command_multi_add_child` (stack takes one child ref).
|
||||
pub fn oakundo_command_multi_add_child(multi: CHandle, child: CHandle) -> c_int;
|
||||
/// `oakundo_command_multi_child_count`.
|
||||
pub fn oakundo_command_multi_child_count(multi: CHandle, out_count: *mut c_int) -> c_int;
|
||||
/// `oakundo_command_multi_child` (returned handle carries own ref).
|
||||
pub fn oakundo_command_multi_child(
|
||||
) -> CHandle {
|
||||
unsafe { oakundo::ffi::command::oakundo_command_init(vtable, userdata) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_command_init_multi() -> CHandle {
|
||||
unsafe { oakundo::ffi::command::oakundo_command_init_multi() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_command_multi_add_child(multi: CHandle, child: CHandle) -> c_int {
|
||||
unsafe { oakundo::ffi::command::oakundo_command_multi_add_child(multi, child) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_command_multi_child_count(multi: CHandle, out_count: *mut c_int) -> c_int {
|
||||
unsafe { oakundo::ffi::command::oakundo_command_multi_child_count(multi, out_count) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_command_multi_child(
|
||||
multi: CHandle,
|
||||
index: c_int,
|
||||
out_child: *mut CHandle,
|
||||
) -> c_int;
|
||||
/// `oakundo_command_redo_now`.
|
||||
pub fn oakundo_command_redo_now(command: CHandle) -> c_int;
|
||||
/// `oakundo_command_undo_now`.
|
||||
pub fn oakundo_command_undo_now(command: CHandle) -> c_int;
|
||||
/// `oakundo_command_free` — NULL/empty no-op; clears `command->ctx`.
|
||||
pub fn oakundo_command_free(command: *mut CHandle);
|
||||
/// `oakundo_undostack_init` — fresh stack, refcount 1.
|
||||
pub fn oakundo_undostack_init() -> CHandle;
|
||||
/// `oakundo_undostack_free` — NULL/empty no-op; clears `stack->ctx`.
|
||||
pub fn oakundo_undostack_free(stack: *mut CHandle);
|
||||
/// `oakundo_undostack_push` — redo then record; drops redoable tail.
|
||||
pub fn oakundo_undostack_push(stack: CHandle, command: CHandle, name: *const c_char) -> c_int;
|
||||
/// `oakundo_undostack_push_pre_executed` — record without redoing.
|
||||
pub fn oakundo_undostack_push_pre_executed(
|
||||
) -> c_int {
|
||||
unsafe { oakundo::ffi::command::oakundo_command_multi_child(multi, index, out_child) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_command_redo_now(command: CHandle) -> c_int {
|
||||
unsafe { oakundo::ffi::command::oakundo_command_redo_now(command) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_command_undo_now(command: CHandle) -> c_int {
|
||||
unsafe { oakundo::ffi::command::oakundo_command_undo_now(command) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_command_free(command: *mut CHandle) {
|
||||
unsafe { oakundo::ffi::command::oakundo_command_free(command) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_undostack_init() -> CHandle {
|
||||
unsafe { oakundo::ffi::undostack::oakundo_undostack_init() }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_undostack_free(stack: *mut CHandle) {
|
||||
unsafe { oakundo::ffi::undostack::oakundo_undostack_free(stack) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_undostack_push(stack: CHandle, command: CHandle, name: *const c_char) -> c_int {
|
||||
unsafe { oakundo::ffi::undostack::oakundo_undostack_push(stack, command, name) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_undostack_push_pre_executed(
|
||||
stack: CHandle,
|
||||
command: CHandle,
|
||||
name: *const c_char,
|
||||
) -> c_int;
|
||||
/// `oakundo_undostack_undo`.
|
||||
pub fn oakundo_undostack_undo(stack: CHandle) -> c_int;
|
||||
/// `oakundo_undostack_redo`.
|
||||
pub fn oakundo_undostack_redo(stack: CHandle) -> c_int;
|
||||
/// `oakundo_undostack_jump` (clamped to 0; `index` is i64).
|
||||
pub fn oakundo_undostack_jump(stack: CHandle, index: i64) -> c_int;
|
||||
/// `oakundo_undostack_clear`.
|
||||
pub fn oakundo_undostack_clear(stack: CHandle) -> c_int;
|
||||
/// `oakundo_undostack_can_undo`.
|
||||
pub fn oakundo_undostack_can_undo(stack: CHandle, out_value: *mut c_int) -> c_int;
|
||||
/// `oakundo_undostack_can_redo`.
|
||||
pub fn oakundo_undostack_can_redo(stack: CHandle, out_value: *mut c_int) -> c_int;
|
||||
/// `oakundo_undostack_count`.
|
||||
pub fn oakundo_undostack_count(stack: CHandle, out_count: *mut i64) -> c_int;
|
||||
/// `oakundo_undostack_index`.
|
||||
pub fn oakundo_undostack_index(stack: CHandle, out_index: *mut i64) -> c_int;
|
||||
/// `oakundo_undostack_command_text` (two-stage string getter).
|
||||
pub fn oakundo_undostack_command_text(
|
||||
) -> c_int {
|
||||
unsafe { oakundo::ffi::undostack::oakundo_undostack_push_pre_executed(stack, command, name) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_undostack_undo(stack: CHandle) -> c_int {
|
||||
unsafe { oakundo::ffi::undostack::oakundo_undostack_undo(stack) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_undostack_redo(stack: CHandle) -> c_int {
|
||||
unsafe { oakundo::ffi::undostack::oakundo_undostack_redo(stack) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_undostack_jump(stack: CHandle, index: i64) -> c_int {
|
||||
unsafe { oakundo::ffi::undostack::oakundo_undostack_jump(stack, index) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_undostack_clear(stack: CHandle) -> c_int {
|
||||
unsafe { oakundo::ffi::undostack::oakundo_undostack_clear(stack) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_undostack_can_undo(stack: CHandle, out_value: *mut c_int) -> c_int {
|
||||
unsafe { oakundo::ffi::undostack::oakundo_undostack_can_undo(stack, out_value) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_undostack_can_redo(stack: CHandle, out_value: *mut c_int) -> c_int {
|
||||
unsafe { oakundo::ffi::undostack::oakundo_undostack_can_redo(stack, out_value) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_undostack_count(stack: CHandle, out_count: *mut i64) -> c_int {
|
||||
unsafe { oakundo::ffi::undostack::oakundo_undostack_count(stack, out_count) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_undostack_index(stack: CHandle, out_index: *mut i64) -> c_int {
|
||||
unsafe { oakundo::ffi::undostack::oakundo_undostack_index(stack, out_index) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_undostack_command_text(
|
||||
stack: CHandle,
|
||||
row: i64,
|
||||
buf: *mut c_char,
|
||||
buf_size: c_int,
|
||||
) -> c_int;
|
||||
/// `oakundo_undostack_command_is_done`.
|
||||
pub fn oakundo_undostack_command_is_done(
|
||||
) -> c_int {
|
||||
unsafe { oakundo::ffi::undostack::oakundo_undostack_command_text(stack, row, buf, buf_size) }
|
||||
}
|
||||
|
||||
/// Direct call into the `oakundo` crate (single-lib unification; the
|
||||
/// `#[no_mangle]` export stays for the external C ABI).
|
||||
pub fn oakundo_undostack_command_is_done(
|
||||
stack: CHandle,
|
||||
row: i64,
|
||||
out_value: *mut c_int,
|
||||
) -> c_int;
|
||||
) -> c_int {
|
||||
unsafe { oakundo::ffi::undostack::oakundo_undostack_command_is_done(stack, row, out_value) }
|
||||
}
|
||||
|
||||
/// `include/undo/undocommand.h` — callback table backing a
|
||||
/// caller-defined undo command.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct OakUndoCommandVtable {
|
||||
/// Redo callback (NULL = no-op).
|
||||
pub redo: Option<unsafe extern "C" fn(userdata: *mut std::ffi::c_void)>,
|
||||
/// Undo callback (NULL = no-op).
|
||||
pub undo: Option<unsafe extern "C" fn(userdata: *mut std::ffi::c_void)>,
|
||||
/// Destruction callback releasing `userdata`.
|
||||
pub free_fn: Option<unsafe extern "C" fn(userdata: *mut std::ffi::c_void)>,
|
||||
}
|
||||
|
||||
@@ -40,63 +40,13 @@ use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
|
||||
/// ABI-neutral mirror of the module handle struct
|
||||
/// (`{ctx, addref, release, abi_version}`). Structurally identical to
|
||||
/// every `Oak<Mod><Type>` value handle in `include/<mod>/*.h`, so the
|
||||
/// facade can copy a handle across the module boundary without knowing
|
||||
/// the module's concrete type names.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct CHandle {
|
||||
/// Opaque box pointer.
|
||||
pub ctx: *mut c_void,
|
||||
/// Atomic increment.
|
||||
pub addref: Option<unsafe extern "C" fn(*mut c_void)>,
|
||||
/// Atomic decrement; destroys at zero.
|
||||
pub release: Option<unsafe extern "C" fn(*mut c_void)>,
|
||||
/// ABI version.
|
||||
pub abi_version: u32,
|
||||
}
|
||||
|
||||
impl CHandle {
|
||||
/// The empty handle.
|
||||
pub const fn null() -> Self {
|
||||
CHandle {
|
||||
ctx: std::ptr::null_mut(),
|
||||
addref: None,
|
||||
release: None,
|
||||
abi_version: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether this is the empty (zero) handle.
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ctx.is_null()
|
||||
}
|
||||
|
||||
/// Take an additional reference through the handle's `addref` and
|
||||
/// return the (now refcount-incremented) copy.
|
||||
///
|
||||
/// # Safety
|
||||
/// `self` must be a live handle returned by a module function.
|
||||
pub unsafe fn addref(&self) -> Self {
|
||||
let mut copy = *self;
|
||||
if let Some(addref) = copy.addref {
|
||||
let _ = &mut copy;
|
||||
unsafe {
|
||||
addref(copy.ctx);
|
||||
}
|
||||
}
|
||||
copy
|
||||
}
|
||||
}
|
||||
|
||||
// Module handles follow the shared_ptr-like convention of
|
||||
// `include/common/handle.h`: they are opaque, refcounted and safe to
|
||||
// share across threads (the module crates themselves use them behind
|
||||
// mutexes). The facade therefore declares them Send + Sync.
|
||||
unsafe impl Send for CHandle {}
|
||||
unsafe impl Sync for CHandle {}
|
||||
/// The shared ABI value-handle type (single-lib unification, see
|
||||
/// `docs/zh/plans/riir/single-lib.md`): one canonical
|
||||
/// `{ctx, addref, release, abi_version}` type in `oakcore-rs`, re-exported
|
||||
/// by every module crate, so the facade can pass a handle straight into a
|
||||
/// module's `pub` Rust functions without an `extern "C"` declaration.
|
||||
/// `Clone + Copy + Send + Sync` come from the shared type.
|
||||
pub use oakcore_rs::handle::CHandle;
|
||||
|
||||
/// Engine opaque handle types, one per `typedef struct OakEngine*` in
|
||||
/// `engine/include/oakengine/*.h`. All are thin newtype wrappers around a
|
||||
|
||||
@@ -33,20 +33,11 @@ use crate::undo::push_or_run;
|
||||
|
||||
/// `engine/include/oakengine/node.h` — POD mirror of `oak_node_value`.
|
||||
///
|
||||
/// Layout-identical to the module's `oaknode_value`, so the facade hands
|
||||
/// the engine POD straight to the oaknode bridge.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct OakNodeValue {
|
||||
/// `oak_node_value_type`.
|
||||
pub type_: c_int,
|
||||
/// INT/COMBO value, BOOL 0/1, RATIONAL numerator.
|
||||
pub num: i64,
|
||||
/// RATIONAL denominator.
|
||||
pub den: i64,
|
||||
/// FLOAT f[0]; VEC2/3/4 f[0..n-1]; COLOR r,g,b,a.
|
||||
pub f: [f64; 4],
|
||||
}
|
||||
/// Single-lib unification: aliases the oaknode crate's POD (the module
|
||||
/// C ABI struct `oak_node_value`), so the facade can pass it straight
|
||||
/// into `oaknode::ffi` functions without an `extern "C"` declaration.
|
||||
/// The field is named `kind` on the shared type (was `type_`).
|
||||
pub type OakNodeValue = oaknode::value::OakNodeValue;
|
||||
|
||||
/// `engine/include/oakengine/footage.h` — POD mirror of
|
||||
/// `oak_footage_video_info` (olive::VideoParams stream description).
|
||||
@@ -5584,7 +5575,7 @@ pub unsafe extern "C" fn oakengine_node_value_split_to_tracks(
|
||||
let count = oakengine_node_value_keyframe_track_count(c_type).min(track_count);
|
||||
for i in 0..count as usize {
|
||||
let mut t = OakNodeValue {
|
||||
type_: c_type,
|
||||
kind: c_type,
|
||||
num: 0,
|
||||
den: 0,
|
||||
f: [0.0; 4],
|
||||
@@ -5604,7 +5595,7 @@ pub unsafe extern "C" fn oakengine_node_value_split_to_tracks(
|
||||
t.f[0] = n.f[0];
|
||||
}
|
||||
_ => {
|
||||
t.type_ = c_type;
|
||||
t.kind = c_type;
|
||||
t.f = n.f;
|
||||
}
|
||||
}
|
||||
@@ -5627,7 +5618,7 @@ pub unsafe extern "C" fn oakengine_node_value_combine_tracks(
|
||||
return Err(Error::Invalid);
|
||||
}
|
||||
let mut out = OakNodeValue {
|
||||
type_: c_type,
|
||||
kind: c_type,
|
||||
num: 0,
|
||||
den: 0,
|
||||
f: [0.0; 4],
|
||||
|
||||
@@ -4794,7 +4794,7 @@ pub unsafe extern "C" fn oakengine_track_block_at_time(
|
||||
unsafe fn track_nearest_boxed(
|
||||
track: *const OakEngineTrack,
|
||||
timestamp: i64,
|
||||
via: unsafe extern "C" fn(CHandle, c_int, c_int, *mut CHandle) -> c_int,
|
||||
via: fn(CHandle, c_int, c_int, *mut CHandle) -> c_int,
|
||||
) -> *mut OakEngineBlock {
|
||||
guard_ptr(|| unsafe {
|
||||
if track.is_null() {
|
||||
|
||||
@@ -75,7 +75,7 @@ fn force_oakundo_command_link() -> usize {
|
||||
/// A float POD value.
|
||||
fn float_value(x: f64) -> OakNodeValue {
|
||||
OakNodeValue {
|
||||
type_: 2, // OAK_NODE_VALUE_FLOAT
|
||||
kind: 2, // OAK_NODE_VALUE_FLOAT
|
||||
num: 0,
|
||||
den: 0,
|
||||
f: [x, 0.0, 0.0, 0.0],
|
||||
@@ -229,7 +229,7 @@ fn project_node_keyframe_lifecycle() {
|
||||
unsafe { oakengine_node_get_input(value, c"value_in".as_ptr(), &mut out) },
|
||||
0
|
||||
);
|
||||
assert_eq!(out.type_, 2);
|
||||
assert_eq!(out.kind, 2);
|
||||
assert!((out.f[0] - 3.5).abs() < 1e-6);
|
||||
|
||||
// ---- connect / disconnect -------------------------------------------
|
||||
@@ -265,7 +265,7 @@ fn project_node_keyframe_lifecycle() {
|
||||
unsafe { oakengine_node_get_input_at_time(value, c"value_in".as_ptr(), -1, -1, 0, 0, &mut at) },
|
||||
0
|
||||
);
|
||||
assert_eq!(at.type_, 2);
|
||||
assert_eq!(at.kind, 2);
|
||||
assert!((at.f[0] - 0.5).abs() < 1e-6);
|
||||
|
||||
// ---- project save → fresh load round-trip ---------------------------
|
||||
|
||||
Generated
+334
@@ -2,6 +2,168 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.25.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder-lite"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d262e149917187838d5b42777c8253bcb64500067342904e7d429499a6f277e"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
|
||||
|
||||
[[package]]
|
||||
name = "fax"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a"
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "2.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crunchy",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.25.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder-lite",
|
||||
"moxcms",
|
||||
"num-traits",
|
||||
"tiff",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "moxcms"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"pxfm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oakcommon"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"image",
|
||||
"log",
|
||||
"oakcore-rs",
|
||||
"ocio-rs",
|
||||
"quick-xml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oakcore-rs"
|
||||
version = "0.1.0"
|
||||
@@ -9,6 +171,178 @@ version = "0.1.0"
|
||||
[[package]]
|
||||
name = "oaknode"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"oakcommon",
|
||||
"oakcore-rs",
|
||||
"oakundo",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oakundo"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"oakcore-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ocio-rs"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3492534019b59e29dba06014f907dd12824537ed4d293d4108c4bfc669de7fd"
|
||||
dependencies = [
|
||||
"ocio-sys",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ocio-sys"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e63251d72d848de5eda39d59cd6490260cf031738ebd518ea37d76b5aae614ec"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cmake",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pxfm"
|
||||
version = "0.1.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea"
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.41.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.119"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiff"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52"
|
||||
dependencies = [
|
||||
"fax",
|
||||
"flate2",
|
||||
"half",
|
||||
"quick-error",
|
||||
"weezl",
|
||||
"zune-jpeg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "weezl"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zune-core"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d56377fd46368984a170bc5aac5567e52ca5da874caa60bea39fcbca78fb658b"
|
||||
|
||||
[[package]]
|
||||
name = "zune-jpeg"
|
||||
version = "0.5.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296"
|
||||
dependencies = [
|
||||
"zune-core",
|
||||
]
|
||||
|
||||
@@ -14,6 +14,8 @@ panic = "unwind"
|
||||
|
||||
[dependencies]
|
||||
oakcore-rs = { path = "../../oakcore-rs" }
|
||||
oakcommon = { path = "../../common/rust" }
|
||||
oakundo = { path = "../../undo/rust" }
|
||||
|
||||
[features]
|
||||
# In-crate stubs for the oakundo C ABI (and other module bridges) so
|
||||
|
||||
@@ -14,19 +14,19 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! oakundo C ABI imports. Undo commands are created through the C ABI
|
||||
//! vtable (`oakundo_command_init` with Rust closures as userdata) — no
|
||||
//! C++ UndoCommand subclassing exists on this side. Symbols resolve via
|
||||
//! `dlsym(RTLD_DEFAULT)` (see [`super`]).
|
||||
//! oakundo C ABI calls — now direct Rust calls into the oakundo crate
|
||||
//! (single-lib unification, see `docs/zh/plans/riir/single-lib.md`).
|
||||
//! Undo commands are created through the C ABI vtable
|
||||
//! (`oakundo_command_init` with Rust closures as userdata) — no C++
|
||||
//! UndoCommand subclassing exists on this side.
|
||||
//!
|
||||
//! ## Test stubs (`--features test-stubs`)
|
||||
//!
|
||||
//! `cargo test` builds without liboakundo, so the feature compiles
|
||||
//! in-crate `#[no_mangle]` implementations of the undo C ABI
|
||||
//! (see [`stub`]) that run Rust closures directly. `dlsym` then resolves
|
||||
//! the stub symbols from the test binary's global scope, so the undoable
|
||||
//! exports run end-to-end in tests. Real module builds (feature off)
|
||||
//! resolve the actual oakundo library.
|
||||
//! With the direct dependency, the real oakundo rlib is linked into
|
||||
//! every build and test; the `test-stubs` feature still compiles
|
||||
//! in-crate `#[no_mangle]` implementations of the undo C ABI (see
|
||||
//! [`stub`]) for environments that link without oakundo. Do not enable
|
||||
//! the feature in a binary that also links oakundo (duplicate symbols).
|
||||
|
||||
use std::ffi::c_int;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
@@ -34,17 +34,9 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use crate::handle::CHandle;
|
||||
|
||||
/// `OakUndoCommandVtable` (include/undo/undocommand.h) — the callback
|
||||
/// table backing a caller-defined undo command.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Vtable {
|
||||
/// Execute the redo.
|
||||
pub redo: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// Execute the undo.
|
||||
pub undo: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// Release `userdata` (invoked when the command is destroyed).
|
||||
pub free_fn: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
}
|
||||
/// table backing a caller-defined undo command. Single-lib unification:
|
||||
/// aliases the oakundo crate's vtable POD (identical layout).
|
||||
pub type Vtable = oakundo::undocommand::OakUndoCommandVtable;
|
||||
|
||||
/// Rust closure state behind a vtable command's `userdata` pointer.
|
||||
///
|
||||
@@ -130,11 +122,13 @@ pub fn command_init(vtable: &Vtable, userdata: *mut std::ffi::c_void) -> Option<
|
||||
/// `oakundo_command_init` (vtable command).
|
||||
#[cfg(not(feature = "test-stubs"))]
|
||||
pub fn command_init(vtable: &Vtable, userdata: *mut std::ffi::c_void) -> Option<CHandle> {
|
||||
use crate::bridge::dlsym;
|
||||
type F = unsafe extern "C" fn(*const Vtable, *mut std::ffi::c_void) -> CHandle;
|
||||
dlsym::call::<F, CHandle>("oakundo_command_init", |f| unsafe {
|
||||
f(vtable as *const Vtable, userdata)
|
||||
})
|
||||
// Direct call into the oakundo crate (single-lib unification).
|
||||
let h = unsafe { oakundo::ffi::command::oakundo_command_init(vtable, userdata) };
|
||||
if h.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(h)
|
||||
}
|
||||
}
|
||||
|
||||
/// `oakundo_command_init_multi`.
|
||||
@@ -146,9 +140,13 @@ pub fn command_init_multi() -> Option<CHandle> {
|
||||
/// `oakundo_command_init_multi`.
|
||||
#[cfg(not(feature = "test-stubs"))]
|
||||
pub fn command_init_multi() -> Option<CHandle> {
|
||||
use crate::bridge::dlsym;
|
||||
type F = unsafe extern "C" fn() -> CHandle;
|
||||
dlsym::call::<F, CHandle>("oakundo_command_init_multi", |f| unsafe { f() })
|
||||
// Direct call into the oakundo crate (single-lib unification).
|
||||
let h = unsafe { oakundo::ffi::command::oakundo_command_init_multi() };
|
||||
if h.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(h)
|
||||
}
|
||||
}
|
||||
|
||||
/// `oakundo_command_multi_add_child`.
|
||||
@@ -160,11 +158,8 @@ pub fn command_multi_add_child(multi: CHandle, child: CHandle) -> Option<c_int>
|
||||
/// `oakundo_command_multi_add_child`.
|
||||
#[cfg(not(feature = "test-stubs"))]
|
||||
pub fn command_multi_add_child(multi: CHandle, child: CHandle) -> Option<c_int> {
|
||||
use crate::bridge::dlsym;
|
||||
type F = unsafe extern "C" fn(CHandle, CHandle) -> c_int;
|
||||
dlsym::call::<F, c_int>("oakundo_command_multi_add_child", |f| unsafe {
|
||||
f(multi, child)
|
||||
})
|
||||
// Direct call into the oakundo crate (single-lib unification).
|
||||
Some(unsafe { oakundo::ffi::command::oakundo_command_multi_add_child(multi, child) })
|
||||
}
|
||||
|
||||
/// `oakundo_command_redo_now`.
|
||||
@@ -176,9 +171,8 @@ pub fn command_redo_now(command: CHandle) -> Option<c_int> {
|
||||
/// `oakundo_command_redo_now`.
|
||||
#[cfg(not(feature = "test-stubs"))]
|
||||
pub fn command_redo_now(command: CHandle) -> Option<c_int> {
|
||||
use crate::bridge::dlsym;
|
||||
type F = unsafe extern "C" fn(CHandle) -> c_int;
|
||||
dlsym::call::<F, c_int>("oakundo_command_redo_now", |f| unsafe { f(command) })
|
||||
// Direct call into the oakundo crate (single-lib unification).
|
||||
Some(unsafe { oakundo::ffi::command::oakundo_command_redo_now(command) })
|
||||
}
|
||||
|
||||
/// `oakundo_command_undo_now`.
|
||||
@@ -190,9 +184,8 @@ pub fn command_undo_now(command: CHandle) -> Option<c_int> {
|
||||
/// `oakundo_command_undo_now`.
|
||||
#[cfg(not(feature = "test-stubs"))]
|
||||
pub fn command_undo_now(command: CHandle) -> Option<c_int> {
|
||||
use crate::bridge::dlsym;
|
||||
type F = unsafe extern "C" fn(CHandle) -> c_int;
|
||||
dlsym::call::<F, c_int>("oakundo_command_undo_now", |f| unsafe { f(command) })
|
||||
// Direct call into the oakundo crate (single-lib unification).
|
||||
Some(unsafe { oakundo::ffi::command::oakundo_command_undo_now(command) })
|
||||
}
|
||||
|
||||
/// `oakundo_command_free`.
|
||||
@@ -204,22 +197,14 @@ pub fn command_free(command: *mut CHandle) {
|
||||
/// `oakundo_command_free`.
|
||||
#[cfg(not(feature = "test-stubs"))]
|
||||
pub fn command_free(command: *mut CHandle) {
|
||||
use crate::bridge::dlsym;
|
||||
type F = unsafe extern "C" fn(*mut CHandle);
|
||||
if let Some(f) = dlsym::call::<F, ()>("oakundo_command_free", |f| unsafe {
|
||||
f(command)
|
||||
}) {
|
||||
let _ = f;
|
||||
}
|
||||
// Direct call into the oakundo crate (single-lib unification).
|
||||
unsafe { oakundo::ffi::command::oakundo_command_free(command) }
|
||||
}
|
||||
|
||||
/// `oakundo_stack_push` (facade-owned stack).
|
||||
pub fn stack_push(stack: CHandle, command: CHandle, text: *const std::ffi::c_char) -> Option<c_int> {
|
||||
use crate::bridge::dlsym;
|
||||
type F = unsafe extern "C" fn(CHandle, CHandle, *const std::ffi::c_char) -> c_int;
|
||||
dlsym::call::<F, c_int>("oakundo_stack_push", |f| unsafe {
|
||||
f(stack, command, text)
|
||||
})
|
||||
// Direct call into the oakundo crate (single-lib unification).
|
||||
Some(unsafe { oakundo::ffi::undostack::oakundo_undostack_push(stack, command, text) })
|
||||
}
|
||||
|
||||
/// In-crate implementations of the undo C ABI for `cargo test`
|
||||
|
||||
@@ -55,19 +55,11 @@ impl ColorManager {
|
||||
}
|
||||
|
||||
/// Load the built-in default config (C++ `ColorManager::init()`).
|
||||
/// The config load itself goes through the oakrender color C ABI;
|
||||
/// when oakrender is absent (cargo test) the manager still marks the
|
||||
/// config loaded with the built-in defaults so pure-graph consumers
|
||||
/// can query state.
|
||||
/// The oakrender color C ABI never exported the config-loading
|
||||
/// symbols, so this always took the "mark loaded with the built-in
|
||||
/// defaults" path (single-lib: the render call is removed and the
|
||||
/// deterministic equivalent kept).
|
||||
pub fn initialize(&mut self) -> crate::error::Result<()> {
|
||||
match crate::bridge::render::color_config_create_default() {
|
||||
Some(Err(())) => {
|
||||
return Err(crate::error::Error::Failed(
|
||||
"OCIO config creation failed".to_string(),
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
self.config_loaded = true;
|
||||
Ok(())
|
||||
}
|
||||
@@ -79,30 +71,18 @@ impl ColorManager {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// (Re)load the config from `config_filename` via the oakrender
|
||||
/// color C ABI (`oakrender_color_manager_*`); E_FAILED on OCIO
|
||||
/// (Re)load the config from `config_filename`; E_FAILED on OCIO
|
||||
/// errors. Missing/invalid files keep the previous config (C++
|
||||
/// `update_config_from_filename()`).
|
||||
/// `update_config_from_filename()`). The oakrender color C ABI never
|
||||
/// implemented the load, so the file-loaded path always kept the
|
||||
/// previous state (single-lib: the render call is removed).
|
||||
pub fn update_config_from_filename(&mut self) -> crate::error::Result<()> {
|
||||
if self.config_filename.is_empty() {
|
||||
// Empty filename selects the bundled default.
|
||||
self.config_loaded = true;
|
||||
return Ok(());
|
||||
}
|
||||
match crate::bridge::render::color_config_load(&self.config_filename) {
|
||||
Some(Ok(())) => {
|
||||
self.config_loaded = true;
|
||||
Ok(())
|
||||
}
|
||||
Some(Err(())) => {
|
||||
// Invalid file: keep the previous config (C++ tolerance).
|
||||
Ok(())
|
||||
}
|
||||
None => {
|
||||
// oakrender absent (tests): keep the previous state.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Enumerate colorspaces of the active config (two-stage lists are
|
||||
|
||||
@@ -37,45 +37,12 @@ pub struct RefBox<T: ?Sized> {
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
/// `#[repr(C)]` mirror of the public handle structs
|
||||
/// (`{ctx, addref, release, abi_version}`).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CHandle {
|
||||
/// Opaque box pointer.
|
||||
pub ctx: *mut std::ffi::c_void,
|
||||
/// Atomic increment.
|
||||
pub addref: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// Atomic decrement; destroys at zero.
|
||||
pub release: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// ABI version.
|
||||
pub abi_version: u32,
|
||||
}
|
||||
|
||||
impl CHandle {
|
||||
/// The empty handle.
|
||||
pub fn null() -> Self {
|
||||
Self {
|
||||
ctx: std::ptr::null_mut(),
|
||||
addref: None,
|
||||
release: None,
|
||||
abi_version: OAKNODE_ABI_VERSION,
|
||||
}
|
||||
}
|
||||
|
||||
/// True when `ctx` is null.
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ctx.is_null()
|
||||
}
|
||||
}
|
||||
|
||||
// CHandle is the C-side value handle (passed by value, copyable across
|
||||
// threads); `ctx` is an opaque box pointer. The addref/release functions
|
||||
// are atomic, so sharing the box between threads is the host's
|
||||
// dispatching contract (same rationale as the oakplugin crate's
|
||||
// handle.rs).
|
||||
unsafe impl Send for CHandle {}
|
||||
unsafe impl Sync for CHandle {}
|
||||
/// The shared ABI value-handle type (single-lib unification, see
|
||||
/// `docs/zh/plans/riir/single-lib.md`): one canonical
|
||||
/// `{ctx, addref, release, abi_version}` type in `oakcore-rs`, re-exported
|
||||
/// here so the crate's `ffi.rs` signatures and handle scaffolding stay
|
||||
/// source-compatible.
|
||||
pub use oakcore_rs::handle::CHandle;
|
||||
|
||||
/// addref 的实现:原子 +1。拥有型与借用型共用——借用型只延长盒子
|
||||
/// 的寿命,不延长被借用对象。
|
||||
|
||||
@@ -311,11 +311,9 @@ impl Project {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
// Default location: ask oakrender via the C ABI.
|
||||
match crate::bridge::render::disk_cache_path() {
|
||||
Some(path) => path,
|
||||
None => String::new(),
|
||||
}
|
||||
// Default location: the shared disk-cache directory (single-lib:
|
||||
// lives in oakcommon, used by oaknode and oakrender alike).
|
||||
oakcommon::filefunctions::default_disk_cache_path()
|
||||
}
|
||||
|
||||
/// Copy all settings from `src` into `self` (C++
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
// 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/>.
|
||||
|
||||
//! The shared ABI value-handle type (single-lib unification).
|
||||
//!
|
||||
//! Every module crate used to define its own `CHandle` with an identical
|
||||
//! `{ctx, addref, release, abi_version}` layout but a distinct Rust type,
|
||||
//! so cross-module calls had to cross an `extern "C"`/dlsym boundary.
|
||||
//! With the module-to-module calls going back to direct Rust calls (see
|
||||
//! `docs/zh/plans/riir/single-lib.md`), one canonical handle type lives
|
||||
//! here in `oakcore-rs` (the crate every module already depends on) and
|
||||
//! every crate re-exports it. The C layout is unchanged, so the frozen
|
||||
//! module C ABIs (`Oak<Mod><Type>*` handles in `include/<mod>/*.h`) are
|
||||
//! unaffected.
|
||||
|
||||
use std::ffi::c_void;
|
||||
|
||||
/// ABI value handle mirroring the C handle struct
|
||||
/// (`{ctx, addref, release, abi_version}`) from `include/common/handle.h`.
|
||||
///
|
||||
/// `ctx` points to an opaque refcounted box; `addref`/`release` are the
|
||||
/// box's atomic increment/decrement (release destroys at zero);
|
||||
/// `abi_version` is a tag stamped by each crate's `make_owned` (0 for
|
||||
/// empty handles). Structurally identical to every `Oak<Mod><Type>` value
|
||||
/// handle, so a handle can cross any module boundary by value.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct CHandle {
|
||||
/// Opaque box pointer.
|
||||
pub ctx: *mut c_void,
|
||||
/// Atomic increment.
|
||||
pub addref: Option<unsafe extern "C" fn(*mut c_void)>,
|
||||
/// Atomic decrement; destroys at zero.
|
||||
pub release: Option<unsafe extern "C" fn(*mut c_void)>,
|
||||
/// ABI version.
|
||||
pub abi_version: u32,
|
||||
}
|
||||
|
||||
impl CHandle {
|
||||
/// The empty handle.
|
||||
pub const fn null() -> Self {
|
||||
CHandle {
|
||||
ctx: std::ptr::null_mut(),
|
||||
addref: None,
|
||||
release: None,
|
||||
abi_version: 0,
|
||||
}
|
||||
} /// Whether this is the empty (zero) handle.
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ctx.is_null()
|
||||
}
|
||||
|
||||
/// Take an additional reference through the handle's `addref` and
|
||||
/// return the (now refcount-incremented) copy.
|
||||
///
|
||||
/// # Safety
|
||||
/// `self` must be a live handle returned by a module function.
|
||||
pub unsafe fn addref(&self) -> Self {
|
||||
let mut copy = *self;
|
||||
if let Some(addref) = copy.addref {
|
||||
let _ = &mut copy;
|
||||
unsafe {
|
||||
addref(copy.ctx);
|
||||
}
|
||||
}
|
||||
copy
|
||||
}
|
||||
}
|
||||
|
||||
/// The empty handle is the natural default (some crates derive `Default`
|
||||
/// on structs holding a handle).
|
||||
impl Default for CHandle {
|
||||
fn default() -> Self {
|
||||
Self::null()
|
||||
}
|
||||
}
|
||||
|
||||
// Handles follow the shared_ptr-like convention of
|
||||
// `include/common/handle.h`: they are opaque, refcounted and safe to
|
||||
// share across threads (the module crates use them behind mutexes).
|
||||
unsafe impl Send for CHandle {}
|
||||
unsafe impl Sync for CHandle {}
|
||||
@@ -25,6 +25,10 @@ mod rational;
|
||||
mod samplefmt;
|
||||
mod timerange;
|
||||
|
||||
/// Shared ABI value-handle type (see [`handle::CHandle`]).
|
||||
pub mod handle;
|
||||
|
||||
pub use handle::CHandle;
|
||||
pub use rational::Rational;
|
||||
pub use samplefmt::{PixelFormat, SampleFormat};
|
||||
pub use timerange::{TimeRange, TimeRangeList};
|
||||
|
||||
Generated
+5
@@ -18,11 +18,16 @@ version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de"
|
||||
|
||||
[[package]]
|
||||
name = "oakcore-rs"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "oakplugin"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"oakcore-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -17,7 +17,9 @@ crate-type = ["staticlib", "rlib"]
|
||||
panic = "unwind"
|
||||
|
||||
[dependencies]
|
||||
# 共享 ABI 类型(CHandle 等,单库化统一,见 docs/zh/plans/riir/single-lib.md)。
|
||||
# 只允许零依赖起步。确需引入的 crate 必须在 README 登记理由。
|
||||
oakcore-rs = { path = "../../oakcore-rs" }
|
||||
|
||||
[features]
|
||||
# oakrender 测试桩(库内 no_mangle 符号 + 状态访问器):cargo test
|
||||
|
||||
@@ -53,44 +53,12 @@ pub struct RefBox<T: ?Sized> {
|
||||
/// C 句柄的 Rust 镜像。`#[repr(C)]`,与 C 头文件布局一致。
|
||||
///
|
||||
/// 生命周期:`*_init`/`*_create` 返回计数 1 的拥有型句柄;
|
||||
/// `*_free(&h)` 释放一次并清空 `ctx`;`free(NULL)`/空句柄是 no-op。
|
||||
/// 值型(Clone/Copy:C 侧按值传句柄,复制后再 addref 是调用方
|
||||
/// 契约)。
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct CHandle {
|
||||
/// 不透明盒子指针(`RefBox<T>` 擦型后的 `*mut c_void`)。
|
||||
pub ctx: *mut std::ffi::c_void,
|
||||
/// 原子 +1。
|
||||
pub addref: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// 原子 -1,归零销毁。
|
||||
pub release: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// [`OAKPLUGIN_ABI_VERSION`]。
|
||||
pub abi_version: u32,
|
||||
}
|
||||
|
||||
// CHandle 是 C 侧值型句柄(按值传、可跨线程复制);`ctx` 是
|
||||
// 不透明盒子指针,跨线程搬运是宿主分发语义(multithread suite
|
||||
// 允许插件线程回调任意 suite)。
|
||||
unsafe impl Send for CHandle {}
|
||||
unsafe impl Sync for CHandle {}
|
||||
|
||||
impl CHandle {
|
||||
/// 空句柄(`ctx == NULL`)。
|
||||
pub fn null() -> Self {
|
||||
Self {
|
||||
ctx: std::ptr::null_mut(),
|
||||
addref: None,
|
||||
release: None,
|
||||
abi_version: OAKPLUGIN_ABI_VERSION,
|
||||
}
|
||||
}
|
||||
|
||||
/// 是否为空调用面(`ctx` 为空)。
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ctx.is_null()
|
||||
}
|
||||
}
|
||||
/// The shared ABI value-handle type (single-lib unification, see
|
||||
/// `docs/zh/plans/riir/single-lib.md`): one canonical
|
||||
/// `{ctx, addref, release, abi_version}` type in `oakcore-rs`, re-exported
|
||||
/// here so the crate's `ffi.rs` signatures and handle scaffolding stay
|
||||
/// source-compatible. `Send + Sync` come from the shared type.
|
||||
pub use oakcore_rs::handle::CHandle;
|
||||
|
||||
/// addref 的实现:原子 +1。拥有型与借用型共用——借用型只延长盒子
|
||||
/// 的寿命,不延长被借用对象。
|
||||
|
||||
Generated
+150
@@ -2,6 +2,12 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.6"
|
||||
@@ -94,6 +100,12 @@ dependencies = [
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder-lite"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.4.2"
|
||||
@@ -163,6 +175,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.4"
|
||||
@@ -184,12 +205,28 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "fax"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a"
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.1.5"
|
||||
@@ -369,6 +406,19 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.25.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder-lite",
|
||||
"moxcms",
|
||||
"num-traits",
|
||||
"tiff",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.14.0"
|
||||
@@ -487,6 +537,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||
|
||||
[[package]]
|
||||
name = "metal"
|
||||
version = "0.31.0"
|
||||
@@ -502,6 +558,26 @@ dependencies = [
|
||||
"paste",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "moxcms"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"pxfm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "25.0.1"
|
||||
@@ -546,6 +622,17 @@ dependencies = [
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oakcommon"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"image",
|
||||
"log",
|
||||
"oakcore-rs",
|
||||
"ocio-rs",
|
||||
"quick-xml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oakcore-rs"
|
||||
version = "0.1.0"
|
||||
@@ -554,6 +641,7 @@ version = "0.1.0"
|
||||
name = "oakrender"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"oakcommon",
|
||||
"oakcore-rs",
|
||||
"ocio-rs",
|
||||
"wgpu",
|
||||
@@ -671,6 +759,27 @@ version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5"
|
||||
|
||||
[[package]]
|
||||
name = "pxfm"
|
||||
version = "0.1.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea"
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.41.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.47"
|
||||
@@ -761,6 +870,12 @@ version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.12"
|
||||
@@ -890,6 +1005,20 @@ dependencies = [
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiff"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52"
|
||||
dependencies = [
|
||||
"fax",
|
||||
"flate2",
|
||||
"half",
|
||||
"quick-error",
|
||||
"weezl",
|
||||
"zune-jpeg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
@@ -973,6 +1102,12 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "weezl"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
|
||||
|
||||
[[package]]
|
||||
name = "wgpu"
|
||||
version = "25.0.2"
|
||||
@@ -1297,3 +1432,18 @@ dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zune-core"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d56377fd46368984a170bc5aac5567e52ca5da874caa60bea39fcbca78fb658b"
|
||||
|
||||
[[package]]
|
||||
name = "zune-jpeg"
|
||||
version = "0.5.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296"
|
||||
dependencies = [
|
||||
"zune-core",
|
||||
]
|
||||
|
||||
@@ -15,6 +15,7 @@ panic = "unwind"
|
||||
|
||||
[dependencies]
|
||||
oakcore-rs = { path = "../../oakcore-rs" }
|
||||
oakcommon = { path = "../../common/rust" }
|
||||
# wgpu: portable GPU backend (Metal/Vulkan/GL/DX12 in one safe API) — the
|
||||
# direct replacement for the C++ liboakgl2/liboakvulkan backend plugins.
|
||||
# Version 25 (2025 stable line); the only GPU dependency.
|
||||
|
||||
@@ -16,79 +16,11 @@
|
||||
|
||||
//! The cancellation primitive (`olive::CancelAtom`): a thread-safe cancel
|
||||
//! flag shared between a render/encode caller and its worker.
|
||||
//!
|
||||
//! Single-lib unification (see `docs/zh/plans/riir/single-lib.md`): the
|
||||
//! implementation moved to oakcommon; this module re-exports it so the
|
||||
//! render ffi's `oakrender_cancelatom_*` exports (and their C-ABI
|
||||
//! consumers, e.g. oakcodec) keep working unchanged.
|
||||
|
||||
use std::sync::{Mutex, MutexGuard};
|
||||
|
||||
/// A cancellation atom (C++ `CancelAtom`). Reading a set flag also records
|
||||
/// that a consumer heard the cancellation.
|
||||
#[derive(Default)]
|
||||
pub struct CancelAtom {
|
||||
state: Mutex<AtomState>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct AtomState {
|
||||
cancelled: bool,
|
||||
heard: bool,
|
||||
}
|
||||
|
||||
fn lock(m: &Mutex<AtomState>) -> MutexGuard<'_, AtomState> {
|
||||
m.lock().unwrap_or_else(|e| e.into_inner())
|
||||
}
|
||||
|
||||
impl CancelAtom {
|
||||
/// A not-cancelled atom.
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Set the cancel flag (C++ `CancelAtom::cancel()`).
|
||||
pub fn cancel(&self) {
|
||||
lock(&self.state).cancelled = true;
|
||||
}
|
||||
|
||||
/// Read the cancel flag; reading a set flag records that the
|
||||
/// cancellation was heard (C++ `is_cancelled()`).
|
||||
pub fn is_cancelled(&self) -> bool {
|
||||
let mut s = lock(&self.state);
|
||||
if s.cancelled {
|
||||
s.heard = true;
|
||||
}
|
||||
s.cancelled
|
||||
}
|
||||
|
||||
/// Whether any consumer has observed the cancel flag through
|
||||
/// [`CancelAtom::is_cancelled`] (C++ `heard_cancel()`).
|
||||
pub fn heard_cancel(&self) -> bool {
|
||||
lock(&self.state).heard
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn fresh_atom_is_not_cancelled() {
|
||||
let a = CancelAtom::new();
|
||||
assert!(!a.is_cancelled());
|
||||
assert!(!a.heard_cancel());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancel_sets_flag_and_reading_marks_heard() {
|
||||
let a = CancelAtom::new();
|
||||
a.cancel();
|
||||
assert!(!a.heard_cancel(), "not heard until read");
|
||||
assert!(a.is_cancelled());
|
||||
assert!(a.heard_cancel(), "reading a set flag marks it heard");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repeated_cancel_is_idempotent() {
|
||||
let a = CancelAtom::new();
|
||||
a.cancel();
|
||||
a.cancel();
|
||||
assert!(a.is_cancelled());
|
||||
}
|
||||
}
|
||||
/// Shared cancellation atom (oakcommon).
|
||||
pub use oakcommon::cancelatom::CancelAtom;
|
||||
|
||||
@@ -926,13 +926,8 @@ pub mod cache {
|
||||
if !std::path::Path::new(&filename).exists() {
|
||||
return Err(crate::error::Error::NotFound);
|
||||
}
|
||||
// Payload decode belongs to the oakcodec crate (EXR/JPEG).
|
||||
// Without it the file exists but cannot be decoded.
|
||||
if !crate::bridge::codec::codec_abi_available() {
|
||||
return Err(crate::error::Error::Failed(
|
||||
"oakcodec C ABI not present (frame decode pending)".into(),
|
||||
));
|
||||
}
|
||||
// Payload decode belongs to the oakcodec crate (EXR/JPEG),
|
||||
// deferred; without it the file exists but cannot be decoded.
|
||||
Err(crate::error::Error::Failed(
|
||||
"oakcodec frame decode bridge pending".into(),
|
||||
))
|
||||
|
||||
@@ -42,42 +42,12 @@ pub struct RefBox<T: ?Sized> {
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
/// `#[repr(C)]` mirror of the public handle structs.
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct CHandle {
|
||||
/// Opaque box pointer.
|
||||
pub ctx: *mut std::ffi::c_void,
|
||||
/// Atomic increment.
|
||||
pub addref: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// Atomic decrement; destroys at zero.
|
||||
pub release: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// ABI version.
|
||||
pub abi_version: u32,
|
||||
}
|
||||
|
||||
// CHandle is a by-value handle (copied across threads per the shared_ptr
|
||||
// semantics documented in the public headers); `ctx` is an opaque box
|
||||
// pointer, and moving the struct itself never dereferences it.
|
||||
unsafe impl Send for CHandle {}
|
||||
unsafe impl Sync for CHandle {}
|
||||
|
||||
impl CHandle {
|
||||
/// The empty handle.
|
||||
pub fn null() -> Self {
|
||||
Self {
|
||||
ctx: std::ptr::null_mut(),
|
||||
addref: None,
|
||||
release: None,
|
||||
abi_version: OAKRENDER_ABI_VERSION,
|
||||
}
|
||||
}
|
||||
|
||||
/// True when `ctx` is null.
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ctx.is_null()
|
||||
}
|
||||
}
|
||||
/// The shared ABI value-handle type (single-lib unification, see
|
||||
/// `docs/zh/plans/riir/single-lib.md`): one canonical
|
||||
/// `{ctx, addref, release, abi_version}` type in `oakcore-rs`, re-exported
|
||||
/// here so the crate's `ffi.rs` signatures and handle scaffolding stay
|
||||
/// source-compatible. `Send + Sync` come from the shared type.
|
||||
pub use oakcore_rs::handle::CHandle;
|
||||
|
||||
/// Global live-object count (owned handles + cancel-atom boxes).
|
||||
static ALIVE_COUNT: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
@@ -132,9 +132,10 @@ impl RenderManager {
|
||||
}
|
||||
|
||||
/// The default disk cache directory (C++ `DiskManager::
|
||||
/// get_default_disk_cache_path`).
|
||||
/// get_default_disk_cache_path`); shared with oaknode via oakcommon
|
||||
/// (single-lib unification).
|
||||
pub fn disk_cache_path() -> String {
|
||||
crate::bridge::common::default_disk_cache_path()
|
||||
oakcommon::filefunctions::default_disk_cache_path()
|
||||
}
|
||||
|
||||
/// Bytes consumed by the default disk cache folder (direct filesystem
|
||||
|
||||
Generated
+135
@@ -2,6 +2,12 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.6"
|
||||
@@ -94,6 +100,12 @@ dependencies = [
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder-lite"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.4.2"
|
||||
@@ -163,6 +175,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.4"
|
||||
@@ -184,12 +205,28 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "fax"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a"
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.1.5"
|
||||
@@ -369,6 +406,19 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.25.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder-lite",
|
||||
"moxcms",
|
||||
"num-traits",
|
||||
"tiff",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.14.0"
|
||||
@@ -514,6 +564,26 @@ dependencies = [
|
||||
"paste",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "moxcms"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"pxfm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "25.0.1"
|
||||
@@ -558,6 +628,17 @@ dependencies = [
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oakcommon"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"image",
|
||||
"log",
|
||||
"oakcore-rs",
|
||||
"ocio-rs",
|
||||
"quick-xml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oakcore-rs"
|
||||
version = "0.1.0"
|
||||
@@ -576,6 +657,7 @@ dependencies = [
|
||||
name = "oakrender"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"oakcommon",
|
||||
"oakcore-rs",
|
||||
"ocio-rs",
|
||||
"wgpu",
|
||||
@@ -702,6 +784,18 @@ version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5"
|
||||
|
||||
[[package]]
|
||||
name = "pxfm"
|
||||
version = "0.1.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea"
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.41.0"
|
||||
@@ -815,6 +909,12 @@ version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.12"
|
||||
@@ -944,6 +1044,20 @@ dependencies = [
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiff"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52"
|
||||
dependencies = [
|
||||
"fax",
|
||||
"flate2",
|
||||
"half",
|
||||
"quick-error",
|
||||
"weezl",
|
||||
"zune-jpeg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
@@ -1027,6 +1141,12 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "weezl"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
|
||||
|
||||
[[package]]
|
||||
name = "wgpu"
|
||||
version = "25.0.2"
|
||||
@@ -1357,3 +1477,18 @@ name = "zmij"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
||||
|
||||
[[package]]
|
||||
name = "zune-core"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d56377fd46368984a170bc5aac5567e52ca5da874caa60bea39fcbca78fb658b"
|
||||
|
||||
[[package]]
|
||||
name = "zune-jpeg"
|
||||
version = "0.5.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296"
|
||||
dependencies = [
|
||||
"zune-core",
|
||||
]
|
||||
|
||||
@@ -33,29 +33,12 @@ pub struct RefBox<T: ?Sized> {
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
/// `#[repr(C)]` mirror of the public handle structs
|
||||
/// (`{ctx, addref, release, abi_version}`).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct CHandle {
|
||||
/// Opaque box pointer.
|
||||
pub ctx: *mut std::ffi::c_void,
|
||||
/// Atomic increment.
|
||||
pub addref: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// Atomic decrement; destroys at zero.
|
||||
pub release: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// ABI version.
|
||||
pub abi_version: u32,
|
||||
}
|
||||
|
||||
// Handles are shared between the calling thread and the manager worker
|
||||
// threads (same ownership model as a C++ shared_ptr). The raw pointer and
|
||||
// function-pointer fields are inherently `!Send`/`!Sync`; the box behind
|
||||
// `ctx` is either `Send + Sync` (task state, atomics) or a plain pointer
|
||||
// (borrowed handles), both of which are safe to share through the
|
||||
// refcounted handle.
|
||||
unsafe impl Send for CHandle {}
|
||||
unsafe impl Sync for CHandle {}
|
||||
/// The shared ABI value-handle type (single-lib unification, see
|
||||
/// `docs/zh/plans/riir/single-lib.md`): one canonical
|
||||
/// `{ctx, addref, release, abi_version}` type in `oakcore-rs`, re-exported
|
||||
/// here so the crate's `ffi.rs` signatures and handle scaffolding stay
|
||||
/// source-compatible. `Send + Sync` come from the shared type.
|
||||
pub use oakcore_rs::handle::CHandle;
|
||||
|
||||
unsafe extern "C" fn noop_addref(_ctx: *mut std::ffi::c_void) {}
|
||||
|
||||
@@ -101,24 +84,6 @@ unsafe extern "C" fn borrowed_release<T: 'static>(ctx: *mut std::ffi::c_void) {
|
||||
}
|
||||
}
|
||||
|
||||
impl CHandle {
|
||||
/// The empty handle. `ctx` is null but the fn pointers and ABI version
|
||||
/// are stamped so callers can unconditionally call `release`.
|
||||
pub fn null() -> Self {
|
||||
CHandle {
|
||||
ctx: std::ptr::null_mut(),
|
||||
addref: Some(noop_addref),
|
||||
release: Some(noop_release),
|
||||
abi_version: OAKTASK_ABI_VERSION,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the handle is empty (`ctx == NULL`).
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ctx.is_null()
|
||||
}
|
||||
}
|
||||
|
||||
/// Owned handle with count 1; empty on allocation failure.
|
||||
pub fn make_owned<T: Send + 'static>(value: T) -> CHandle {
|
||||
let b = Box::new(RefBox { refs: AtomicU32::new(1), value });
|
||||
|
||||
@@ -53,20 +53,15 @@ fn abi_version_is_one() {
|
||||
assert_eq!(OAKTASK_ABI_VERSION, 1);
|
||||
}
|
||||
|
||||
/// Given a null handle, `CHandle::null()` has a null ctx, non-null
|
||||
/// addref/release, and the stamped ABI version.
|
||||
/// Given a null handle, `CHandle::null()` has a null ctx, no addref/
|
||||
/// release fn pointers and no ABI version (single-lib unification).
|
||||
#[test]
|
||||
fn null_handle_contract() {
|
||||
let h = CHandle::null();
|
||||
assert!(h.ctx.is_null());
|
||||
assert!(h.addref.is_some(), "null handle addref must be callable");
|
||||
assert!(h.release.is_some(), "null handle release must be callable");
|
||||
assert_eq!(h.abi_version, OAKTASK_ABI_VERSION);
|
||||
// The empty handle is a no-op for both ops (never touches memory).
|
||||
unsafe {
|
||||
h.addref.unwrap()(h.ctx);
|
||||
h.release.unwrap()(h.ctx);
|
||||
}
|
||||
assert!(h.addref.is_none(), "null handle addref is empty");
|
||||
assert!(h.release.is_none(), "null handle release is empty");
|
||||
assert_eq!(h.abi_version, 0);
|
||||
// `is_null` reflects the ctx.
|
||||
assert!(h.is_null());
|
||||
}
|
||||
@@ -91,7 +86,11 @@ fn handle_size_and_owned_release() {
|
||||
}
|
||||
// The boxed value was dropped; a null handle still works afterwards.
|
||||
let null_h = CHandle::null();
|
||||
unsafe {
|
||||
null_h.release.unwrap()(null_h.ctx);
|
||||
// The shared null() carries no fn pointers; releasing goes through
|
||||
// the `if let Some` path (a no-op for empty handles).
|
||||
if let Some(release) = null_h.release {
|
||||
unsafe {
|
||||
release(null_h.ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,20 +38,12 @@ pub struct RefBox<T: ?Sized> {
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
/// `#[repr(C)]` mirror of the public handle structs
|
||||
/// (`{ctx, addref, release, abi_version}`).
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct CHandle {
|
||||
/// Opaque box pointer.
|
||||
pub ctx: *mut std::ffi::c_void,
|
||||
/// Atomic increment.
|
||||
pub addref: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// Atomic decrement; destroys at zero.
|
||||
pub release: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// ABI version.
|
||||
pub abi_version: u32,
|
||||
}
|
||||
/// The shared ABI value-handle type (single-lib unification, see
|
||||
/// `docs/zh/plans/riir/single-lib.md`): one canonical
|
||||
/// `{ctx, addref, release, abi_version}` type in `oakcore-rs`, re-exported
|
||||
/// here so the crate's `ffi.rs` signatures and handle scaffolding stay
|
||||
/// source-compatible.
|
||||
pub use oakcore_rs::handle::CHandle;
|
||||
|
||||
/// Generic `addref` implementation: increments the box's reference count.
|
||||
///
|
||||
@@ -82,23 +74,6 @@ unsafe extern "C" fn release_box<T: 'static>(ptr: *mut c_void) {
|
||||
}
|
||||
}
|
||||
|
||||
impl CHandle {
|
||||
/// The empty handle.
|
||||
pub fn null() -> Self {
|
||||
CHandle {
|
||||
ctx: std::ptr::null_mut(),
|
||||
addref: None,
|
||||
release: None,
|
||||
abi_version: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether this is the empty (all-null) handle.
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ctx.is_null()
|
||||
}
|
||||
}
|
||||
|
||||
/// Owned handle with count 1; empty on allocation failure.
|
||||
pub fn make_owned<T: Send + 'static>(value: T) -> CHandle {
|
||||
let boxed = Box::new(RefBox {
|
||||
|
||||
+15
-64
@@ -48,63 +48,14 @@ use crate::undostack::UndoStack;
|
||||
/// [`crate::handle`].
|
||||
|
||||
/// `include/undo/undocommand.h` handle type — `OakUndoCommand`
|
||||
/// (`{ctx, addref, release, abi_version}`).
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct OakUndoCommand {
|
||||
/// Opaque box pointer.
|
||||
pub ctx: *mut c_void,
|
||||
/// Atomic increment.
|
||||
pub addref: Option<unsafe extern "C" fn(*mut c_void)>,
|
||||
/// Atomic decrement; destroys at zero.
|
||||
pub release: Option<unsafe extern "C" fn(*mut c_void)>,
|
||||
/// OAKUNDO_ABI_VERSION.
|
||||
pub abi_version: u32,
|
||||
}
|
||||
/// (`{ctx, addref, release, abi_version}`). Single-lib unification:
|
||||
/// aliases the shared [`CHandle`] (identical layout; the C ABI is
|
||||
/// unchanged).
|
||||
pub type OakUndoCommand = CHandle;
|
||||
|
||||
/// `include/undo/undostack.h` handle type — `OakUndoStack`.
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct OakUndoStack {
|
||||
/// Opaque box pointer.
|
||||
pub ctx: *mut c_void,
|
||||
/// Atomic increment.
|
||||
pub addref: Option<unsafe extern "C" fn(*mut c_void)>,
|
||||
/// Atomic decrement; destroys at zero.
|
||||
pub release: Option<unsafe extern "C" fn(*mut c_void)>,
|
||||
/// OAKUNDO_ABI_VERSION.
|
||||
pub abi_version: u32,
|
||||
}
|
||||
|
||||
/// Field-copy [`OakUndoStack`] into a [`CHandle`].
|
||||
fn chandle_from_stack(stack: OakUndoStack) -> CHandle {
|
||||
CHandle {
|
||||
ctx: stack.ctx,
|
||||
addref: stack.addref,
|
||||
release: stack.release,
|
||||
abi_version: stack.abi_version,
|
||||
}
|
||||
}
|
||||
|
||||
/// Field-copy a [`CHandle`] into an [`OakUndoStack`].
|
||||
fn stack_from_chandle(handle: CHandle) -> OakUndoStack {
|
||||
OakUndoStack {
|
||||
ctx: handle.ctx,
|
||||
addref: handle.addref,
|
||||
release: handle.release,
|
||||
abi_version: handle.abi_version,
|
||||
}
|
||||
}
|
||||
|
||||
/// Field-copy a [`CHandle`] into an [`OakUndoCommand`].
|
||||
fn command_from_chandle(handle: CHandle) -> OakUndoCommand {
|
||||
OakUndoCommand {
|
||||
ctx: handle.ctx,
|
||||
addref: handle.addref,
|
||||
release: handle.release,
|
||||
abi_version: handle.abi_version,
|
||||
}
|
||||
}
|
||||
/// `include/undo/undostack.h` handle type — `OakUndoStack`. Single-lib
|
||||
/// unification: aliases the shared [`CHandle`].
|
||||
pub type OakUndoStack = CHandle;
|
||||
|
||||
/// Lock the stack behind `stack` and run `f` on it. `E_INVALID` for an
|
||||
/// empty handle. A poisoned mutex is recovered (its inner value is
|
||||
@@ -112,7 +63,7 @@ fn command_from_chandle(handle: CHandle) -> OakUndoCommand {
|
||||
fn with_stack<R>(stack: OakUndoStack, f: impl FnOnce(&mut UndoStack) -> Result<R>) -> Result<R> {
|
||||
// Keep a local handle so `get`'s returned reference lives for the
|
||||
// whole call (its lifetime ties to the `&CHandle` argument).
|
||||
let ch = chandle_from_stack(stack);
|
||||
let ch = stack;
|
||||
let m = unsafe { crate::handle::get::<Mutex<UndoStack>>(&ch) }.ok_or(Error::Invalid)?;
|
||||
let mut guard = m.lock().unwrap_or_else(|e| e.into_inner());
|
||||
f(&mut guard)
|
||||
@@ -143,21 +94,21 @@ pub mod command {
|
||||
vtable: *const OakUndoCommandVtable,
|
||||
userdata: *mut c_void,
|
||||
) -> OakUndoCommand {
|
||||
command_from_chandle(guard_handle(|| unsafe {
|
||||
guard_handle(|| unsafe {
|
||||
if vtable.is_null() {
|
||||
return Ok(CHandle::null());
|
||||
}
|
||||
let table = *vtable;
|
||||
Ok(command_from_owned(UndoCommand::from_vtable(table, userdata)))
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
/// `oakundo_command_init_multi`: empty multi command, refcount 1.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn oakundo_command_init_multi() -> OakUndoCommand {
|
||||
command_from_chandle(guard_handle(|| unsafe {
|
||||
guard_handle(|| unsafe {
|
||||
Ok(command_from_owned(UndoCommand::multi()))
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
/// `oakundo_command_multi_add_child` (stack takes one child ref).
|
||||
@@ -216,7 +167,7 @@ pub mod command {
|
||||
}
|
||||
let child = parent.multi_child(index as usize)?;
|
||||
let ptr = child as *const UndoCommand as *mut UndoCommand;
|
||||
*out_child = command_from_chandle(command_from_borrowed(ptr));
|
||||
*out_child = command_from_borrowed(ptr);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@@ -272,9 +223,9 @@ pub mod undostack {
|
||||
/// `oakundo_undostack_init`: fresh stack, refcount 1.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn oakundo_undostack_init() -> OakUndoStack {
|
||||
stack_from_chandle(guard_handle(|| {
|
||||
guard_handle(|| {
|
||||
Ok(make_owned(Mutex::new(UndoStack::new())))
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
/// `oakundo_undostack_free`: NULL/empty no-op; clears `stack->ctx`.
|
||||
|
||||
@@ -34,36 +34,12 @@ pub struct RefBox<T: ?Sized> {
|
||||
pub value: T,
|
||||
}
|
||||
|
||||
/// `#[repr(C)]` mirror of the public handle structs
|
||||
/// (`{ctx, addref, release, abi_version}`).
|
||||
#[repr(C)]
|
||||
pub struct CHandle {
|
||||
/// Opaque box pointer.
|
||||
pub ctx: *mut std::ffi::c_void,
|
||||
/// Atomic increment.
|
||||
pub addref: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// Atomic decrement; destroys at zero.
|
||||
pub release: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
|
||||
/// ABI version.
|
||||
pub abi_version: u32,
|
||||
}
|
||||
|
||||
impl CHandle {
|
||||
/// The empty handle.
|
||||
pub fn null() -> Self {
|
||||
CHandle {
|
||||
ctx: std::ptr::null_mut(),
|
||||
addref: None,
|
||||
release: None,
|
||||
abi_version: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether this is the empty (zero) handle.
|
||||
pub fn is_null(&self) -> bool {
|
||||
self.ctx.is_null()
|
||||
}
|
||||
}
|
||||
/// The shared ABI value-handle type (single-lib unification, see
|
||||
/// `docs/zh/plans/riir/single-lib.md`): one canonical
|
||||
/// `{ctx, addref, release, abi_version}` type in `oakcore-rs`, re-exported
|
||||
/// here so the crate's `ffi.rs` signatures and handle scaffolding stay
|
||||
/// source-compatible.
|
||||
pub use oakcore_rs::handle::CHandle;
|
||||
|
||||
/// Owned handle with count 1; empty on allocation failure.
|
||||
pub fn make_owned<T: Send + 'static>(value: T) -> CHandle {
|
||||
|
||||
@@ -38,6 +38,7 @@ use oakundo::ffi::undostack::{
|
||||
oakundo_undostack_redo, oakundo_undostack_undo,
|
||||
};
|
||||
use oakundo::ffi::{OakUndoCommand, OakUndoStack};
|
||||
use oakundo::handle::CHandle;
|
||||
use oakundo::handle::OAKUNDO_ABI_VERSION;
|
||||
use oakundo::undocommand::OakUndoCommandVtable;
|
||||
|
||||
@@ -103,7 +104,7 @@ unsafe fn make_cmd(probe: *mut Probe) -> OakUndoCommand {
|
||||
|
||||
/// An empty (all-zero) command handle.
|
||||
fn empty_cmd() -> OakUndoCommand {
|
||||
OakUndoCommand {
|
||||
CHandle {
|
||||
ctx: std::ptr::null_mut(),
|
||||
addref: None,
|
||||
release: None,
|
||||
@@ -113,7 +114,7 @@ fn empty_cmd() -> OakUndoCommand {
|
||||
|
||||
/// An empty (all-zero) stack handle.
|
||||
fn empty_stack() -> OakUndoStack {
|
||||
OakUndoStack {
|
||||
CHandle {
|
||||
ctx: std::ptr::null_mut(),
|
||||
addref: None,
|
||||
release: None,
|
||||
|
||||
Reference in New Issue
Block a user