Refactors the PortAudio backend to fix issues with DirectSound and MME crackling and not loading properly, as well as to improve code quality and maintainability.
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
This refactors the export dialog to no longer use the export_project.ui file and moves it into standard C++ Qt code. This also brings minor changes to the dialog, such as horizontal labels instead of vertical ones.
* reimplement getter and setter of FloatModelEditorBase::m_volumeKnob to avoid undo checkpoint creation
* convert FloatModelEditorBase::m_volumeKnob from BoolModel to bool
* clean up
* remove unnecessary inline keywords and fix formatting
---------
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
Removes `SampleLoader`. File dialog functions were moved into `FileDialog`. Creation functions were moved into `SampleBuffer`.
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
This PR modifies how the Detuning tool works in the piano roll to let the user modify the automation curve right on the notes. This is actually fairly simple, as automation clips already contain the functions for dragging and removing points like in the Automation Editor. So essentially all that's being done is calculating the relative pos of the mouse to the nearest note, and setting the drag value in the automation clip to that position and key.
You can still access the old automation editor version by shift-click
messmerd asked if the code could be made general for any future note parameter besides detuning, in preparation for CLAP per-note parameter automation. I have refactored the relevant functions to accept an enum type for the kind of note parameter, although currently only detuning is supported.
---------
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
Co-authored-by: Sotonye Atemie <satemiej@gmail.com>
Co-authored-by: szeli1 <143485814+szeli1@users.noreply.github.com>
Fixes#8182
When #7454 was merged, the frameOffset variable inside Song::PlayPos which kept track of the actual frame position which the song was playing at relative to the last tick, was moved to Timeline. In the process, the type was inadvertently changed from float to f_cnt_t.
This caused the frame offset to be truncated ever time it was updated in Song::processNextBuffer, causing the song playback to slowly drift back ever so slightly, just a handful of frames every bar. This caused any new sample clips spawned to be created slightly late, becoming out of sync with any existing playing samples.
This PR fixes the issue by reverting the frameOffset variable type to be float again, allowing it to track sub-sample offsets over time.
Closes#7869
This PR aims to fix linking bugs and it aims to make linking code faster. In the future I would like to replace controller and automation code with linked models, so it is essential for this feature to work as efficiently as possible.
Before this PR:
- AutomatableModels store a list of AutomatableModels that they are linked to.
- setValue() and other functions make recursive calls to themself resulting in the #7869 crash.
- Each AutomatableModel can unlink from other AutomatableModels, unlinking is the inverse operation to linking.
After this PR:
- AutomatableModels store a pointer to an other AutomatableModel making a linked list. The end is connected to the first element resulting in a "ring".
- setValue() and others are now recursion free, the code runs for every linked model, more efficiently than before.
- Each AutomatableModel can NOT unlink form other AutomatableModels, unlinking is NOT the inverse operation to linking. AutomatableModels can unlink themself from the linked list, they can not unlink themself from single models.
---------
Co-authored-by: allejok96 <allejok96@gmail.com>
Previously, this PR simply added a new signal to the Timeline class and had it emitted by the TimeLineWidget class in order to solve #7351.
However, as messmerd pointed out in his review comments, that was quite a hacky solution, and ideally the positionChanged signal would be solely managed by the backend Timeline class, while the frontend TimeLineWidget class would connect to those signals, instead of the other way around.
This PR is no longer a simple bugfix, but instead a refactoring of the Timeline/TimeLineWidget signal/slots.
Changes
- The positionChanged signal and updatePosition slot were removed from TimeLineWidget and moved to Timeline.
- Removed PlayPos, and instead store the timeline position in a TimePos along with a separate frame offset counter variable. The functions to set the ticks/timepos in Timeline emit the positionChanged signal. (Also, may emit positionJumped signal if the ticks were forcefully set--see below)
- The pos() method and PlayPos m_pos were removed from TimeLineWidget;
- The constructor for TimeLineWidget no longer requires a PlayPos reference.
- Since each TimeLineWidget stores a reference to its Timeline, a new method was added, timeline(), for other classes to access it.
- Removed array of PlayPos'es in Song. Now each Timeline holds their respective TimePos.
- Song's methods for getPlayPos were changed to return the TimePos of the respective Timeline. The non-const versions of the methods were removed because Timeline does not expose its TimePos to write.
- All of the places where Timelines are used were updated, along with their calls to access/modify the PlayPos. For example, occurrences of m_timeline->pos() were replaced with m_timeline->timeline()->pos(), and calls to m_timeline->pos().setTicks(ticks) were changed to m_timeline->timeline()->setTicks(ticks).
- ALSO: Removed m_elapsedMilliseconds, m_elapsedBars, and m_elapsedTicks from Song. The elapsed milliseconds is now handled individually by each Timeline.
- NEW: The m_jumped variable has been removed from Timeline. Now jumped events emit Timeline::positionJumped automatically whenever the ticks are forcefully set. This means it is no longer necessary to call timeline->setJumped(true) or timeline->setFrameOffset(0) whenever the playhead position is forcefully set. Many places in the codebase were already missing these calls, so this may fix some unknown bugs.
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Co-authored-by: saker <sakertooth@gmail.com>
Co-authored-by: Alex <allejok96@gmail.com>
Fixes#8152
Revert PianoRoll closing when empty (caused issues with detached windows)
Remove TextFloat warning when there are no instruments/multiple clips (showed up when reloading project)
(Keep clip creation for empty projects)
Add an icon and updated message in empty PianoRoll.
Mark PianoRollWindow invalid when there is no clip, making buttons impossible to click
---------
Co-authored-by: Fawn <rubiefawn@gmail.com>
Clang was incorrectly displayed as 'GCC Clang' because __GNUC__ is
defined by Clang for compatibility. Reordered preprocessor checks in
versioninfo.h to test for __clang__ before __GNUC__.
Fixes#8120
This bug was noticed when testing out #7559, but the PR had been open for over a year, so it was decided to merge it and fix it in this one.
Basically, when adding or removing a track, the TrackContainer sends out signals such as trackAdded or trackRemoved which PatternClipView uses to know when to update.
However, it does not send out a signal when a track has been moved.
This is because for some reason, it's done by the GUI TrackContainerView instead of the core TrackContainer.
This PR changes that by moving the core code to the core where it probably belongs, adding an appropriate trackMoved signal to TrackContainer, and connecting that to PatternClipView to update properly.
---------
Co-authored-by: Fawn <rubiefawn@gmail.com>
This PR changes the way PatternClips are drawn in include a simple "beat preivew," where each note in any non-empty instrument tracks within the pattern are drawn as short little rectangles on the ClipView. SampleClips and AutomationClips within patterns are not currently supported.
The height of the note boxes changes depending on how many tracks there are in the pattern, and how many of them actually have notes (empty tracks are only drawn half as tall).
There is also some padding at the top and bottom along with a little bit of spacing between each note, both vertically and horizontally. This can be edited in the css, along with the note color.
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Co-authored-by: Fawn <rubiefawn@gmail.com>
Previously, the autoscroll state of the song editor and piano roll (continuous, stepped, none) was not saved. This can be an issue for users who want to permanently set their autoscroll settings, without having to change them every time they start up LMMS.
This PR adds an option in the settings window to change the default autoscroll state.
* SVG-ify arrow buttons
These buttons are used in the instrument window, Vestige, and VST
effects. Separate versions of the arrow icons are used for the classic
theme.
* Fix some unrelated SVG formatting and metadata
* Revert accidental change to classic border radius
* Add some XML stuff back to appease Github
LMMS renders these SVGs just fine, but apparently the removal of the
XML declaration completely breaks Github's ability to render the image,
so I am adding these back for the sake of those who want to actually
look at the diff on the website lmao
* Attempt to fix Github SVG previews again (`xmlns`)
* Fix crossover eq band mute button icon size
You may ask, "what does this have to do with the arrow buttons?" and you
would be right to assume this is unrelated. However, I'm already
touching the relevant lines of the stylesheet so I may as well sneak it
in there.
* Add missing metadata to fader_knob.svg
And fix mixed indentation in headphones.svg
* Add missing `xmlns` to fader_knob.svg
GRADIENTS!!!!!!!!!!!!
* Fix classic theme arrow buttons
The originals were right angle chevrons
* Remove unused getters
- Display a message when a user attempts to open the piano roll in a project with no MIDI clips instead of opening a non-functional piano roll.
- Create a MIDI clip in the first instrument track when the piano roll is opened in an empty project.
* Rebase against master
Co-authored-by: michaelgregorius <michael.gregorius.git@arcor.de>
Co-authored-by: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com>
* Fix Qt6 DMG on Apple (#7240)
- Fix linking issues with Qt Framework files
- Fix qmake detection
* Fixes after rebase
* Fix embed.cpp compilation
Fix implicit conversion from int when using QString.arg(...)
* Fix Qt6 signature change for nativeEventFilter (#7254)
* Adds win32EventFilter a wrapper for nativeEventFilter on Windows
* win32EventFilter is currently used to intercept top-level Window events (currently, to avoid VSTs setting transparency of the parent application)
* fix broken signal slot connections (#7274)
QComboBox activated() replaced with textActivated() since Qt 5.14
* Enabled VSTs on Qt 6 (#7273)
* enabled VST support for Qt 6 builds
* Note : Embedding on QT6 will be buggy on linux as a result of using qt embedding, which unfortunately is a qt bug which hasn't been resolved.
* Changed bar lines to follow snap size (#7034)
* Added lines in between bars
* Changed bar lines to follow snap size
* Changed default zoom and quantization value
* Added constants for line widths
* Added QSS configuration for new grid line colors
* Tied line widths to QSS properties
* Changed default quantization to 1/4
* Removed clear() from destructor model
* Removed destructor in ComboBoxModel.h
* Changed member set/get functions to pass by value
* Updated signal connection with newer syntax
* Fix compilation
* Fix MSVC builds
* fix nullptr deref in AudioFileProcessor (qt6 branch) (#7532)
* ensured mouse event != nullptr before deref
* separation of concerns: AFP WaveView updateCursor
extract check to pointerCloseToStartEndOrLoop()
* marked some function parameters as const
* Remove Core5Compat usage
* Fix bad merge
* Fixes after rebase
* Simplify QTX_WRAP_CPP call
* Remove comments that are obvious to a developer
* Whitespace
* Try using Qt 6 for MSVC CI
I chose Qt 6.5 because it's the last Qt LTS release with declared
support for Visual Studio 2019. Once we upgrade to Visual Studio 2022,
we could upgrade Qt as well.
* Fix MSVC build
Also fixes two memory leaks in MidiWinMM
* Fix GuiApplication on MSVC
* Fix interpolateInRgb
* Try building with patched Calf
* Fix submodule
* Fix OpulenZ build
* Try to fix zyn
* Fix comment
* Ty to fix zyn (again)
* Ty to fix RemotePluginBase
* Revert "Ty to fix RemotePluginBase"
This reverts commit 92dac44ffb11e19d1d5a21d9155369f017bd59e9.
* Update plugins/ZynAddSubFx/CMakeLists.txt
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
* Fix vertical & horizontal scroll wheel in SongEditor
* AppImage: Fix finding of Qt6 libs
* Fix implicit QString --> QFileInfo conversion
* Point submodule to lmms
* Fix multiple deprecation warnings
* Fix for Clang compiler
* Build with latest Qt LTS version now that we use MSVC 2022
* Update jurplel/install-qt-action to v4.3.0
* Bump minimum Qt6 version for MSVC
* Fix incorrect Qt version checks
Some comparisons were using ">" rather than ">="
* `QSize()` != `QSize(0, 0)`
* Fix more deprecation warnings
* Fix style
* Simplify Spectrum Analyzer mouse events
The Qt bug that used to be present appears to have been fixed, so the
workaround can be removed
* Minor changes
* Fix deprecated QCheckBox signal
* Fix setContent helper functions
* Remove QMultiMap usage from ControlLayout
* Remove SIGNAL and SLOT macros
* Revert TrackView.cpp changes
* Remove Q_DISABLE_MOVE usage since it does not seem to be available in Qt6
---------
Co-authored-by: michaelgregorius <michael.gregorius.git@arcor.de>
Co-authored-by: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com>
Co-authored-by: BoredGuy1 <66702733+BoredGuy1@users.noreply.github.com>
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
Co-authored-by: Lisa Magdalena Riedler <git@riedler.wien>
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
PathUtil: Serialization and Formatting
* Serialize all operations to use / instead of platform specific paths.
* Formatting changes for consistency.
* Reorder functions, add serialization enforcement to the other two functions.
Given these changes, the knife tool now uses `Qt::SplitHCursor`, but `Qt::IBeamCursor` is also a a viable option. I am noting this should substantial concern arise over the appearance of `Qt::SplitHCursor` due to cursor themes, such as the default one applied to applications running under WSL.
This cleans up typos in source comments and some user-facing strings.
Found via `codespell -q 3 -S "./plugins,./src/3rdparty,./data/locale,*.in,*.xpf" -L continous,currenty,globaly,inports,localy,nd,ot,sie,te,trough`
This PR simplifies #7762 by removing the editor-specific code from MainWindow and m_lastPlayMode from Song, and instead uses a static variable in Editor which keeps track of the last played editor.
This PR also removes the spacebar shortcut from MixerChannelView for changing the volume, as multiple users have noticed that it clashes with their intuition after getting used to the spacebar working everywhere else.
- Fixes: when right clicking on a piano key close to the lower edge of the screen, "Mark semitone" will mark the wrong key because it uses the upper edge of the context menu as reference.
- Fixes: getKey() is off by 2 pixels
- Introduces: yCoordOfKey() which is the reverse of getKey()
- Removes: section of code that can never be reached
---------
Co-authored-by: Johannes Lorenz <1042576+JohannesLorenz@users.noreply.github.com>
- Add `SampleType` concept
- Make `channels()` static when possible
- Add `dataSizeBytes()` and `dataView()` to `InterleavedBufferView`
- Support conversions between `std::span<SampleFrame>` and `InterleavedBufferView<float, 2>`
- Support iteration over frames of `InterleavedBufferView`
- Add `subspan` method
- Add `AudioBufferView` concept
---------
Co-authored-by: Sotonye Atemie <sakertooth@gmail.com>
Major changes:
- Remove Gate knob from effects, effectively hard coding its value to zero
- Replace effect RMS calculations with a more efficient way of detecting silent buffers
- Only perform silent buffer detection when `ProcessStatus::ContinueIfNotQuiet` is returned from a plugin AND auto-quit is enabled
Minor changes:
- Remove gate from presets
- Remove gate from .mmp projects
- Move `Effect::processorCount()` to `LadspaEffect`
- Rename `Effect::checkGate` to `Effect::handleAutoQuit`
- Adjust silence threshold for better compatibility with old RMS calculations
- Remove some unnecessary methods from `Effect`
- Reset quiet buffer count in `stopRunning`
- Use positive name for auto-quit boolean
- Simplify `m_autoQuitEnabled` initialization
Follow-Up of 7db3fa94a1 .
This was done by setting `CMAKE_C_INCLUDE_WHAT_YOU_USE` and
`CMAKE_CXX_INCLUDE_WHAT_YOU_USE` to (broken down into multiple lines here,
note, all below `FL/x.h` is not required for C):
```
include-what-you-use;
-Xiwyu;--mapping_file=/usr/share/include-what-you-use/qt5_11.imp;
-Xiwyu;--keep=*/xmmintrin.h;
-Xiwyu;--keep=*/lmmsconfig.h;
-Xiwyu;--keep=*/weak_libjack.h;
-Xiwyu;--keep=*/sys/*;
-Xiwyu;--keep=*/debug.h;
-Xiwyu;--keep=*/SDL/*;
-Xiwyu;--keep=*/alsa/*;
-Xiwyu;--keep=*/FL/x.h;
-Xiwyu;--keep=*/MidiApple.h;
-Xiwyu;--keep=*/MidiWinMM.h;
-Xiwyu;--keep=*/AudioSoundIo.h;
-Xiwyu;--keep=*/OpulenZ/adplug/*;
-Xiwyu;--keep=QPainterPath;
-Xiwyu;--keep=QtTest
```
FAQ:
* Q: Does this speed-up a completely fresh compile?
* A: No, I measured it.
* Q: Does it speed up anything else?
* A: Yes. If you change one header, it can reduce the number of CPP files
that your compiler needs to recompile, or your IDE has to re-scan.
* Q: What other reasons are for this PR?
* A: It's idiomatic to only include headers if you need them. Also, it will
reduce output for those who want to use IWYU for new PRs.
Background:
This is just a remainder PR of what I planned. My original idea was to setup
a CI which warns you of useless includes (but not of all issues that IWYU
complains about). However, I could not see that this was favored on Discord.
A full IWYU CI also has the problem that it (possibly??) needs to compile
with `make -j 1`, which would make CI really slow.
However, for that plan, I had to fix the whole code base to be IWYU
compliant - which it now is.
# GUI
## Present inputs/outputs in hierarchical menu
Present the available inputs and outputs in a hierarchical sorted menu
which shows clients with their ports.
The heavy lifting of creating the menu for the tool button is done in the
new method `buildMenu`.
It takes the input/output names in Jack's "Client name:Port name" format.
If an input/output name can be successfully split into the client name
and port name then a sub menu with the client name is created (if it was
not already created before) and the port name is added as an entry.
If the name cannot be split into exactly two components then it is simply
added to the top level menu as is.
Ports of the LMMS client are filtered out to prevent loops.
The menu starts with the client's sub menus in alphabetical order. Then
the top level entries are added in alphabetical order as well.
The callbacks for the `QAction` instances are implemented with lambdas
because MOC does not support nested classes like the setup widget is. For
now the used lambda only sets the text of the `QToolButton` as these are
used for persisting the configuration anyway.
## Disconnected state
Add the option to keep inputs/outputs disconnected.
The disconnected state is represented by the string "-" which is also
what is saved into the configuration in this case. For now the
representation in the GUI and of the save state is the same as it has the
advantage that no translation is necessary and thus not mapping between
display text and save state is necessary.
## Show technical output/input names
Show the technical output and input port names used by LMMS in the setup
dialog. Note: these are the names that are shown in tools like `qjackctl`
or `qpwgraph`.
This was proposed in a review. Personally I like the non-technical names
better but let's see what's accepted.
## Let the tool buttons use available space
Let the tool buttons stretch so that they look uniform and use all the
available space.
# Driver
## Reconnect inputs and outputs
Attempt to reconnect the inputs and outputs from the configuration during
startup of the Jack driver. Nothing will be done for inputs and outputs
that are not available at startup. Example: the users might have saved
some inputs when a device was available. The device is then disconnected
and LMMS restarted. The stored inputs cannot be used anymore. To give the
users the least surprise nothing is done.
`AudioJack::attemptToConnect` does the actual reconnection and also
prints some information for now.
`attemptToReconnectOutput` and `attemptToReconnectInput` delegate to
`attemptToConnect` with the right parameters.
# Technical details
## Generalized number of inputs/outputs
Generalize the number of inputs and outputs by using for loops. This
affects the number of widgets that are created and the amount of
configuration that is stored.
This change is a result of a code review discussion. In my opinion it
adds unnecessary complexity to something that should later be implemented
completely different anyway. It is for example now necessary to compute
the key names that are used during the saving of the configuration based
on the channel number. The commit exists so that its changes can be
discussed further. It might be reverted in one of the next commits.
## Collecting input and output names
Add `AudioJack::setupWidget::getAudioPortNames` which takes the type of
port and then collects all port names which match. Make
`getAudioOutputNames` and `getAudioInputNames` delegate to that method
with the appropriate type. This also hides the different terminologies a
bit.
## Separate Jack client in the GUI
The separate Jack client is necessary because the setup dialog does not
have any access to the actual driver. So a new client is created when the
dialog is opened and deleted when it is closed, i.e. when the dialog is
deleted itself.
## Repeated strings
Repeatedly used hard-coded strings are defined as static constant
variables in the anonymous namespace. This should prevent subtle mistakes
when working with the configuration values of the Jack driver.
## Saving the settings
`AudioJack::setupWidget::saveSettings` saves the selections that have
been made from the widgets right into the configuration.
- Build RemoteVstPlugin in C++20 mode
- Avoids using std::wstring due to strange issues with it when built
with wineg++. See https://bugs.winehq.org/show_bug.cgi?id=58465
- Fix some memory leaks + minor cleanup of RemoteVstPlugin code
- Rename `F_OPEN_UTF8` to `fopenUtf8`
- Use C++20 in our `determine_version_from_source` CMake function
- Update ZynAddSubFX submodule
* Remove Knob::setHtmlLabel
Remove the unused method `Knob::setHtmlLabel` and its associated members.
This removes some unnecessary complexity from the code.
* Public label methods
Make `Knob::setLabel` public. Add `Knob::getLabel` for completeness.
* Delegate in KnobControl::setText
Make `KnobControl::setText` delegate to the `Knob` instance now that `Knob::setLabel` is public again.
Users can now choose if they only want to export the selected notes when
exporting a MIDI clip as an `xpt` or `xptz` file in the piano roll. The
export file dialog now shows a checkbox with the label "Export only
selected notes".
## Technical details
Add the new public method `exportToXML` to `MidiClip`. Compared to
`saveSettings` it has an additional parameter `onlySelectedNotes` which
controls which notes are exported. The default is to export all notes.
The method `saveSettings` now simply delegates to `exportToXML` using the
default.
`PianoRollWindow::exportMidiClip` now adds a check box to the export
dialog which lets users select if they only want to export the selected
notes or all notes. The default is to export all notes. The method now
uses the new method `exportToXML` for the export and passes the state of
the check box into the method.
Makes it so that editor zoom, automation tension, along with quantization, note length, and all other combo boxes are not added to the undo history.
---------
Co-authored-by: szeli1 <143485814+szeli1@users.noreply.github.com>
Fixes TextFloat flickering which occurs when scrolling on knobs, faders, and note volume in the piano roll.
---------
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
Adds two non-owning views for audio buffers: `InterleavedBufferView` and `PlanarBufferView`.
The channel count can be specified at either compile-time or runtime. Specifying at compile-time provides both performance and space optimizations. The way this works is the same as `std::span` except this uses the new `DynamicChannelCount` constant rather than `std::dynamic_extent`.
This PR makes it so that when you double-click on a sample clip and select a new sample, it will automatically update the length of the clip, as long as the clip has auto-resize enabled.