This PR refactors how the spacebar is handled by the editors and the MainWindow to allow it to play/stop (Shift+Space for play/pause) the last played editor, no matter if it is in focus or not.
---------
Co-authored-by: Fawn <rubiefawn@gmail.com>
Co-authored-by: Sotonye Atemie <satemiej@gmail.com>
* Use dbFS scale for the faders
Make the faders use a linear dbFS scale. They now also change position on first click and can then be dragged.
The `Fader` class now has a new property called `m_faderMinDb`. It's the minimum value before the amplification drops down fully to 0. It is needed because we cannot represent a scale from -inf to maxDB.
Rename `knobPosY` to `calculateKnobPosYFromModel` and move the implementation into the cpp file. The method now first converts the model's current amplification value to dbFS and then computes a ratio based on that values and the minimum and maximum dbFS values.
Add the method `setVolumeByLocalPixelValue` which takes a local y coordinate of the widget and sets the amplification of the model based on a dbFS scale.
Adjust `mousePressEvent` and `mouseMoveEvent` so that they mostly take the local y coordinate of the event and use that to adjust the model via `setVolumeByLocalPixelValue`.
Remove `m_moveStartPoint` and `m_startValue` and they are not needed anymore.
* Apply curve to faders
Apply a curve, i.e. the cube function and its inverse, to the fader
positions to that we have more space to work with in the "interesting"
areas around 0 dB and less space in the area where we tend to "-inf dB".
Set the minimum dB value of the fader to -120 dB to increase the potential
headroom.
* Support for dB models
Add support for models that are in dB.
There's a new member `m_modelIsLinear` which can be set via the
constructor. The default value in the constructor is `true`.
Add the method `modelIsLinear` which can be used to query the parameter.
It is used in `calculateKnobPosYFromModel` and
`setVolumeByLocalPixelValue`. Both methods got extended to deal with
models in dB. They were also refactored to extract code that is common
for both cases.
Ensure that the constructor of `Fader` is called with `false` for
`CrossoverEQControlDialog` and `EqFader` because these use models that
are in dB.
* Show current dB value of fader in tool tip
Show the current value of the fader in its tool tip. Please note that
this value is always shown in dB because the goal should be to get rid
of the linear values for the faders.
Some of the code is extracted into the new method
`Fader::getModelValueAsDbString` which is shared by
`Fader::modelValueChanged` (also new) and `Fader::updateTextFloat`.
Please note that `getModelValueAsDbString` will use "dB" instead of
"dBFS" as the unit and that it will format "-inf dB" instead of "-∞ dB".
These changes will also be visible in the text float that is used to
show the new values as the fader is being dragged.
* Let users enter values in dB
Let users enter values in dB in the dialog that opens with a double
click.
The minimum value that can be entered is the minimum value that the
fader allows to set, i.e. -120 dB. The maximum value is the maximum
value of the model converted to dB. As of now this is ~6 dB. The
current value is converted to dB. If it corresponds to "-inf dB", i.e.
if the amplification is 0 then the minimum value is used.
* Remove option "Display volume as dBFS"
Remove the option "Display volume as dBFS" from the settings dialog and
the check box option "Volume as dBFS" from the "View" menu. Volumes are
now always treated as dB, i.e. all evaluations of the property
"displaydbfs" have been removed which results in assuming that this
option is always true.
The upgrade code in `ConfigManager::upgrade_1_1_91` was left as is.
However, a note was added which informs the reader that the value of
"displaydbfs" is not evaluated anymore.
* Extend Fader::wheelEvent
Extend `Fader::wheelEvent` for the case where the model is not a dB
model (`modelIsLinear() == true`), e.g. for the mixer faders. In that
case it works as follows. Each step increments or decrements by 1 dB if
no modifier is pressed. With "Shift" pressed the increment value is 3 dB.
With "STRG" ("CTRL") pressed the increment value is reduced to 0.1 dB. If
the value goes below the minimum positive dB value that is allowed by the
fader then the fader is set to "-inf dB", i.e. zero amplification. If the
fader is set to "-inf dB" and the users want to increase the value then
it is first set to the minimum positive value that is allowed by the
fader.
If the model is a dB model then the same behavior as before is used.
Although it should be considered to adjust this case as well. These
models are used by the faders of the Crossover Equalizer, Equalizer,
Compressor and Delay and they are not very usable with the mouse wheel.
* Adjust the wheel behavior for faders with dB models
Make the faders of the Crossover Equalizer, Equalizer, Compressor and
Delay behave like the mixer faders, i.e. step in sizes of 3 dB, 1dB and
0.1 dB depending on whether a modifier key is pressed or not.
Extract some common code to do so and add some `const` keywords.
* Less "jumpy" knobs
Implement a more stable knob behavior.
Remove the jumping behavior if the users directly click on a volume
knob. By storing the offset from the knob center and taking it into
account during the changes it now also feels like the users are
dragging the knob.
Changes to the amplification are now only applied when the mouse is
moved. This makes the double click behavior much more stable, i.e. if
users click on the knob when it is at 0 dB the dialog will also show
0 dB and not something like 0.3 dB because the first click is already
registered as a change of volume.
If the users click next to the knob the amplification will still be
changed immediately to that value.
## Technical details
To make the knobs more stable a variable called `m_knobCenterOffset` was
introduced. It stores the offset of the click from the knob center so
that this value can be taken into account for in the method
`setVolumeByLocalPixelValue`.
* Make MSVC happy
Add an indication that a float value is assigned to a float variable.
* Introduce constexpr for scaling exponent
Introduce the `constexpr c_dBScalingExponent` which describes the
scaling exponent that's used to scale the dB scale in both directions.
This will simplify potential adjustments by keeping the values
consistent everywhere.
* Draw fader ticks
Draw fader ticks in case the model is a linear one. This means that for
now they should only be painted for the mixer faders but not for the
faders of the Compressor, Delay, etc.
Extract the computation of the scaled ratio between the maximum model dB
value and the minimum supported fader dB value into the new private
method `computeScaledRatio`. This is necessary because it is needed to
paint the fader knob at the correct position (using the knob bottom as
the reference) and to paint the fader ticks at the correct position
(using the knob center).
Introduce the private method `paintFaderTicks` which paints the fader
ticks.
Note: to paint some non-evenly spaced fader ticks replace the `for`
expression in `paintFaderTicks` with something like the following:
```
for (auto & i : {6.f, 0.f, -6.f, -12.f, -24.f, -36.f, -48.f, -60.f, -72.f, -84.f, -96.f, -108.f, -120.f})
```
* Fader adjustments via keyboard
Allow the adjustment of the faders via the keyboard. Using the up or
plus key will increment the fader value whereas the down or minus key
will decrement it. The same key modifiers as for the wheel event apply:
* No modifier: adjust by 1 dB
* Shift: adjust by 3 dB
* Control: adjust by 0.1 dB
Due to the very similar behavior of the mouse wheel and key press
handling some common functionality was factored out:
* Determinination of the (absolute) adjustment delta value by
insprecting the modifier keys of an event. Factored into
`determineAdjustmentDelta`.
* Adjustment of the model by a given dB delta value. Factored into
`adjustModelByDBDelta`.
* Move the fader of the selected channel
Move the fader of the selected channel instead of the fader that has
focus when the up/plus or down/minus keys are pressed. Doing so also
feels more natural because users can already change the selected
channel via the left and right keys and now they can immediately adjust
the volume of the currently selected channel while doing so.
Key events are now handled in `MixerView::keyPressEvent` instead of
`Fader::keyPressEvent` and the latter is removed. `MixerChannelView`
now has a method called `fader` which provides the associated fader.
This is needed so that the event handler of `MixerView` can act upon
the currently selected fader.
## Changes in Fader
The `Fader` class provides two new public methods.
The `adjust` method takes the modifier key(s) and the adjustment
direction and then decides internally how the modifier keys are mapped
to increment values. This is done to keep the mapping between modifier
keys and increment values consistent across different clients, e.g. the
key event of the `MixerView` and the wheel event of the `Fader` itself.
The direction is provided by the client because the means to determine
the direction can differ between clients and cases, e.g. a wheel event
determines the direction differently than a key event does.
The method `adjustByDecibelDelta` simply adjusts the fader by the given
delta amount. It currently is not really used in a public way but it
still makes sense to provide this functionality in case a parent class
or client wants to manipulate the faders by its very own logic.
Because the `Fader` class does not react itself to key press events
anymore the call to `setFocusPolicy` is removed again.
* Enter fader value when space key pressed
Let the users enter the fader value via dialog when the space key is
pressed.
Extract the dialog logic into the new method `adjustByDialog` and call
it from `MixerView::keyPressEvent`.
Make `Fader::mouseDoubleClickEvent` delegate to `adjustByDialog` and
also fix the behavior by accepting the event.
* More prominent fader ticks around 0 dB
Make the fader ticks around 0 dB more prominent but drawing them
slightly wider and with a more opaque color.
* Work around a Qt bug
Work around a Qt bug in conjunction with the scroll wheel and the Alt
key. Simply return 0 for the fader delta as soon as Alt is pressed.
* Fix wheel events without any modifier
Fix the handling of wheel events without any modifier key being pressed.
Commit ff435d551b accidentally tested against Alt using a logical OR
instead of an AND.
* Code review changes
First set of code review changes:
* Use Doxygen style documentation comments
* Remove comment about `displaydbfs` from upgrade routine
* White-space changes for touched lines.
* Make minimum dB value a constexpr
Make the minimum dB value a constexpr in the implementation file because
currently it's an implementation detail that should not be of any
interest to any other client.
So `m_faderMinDb` becomes `c_faderMinDb`.
* More flexible painting of fader ticks
Paint the fader ticks in a more systematic and flexible way. This also
removes some "magic numbers", e.g. by using `c_faderMinDb` instead of
`-120.f` as the lower limit.
The upper limit, i.e. the "starting point" is now also computed using
the maximum value of the model so that the fader will still paint
correctly if it ever changes.
* Make the zero indicator bolder
Make the zero indicator tick of the fader bolder.
* Make rendering of fader ticks a preference
Make rendering of fader ticks a preference which is off by default.
Introduce the new option "Show fader ticks" to the setup dialog and save
it to the UI attribute `showfaderticks`.
The configuration value is currently evaluated in `Fader::paintEvent`.
If this leads to performance problems it might be better to introduce a
boolean member to the `Fader` class which caches that value.
* Move constexprs to anonymous namespace
Add peak indicators to the mixer strips. They show the maximum peak value
that was observed and can be reset by clicking on them.
## Implementation details
The implementation works via a signal/slot mechanism. The `Fader` class
has a new signal `peakChanged` which reports peak values as
amplifications. A new class `PeakIndicator` is added which has a slot
`updatePeak` which is connected to the new signal in `Fader`.
The `PeakIndicator` inherits from `QLabel` and mainly deals with updating
the label text from the current peak value.
Add a `PeakIndicator` instance to `MixerChannelView`. Add a `reset`
method to `MixerChannelView` so that the mixer channel can be reset on
the loading of new projects, etc. The current implementation resets the
peak indicator back to -inf dbFS. The `reset` method is called in
`MixerView::clear`.
Remove the clamping in `Fader::setPeak` so that all peaks are reported.
Emit the new signal if the peak changes.
Moves the confirmation to remove mixer channels outside of `MixerView::deleteChannel` and into `MixerChannelView::removeChannel`. This is so that the confirmation only applies when the user uses the context menu to remove a channel, which is important since no confirmation should apply when, for example, the mixer view is cleared with calls to `MixerView::clear`.
Reduce code repetition in `MixerChannelView` by introducing methods that:
* Retrieve the `MixerChannel` that's associated with the view
* Check if the associated channel is the master channel
This abstracts some functionality and also reduces direct usage of the variable `m_channelIndex`.
Use Qt layouts for the mixer channels. These changes will enable several other improvements, like for example making the mixer and faders resizable, adding peak indicators, etc.
This is a squash commit which consists of the following individual commits:
* Remove extra transparency in send/receive arrows
The extra transparency was conflicting with the positioning of
the arrows in the layout
* Begin reimplementing MixerChannelView
MixerChannelView is now a combination of the
MixerLine with the previous MixerChannelView
* Adjust SendButtonIndicator to use MixerChannelView
* Remove MixerLine
- Move MixerChannelView into src/gui
* Remove MixerView::MixerChannelView
* Remove header of MixerLine
* Change MixerView.h to use MixerChannelView
Change MixerView.h to use MixerChannelView rather than MixerLine
Also do some cleanup, such as removing an unused forward declaration
of QButtonGroup
* Create EffectRackView
+ Set height of sizeHint() using MIXER_CHANNEL_HEIGHT (287)
* Remove include of MixerLine
- Include MixerChannelView
* Phase 1: Adjust MixerView to use new MixerChannelView
* Move children wigets into header file
* Phase 2: Adjust MixerView to use new MixerChannelView
* Phase 3: Adjust MixerView to use new MixerChannelView
* Phase 4: Adjust MixerView to use new MixerChannelView
* Phase 5: Adjust MixerView to use new MixerChannelView
* Phase 5: Adjust MixerView to use new MixerChannelView
* Remove places where MixerChannelView is being deleted
Before, MixerChannelView was not inherited by QWidget,
meaning it could not have a parent and had to be deleted
when necessary. Since the MixerView owns the
new MixerChannelView, this is no longer necessary.
* Replace MixerLine with MixerChannelView
- Include MixerChannelView in MixerView
* Replace setCurrentMixerLine calls with setCurrentMixerChannel around codebase
* Add event handlers in MixerChannelView
* Implement MixerChannelView::eventFilter
* Update theme styles to use MixerChannelView
* Add QColor properties from style
- Set the Qt::WA_StyledBackground attribute on
* Add effect rack to rack layout when adding channel
* Set size for MixerChannelView
- Change nullptr to this for certain widgets
- Some custom widgets may expect there to be a parent
- Add spacing in channel layout
- Increase size of mixer channel
* Retain size when widgets are hidden
* Implement paintEvent
- Rename states in SendReceiveState
* Implement send/receive arrow toggling
- Make maxTextHeight constexpr in elideName
- Remove background changing on mouse press
(is now handled in paintEvent)
* Implement renaming mixer channels
* Implement color functions
* Implement channel moving/removing functions
* Do some cleanup
Not sure if that connection with the mute model was needed, but removing
it did not seem to introduce any issues.
* Include cassert
* Replace references to MixerLine with MixerChannelView
* Reduce height
+ Make m_renameLineEdit transparent
+ Retain size when LCD is hidden
+ Remove stretch after renameLineEdit in layout
* Remove trailing whitespace
* Make m_renameLineEdit read only
+ Transpose m_renameLineEditView rectangle (with 5px offset)
* Set spacing in channel layout back to 0
* Remove sizeHint override and constant size
* Use sizeHint for mixerChannelSize
+ Leave auto fill background to false in MixerChannelView
+ Only set width for EffectRackView
* Set margins to 4 on all sides in MixerChannelView
* Move solo and mute closer to each other
Move the solo and mute buttons closer to each other in the mixer channels.
Technically this is accomplished by putting them into their own layout with minimal margins and spacing.
* Fixes for CodeFactor
* Code review changes
Mostly whitespace and formatting changes: remove tabs, remove spaces in parameter lists, remove underscores from parameter names.
Some lines have been shortened by introducing intermediate variables, e.g. in `MixerChannelView`.
`MixerView` has many changes but only related to whitespace. Spaces have been introduced for if and for statements. Whitespace at round braces has been removed everywhere in the implementation file even if a line was not touched by the intial changes.
Remove duplicate forward declaration of `MixerChannelView`.
* Adjust parameter order in MixerChannelView's constructor
Make the parent `QWidget` the first parameter as it is a Qt convention. The default parameter had to be removed due to this.
* Move styling of rename line edit into style sheets
Move the style of the `QGraphicsView` for the rename line edit from the code into the style sheets of the default and classic theme.
* More code review changes
Fix spaces between types and references/pointers, e.g. use `const QBrush& c` instead of `const QBrush & c`.
Remove underscores from parameter names.
Remove spaces near parentheses.
Replace tabs with spaces.
Introduce intermediate variable to resolve "hanging" + operator.
Replace the connection for the periodic fader updates with one that uses function pointers instead of `SIGNAL` and `SLOT`.
---------
Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de>