-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Do not save MIDI connections in presets #7445
Do not save MIDI connections in presets #7445
Conversation
Ensure that no MIDI information is stored in presets. Add the new protected method `isSimpleSerializing` that can be used by sub classes to find out if they are temporarily in preset saving mode or not. Please note that the existing implementation is very brittle because an instance might accidentally stay in that mode. Use the information in `InstrumentTrack::saveTrackSpecificSettings`.
Reduce direct accesses to `m_simpleSerializingMode` by using the method `isSimpleSerializing` and extending `setSimpleSerializing` with a parameter.
Rename "SimpleSerializing" to "PresetMode" everywhere because that is what this mode describes in fact.
Added @zonkmachine as a reviewer because he has created issue #3922 and @PhysSong because he's been active in there as well and did the changes in #4207. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One minor styling nitpick. Everything else looks fine for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works like a charm. No midi channel information are in the presets but are still saved/loaded for projects. The preset are also backward compatible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, only minor questions and optional points.
Make `isPresetMode` a one-liner and initialize `m_presetMode` in the header instead of in the constructor (list).
A bit out of scope but will it make sense to seperate out saving presets into it's own area? |
What do you mean exactly? |
I mean move the preset saving, loading and handling logic to it's own file. |
I am not really sure if that would work because the presets are subsets of the full data that's stored for an instrument for example. If that code was to be extracted and moved into it's own file then it might diverge. Depending of what constitutes to a preset it might be an option though to structure the data differently so that in the full set there's one section with everything related to preset data and one section with the rest that does not go into the presets like for example the MIDI connections. In that case saving a preset would just mean to save the preset section into a separate file. In a way the full set would be build additively by adding preset and non-preset data whereas now the presets seem to be stored in a subtractive or selective way. |
Enable to make `setPresetMode` protected. This is accomplished by adding the new methods `savePreset` and `loadPreset` to `InstrumentTrack`. These methods manage the calling of `setPresetMode` so that callers won't have to know about this implementation detail. Then `saveSettings` and `loadSettings` are called respectively which in turn will delegate to `Track`. All context that use `loadPreset` or `savePreset` already known that they are dealing with an `InstrumentTrack` which is the reason why this works: * Loading of a preset file * Saving a preset * Replacement of an instrument Therefore in these place `loadPreset` and `savePreset` can be called and it's not necessary anymore to call `setPresetMode` there.
@JohannesLorenz, commit eb8633a improves a bit more on the situation. It adds the new methods
I will have to check if this can somehow be disentangled any further. However, currently it's a strange back and forth between By the way are there any other presets than instrument presets? If there are only instrument presents then this might be what's causing these problems and this back and forth. Another thing that's strange is that the presets are not really instrument presets but rather track presets. So I am pushing a button in the instrument window and what it will do is to also save information about the track that the instrument is in. This is also a bit smelly with regards to the design. I would have expected that an instrument preset only stores instrument specific information. This oddity is also reflected in the preset saving code in What do you think about merging this PR as is? It fixes a problem and the remaining stuff rather seem to be design problems that could be tackled in an extra PR. |
This is basically what i thought of when i asked for splitting the preset logic to it's own file. It was poor articulation on my end. Also for presets, ideally we should save the preset xpf and add an entry in the mmp xml as a node for a track if it's a preset. I hope you understand. |
I think we are almost on the same page. IMO there could be at least two types of presets:
Instrument presets only contain instrument information. They do not contain any information about tracks because logically these are enclosing objects. So instrument presets do not contain any information about mute, solo, height, color, etc. A track preset is used to add templated tracks. A track preset contains the track information like solo, mute, height, color, etc. It can also optionally contain a track object like an instrument, sample, pattern or automation. The object in turn can also optionally contain a preset. If no preset is contained then the potentially contained object is created in its default state. The project save files, i.e. MMP, should not contain contain any information about whether something was added as a preset or not because that information is not really useful. I think we have a different view here. |
It looks like the value of |
@PhysSong, it only looks like this. The restore is currently done in
The implementation was like that before and it is of course sub-optimal (to put it nicely). If an exception occurs anywhere in between setting the member to preset mode and restoring it then it might not be restored at all. I guess I will implement a guard-like RAII class which will get the |
Add the new local class `BoolGuard` which uses RAII to safely set a boolean to a value and later reset it to the old value. The guard is needed to ensure that the boolean `m_presetMode` is safely set to `true` in `savePreset` and `loadPreset` and reset even in case of exceptions. For this to work `m_presetMode` had to be changed to protected visibility. On this other hand this enables the removal of `setPresetMode`. Add comments to the two places where previously the mode was reset so that people do not wonder why nothing is reset and potentially put the code back in there.
I am just a bit sad about the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only editorials
Get rid of the protected member `m_presetMode` and its corresponding method `isPresetMode()`. This is accomplished by introducing two new methods `saveTrack` and `loadTrack`. These methods have a similar interface to `saveSettings` and `loadSettings` but they additionally contain a boolean which indicates if a preset is saved/loaded or a whole track. Both new methods contain the previous code of `saveSettings` and `loadSettings`. The latter two now only delegate to the new methods assuming that the full track is to be stored/loaded if called via the overridden methods `saveSettings` and `loadSettings`. Adjust `saveTrackSpecificSettings` so that it also passes information of whether a preset or a whole track is stored. This leads to changes in the interfaces of `AutomationTrack`, `InstrumentTrack`, `PatternTrack` and `SampleTrack`. Only the implementation of `InstrumentTrack` uses the new information though. Remove the `BoolGuard` class and adjust the implementation of `InstrumentTrack::savePreset` and `InstrumentTrack::loadPreset` to simply delegate to the `saveTrack` and `loadTrack` methods with the correct parameters. The methods `savePreset` and `loadPreset` are kept because they make the code more readable. Implementation notes --------------------- It could be considered to move `savePreset` and `loadPreset` into `Track`. The method `loadTrackSpecificSettings` was not adjusted with an additional boolean because for now no implementation needs to explicitly know if a preset or a track is restored. It could be considered to make the interfaces symmetrical though.
@JohannesLorenz, I don't know what you mean with " Please refer to the commit message for more details and two potential considerations which are listed at the end of the message. |
Noooooo 😭
I thought we could get around extending the All in all, the PR is good. I still wonder, though, if the parameter |
If this was only about the essential part of the PR then we could have kept the fix with the old brittle implementation. In fact I will attempt to pull
To me this implementation would sound rather brittle. That way the implementation of the The current implementation also makes the code much easier to understand. Looking at the interface of |
Move the methods `savePreset` and `loadPreset` into track because it potentially makes sense for all types of tracks to save a preset. Make `Track::saveTrack` and `Track::loadTrack` private because the public interface for saving and loading full tracks is `saveSettings` and `loadSettings` and for saving and loading presets it's `savePreset` and `loadPreset`.
With commit 4e2158b |
Ok from my side. Feel free to ask for more reviews/testing or merge. |
I have merged the changes. If any problems show up we either revert the changes or fix forward. |
Ensure that no MIDI information (connected inputs, outputs, etc.) is stored in presets. This main fix can be found in `InstrumentTrack::saveTrackSpecificSettings` where the state of the MIDI ports are now only saved if we are not in preset mode. The remaining changes are concered with a refactoring of the code that's related to saving and loading presets. The refactoring mainly revolves around the removal of the member `m_simpleSerializingMode` and the method `setSimpleSerializing` in `Track`. This is accomplished by introducing two new methods `saveTrack` and `loadTrack`. These methods have a similar interface to `saveSettings` and `loadSettings` but they additionally contain a boolean which indicates if a preset is saved/loaded or a whole track. Both new methods contain the previous code of `saveSettings` and `loadSettings`. The latter two now only delegate to the new methods assuming that the full track is to be stored/loaded if called via the overridden methods `saveSettings` and `loadSettings`. The methods `savePreset` and `loadPreset` are added as well. They call `saveTrack` and `loadTrack` with the preset boolean set to `true`. These methods are now used by all places in the code where presets are saved or loaded which makes the code more readable. Clients also do not need to know any implementation details of `Track`, e.g. like having to call `setSimpleSerializing`. Adjust `saveTrackSpecificSettings` so that it also passes information of whether a preset or a whole track is stored. This leads to changes in the interfaces of `AutomationTrack`, `InstrumentTrack`, `PatternTrack` and `SampleTrack`. Only the implementation of `InstrumentTrack` uses the new information though.
Ensure that no MIDI information (connected inputs, outputs, etc.) is stored in presets. This main fix can be found in `InstrumentTrack::saveTrackSpecificSettings` where the state of the MIDI ports are now only saved if we are not in preset mode. The remaining changes are concered with a refactoring of the code that's related to saving and loading presets. The refactoring mainly revolves around the removal of the member `m_simpleSerializingMode` and the method `setSimpleSerializing` in `Track`. This is accomplished by introducing two new methods `saveTrack` and `loadTrack`. These methods have a similar interface to `saveSettings` and `loadSettings` but they additionally contain a boolean which indicates if a preset is saved/loaded or a whole track. Both new methods contain the previous code of `saveSettings` and `loadSettings`. The latter two now only delegate to the new methods assuming that the full track is to be stored/loaded if called via the overridden methods `saveSettings` and `loadSettings`. The methods `savePreset` and `loadPreset` are added as well. They call `saveTrack` and `loadTrack` with the preset boolean set to `true`. These methods are now used by all places in the code where presets are saved or loaded which makes the code more readable. Clients also do not need to know any implementation details of `Track`, e.g. like having to call `setSimpleSerializing`. Adjust `saveTrackSpecificSettings` so that it also passes information of whether a preset or a whole track is stored. This leads to changes in the interfaces of `AutomationTrack`, `InstrumentTrack`, `PatternTrack` and `SampleTrack`. Only the implementation of `InstrumentTrack` uses the new information though.
The relevant change can be found in
InstrumentTrack::saveTrackSpecificSettings
where the new methodisPresetMode
is used to decide whether to store the MIDI port or not.The other changes are mostly refactoring.
Fixes #3922.