Add visible, keyframeable track volume filters #1907

Open
bmatherly opened 1:08pm on August 30, 2026 wants to merge 446 Δ into mltframework/shotcut master from
track_volume_filter

Pull Request Overview

  • Opened on August 30, 2026
  • Status Open
  • Commit count 3 with first commit August 30, 2026

Total Delta

446 Total Diff Delta

Open Days

Open 15 weekdays

Test Delta

0 Diff Delta in Test Files
Breakdown by Phase

How long has this pull request spent in each phase of its lifecycle?

Fraction of total time Business days Phase
 
0.2 days Authoring 1 commit before pull request opened for review
 
0.0 days Awaiting first review
 
15.1 days Revising work with 2 commits in response to 1 review that left 16 comments

Total time for pull request still awaiting merge (longer than repo's target): 15.3 business days

Author avatar

Add visible, keyframeable track volume filters

Create a Track Volume Audio Gain filter on demand when a track gain changes. Expose it in Filters with a track-specific heading, synchronize its name after track renames and moves, and keep timeline/header/filter-panel gain controls in sync, including animated values during playback.

Keep the filter last among visible track filters and prevent reordering it. It remains deletable; deleting it resets the track gain to 0 dB. Copying it creates a normal Audio Gain filter without the Track Volume marker.

I'm posting this for consideration and discussion. The current track volume sliders create a hidden gain filter that can not be manipulated by the user and does not support keyframes. This changes it so the filter is visible and the user can add keyframes. The track volume sliders move back and forth as the keyframes animate the volume.

Comments Threads Pending Resolution

ljharb reviewed on August 31, 2026
ljharb left a comment

## Pull request overview

This PR makes per-track volume implemented as a visible, keyframeable Audio Gain filter (marked as “Track Volume”), keeps track/timeline/filter-panel gain controls synchronized (including during playback), and prevents reordering so it stays last among track-visible filters.

**Changes:**
- Introduces `shotcut:trackVolume` + `shotcut:trackVolumeName` properties and uses them to identify and label the special track-volume filter.
- Creates/removes the track-volume filter on demand when track gain changes, and updates UI/model gain values from animated keyframes during playback.
- Prevents moving/reordering the track-volume filter in the filter UI and model; ensures copy/paste clears the marker and keeps it positioned at the end.

### Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.

Show a summary per file

| File | Description |
| ---- | ----------- |
| src/shotcut_mlt_properties.h | Adds new MLT property keys to tag and name track-volume filters. |
| src/qml/views/filter/filterview.qml | Disables move-up/move-down actions for the track-volume filter. |
| src/qml/views/filter/AttachedFilters.qml | Blocks drag initiation for the track-volume filter. |
| src/qml/filters/audio_gain/ui.qml | Adds a track-specific heading when the filter is marked as track volume. |
| src/models/multitrackmodel.h | Adds track-gain update support and track-volume filter helper declaration/state. |
| src/models/multitrackmodel.cpp | Implements track-volume filter creation/removal, animated gain readback, and name syncing. |
| src/models/attachedfiltersmodel.h | Adds API to detect/find the track-volume filter from QML/model. |
| src/models/attachedfiltersmodel.cpp | Prevents moving the track-volume filter and keeps new inserts above it. |
| src/mltcontroller.cpp | Ensures track-volume filters are handled in copy/paste and moved to the end. |
| src/docks/timelinedock.cpp | Updates track gains each frame/seek to reflect animated values. |
| src/controllers/filtercontroller.cpp | Emits a property-scoped change for gain updates (`level`). |
| src/commands/filtercommands.cpp | Adjusts paste undo behavior regarding track-volume filters. |

Suppressed comments (1)

**src/models/attachedfiltersmodel.cpp:782**
* AttachedFiltersModel::remove() creates a QScopedPointer named filter that is never used. This should be removed (or used) to avoid unused-variable warnings and keep the code clear.
```
int mltIndex = mltFilterIndex(m_producer.get(), row);
QScopedPointer filter(mltIndex >= 0 ? m_producer->filter(mltIndex) : nullptr);
```

---

💡 Add a `code-review` agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Resolved Comment Threads

ljharb reviewed on August 31, 2026
ljharb left a comment

## Pull request overview

This PR makes per-track volume implemented as a visible, keyframeable Audio Gain filter (marked as “Track Volume”), keeps track/timeline/filter-panel gain controls synchronized (including during playback), and prevents reordering so it stays last among track-visible filters.

**Changes:**
- Introduces `shotcut:trackVolume` + `shotcut:trackVolumeName` properties and uses them to identify and label the special track-volume filter.
- Creates/removes the track-volume filter on demand when track gain changes, and updates UI/model gain values from animated keyframes during playback.
- Prevents moving/reordering the track-volume filter in the filter UI and model; ensures copy/paste clears the marker and keeps it positioned at the end.

### Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.

Show a summary per file

| File | Description |
| ---- | ----------- |
| src/shotcut_mlt_properties.h | Adds new MLT property keys to tag and name track-volume filters. |
| src/qml/views/filter/filterview.qml | Disables move-up/move-down actions for the track-volume filter. |
| src/qml/views/filter/AttachedFilters.qml | Blocks drag initiation for the track-volume filter. |
| src/qml/filters/audio_gain/ui.qml | Adds a track-specific heading when the filter is marked as track volume. |
| src/models/multitrackmodel.h | Adds track-gain update support and track-volume filter helper declaration/state. |
| src/models/multitrackmodel.cpp | Implements track-volume filter creation/removal, animated gain readback, and name syncing. |
| src/models/attachedfiltersmodel.h | Adds API to detect/find the track-volume filter from QML/model. |
| src/models/attachedfiltersmodel.cpp | Prevents moving the track-volume filter and keeps new inserts above it. |
| src/mltcontroller.cpp | Ensures track-volume filters are handled in copy/paste and moved to the end. |
| src/docks/timelinedock.cpp | Updates track gains each frame/seek to reflect animated values. |
| src/controllers/filtercontroller.cpp | Emits a property-scoped change for gain updates (`level`). |
| src/commands/filtercommands.cpp | Adjusts paste undo behavior regarding track-volume filters. |

Suppressed comments (1)

**src/models/attachedfiltersmodel.cpp:782**
* AttachedFiltersModel::remove() creates a QScopedPointer named filter that is never used. This should be removed (or used) to avoid unused-variable warnings and keep the code clear.
```
int mltIndex = mltFilterIndex(m_producer.get(), row);
QScopedPointer filter(mltIndex >= 0 ? m_producer->filter(mltIndex) : nullptr);
```

---

💡 Add a `code-review` agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.