1/* 2 * Copyright (c) 2013-2021 Meltytech, LLC 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18import QtQuick 2.12 19import QtQuick.Controls 2.12 20import QtQuick.Layouts 1.12 21import Shotcut.Controls 1.0 as Shotcut 22 23Item { 24 width: 200 25 height: 50 26 property bool blockUpdate: true 27 property double startValue: 0.0 28 property double middleValue: 0.0 29 property double endValue: 0.0 30 31 Component.onCompleted: { 32 if (filter.isNew) { 33 // Set default parameter values 34 filter.set('level', 0) 35 filter.savePreset(preset.parameters) 36 } else { 37 // Convert old version of filter. 38 if (filter.getDouble('gain') !== 0.0) { 39 filter.set('level', toDb(filter.getDouble('gain'))) 40 filter.resetProperty('gain') 41 } 42 43 middleValue = filter.getDouble('level', filter.animateIn) 44 if (filter.animateIn > 0) 45 startValue = filter.getDouble('level', 0) 46 if (filter.animateOut > 0) 47 endValue = filter.getDouble('level', filter.duration - 1) 48 } 49 setControls() 50 } 51 52 Connections { 53 target: filter 54 onInChanged: updateFilter(null) 55 onOutChanged: updateFilter(null) 56 onAnimateInChanged: updateFilter(null) 57 onAnimateOutChanged: updateFilter(null) 58 } 59 60 Connections { 61 target: producer 62 onPositionChanged: { 63 if (filter.animateIn > 0 || filter.animateOut > 0) { 64 setControls() 65 } else { 66 blockUpdate = true 67 gainSlider.value = filter.getDouble('level', getPosition()) 68 blockUpdate = false 69 gainSlider.enabled = true 70 } 71 } 72 } 73 74 function toDb(value) { 75 return 20 * Math.log(value) / Math.LN10 76 } 77 78 function getPosition() { 79 return Math.max(producer.position - (filter.in - producer.in), 0) 80 } 81 82 function setControls() { 83 var position = getPosition() 84 blockUpdate = true 85 gainSlider.value = filter.getDouble('level', position) 86 blockUpdate = false 87 gainSlider.enabled = position <= 0 || (position >= (filter.animateIn - 1) && position <= (filter.duration - filter.animateOut)) || position >= (filter.duration - 1) 88 gainKeyframesButton.checked = filter.keyframeCount('level') > 0 && filter.animateIn <= 0 && filter.animateOut <= 0 89 } 90 91 function updateFilter(position) { 92 if (blockUpdate) return 93 94 if (position !== null) { 95 if (position <= 0 && filter.animateIn > 0) 96 startValue = gainSlider.value 97 else if (position >= filter.duration - 1 && filter.animateOut > 0) 98 endValue = gainSlider.value 99 else 100 middleValue = gainSlider.value 101 } 102 103 if (filter.animateIn > 0 || filter.animateOut > 0) { 104 filter.resetProperty('level') 105 gainKeyframesButton.checked = false 106 if (filter.animateIn > 0) { 107 filter.set('level', startValue, 0) 108 filter.set('level', middleValue, filter.animateIn - 1) 109 } 110 if (filter.animateOut > 0) { 111 filter.set('level', middleValue, filter.duration - filter.animateOut) 112 filter.set('level', endValue, filter.duration - 1) 113 } 114 } else if (!gainKeyframesButton.checked) { 115 filter.resetProperty('level') 116 filter.set('level', middleValue) 117 } else if (position !== null) { 118 filter.set('level', gainSlider.value, position) 119 } 120 } 121 122 GridLayout { 123 columns: 4 124 anchors.fill: parent 125 anchors.margins: 8 126 127 Label { 128 text: qsTr('Preset') 129 Layout.alignment: Qt.AlignRight 130 } 131 Shotcut.Preset { 132 id: preset 133 Layout.columnSpan: parent.columns - 1 134 parameters: ['level'] 135 onBeforePresetLoaded: { 136 filter.resetProperty(parameters[0]) 137 } 138 onPresetSelected: { 139 setControls() 140 middleValue = filter.getDouble(parameters[0], filter.animateIn) 141 if (filter.animateIn > 0) 142 startValue = filter.getDouble(parameters[0], 0) 143 if (filter.animateOut > 0) 144 endValue = filter.getDouble(parameters[0], filter.duration - 1) 145 } 146 } 147 148 Label { 149 text: qsTr('Level') 150 Layout.alignment: Qt.AlignRight 151 } 152 Shotcut.SliderSpinner { 153 id: gainSlider 154 minimumValue: -70 155 maximumValue: 24 156 suffix: ' dB' 157 decimals: 1 158 onValueChanged: updateFilter(getPosition()) 159 } 160 Shotcut.UndoButton { 161 onClicked: gainSlider.value = 0.0 162 } 163 Shotcut.KeyframesButton { 164 id: gainKeyframesButton 165 onToggled: { 166 if (checked) { 167 blockUpdate = true 168 filter.clearSimpleAnimation('level') 169 blockUpdate = false 170 filter.set('level', gainSlider.value, getPosition()) 171 } else { 172 filter.resetProperty('level') 173 filter.set('level', gainSlider.value) 174 } 175 } 176 } 177 178 Item { 179 Layout.fillHeight: true 180 } 181 } 182} 183