timeremap: add keyframe type support and curve visualization to RemapView
Adds per-keyframe interpolation types to the Time Remapping panel, so speed changes can ease in and out instead of switching abruptly at every keyframe boundary. Each keyframe can be set to its own interpolation type from a new Type selector, and a curve band showing the actual interpolated shape is drawn between the existing input and output rulers.
The selector offers the 13 interpolation types the effect stack already uses elsewhere, which is everything in KeyframeModel::getKeyframeTypes() apart from the deprecated Curve entry. Bounce and elastic are worth calling out: they overshoot the keyframe value, and on a time map an overshoot means source time briefly runs backwards, so the clip plays in reverse for a few frames around the keyframe. Measured against MLT over a 50 frame span, bounce runs backwards for 16 frames and elastic for 23, with elastic also reaching source positions outside the clip's own duration. They are included because that behavior is usable on purpose, and are listed last so the well behaved types come first. Exponential and circular were expected to overshoot as well but measured clean, staying monotonic and in range.
What changed
- Each keyframe stores its own interpolation type, keyed by output position in
m_keyframeTypes. An absent key means linear, so existing projects load as all linear with no migration step - Types are serialized through MLT's own animation API (
anim_setwith anmlt_keyframe_type, thenserialize_cut) rather than by hand, so thetime_mapstring stays in whatever format MLT expects. Parsing reads the type back withMlt::Animation::key_get - A Type combo box in the remap dialog sets the type of the currently selected keyframe, and follows the selection as it changes
- The curve is sampled per pixel from the parsed
time_mapanimation, so what is drawn is what MLT will actually play back rather than a redrawn approximation of the keyframe values - The curve is drawn between the two rulers as an additional band. The existing input and output rulers, keyframe dragging, and the before/after speed spinboxes are unchanged
- Keyframe types follow their keyframes through drags, clip resizes, and deletion, and are captured in the undo and redo lambdas alongside the keyframe positions
Screenshots
Type selector with Linear selected: 
Type selector with Cubic In selected: 
Testing
Manually verified in the running app:
- Existing projects with time remapping load with all keyframes linear, and play back exactly as before
- Setting a keyframe to Smooth, Cubic In or Cubic Out changes the curve shape in the panel, and the speed ramp is audible and visible in playback
- The drawn curve follows the selected type, and matches the direction of the speed change either side of the keyframe
- Undo and redo through a series of type changes restores both the type and the curve, with no crash and no desync between the combo box and the drawn curve
- Types survive dragging a keyframe, resizing the clip from either end, and deleting a neighbouring keyframe
- Saving and reopening a project preserves the types
- Linear-only projects round trip through save and reload without gaining any type properties
Notes
- The type list was expanded from an initial curated four to the full 13 after review, and the Type selector now sits in the toolbar next to the keyframe buttons rather than below the speed fields
- Build is clean with no new warnings
- No unit tests added this time.
RemapViewis aQWidgetholding the remap state in the widget itself, so the type storage and serialization are not reachable from the existing test harness without splitting them out first