* Update ringbuffer submodule to fix includes
* Remove cyclic includes
* Remove Qt include prefixes
* Include C++ versions of C headers
E.g.: assert.h -> cassert
* Move CLIP_BORDER_WIDTH into ClipView
This allows to remove includes to TrackView.h in ClipView cpp files.
* Elliminate useless includes
This improves the include structure by elliminating includes that are
not used. Most of this was done by using `include-what-you-use` with
`CMAKE_C_INCLUDE_WHAT_YOU_USE` and `CMAKE_CXX_INCLUDE_WHAT_YOU_USE`
set to (broken down here):
```
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
```
* Fixup: Remove empty #if-#ifdef pairs
* Remove LMMS_HAVE_STD(LIB|INT)_H
Summary:
* `NULL` -> `nullptr`
* `gui` -> Function `getGUI()`
* `pluginFactory` -> Function `getPluginFactory()`
* `assert` (redefinition) -> using `NDEBUG` instead, which standard `assert` respects.
* `powf` (C stdlib symbol clash) -> removed and all expansions replaced with calls to `std::pow`.
* `exp10` (nonstandard function symbol clash) -> removed and all expansions replaced with calls to `std::pow`.
* `PATH_DEV_DSP` -> File-scope QString of identical name and value.
* `VST_SNC_SHM_KEY_FILE` -> constexpr char* with identical name and value.
* `MM_ALLOC` and `MM_FREE` -> Functions with identical name and implementation.
* `INVAL`, `OUTVAL`, etc. for automation nodes -> Functions with identical names and implementations.
* BandLimitedWave.h: All integer constant macros replaced with constexpr ints of same name and value.
* `FAST_RAND_MAX` -> constexpr int of same name and value.
* `QSTR_TO_STDSTR` -> Function with identical name and equivalent implementation.
* `CCONST` -> constexpr function template with identical name and implementation.
* `F_OPEN_UTF8` -> Function with identical name and equivalent implementation.
* `LADSPA_PATH_SEPARATOR` -> constexpr char with identical name and value.
* `UI_CTRL_KEY` -> constexpr char* with identical name and value.
* `ALIGN_SIZE` -> Renamed to `LMMS_ALIGN_SIZE` and converted from a macro to a constexpr size_t.
* `JACK_MIDI_BUFFER_MAX` -> constexpr size_t with identical name and value.
* versioninfo.h: `PLATFORM`, `MACHINE` and `COMPILER_VERSION` -> prefixed with `LMMS_BUILDCONF_` and converted from macros to constexpr char* literals.
* Header guard _OSCILLOSCOPE -> renamed to OSCILLOSCOPE_H
* Header guard _TIME_DISPLAY_WIDGET -> renamed to TIME_DISPLAY_WIDGET_H
* C-style typecasts in DrumSynth.cpp have been replaced with `static_cast`.
* constexpr numerical constants are initialized with assignment notation instead of curly brace intializers.
* In portsmf, `Alg_seq::operator[]` will throw an exception instead of returning null if the operator index is out of range.
Additionally, in many places, global constants that were declared as `const T foo = bar;` were changed from const to constexpr, leaving them const and making them potentially evaluable at compile time.
Some macros that only appeared in single source files and were unused in those files have been removed entirely.
* Fix bug introduced by #5657
There was a bug introduced by #5657 where reloading a project
and playing it could cause a Segmentation Fault crash. After some
debugging, @DomClark tracked the issue to be likely a use-after-free
being caused by m_oldAutomatedValues not being cleared when the project
was loaded again.
This commit adds a line to clear the m_oldAutomatedValues map on
Song::clearProject(), which is called from Song::loadProject().
Now, instead of using a Signal/Slot connection to move the
control of the models back to the controllers, every time the song is
processing the automations, the control of the models that were
processed in the last cycle are moved back to the controller. The same
is done under Song::stop(), so the last cycle models control is moved
back to the controller.
That removes the need to have a pointer to the controlled model
in the controller object.
Adds mixer model change request to avoid race condition.
Co-authored-by: Dominic Clark <mrdomclark@gmail.com>
* Adds a baseDir for the local path
Adds a new Base for paths called "local:", which will translate to the dir where the currently opened project file is at. In the future this will allow us to make project bundles and make it easier to export and transfer projects to other people without breaking the paths to samples, presets, plugins and others.
* Starts implementing the makeBundle functionality
For now, to make a bundle LMMS has to be run through CLI with the makeBundle/--makeBundle command, followed by an input file and an output file ('lmms --makeBundle input.mmp output.mmp'). DataFile::writeBundle() is then called. For now, it only saves the mmp/mmpz file normally and also creates a "resources" folder if it doesn't exists. Later it will also manipulate the DataFile so all paths are local and copy all files to the resources folder.
TODO:
-Remove warnings.
-Implement the logic to manipulate the DataFile and copy files.
* Starts implementing logic to go through resources
Starts implementing the logic that will go through all the resources of the project file and add them to the bundle. We use a std::map of QString to std::vector<QString>: The first string is the DOM element tagname that is going to be searched for. The vector of strings holds all attributes this element can have that accesses resources. For now we just print those to the screen.
* Adds logic to copy files and update the project
The raw logic for creating the bundle is finished. It now copies the resource files and update the project to use "local:" paths to the new file now.
Now it's a matter of organizing things and adding safety checks for file operation errors basically.
* Makes the writeBundle method more organized
Improves comments and debugging warnings to make the writeBundle a bit more organized for review.
* Adds a project bundle folder
Adds a project bundle folder, inside which the bundles will be created. Instead of receiving an output project file name, the makeBundle command now receives a bundle name that will be used as the name of the bundle's folder.
Uses a typedef for the std::map with the tags and attributes with resources.
TODO:
- Fix the local: prefix so it works when we don't have the project file open (for CLI usage, or find another way to deal with it).
- Sanitize the bundle name.
- Allow overwriting bundles?
* Handles local paths when a project isn't open
The PathUtil base prefix conversion for "local:" uses the loaded song file name. When we are running the makebundle command from the CLI there isn't a loaded project, so those prefixes aren't converted properly. Now, when there isn't a project open PathUtil will return "local:" again when it tries to convert this base prefix. DataFile can then check if the base prefix is still there, and if it is it knows the conversion wasn't possible, so it does the conversion itself. To do that, a member called m_fileName was added to DataFile, which will hold the file being manipulated if that's where the DataFile originated from, and the local path can be retrieved from it.
* Sanitizes the bundle name
The bundle name is now sanitized. Since it's going to be used as a folder name, we need to keep the user from giving invalid folder names as a bundle's name. The rules for the name are:
1) It must start with a word character (either a digit or letter)
2) It can be followed by any number of letters, digits, whitespaces or hyphens
3) It must end with a word character (either a digit or letter)
A Regexp is used to check for the name validity.
* Moves away from projectbundle folder concept
This commit regresses some functionality. Project bundles will be saved just as any other project, except they will also have the resources folder. It will be up to the user to organize the bundles on their own folders. It's currently not allowed to save a bundle on a folder where there's one already though (if there's a resources folder already). Later it might be allowed to overwrite bundles in that case.
The projectbundles folder was dropped. The user can save project bundles anywhere in the system.
The DataFile::writeBundle was removed. It's functionality was merged into the DataFile::writeFile method, by adding a boolean on the parameters defining whether it should be saved with resources. The logic of copying the resource files and changing the paths inside the project DataFile was moved to DataFile::copyResources, making the methods a little bit less dense.
* Adds an option to save project as bundle
The "Save As" dialog now has an option to save project as a project bundle (with resources), which will save the file as a bundle.
Known bug:
- Because the "local:" base prefix is translated to the filename from the Engine::getSong(), it breaks when Song::guiSaveProjectAs is called, because that method changes the project name before saving. Urgent fix!
* Fix local: prefix saving bug
There was a bug where "local:" prefixes weren't resolved properly during saving because Song::guiSaveProjectAs() changed the project name to the destiny file name before saving. This resulted in the local paths using the destination file as a reference. Both Song::guiSaveProject() and Song::guiSaveProjectAs() were rewritten, and now they only rename the project after it's saved.
* Adds a warning message box
When the user tries to save a project bundle on a folder that already has a project bundle (contains a resources folder) a message box pops up telling the user it's not permitted and that another path should be chosen.
* Removes unused header
Forgot to remove <QRegExp> header when I removed the code that used it.
* Removes Vestige plugins bundling
For safety reasons, remove the possibility to bundle VSTs loaded
through vestige. Also runs a safety check during the project being
loaded (Song::loadProject) to check if either Vestige plugins or effect
plugins are using local paths, and abort the project load if so. That is
to avoid malicious code being run because of bad DLLs being shipped with
a project file.
* Extracts code from loadProject to another method
Extracts code that checks if a DataFile contains local paths to
plugins to another method inside DataFile.
* Removes debug warnings
Removes warnings previously used for debugging. Improves a
warning message on PathUtil.
* Fixes small bug with error logging
Fixes small bug, where a QMessageBox was being used to prompt an
error without checking if the gui is loaded first. Now we check for the
GUI and if we are in CLI mode we use a QTextStream instead.
* Saves the bundle in a newly created folder
Now a folder with the project name is created inside which the
bundle will be saved. This makes the process more convenient.
Some save errors that previously only triggered qWarnings now
trigger message boxes to warn the user of what happened (using a lambda
function that either shows message boxes or trigger qWarnings depending
whether a gui is present).
Makes it so saving a bundle doesn't change the loaded project
path, that way the user won't be able to accidentally "Save" over a
bundle which should not be done for now.
* Enhances the name conflict workaround
Now, instead of replacing the resource names with meaningless
numbers, the bundle save will just append a counter to the end of
filenames that have been repeated.
* Starts addressing Johannes review
* Adds makebundle action to bash completion file
Adds the bash completion code for the made bundle action.
* Improves safety check on project files
Now, instead of checking certain XML tags for local paths,
DataFile::hasLocalPlugin() will return true if ANY tag that isn't on the
RESOURCE_ELEMENTS list contains an attribute that starts with "local:".
The method is now recursive so it can go through all XML tags
during this check.
* Addresses Spekular change request
Uses basePrefix(Base::LocalDir) instead of "local:" on the
return of unresolved local paths.
* Makes hasLocalPlugins method const
* Replaces literal uses of "local:"
Instead of using "local:" we are now retrieving the base prefix
from PathUtil, so if we change the prefix on the future we don't need to
replace every mention to it as well.
* Fix some comments on the header and cpp file
* Changes variable on PathUtil to const
Changes the retrieved pointer to the song object to a const
pointer.
* Leave doxygen comment on CPP file only
There was 2 doxygen comments for the same method, on the header
and CPP file. The latter was kept since it goes into more details about
the functionality of the method.
* Fix doxygen comment @param
Fixes the doxygen comment from hasLocalPlugin().
* Remove assert statements
Some assert statements were being done wrong and are probably
even unnecessary for that piece of code, so they were removed.
* Skips local paths when looking for shortest path
PathUtil::toShortestRelative() was including the local paths on
the candidate paths, which could lead to a unallowed resource (i.e.:
vst plugin) to be assigned a local path even on a regular save.
The local paths are now skipped when looking for the shortest
relative path, since they should only be used by the bundle save on the
allowed resources.
* Address Spekular's review
Changes some of the PathUtil methods to allow a boolean pointer
to be used to return the status of the method, setting it to false if it
failed somewhere.
Also adds a parameter to toShortestRelative to either allow or
forbid local paths in the search for the shortest relative path.
* Replaces "ok" with "error"
* Fix wrong lengths of exported tracks, when tracks have different lengths.
Song::updateLength() was called in ProjectRenderer::run() after Song::startExport(),
updating m_length too late, resulting in it being used as the length of the wrong track.
* Fix "Export as loop" resetting after rendering the first track
Co-authored-by: Hyunjin Song <tteu.ingog@gmail.com>
* Song: add isSavingProject.
* VersionedSaveDialog: Add support for a custom option dialog.
* AutomatableModel: Support the discardMIDIConnections save option.
* InstrumentTrack: Support the discardMIDIConnections save option.
* SaveOptions: Show the save option dialog on "save as".
Switches some signal-slot connections to Qt::DirectConnection.
Now LMMS can handle loop points correctly and export samples without glitches.
Also tweaks some Mixer-related code to avoid related deadlocks on export.
Changed according to feedback from AudioBlast. The flag used to be set most of the time, now it is only set when playback starts/stops, looping is toggled, or playback jumps around.
Fixes regression from 75077f6200 that caused
global automation tracks to have priority in processing.
Adds a test checking for the desired behaviour.
Fixes#4268
Finally remove Song's dependency to MainWindow by moving the window
title update which is triggered due to a changed project file name from
the class Song into MainWindow.
Implementation details:
Add a new signal projectFileNameChanged to Song and connect the new slot
method MainWindow::onProjectFileNameChanged to it. Update the window
title whenever the slot is triggered.
Add a new private method Song::setProjectFileName which sets the project
file name and emits the signal (only if the file name really changes).
Call setProjectFileName everywhere where m_fileName was manipulated
directly. This is done to ensure that the signal can be potentially
emitted in all relevant situations.
Remove the calls to gui->mainWindow from
Song::createNewProjectFromTemplate.
These changes finally remove the include to "MainWindow.h". The include
for "ConfigManager.h" was previously done implicitly through the include
of "MainWindow.h" and therefore had to be added explicitly after the
latter is removed.
Move the window title updates which are triggered due to a changed
modify state from Song to MainWindow.
Implementation details:
Add a new signal modified to Song and connect the new slot method
MainWindow::onSongModified to it.
Currently only the window title is updated in the slot. It is only
updated if the code is executed from the GUI main thread. This
implementation was taken over from the original implementation of
Song::setModified. The assumption here seems to be that the Song might
also be set as modified from other threads (which is a bad design).
Add a new private method Song::setModified(bool) and replace all direct
manipulations of m_modified in Song by calls to this method. This is done
to ensure that the signal can be emitted in all these cases. Make
Song::setModified() delegates to Song::setModified(bool) for the same
reason.
Other changes:
Slightly refactor MainWindow::resetWindowTitle to get rid of an
unnecessary if statement.
Add the new signal Song::stopped which is emitted when the song is
stopped. Connect the new slot method MainWindow::onSongStopped to that
signal. Remove all GUI updates from Song::stop and handle them in
MainWindow::onSongStopped.
Move the showing of save result dialogs, e.g. "The project XYZ is now
saved.", from the class Song into the class MainWindow.
Implementation details:
Add three new methods guiSaveProject, guiSaveProjectAs and
handleSaveResult to MainWindow. The first two correspond to the methods
with the same name in Song which don't do anything GUI related anymore.
The GUI related actions are instead implemented in the two new methods
in MainWindow. The method handleSaveResult shows the dialogs for
successful and failed saves, updates the list of recent files and the
title bar of the main window.
This commit also fixes a problem in Song::guiSaveProject where a failed
saved without a GUI would still have returned true, i.e. success.
Move the functionality of the method Song::importProject into the
MainWindow as it mainly consists of GUI related actions.
Add a new method Song::setLoadOnLauch to ensure that the boolean
Song::m_loadOnLaunch is still set at the end of the import.
The code to export a song and the tracks of a song mainly consisted of
GUI code. Therefore it was moved completely into MainWindow.
Add two new slots and a method that does the actual work to MainWindow.
Make both slots delegate to the worker method.
Move all GUI dependencies out of Song::exportProjectMidi and move them
into the MainWindow.
Show the GUI in the new slot method MainWindow::onExportProjectMidi and
delegate to Song::exportProjectMidi once the file name has been
determined. The file name is given as a parameter to
Song::exportProjectMidi which still contains the business logic of
exporting the data.
Default project when cancelling project loading
If a user isn't aware that the loading of a project has been
cancelled, it may be in an incomplete state. Saving such a project
will overwrite the original file and result in data loss. This is
solved by loading the default project on cancelling project loading.
Add Mixer::clearNewPlayHandles() to prevent crash when cancelling
loading of a single streamed instrument.