Commit Graph

4274 Commits

Author SHA1 Message Date
saker
449e669067 Revert "Reduce Memory Leaks (#7345)" (#7360)
This reverts commit 0bc911e266.
2024-07-01 13:43:05 -04:00
Andrew Wiltshire
0bc911e266 Reduce Memory Leaks (#7345) 2024-07-01 10:29:15 -04:00
Andrew Wiltshire
fb5268ebae Adds "Show Hidden Content" checkbox (#7309)
* Adds "Show Hidden Content Dialogue"

* Update FileBrowser.cpp

* Automatically rearrange layout to fit check boxes

* check if files are hidden in a cross platform manner

* put the hidden files checkbox below the user and factory check boxes at all times

* removed layout rearrangement code

* moved checkbox code to FileBrowser

* Removed unused include

* Cleanup in FileBrowser

Move the method `addContentCheckBox` to the other private methods.
Remove the method parameters because it can use the members.

Remove the conditional when adding the "Hidden content" checkbox because
it was always true.

---------

Co-authored-by: Michael Gregorius <michael.gregorius.git@arcor.de>
2024-06-30 22:23:19 +02:00
FyiurAmron
edf6bf8dfe Remove mingw-std-threads from 3rd party deps and use native libs/headers instead (#7283)
* Remove mingw-std-threads from 3rd party deps

 and use native libs/headers instead

* switch MinGW to POSIX in CI
2024-06-30 15:49:06 -04:00
saker
13a05b99d3 Use recursive mutex for requestChangeInModel/doneChangeInModel (#7359)
* Make model change mutex recursive

* Initialize s_renderingThread
2024-06-30 14:54:20 -04:00
Michael Gregorius
286e62adf5 Simplify sample frame operations (make it a class) (#7156)
* Remove the struct StereoSample

Remove the struct `StereoSample`. Let `AudioEngine::getPeakValues` return a `sampleFrame` instead.

Adjust the calls in `Mixer`  and `Oscilloscope`.

* Simplify AudioEngine::getPeakValues

* Remove surroundSampleFrame

Some code assumes that `surroundSampleFrame` is interchangeable with `sampleFrame`. Thus, if the line `#define LMMS_DISABLE_SURROUND` is commented out in `lmms_basics.h` then the code does not compile anymore because `surroundSampleFrame` now is defined to be an array with four values instead of two. There also does not seem to be any support for surround sound (four channels instead of two) in the application. The faders and mixers do not seem to support more that two channels and the instruments and effects all expect a `sampleFrame`, i.e. stereo channels. It therefore makes sense to remove the "feature" because it also hinders the improvement of `sampleFrame`, e.g. by making it a class with some convenience methods that act on `sampleFrame` instances.

All occurrences of `surroundSampleFrame` are replaced with `sampleFrame`.

The version of `BufferManager::clear` that takes a `surroundSampleFrame` is removed completely.

The define `SURROUND_CHANNELS` is removed. All its occurrences are replaced with `DEFAULT_CHANNELS`.

Most of the audio devices classes, i.e. classes that inherit from `AudioDevice`, now clamp the configuration parameter between two values of `DEFAULT_CHANNELS`. This can be improved/streamlined later.

`BYTES_PER_SURROUND_FRAME` has been removed as it was not used anywhere anyway.

* Make sampleFrame a class

Make `sampleFrame` a class with several convenience methods. As a first step and demonstration adjust the follow methods to make use of the new functionality:
* `AudioEngine::getPeakValues`: Much more concise now.
* `lmms::MixHelpers::sanitize`: Better structure, better readable, less dereferencing and juggling with indices.
* `AddOp`, `AddMultipliedOp`, `multiply`: Make use of operators. Might become superfluous in the future.

* More operators and methods for sampleFrame

Add some more operators and methods to `sampleFrame`:
* Constructor which initializes both channels from a single sample value
* Assignment operator from a single sample value
* Addition/multiplication operators
* Scalar product

Adjust some more plugins to the new functionality of `sampleFrame`.

* Adjust DelayEffect to methods in sampleFrame

* Use composition instead of inheritance

Using inheritance was the quickest way to enable adding methods to `sampleFrame` without having to reimpement much of `std::array`s interface.

This is changed with this commit. The array is now a member of `sampleFrame` and the interface is extended with the necessary methods `data` and the index operator.

An `average` method was added so that no iterators need to be implemented (see changes in `SampleWaveform.cpp`).

* Apply suggestions from code review

Apply Veratil's suggestions from the code review

Co-authored-by: Kevin Zander <veratil@gmail.com>

* Fix warnings: zeroing non-trivial type

Fix several warnings of the following form:

Warnung: »void* memset(void*, int, size_t)« Säubern eines Objekts von nichttrivialem Typ »class lmms::sampleFrame«; use assignment or value-initialization instead [-Wclass-memaccess]

* Remove unnecessary reinterpret_casts

Remove some unnecessary reinterpret_casts with regards to `sampleFrame` buffers.

`PlayHandle::m_playHandleBuffer` already is a `sampleFrame*` and does not need a reinterpret_cast anymore.

In `LadspaEffect::processAudioBuffer` the `QVarLengthArray` is now directly initialized as an array of `sampleFrame` instances.

I guess in both places the `sampleFrame` previously was a `surroundSampleFrame` which has been removed.

* Clean up zeroSampleFrames code

* Fix warnings in RemotePlugin

Fix some warnings related to calls to `memcpy` in conjunction with`sampleFrame` which is now a class.

Add the helper functions `copyToSampleFrames` and `copyFromSampleFrames` and use them. The first function copies data from a `float` buffer into a `sampleFrame` buffer and the second copies vice versa.

* Rename "sampleFrame" to "SampleFrame"

Uppercase the name of `sampleFrame` so that it uses UpperCamelCase convention.

* Move SampleFrame into its own file

Move the class `SampleFrame` into its own class and remove it from `lmms_basics.h`.

Add forward includes to all headers where possible or include the `SampleFrame` header if it's not just referenced but used.

Add include to all cpp files where necessary.

It's a bit surprising that the `SampleFrame` header does not need to be included much more often in the implementation/cpp files. This is an indicator that it seems to be included via an include chain that at one point includes one of the headers where an include instead of a forward declaration had to be added in this commit.

* Return reference for += and *=

Return a reference for the compound assignment operators `+=` and `-=`.

* Explicit float constructor

Make the  constructor that takes a `float` explicit.

Remove the assignment operator that takes a `float`. Clients must use the
explicit `float` constructor and assign the result.

Adjust the code in "BitInvader" accordingly.

* Use std::fill in zeroSampleFrames

* Use zeroSampleFrames in sanitize

* Replace max with absMax

Replace `SampleFrame::max` with `SampleFrame::absMax`.

Use `absMax` in `DelayEffect::processAudioBuffer`. This should also fix
a buggy implementation of the peak computation.

Add the function `getAbsPeakValues`. It  computes the absolute peak
values for a buffer.

Remove `AudioEngine::getPeakValues`. It's not really the business of the
audio engine. Let `Mixer` and `Oscilloscope` use `getAbsPeakValues`.

* Replace scalarProduct

Replace the rather mathematical method `scalarProduct` with
`sumOfSquaredAmplitudes`. It was always called on itself anyway.

* Remove comment/TODO

* Simplify sanitize

Simplify the `sanitize` function by getting rid of the `bool found` and
by zeroing the buffer as soon as a problem is found.

* Put pointer symbols next to type

* Code review adjustments

* Remove "#pragme once"
* Adjust name of include guard
* Remove superfluous includes (leftovers from previous code changes)

---------

Co-authored-by: Kevin Zander <veratil@gmail.com>
2024-06-30 20:21:19 +02:00
Andrew Wiltshire
7c74fbc8c5 Capitalise root sidebar widget (#7350)
Co-authored-by: Rossmaxx <74815851+Rossmaxx@users.noreply.github.com>
2024-06-27 20:59:33 +05:30
Rossmaxx
aaca5fbd0e Remove MemoryHelper (#7335)
* remove memory helper and replace alignedMalloc with stl version

* it's aligned_alloc

* forgot about destructor

* switch to unique pointers

Co-authored-by: saker <sakertooth@gmail.com>

* compile fix

---------

Co-authored-by: saker <sakertooth@gmail.com>
2024-06-24 21:22:19 +05:30
Dominic Clark
a1f7753a94 Fix MSVC warnings up to level 2 (#7329)
* Fix MSVC warnings up to /W2

* Fix large shift UB warning
2024-06-22 02:05:14 -04:00
Monospace-V
26646c653c Style format DrumSynth (#7189)
Co-authored-by: saker <sakertooth@gmail.com>
2024-06-22 10:38:01 +05:30
notaz
e400d81ecc set "child subreaper" process attribute on Linux (#7315)
When launching the wine VST process various wrappers may be involved,
when they exit the VST process becomes orphaned. This breaks the
PollParentThread mechanism which is responsible for cleaning up
processes in case of a crash. Because of this 64bit VST process exits
prematurely, in other words 64bit VST is currently broken in a typical
wine configuration.

A solution suggested by Lukas W is to set the PR_SET_CHILD_SUBREAPER
flag which makes the kernel reparent such process to lmms and
PollParentThread then works as intended.

Co-authored-by: Lukas W <lukaswhl@gmail.com>
2024-06-18 14:51:07 +05:30
Dominic Clark
e76a99ee76 Suppress warnings in third-party code (#7319) 2024-06-17 22:48:04 +01:00
szeli1
2adbb166b5 arpeggiator sorted mode fixed (#7025)
Fixes an issue where sorted arpeggios over multiple notes used a largely
unusable algorithm. piano-octave-arp instead of octave-arp-piano.

Fixes #6499
Fixes #4491
2024-06-17 16:11:55 +02:00
saker
01ffa95578 Use src_set_ratio to fix artifacts within Sample playback (#7321) 2024-06-15 18:34:10 -04:00
Michael Gregorius
beedbc18a6 Add support for "factorysample:" prefix / Fix "bassloopes" typo (#7236)
## Add support for "factorysample:" prefix
Add support to upgrade files with `src` tags that are prefixed with "factorysample:".

## Fix "bassloopes" typo
Fix projects that still reference files with the typo "bassloopes" in their name.

The upgrade is implemented in its own method because it is unrelated to the BPM renaming even if it is technically very similar in its solution.

Introduce the helper method `mapSrcAttributeInElementsWithResources` which replaces the `src` attribute in elements with resources (samples and AFP) if it can be found in a map.
2024-06-14 16:22:39 +02:00
Andrew Wiltshire
969943b335 Change the wording of Instrument Plugin Dialogue (#7301)
Drag an instrument into either the Song Editor, the Pattern Editor or ~~into~~ an existing instrument track.

The word "into" seems redundant
2024-06-01 11:23:21 -04:00
Michael Gregorius
042f8ac325 Add peak indicators (#7295)
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.
2024-06-01 12:09:47 +02:00
Michael Gregorius
4e93f51b75 Adjust rendering of BarModelEditor (#7299)
Adjust the rendering of BarModelEditor to make it respect logarithmic
and linear models. The code now uses `inverseScaledValue` instead of
`value` just like the `Knob` class does when calculating the angle.
2024-05-31 23:39:09 +02:00
Michael Gregorius
37795ae20a Resizable mixer channels/strips (#7293)
## Make mixer channels resizable
Make the mixer channels resizable within the mixer view.

Remove the setting of the size policy from `MixerChannelView`. Add the
`Fader` widget with a stretch factor so that it is resized within the
layout of the mixer channel/strip. Remove the stretch that was added to
the layout because the fader now stretches.

In `MixerView` remove the top alignments when widgets are added to the
layout so that they can resize. Set the channel layout to align to the
left so that it behaves correctly when it is resized by the scroll area
it is contained in. Make the widget resizable in the scroll area so that
it always fills the space. Set the minimum height of the scroll area to
the minimum size of the widget plus the scrollbar height so that the
channel strips are never overlapped by the scrollbar.

Set the size policy of the "new channel" button so that it grows
vertically with the mixer view. Set a fixed size so that it is as wide as
a mixer strip.

## Enable maximization for mixer view

Enable the maximize button for the mixer view now that it is fully
resizable.
2024-05-31 13:11:45 +02:00
BoredGuy1
94b1a382dd fixed position line disappearing when zoomed out (#7296) 2024-05-31 08:19:34 +02:00
Raine M. Ekman
6ec1ced49c Don't recalculate the song length for every added TCO while loading (#5236)
Don't make LMMS calculate the song length for every added TCO when a new project is created or a project is loaded. Instead do it only once afterwards. This is accomplished by preventing any calculations in `Song::updateLength` if a song is currently loaded. `Song::updateLength` is then called immediately after the loading flag has been set to `false` in both cases.

---------

Co-authored-by: IanCaio <iancaio_dev@hotmail.com>
2024-05-30 18:37:08 +02:00
saker
bfeb781dc0 Redesign file browser searching (#7130) 2024-05-29 21:46:58 -04:00
Oskar Wallgren
4033406430 Automation Editor - Fix automation point forced snapping to integer value. (#7282)
* Revert "Fix glitch with automation points (#7269)"

This reverts commit d60fd0d022.

* Fix glitch in Automation Editor. This reverts the earlier fix and tries to solve the issue by instead rounding off the values of the top/bottom levels before comparison with the automation point value.

---------

Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
2024-05-28 14:31:09 +02:00
Dalton Messmer
2e6545328c Update MinGW CI to Ubuntu 20.04 (#7259)
Update MinGW CI to Ubuntu 20.04
* Use ghcr.io/lmms/linux.mingw:20.04
* Fix deprecation in ClipView.cpp
* Fix ccache and simplify git configuration
* Apply patch by @DomClark for MinGW's SDL2 target
* Update excludelist-win
2024-05-23 13:21:57 -04:00
Rossmaxx
b803e92d63 Add menu option and hotkeys to move controllers/effects (#7139)
* added controller rack modules

* remove this-> from setFocusPolicy() and obsolete comment

Co-authored-by: saker <sakertooth@gmail.com>

* Use std::swap

Co-authored-by: saker <sakertooth@gmail.com>

* some more cleanup

Co-authored-by: saker <sakertooth@gmail.com>

* Replace slots with function pointers

Co-authored-by: saker <sakertooth@gmail.com>

* Apply fixes

---------

Co-authored-by: ejaaskel <esa.jaaskela@suomi24.fi>
Co-authored-by: saker <sakertooth@gmail.com>
2024-05-23 17:38:47 +05:30
Johannes Lorenz
fa5f2aa41a Lv2Proc: Fix all code-style issues with {} 2024-05-23 00:34:00 +02:00
Tres Finocchiaro
32fe3e50e7 Add "natural" scrolling support for trackpads (#5510)
Adds QWheelEvent::inverted() support to spinboxes, knobs, sliders
2024-05-21 11:32:28 -04:00
Michael Gregorius
75d6be2eac Fix missing initialization (#7271)
Fix the missing initialization of some variables in `TrackContentWidget`.
This led to some performances issues when the widget was painted because
a for loop was executed for which the variable started at a very large
negative number and was then incremented.
2024-05-20 18:46:52 +02:00
BoredGuy1
a527427abf 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
2024-05-20 12:37:18 +02:00
Oskar Wallgren
d60fd0d022 Fix glitch with automation points (#7269)
Co-authored-by: Dalton Messmer <messmer.dalton@gmail.com>
2024-05-20 00:18:11 +02:00
szeli1
76d8f65485 Fix lost connections when restoring automation clip (#7002) 2024-05-19 22:03:07 +01:00
Pascal
0071cb6f63 Fix UI freeze when zooming in on long samples (#7253) 2024-05-19 22:36:30 +02:00
wujekbrezniew
ca109f94f4 Migrate to new LV2 header paths (#6990) 2024-05-19 14:39:20 +01:00
Pascal
0ee05f5ad8 Fix crash in AFP when playing with loop while no sample is loaded (#7266) 2024-05-18 18:40:29 -04:00
Bimal Poudel
f891bb30eb Update widths of combo boxes (#7262)
* Update widths of combo boxes

* Update src/gui/editors/PianoRoll.cpp

no space right after brace

Co-authored-by: saker <sakertooth@gmail.com>

* Update src/gui/editors/PianoRoll.cpp

Co-authored-by: saker <sakertooth@gmail.com>

* Update src/gui/editors/PianoRoll.cpp

Co-authored-by: saker <sakertooth@gmail.com>

* Update src/gui/editors/PianoRoll.cpp

Co-authored-by: saker <sakertooth@gmail.com>

---------

Co-authored-by: saker <sakertooth@gmail.com>
2024-05-17 21:32:59 -04:00
Dominic Clark
95e5f97150 Revamp resource embedding (#7241) 2024-05-12 17:38:14 +01:00
Tres Finocchiaro
6d100d1bba Remove support for msys2 (#7251) 2024-05-12 01:35:10 -04:00
saker
9b6e33aa5c Remove global oversampling (#7228)
Oversampling can have many different effects to the audio signal such as latency, phase issues, clipping, smearing, etc, so this should really be an option on a per-plugin basis, not globally across all of LMMS (which, in some places, shouldn't really need to oversample at all but were oversampled anyways).
2024-05-05 04:37:43 -04:00
Michael Gregorius
9bdc8adf33 Inform effects about changes in enabled model (#7237)
Add the virtual method `Effect::onEnabledChanged` which can be overridden by effects so that they can react to state changes with regards to being enabled or bypassed. The call of this methods is connected to state changes of the enabled model in the constructor of `Effect`.

Implement the method in `DualFilterEffect` by resetting the history of the two filters. This is done to prevent pops that have been reported in #4612.
2024-05-05 10:05:22 +02:00
Pascal
d5f5d00a6f Fix shifting of sample waveform during zoom (#7222)
The original code was doing division in `int`, which causes lost of accuracy and results in the waveform randomly shifting when zooming in and out.

This should fix it by casting variables to `float` before dividing, as well as keeping the values in `float` type.

The pull request also changes some type declaration to explicit to increase readability
2024-05-01 20:13:55 -04:00
Michael Gregorius
9ca9143f5b Fix upgrade routine for BPM renamings (#7235)
Fix the upgrade routine that was introduced with pull request #6747 which added the BPM value to some file names.

This also simplifies the implementation by using a map.

Note: this also removes the code about the prefix `factorysample:`. If it is used in some files these entries will also have to be added to the map.
2024-05-01 18:03:35 +02:00
Michael Gregorius
bb6a77aa0f Only set sample clips for valid files (#7224)
Check if a non-empty buffer was loaded and only set the sample clip if that's the case.

## Other changes

Move setting the song to modified towards the core in the context of `SampleClip`. Previously the `SampleClipView` did this but it's none of it's business.

Introduce `SampleClip::changeLengthToSampleLength` which changes the length of the clip to the length of the sample. This was also previously done by the view which is again the wrong place to do the necessary calculations. An unnecessary `static_cast` was removed while carrying over the code.

Add the method `SampleClip::hasSampleFileLoaded` which checks if the loaded sample corresponds to a given file name.

Fix code formatting.
2024-04-29 19:22:37 +02:00
Michael Gregorius
5c0db46a60 Streamline instrument flags (#7227)
## Instrument flags as a property of an instrument
The instruments flags (single streamed, MIDI based, not bendable) are properties of an instrument that do not change over time. Therefore the flags are made a property of the instrument which is initialized at construction time.

Adjust the constructors of all instruments which overrode the `flags` method to pass their flags into the `Instrument` constructor.

## Add helper methods for flags
Add helper methods for the flags. This makes the code more concise and readable and clients do not need to know the technical details on how to evaluate a flag.

## Remove the flags methods
Remove the flags methods to make it an implementation detail on how the flags are managed.
2024-04-27 17:45:55 +02:00
Rossmaxx
6c846684cd Replace call QT5_WRAP_UI with CMAKE_AUTOUIC (#7200) 2024-04-27 16:21:09 +01:00
saker
a53e5ba2f6 Remove high quality mode from codebase (#7219)
Many, many years ago (93a456c), high quality mode was merely disabled after it was noted that it can be problematic rather than being completely removed. Remove it from the codebase so we can get rid of some code and clean things up a bit.
2024-04-27 07:59:02 -04:00
Michael Gregorius
71dd300f43 Instrument release time in milliseconds (#7217)
Make instruments report their release time in milliseconds so that it becomes independent of the sample rate and sounds the same at any sample rate.

Technically this is done by removing the virtual keyword from `desiredReleaseFrames` so that it cannot be overridden anymore. The method now only serves to compute the number of frames from the given release time in milliseconds.

A new virtual method `desiredReleaseTimeMs` is added which instruments can override. The default returns 0 ms just like the default implementation previously returned 0 frames.

The method `computeReleaseTimeMsByFrameCount` is added for instruments that still use a hard coded release in frames. As of now this is only `SidInstrument`.

Add the helper method `getSampleRate` to `Instrument`.

Adjust several instruments to report their release times in milliseconds. The times are computed by taking the release in frames and assuming a sample rate of 44.1 kHz. In most cases the times are rounded to a "nice" next value, e.g.:
*  64 frames -> 1.5 ms (66 frames)
* 128 frames -> 3.0 ms (132 frames)
* 512 frames -> 12. ms (529 frames)
* 1000 frames -> 23 ms (1014 samples)

In parentheses the number of frames are shown which result from the rounded number of milliseconds when converted back assuming a sample rate of 44.1 kHz. The difference should not be noticeable in existing projects.

Remove the overrides for instruments that return the same value as the base class `Instrument` anyway. These are:
* GigPlayer
* Lb302
* Sf2Player

For `MonstroInstrument` the implementation is adjusted to behave in a very similar way. First the maximum of the envelope release times is computed. These are already available in milliseconds. Then the maximum of that value and 1.5 ms is taken and returned as the result.
2024-04-24 20:23:36 +02:00
Dominic Clark
bda042e1eb Add native system semaphore and Windows shared memory (#7212) 2024-04-20 23:21:29 +01:00
Rossmaxx
df11a98902 Bump Qt minimum version to 5.9 (#7204)
* bump qt minimum version to 5.9

* cleanup cmake checks

* Remove the obsoleted check.

* Missed this while removing the check.
2024-04-17 21:51:58 -04:00
Michael Gregorius
d5e1d9e853 Move icon determination into TrackLabelButton again (#7209)
Move icon determination into TrackLabelButton again

Fully undo the changes made in commit 88e0e94dcd because the intermediate revert made in commit 04ecf73395 seems to have led to a performance problem due to the icon being set over and over again in `TrackLabelButton::paintEvent`.

The original intention of the changes made in pull request #7114 was to remove the painting code that dynamically determines the icon over and over again. Ideally the icon that is used by an instrument should be somewhat of a "static" property that should be known very early on when an instrument view is created. There should not be any need to dynamically resolve the icon over and over, especially not in a button class very far down in the widget hierarchy. However, due to technical reasons this is not the case in the current code. See pull request #7132 for more details.
2024-04-17 19:21:23 +02:00
Michael Gregorius
d2c2a80506 Update CMT submodule / Upgrade code for CMT delays (#7206)
## Bump CMT to d8bf8084aa3
Bump the CMT submodule to commit d8bf8084aa3 which contains the underlying fixes for issue #5167.

The CMT delay uses `sprintf` calls to generate the technical names and display names of the delays. These calls are locale dependent. As a consequence for example the feedback delay might have been saved either as "fbdelay_0.1s" (point) or "fbdelay_0,1s" (comma) in a save file.

The CMT fix makes sure that all delays use points in their names and thus that they now always report the same name strings.

## Add upgrade routine for CMT delays
Add an upgrade routine for CMT delays which works in conjunction with the upgraded CMT submodule. Because the delays will now always report their name with points old save files which might contain versions with the comma must be upgraded to a name with a point.
2024-04-14 18:03:39 +02:00