facade (oakengine/oaknode, API only extended):
- oaknode_node_get_effect_input / oaknode_node_get_flags module exports
- oakengine_clip_as_node, oakengine_node_effect_count/at/insert/remove/
move/set_enabled, oakengine_node_identity/is_enabled/get_type_id,
oakengine_node_factory_id_at — chain edits wrap disconnect/reconnect
into single undo groups; insert/move/remove validated against the
factory and the host's effect input
- it_node covers enumeration/insert/remove/move/toggle/undo-redo and
the NULL/illegal-input matrix
app:
- RealEngine binds the selected clip's effect chain to the inspector's
effect stack (cards, enable, reorder, remove, expansion state), all
edits undoable through the facade
- AppEngine gains set_selected_clips / addable_effects / add_effect
(default no-ops keep the mock untouched); the timeline selection
drives the stack target; the inspector gets a small add-effect menu
- known module gap (documented): ClipBlockBehavior sets no effect_input
yet, so timeline clips cannot host effects until oaknode grows tex_in
- processor.rs: resample/channel-convert/time-stretch now runs an
in-process FFmpeg filter graph (abuffer -> atempo -> aformat ->
abuffersink) via ffmpeg-next
- waveform.rs: extraction decodes through oakcodec's FFmpegDecoder
(interleaved f32) instead of the fb_decoder/fb_audio_graph pair
- bridge/ffmpeg.rs and the null fb_* test stubs deleted;
oakcommon::ffmpegutils bridge constants become plain ints
- liboakengine.dylib no longer imports any fb_* symbol (nm -u clean);
the remaining runtime imports are the host-provided oakcore_* symbols
- real decode/resample tests added (generated PCM input, no network)