* clang-tidy: Apply cppcoreguidelines-init-variables everywhere (treating NaNs as zeros)
* Initialize msec and tick outside switch
* Update plugins/Vestige/Vestige.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update plugins/Vestige/Vestige.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update plugins/Vestige/Vestige.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update plugins/VstEffect/VstEffectControls.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update plugins/VstEffect/VstEffectControls.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update plugins/VstEffect/VstEffectControls.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Use initialization with =
* Use tabs
* Use static_cast
* Update DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Do not use tabs for alignment in src/core/DrumSynth.cpp
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Move x variable inside loop
* Use ternary operator for b variable
* Revert "Use tabs"
This reverts commit 07afd8a83f58b539c3673310b2aad4b63c9198a0.
* Remove unnecessary variables in XpressiveView
* Simplify initialization in Plugin
* Combine declaration and initialization in EqCurve
* Combine declaration and initialization in Song
* Combine declaration and initialization in AudioAlsa
* Combine declaration and initialization in EqCurve (again)
* Missed some
* Undo changes made to non-LMMS files
* Undo indentation changes in SidInstrument.cpp
* Combine declaration with assignment in IoHelper
* Combine declaration with assignment using auto in Carla
* Combine declaration with assignment
* Combine declaration with assignment in BasicFilters
* Simplify assignments in AudioFileProcessorWaveView::zoom
* Simplify out sample variable in BitInvader
* Remove sampleLength variable in DelayEffect
* Move gain variable in DynamicsProcessor
* Combine peak variable declaration with assignment in EqSpectrumView
* Move left/right lfo variables in for loop in FlangerEffect
* Use ternary operator for group variable in LadspaControlDialog
* Combine declaration with assignment in Lb302
* Combine declaration with assignment in MidiExport
* Combine declaration with assignment in MidiFile
* Combine declaration with assignment in MidiImport
* Use ternary operator for vel_adjusted variable in OpulenZ
* Move tmpL and dcblkL variables in for loop in ReverbSC
* Combine declaration with initialization in SlicerT
* Combine declaration with assignment in SaSpectrumView
* Combine declaration with assignment in SaWaterfallView
* Combine declaration with assignment in StereoEnhancerEffect
* Combine declaration with assignment in VibratingString
* Combine declaration with assignment in VstEffectControls
* Combine declaration with assignment in Xpressive
* Combine declaration with assignment in AutomatableModel
* Combine declaration with assignment in AutomationClip
* Move sample variable in for loop in BandLimitedWave
* Combine declaration with assignment in DataFile
* Combine declaration with assignment in DrumSynth
* Combine declaration with assignment in Effect
* Remove redundant assignment to nphsLeft in InstrumentPlayHandle
* Combine declaration with assignment in LadspaManager
* Combine declaration with assignment in LinkedModelGroups
* Combine declaration with assignment in MemoryHelper
* Combine declaration with assignment in AudioAlsa
* Combine declaration with assignment in AudioFileOgg
* Combine declaration with assignment in AudioPortAudio
* Combine declaration with assignment in AudioSoundIo
* Combine declaration with assignment in Lv2Evbuf
* Combine declaration with assignment in Lv2Proc
* Combine declaration with assignment in main
* Combine declaration with assignment in MidiAlsaRaw
* Combine declaration with assignment in MidiAlsaSeq
* Combine declaration with assignment in MidiController
* Combine declaration with assignment in MidiJack
* Combine declaration with assignment in MidiSndio
* Combine declaration with assignment in ControlLayout
* Combine declaration with assignment in MainWindow
* Combine declaration with assignment in ProjectNotes
* Use ternary operator for nextValue variable in AutomationClipView
* Combine declaration with assignment in AutomationEditor
* Move length variable in for-loop in PianoRoll
* Combine declaration with assignment in ControllerConnectionDialog
* Combine declaration with assignment in Graph
* Combine declaration with assignment in LcdFloatSpinBox
* Combine declaration with assignment in TimeDisplayWidget
* Remove currentNote variable in InstrumentTrack
* Combine declaration with assignment in DrumSynth (again)
* Use ternary operator for factor variable in BitInvader
* Use ternary operator for highestBandwich variable in EqCurve
Bandwich?
* Move sum variable into for loop in Graph
* Fix format in MidiSndio
* Fixup a few more
* Cleanup error variables
* Use ternary operators and combine declaration with initialization
* Combine declaration with initialization
* Update plugins/LadspaEffect/LadspaControlDialog.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update plugins/OpulenZ/OpulenZ.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update plugins/SpectrumAnalyzer/SaProcessor.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/midi/MidiAlsaRaw.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/gui/MainWindow.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/gui/clips/AutomationClipView.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/gui/editors/AutomationEditor.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/gui/widgets/Fader.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Move static_cast conversion into separate variable
* Use real index when interpolating
* Remove empty line
* Make helpBtn a private member
* Move controller type into separate variable
* Fix format of DrumSynth::waveform function
* Use tabs and static_cast
* Remove redundant if branch
* Refactor using static_cast/reinterpret_cast
* Add std namespace prefix
* Store repeated conditional into boolean variable
* Cast to int before assigning to m_currentLength
* Rename note_frames to noteFrames
* Update src/core/Controller.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/core/DrumSynth.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Update src/gui/widgets/Graph.cpp
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Revert changes that initialized variables redudantly
For situations where the initialization is
more complex or passed into a function
by a pointer, we dont need to do
initialization ourselves since it is
already done for us, just in a different way.
* Remove redundant err variable
* Remove explicit check of err variable
* Clean up changes and address review
* Do not initialize to 0/nullptr when not needed
* Wrap condition in parentheses for readability
---------
Co-authored-by: Kevin Zander <veratil@gmail.com>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* remove the gui_templates header where functions not used
* refactor and replace template with function argument
* refactor: merge pointSizeF function with pointSize
* removed template per michael's review
* use std::max for more readability
* remove the QDesktopWidget header
* cleanup arguments and remove parentheses from return
Enable to set different colors for the oscilloscope channels:
* Left channel color
* Right channel color
* Color of all other channels
The clipping color is now used per channel, i.e. if the left channel clips but the right does not then only the signal of the left channel is painted in the clipping color.
Enable setting the colors in the style sheets and adjust the style sheets of the default and classic theme accordingly.
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`.
* replace QRegExp with QRegularExpression (find n replace)
* follow up to fix errors
* removed rpmalloc
* Fix compilation for qt5, to be fixed when qt6 fully supported.
Co-authored-by: Kevin Zander <veratil@gmail.com>
* Added QtGlobal header for version finding fix
* Use the other syntax to try fix compilation.
* Check for 5.12 instead.
* Fix the header
* Attempt at fixing it further.
* Use version checks properly in header file
* Use QT_VERSION_CHECK macro in sources
* Apply suggestions from messmerd's review
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
---------
Co-authored-by: Kevin Zander <veratil@gmail.com>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Revert some of the changes made in commit 88e0e94dcd. The underlying idea was that the `InstrumentTrackView` should be responsible for assigning the icon that's shown by its `TrackLabelButton`. However, this does not work because in some cases the `InstrumentTrack` that's passed into `InstrumentTrackView::determinePixmap` does not have an `Instrument` assigned. This in turn seems to be caused due to initalizations that are running in parallel in different threads.
Here are the steps to reproduce the threading problem (line numbers refer to commit 360254f):
1. Set a break point in line 1054 of `InstrumentTrack`, i.e. the line in `InstrumentTrack::loadInstrument` where `m_instrument` is being assigned to.
2. Set a break point in `InstrumentTrackView::determinePixmap`, e.g. inside of the first if statement.
3. Drop an instance of "Sf2 Player" onto the Song Editor.
4. The first break point in `InstrumentTrack` is hit in a thread called "lmms::Instrumen" (shown like that in my debugger). Try to step over it.
5. The second break point in `InstrumentTrackView` now gets hit before the code is stepped over. This time we are in the thread called "lmms". I guess this is the GUI main thread.
6. Continue execution.
If you now switch to the application then the icon is shown. I guess the debugger is halted long enough in the main thread so that the InstrumentTrack gets an instrument assigned in another thread.
If you delete/disable the break point in `InstrumentTrack::determinePixmap` and follow the coarse steps above then the icon is not shown because the track has no instrument.
The current fix still delegates to the `InstrumentTrackView` to determine the pixmap in hopes that one day there will be a better solution where the parent component can be fully responsible for its child component.
Fixes#7116.
Fix several NaNs in the context of the basic filters and the Equalizer.
The coefficients of the `BiQuad` were not initialized which seems to have led to NaNs down the line.
Fix a division by zero in `EqEffect::peakBand` and `EqSpectrumView::paintEvent` if the energy is zero.
The condition `m_peakSum <= 0` was removed from `EqSpectrumView::paintEvent` because the value is initialized to 0 down the line and later only potentially positive values are added.
Removes `MemoryManager` and the use of rpmalloc in favor of the `new` and `delete` operators found in C++.
---------
Co-authored-by: Veratil <veratil@gmail.com>
* Fix crash in Audio File Processor
Fix a crash in the Audio File Processor that occurs when an Audio File Processor with a reversed sample is loaded from a save file and then the plugin window is opened.
The problem was caused by a call to `AudioFileProcessorWaveView::slideSampleByFrames` during the execution of constructor of `AudioFileProcessorWaveView`. In that situation the three `knob` members were all `nullptr` because for some reason there was an explicit setter for them which was only called after construction. This is fixed by passing and setting the knobs in the constructor.
Another question is if it's not a problem in the first place that the knobs are given to the `AudioFileProcessorWaveView` instead of their underlying models.
Reenable zooming in the song editor by
* only resizing the track if the alt modifier is pressed and
* only accepting the wheel even if we in fact resize the track.
By doing so all other wheel events bubble up so that zooming and scrolling of the song editor can be handled by parent components.
The code that handles the retrieval of the delta value had to be adjusted as well. The reason is that pressing the alt key messes with the way that deltas are reported in the wheel event. The wheel event is interpreted as a horizontal scroll when alt is pressed.
* Fix invalidated iterator when removing notes in Piano Roll
* fixup - typo
* Add MidiClip::removeNote(iterator) function
* Use iterator version of remoteNote
* Fix parameter name
* Change variable name again
* Simplify TrackLabelButton
Remove the dependency to `Instrument` and `InstrumentTrack` from `TrackLabelButton`. The icon of an `InstrumentTrackView` is now determined in the class `InstrumentTrackView` itself using the new static method `determinePixmap`. This enables the removal of the overridden `paintEvent` method from `TrackLabelButton`.
It was also attempted to keep a non-static member function version and to use the `InstrumentTrackView`'s model with a cast. However, this did not work because 'setModel' is executed as the very last step in the constructor, i.e. the model is not already set when `determinePixmap` is called. Pulling it to the top is too risky right now.
* Add helper method isInCompactMode
Add the helper method `isInCompactMode` which knows how to use the `ConfigManager` to determine if the option for compact track buttons is enabled. This removes duplicate code with intricate knowledge of the keys under which compact mode is stored.
* Set song as modified when track name changes
Extend `Track::setName` to set the song as modified whenever the track name changes. This moves the update into a core class and enables the removal of the dependencies to `Engine` and `Song` from the GUI class `TrackLabelButton`.
Also add a check if the name is really changed and only perform the actions if that's the case.
To make this work the implementation of `setName` had to be moved from the header into the implementation file.
* Keep instrument and sample content at top on resize
Keep the content of the instrument and sample track at the top of the widget if the widget is resized. This is also fixes a bug where the `TrackLabelButton` does not react anymore when the size is increased.
Technically the layout with the actual widgets is put into another vertical layout with a spacer that consumes all remaining space at the bottom.
* Vertical track resizing via mouse wheel
Enable to vertically resize tracks using the mouse wheel. Scrolling the mouse wheel over the track view with the control key pressed will increase/decrease the height by one pixel per wheel event. Pressing the shift key will increase/decrease in steps of five pixels.
Extract code that can be shared between the existing and the new way to resize the track into the private helper method `resizeToHeight`.
* Render beat pattern step buttons at the top
Render the step buttons of beat patterns at the top instead of at the bottom so that they stay aligned with the other elements to the left of them (buttons, knobs, etc).
Set the y offset to 4 so that the step buttons are vertically aligned with the other elements. The previous calculation lead to a minimum offset of 6 which always made the step buttons look misaligned.
Introduce the new static variable `BeatStepButtonOffset` which ensures that the rendering and the evaluation of mouse clicks do not go out of sync.
On plugin instantiation failure, `Lv2Proc::m_valid` was being set to false. However, `Lv2Proc::run` did not evaluate `m_valid` and still called `lilv_instance_run`, which caused undefined behavior, including crashes.
This bug fixes this by not even create such zombie classes, and instead `throw`s right away. The throws are caught in `lmms_plugin_main`, as suggested in the PR discussion and as the VST3 approach.
This revisits two main aspects of playback from `Sample`: copying frames into a temporary playback buffer before resampling, and advancing the state's frame index. Both operations were improperly done, causing distorted audio to be heard when resampling from within the `Sample::play` function.
To fix this, playback into the temporary playback buffer is now done using the `playRaw` function, which copies the frame one by one in a loop, moving through the buffer correctly as determined by the loop mode. In addition, advancement of the playback index is done using the `advance` function, which advances the index by the given amount and handles an out of bounds index for the loop modes as necessary using the modulo operator.
Hide the LED button for "Custom Base Velocity" as it did not have any other effect besides disabling the spinbox in the GUI. It did not affect any model which could be evaluated elsewhere.
## Technical details
Add functionality to show/hide the LED button to `GroupBox`. There's also a corresponding getter called `ledButtonShown`. The latter is evaluated in the following situations:
* Mouse clicks: if the LED button is hidden then the model is not toggled.
* Paining: The X position of the caption changes depending on whether the LED button is shown or not.
At a certain point the class `GroupBox` should be replaced by something that's implemented with layouts and which is used wherever it's possible.
* Add private setters for "from" and "to"
Add private setters for the "from" and "to" values in `AudioFileProcessorWaveView`. When being used the setters will ensure that the bounds are respected.
Also add a `range` method because this computation was done repeatedly throughout the code.
Fixes#7068 but masks some of the original problems with the code that computes out-of-bounds values for "from" and "to" like the `slide` method. Problematic code can still be found by temporarily adding the following assertions to the setters:
* `assert (to <= m_sample->sampleSize());` in `setTo`
* `assert (from >= 0);` in `setFrom`
* Remove superfluous calls to qMax and qMin
## Extract views
Extract the classes `AudioFileProcessorWaveView` and `AudioFileProcessorView` into their own files.
Reformat the new classes by removing unnecessary whitespace and underscores. Add spaces to if-statements.
Cleanup the includes.
## Remove friend relationship
Remove the friend relationship between `AudioFileProcessor` and `AudioFileProcessorView`.
Introduce getters for entities that the view is interested in.
Fixes most of the problem that the MIDI port information is not cloned when a track is cloned.
The bug was caused because cloning is implemented via serialization and deserialization of the Track. The previous code only serialized the MIDI port if `Engine::getSong()->isSavingProject()` is true. However, when we are cloning the statement will be `false` because we are not saving the song. Therefore the MIDI port's state was not saved and the clone was initialized with the default values.
The fix is to serialize the MIDI port in the following cases:
* We are not in song saving mode, i.e. we are in the state that this issue is about, e.g. cloning.
* We save a song and the MIDI connections are not discarded.
Using boolean algebra these conditions can be simplified as seen in the changed statement.
* Fix mixer channel updates on solo/mute
Fix the update of the mixer channels whenever a channel is soloed or muted.
The solution is rather "brutal" as it updates all mixer channel views when one of the models changes.
Introduce private helper method `MixerView::updateAllMixerChannels`. It calls the `update` method on each `MixerChannelView` so that they can get repainted.
Call `updateAllMixerChannels` at the end of the existing method `toggledSolo`.
Introduce a new method `MixerView::toggledMute` which is called whenever the mute model of a channel changes. It also updates all mixer channels.
Fixes#7054.
* Improve mixer channel update for mute events
Improve the mixer channel update for mute events by not delegating to `MixerView` like for the solo case. Instead the `MixerChannelView` now has its own `toggledMute` slot which simply updates the widget on changes to the mute model.
Also fix `MixerChannelView::setChannelIndex` by disconnecting from the signals of the previous mixer channel and connecting to the signals for the new one.
Remove `toggledMute` from `MixerView`.
The solo implementation is kept as is because it also triggers changes to the core model. So the chain seems to be:
* Solo button clicked in mixer channel view
* Button changes solo model
* Solo model signals to mixer view which was connected via the mixer channel view
* Mixer view performs changes in the other core models
* All mixer channels are updated.
Are better chain would first update the core models and then update the GUI from the changes:
* Solo button clicked in mixer channel view
* Button changes solo model
* Solo model signals to core mixer, i.e. not a view!
* Mixer view performs changes in the other core models
* Changed models emit signal to GUI elements
* Revert "Improve mixer channel update for mute events"
This reverts commit ede65963ea.
* Add comment
After the revert done with commit the code is more consistent again but not in a good way. Hence a comment is added which indicates that an inprovement is needed.
* Abstract mixer retrieval
Abstract the retrieval of the mixer behind the new method `getMixer`. This is done in preparation for some dependency injection so that the `MixerView` does not have to ask the `Engine` for the mixer but gets it injected, a.k.a. the "Hollywood principle": "Don't call us, we'll call you."
It's called `getMixer` and not just mixer because it allows for locale variables to be called `mixer` without confusing it with the method.
* Let MixerView connect directly to models
Let the `MixerView` connect directly to the solo and mute models it is connected with.
Remove the connections that are made in `MixerChannelView` which acted as a proxy which only complicated things.
Add `connectToSoloAndMute` which connects the `MixerView` to the solo and mute models of a given channel. Call it whenever a new channel is created.
Add `disconnectFromSoloAndMute` which disconnects the `MixerView` from the solo and mute models of a given channel. Call it when a channel is deleted.
* Code cleanup
Cleanup code related to the creation of the master channel view.
* Inject the Mixer into the MixerView
Inject the `Mixer` into the `MixerView` via the constructor. This makes it more explicit that the `Mixer` is the model of the view. It also implements the "Dependency Inversion Principle" in that the `MIxerView` does not have to ask the `Engine` for the `Mixer` anymore.
The current changes should be safe in that the `Mixer` instance is static and does not change.
* Fix connections on song load
Disconnect and reconnect in `MixerView::refreshDisplay` which is called when a song is loaded.
Caused by not calling `Engine::destroy`, as well as creating tracks/clips on the heap and not freeing the memory at the end of the test.
Instead of creating tracks/clips on the heap, they are now made on the stack, similar to how the surrounding tests create its objects.