Files
oak-editor/crates/oakplugin/examples/scan_probe.rs
T
Mike-Solar 5498504398 fix(plugin): full OFX plugin discovery — host conformance fixes
Real openfx-misc/CImg/Shadertoy bundles (148 plugins at
/Library/OFX/Plugins) all failed to load before; every failure was
silent. Root causes found one by one with a probe example + lldb:

- property suite rejected propSet on undefined properties and
  propGetDimension on empty ones, and disallowed the index==size
  append — OFX semantics are create-on-set and appendable dimensions
  (this alone failed every plugin's describe)
- host property set missed the mandatory OfxPropType/OfxPropAPIVersion
  and the capability props ofxs' fetchHostDescription reads with
  throwOnFailure=true (IsBackground, TemporalClipAccess, MaxPages,
  PageRowColumnCount, host SupportedContexts, ...) — one missing prop
  aborted the read chain and left a half-initialised host description,
  which made every temporal plugin refuse to load
- MultiThreadSuiteV1 lacked the five mutex functions (the plugin reads
  past the short table — UB); implemented as a real counting-semaphore
  registry
- the OfxHost struct was a stack local; ofxs keeps the POINTER past
  setHost, so describe/render-time fetchSuite calls dereferenced a
  dangling stack address (bus error once plugins actually loaded) —
  the struct is now a leaked process global
- General is a standard OFX context and is no longer filtered out
  (Roto/AppendClip/STMap declare only it)
- every scan/load/describe early-out now logs its reason; suite entry
  points report non-OK statuses with caller location under
  OAK_OFX_TRACE
- examples/scan_probe.rs: scans the real plugin dirs and prints
  discovered/registered counts (also usable from CI)

Result: 148/148 plugins discovered, 134 registered as node types (the
remaining 14 need vendor suites — Vegas stereoscopic etc. — and are
logged, not silent)
2026-08-20 22:28:23 +08:00

29 lines
1.1 KiB
Rust

//! Throwaway probe: scan the real system OFX directory and print what the
//! host actually discovers (diagnosing why the effect library is empty).
fn main() {
let host = oakplugin::host::Host::global();
match host.cache.scan() {
Ok(()) => println!("scan: ok"),
Err(e) => println!("scan: FAILED: {e}"),
}
println!("plugins discovered: {}", host.cache.count());
// Direct probe: read the host-level props through the C suite table.
let suite = oakplugin::suites::property::suite_v1();
unsafe {
let handle = &host.props as *const oakplugin::property::PropertySet as *mut std::ffi::c_void;
let name = std::ffi::CString::new("OfxPropName").unwrap();
let mut out: *mut std::ffi::c_char = std::ptr::null_mut();
let stat = (suite.get_string)(handle, name.as_ptr(), 0, &mut out);
println!("direct propGetString(OfxPropName) -> {stat}");
if stat == 0 && !out.is_null() {
println!(" value: {:?}", std::ffi::CStr::from_ptr(out));
}
}
let registered = oakplugin::node_factory::register_plugin_nodes();
println!("factory node types registered: {}", registered.len());
for id in &registered {
println!(" type_id={id}");
}
}