From fb369617b2b33e7b53280e8b25824d9aa17fd001 Mon Sep 17 00:00:00 2001 From: rkfg Date: Tue, 3 May 2022 17:34:35 +0300 Subject: [PATCH] Support keyframes in highpass audio filter --- src/qml/filters/audio_highpass/meta.qml | 29 +++++++ src/qml/filters/audio_highpass/ui.qml | 102 ++++++++++++++++++------ 2 files changed, 108 insertions(+), 23 deletions(-) diff --git a/src/qml/filters/audio_highpass/meta.qml b/src/qml/filters/audio_highpass/meta.qml index 989735afe4..86bc71ffc1 100644 --- a/src/qml/filters/audio_highpass/meta.qml +++ b/src/qml/filters/audio_highpass/meta.qml @@ -7,4 +7,33 @@ Metadata { name: qsTr("High Pass") mlt_service: 'ladspa.1890' qml: 'ui.qml' + keyframes { + allowAnimateIn: true + allowAnimateOut: true + simpleProperties: ['wetness'] + parameters: [ + Parameter { + name: qsTr('Cutoff') + property: '0' + isCurve: true + minimum: 5 + maximum: 21600 + units: 'Hz' + }, + Parameter { + name: qsTr('Rolloff rate') + property: '1' + isCurve: true + minimum: 1 + maximum: 10 + }, + Parameter { + name: qsTr('Wetness') + property: 'wetness' + isCurve: true + minimum: 0 + maximum: 1 + } + ] + } } diff --git a/src/qml/filters/audio_highpass/ui.qml b/src/qml/filters/audio_highpass/ui.qml index acf896e28b..5f00a016ef 100644 --- a/src/qml/filters/audio_highpass/ui.qml +++ b/src/qml/filters/audio_highpass/ui.qml @@ -21,30 +21,54 @@ import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 import Shotcut.Controls 1.0 as Shotcut -Item { +Shotcut.KeyframableFilter { + property string cutoffProperty: '0' + property string stagesProperty: '1' + property string wetnessProperty: 'wetness' width: 350 height: 125 + keyframableParameters: preset.parameters + startValues: [39, 1, 0] + middleValues: [39, 1, 1] + endValues: [39, 1, 0] Component.onCompleted: { if (filter.isNew) { // Set default parameter values - filter.set('0', 39) - filter.set('1', 1) - filter.set('wetness', 1.0) + filter.set(cutoffProperty, 39) + filter.set(stagesProperty, 1) + filter.set(wetnessProperty, 1.0) filter.savePreset(preset.parameters) } setControls() } function setControls() { - sliderCutoff.value = filter.getDouble('0') - sliderStages.value = filter.get('1') - sliderWetness.value = filter.getDouble('wetness') * sliderWetness.maximumValue + var position = getPosition() + blockUpdate = true + sliderCutoff.value = filter.getDouble(cutoffProperty, position) + cutoffKeyframesButton.checked = filter.animateIn <= 0 && filter.animateOut <= 0 && filter.keyframeCount(cutoffProperty) > 0 + sliderStages.value = filter.getDouble(stagesProperty, position) + stagesKeyframesButton.checked = filter.animateIn <= 0 && filter.animateOut <= 0 && filter.keyframeCount(stagesProperty) > 0 + sliderWetness.value = filter.getDouble(wetnessProperty, position) * sliderWetness.maximumValue + wetnessKeyframesButton.checked = filter.animateIn <= 0 && filter.animateOut <= 0 && filter.keyframeCount(wetnessProperty) > 0 + blockUpdate = false + enableControls(isSimpleKeyframesActive()) + } + + function enableControls(enabled) { + sliderCutoff.enabled = sliderStages.enabled = sliderWetness.enabled = enabled + } + + function updateSimpleKeyframes() { + updateFilter(cutoffProperty, sliderCutoff.value, cutoffKeyframesButton, null) + updateFilter(stagesProperty, sliderStages.value, stagesKeyframesButton, null) + updateFilter(wetnessProperty, sliderWetness.value / sliderWetness.maximumValue, wetnessKeyframesButton, null) } GridLayout { anchors.fill: parent anchors.margins: 8 - columns: 3 + columns: 4 Label { text: qsTr('Preset') @@ -52,9 +76,15 @@ Item { } Shotcut.Preset { id: preset - parameters: ['0', '1', '2', 'wetness'] - Layout.columnSpan: 2 - onPresetSelected: setControls() + parameters: [cutoffProperty, stagesProperty, wetnessProperty] + Layout.columnSpan: parent.columns - 1 + onBeforePresetLoaded: { + resetSimpleKeyframes() + } + onPresetSelected: { + setControls() + initializeSimpleKeyframes() + } } Label { text: qsTr('Cutoff frequency') @@ -65,14 +95,18 @@ Item { minimumValue: 5 maximumValue: 21600 suffix: ' Hz' - value: filter.getDouble('0') - onValueChanged: { - filter.set('0', value) - } + onValueChanged: updateFilter(cutoffProperty, value, cutoffKeyframesButton, getPosition()) } Shotcut.UndoButton { onClicked: sliderCutoff.value = 39 } + Shotcut.KeyframesButton { + id: cutoffKeyframesButton + onToggled: { + enableControls(true) + toggleKeyframes(checked, cutoffProperty, sliderCutoff.value) + } + } Label { text: qsTr('Rolloff rate') Layout.alignment: Qt.AlignRight @@ -81,14 +115,18 @@ Item { id: sliderStages minimumValue: 1 maximumValue: 10 - value: filter.get('1') - onValueChanged: { - filter.set('1', value) - } + onValueChanged: updateFilter(stagesProperty, value, stagesKeyframesButton, getPosition()) } Shotcut.UndoButton { onClicked: sliderStages.value = 1 } + Shotcut.KeyframesButton { + id: stagesKeyframesButton + onToggled: { + enableControls(true) + toggleKeyframes(checked, stagesProperty, sliderStages.value) + } + } Label { text: qsTr('Dry') Layout.alignment: Qt.AlignRight @@ -100,17 +138,35 @@ Item { decimals: 1 label: qsTr('Wet') suffix: ' %' - value: filter.getDouble('wetness') * maximumValue - onValueChanged: { - filter.set('wetness', value / maximumValue) - } + onValueChanged: updateFilter(wetnessProperty, value / maximumValue, wetnessKeyframesButton, getPosition()) } Shotcut.UndoButton { onClicked: sliderWetness.value = sliderWetness.maximumValue } + Shotcut.KeyframesButton { + id: wetnessKeyframesButton + onToggled: { + enableControls(true) + toggleKeyframes(checked, wetnessProperty, sliderWetness.value / sliderWetness.maximumValue) + } + } Item { Layout.fillHeight: true } } + Connections { + target: filter + onChanged: setControls() + onInChanged: updateSimpleKeyframes() + onOutChanged: updateSimpleKeyframes() + onAnimateInChanged: updateSimpleKeyframes() + onAnimateOutChanged: updateSimpleKeyframes() + onPropertyChanged: setControls() + } + + Connections { + target: producer + onPositionChanged: setControls() + } }