Let use use EffectEcho as an example.
you can remove forward declarations like:
class wxCheckBox;
class wxSlider;
class wxSpinCtrl;
add line "struct Validator;
" in public section
if the following is declared, remove it:
bool TransferDataToWindow(const EffectSettings &settings) override;
reimplement Effect::PopulateOrExchange
:
remove DECLARE_EVENT_TABLE();
(in .h)
remove the definition of the enum
with ID_***
(in .cpp)
remove the section BEGIN_EVENT_TABLE... END_EVENT_TABLE
(in .cpp)
cut (from .h) all declarations of wxWidgets (wxTextCtrl
, wxSlider
etc.) and paste them in the validator definition (in .cpp)
cut (from .h) all declarations of handlers like void On
Slider
, On
Text
and paste them in the validator definition (in .cpp)
IMPORTANT: at the end of all the handlers, add a call to ValidateUI()
;
in Validator::PopulateOrExchange
remove the calls to .Id(...)
on the ShuttleGui
just after every creation of a widget, add a line like:
where:
1st arg is the just created widget
2nd arg is either wxEVT_TEXT
or wxEVT_SLIDER
or wxEVT_CHECKBOX
according to the widget type
3rd arg is the handler which is meant to handle events coming from the widget
change
bool EffectWahwah::TransferDataToWindow(const EffectSettings &)
to bool EffectWahwah::Validator::UpdateUI()
leaving the contents which is there, but adding at the top:
in each of the control handlers:
add Validator::
just after MyEffect::
in the method definition
place a call to ValidateUI();
at the end
there might be calls to Effect::EnableApply
. Solve them by casting down to class Effect the Validator's mEffect
member.
however, since that commit, the following has changed:
some methods of Instance have a different signature
MakeInstance
now takes no args
the instance does not inherit EffectInstanceWithSampleRate
anymore (?))
add in public section:
Identify members that represent state - comment them out
remove decls of methods: ProcessInitialize, ProcessFinalize, ProcessBlock RealtimeInitialize, RealtimeAddProcessor, RealtimeFinalize, RealtimeProcess
add:
Make the Effect::Process***
methods belong to the instance by:
prepending ::Instance
where needed
replacing the lines you added in step 1:
auto& echoSettings = mSettings;
with this
// temporary - in the final step this will be replaced by
// auto& echoSettings = GetSettings(settings);
// auto& echoSettings = static_cast<const EffectEcho&>(mProcessor).mSettings;
make the effect inherit:
EffectWithSettings<EffectEchoSettings, PerTrackEffect>
if the effect is per-track
EffectWithSettings<EffectEchoSettings, Effect>
otherwise
remove the FetchParameters method
remove mSettings member
add const to arg EffectEchoSettings&
in the Validator constructor
turn Validator::mSettings
from a reference to a non-reference
go to ProcessInitialize, ProcessBlock, ProcessFinalize, RealtimeInitialize
etc.; remove the downcast and enable the commented out GetSettings
go to Validator::ValidateUI
, uncomment the line
//EffectEcho::GetSettings(settings) = mSettings;
go to Validator::UpdateUI
, uncomment the line
//mSettings = GetSettings(settings);
in the effect's ::PopulateOrExchange
, uncomment/comment lines as prescribed
in general, settings are not taken anymore from the effect, like in:
auto& ms = static_cast<const EffectWahwah&>(mProcessor).mSettings;
but taking them from the passed ones, like so:
auto& ms = GetSettings(settings);
Regarding step 2:
"Another possibility, is that I MAY put all the needed calls to GetSettings()
in early, BUT I do not yet use EffectWithSettings<>
and the definition of GetSettings()
that it generates. Instead, I define GetSettings()
to ignore its argument and return mSettings
in the effect object. At the last step of real statelessness, I can delete the definition of GetSettings()
but leave the calls."
Regarding step 4:
"There may be a fifth step: see the commit I recently pushed to the branch for ladspa effects.
MakeSettings
and CopySettingsContents
may require explicit definitions instead of those generated by the template EffectWithSettings
.
That does not apply to built-in effects where the settings structure simply contains several scalar fields and no variable sized containers.
For Ladspa, you can see that MakeSettings()
instead allocates a vector of values, whose size is not known at compilation time but depends on other information that the effect is queried for. So default construction of the settings, as in the generated MakeSettings()
, will not do.
Then CopySettingsContents
must also be overridden, not for correctness but for efficiency. The override is supposed to avoid memory allocations when the main thread calls it, so it should not use the copy constructors of the embedded std::vector
but instead rewrite an existing vector without changing its capacity. The assumption will be made that the destination settings containers are already correctly sized, because MakeSettings did that, or else full copies done in the main thread (where allocations are allowed) already did that.
Other third party effect families like AudioUnits may have Settings structures containing maps from strings to values, instead of vectors, but the problems will be similar."