Require a ProjectWindow as ancestor of effect dialog...

... by passing parent as reference, not pointer, and testing in the dialog
factory function.

This is important so that we know the lifetime of an effect dialog, even when
it is non-modal, is bounded by the lifetime of the associated project.
This commit is contained in:
Paul Licameli 2020-01-06 10:09:18 -05:00
parent f50171ed00
commit bb26b2f2c4
27 changed files with 51 additions and 40 deletions

View File

@ -142,7 +142,8 @@ class AUDACITY_DLL_API EffectClientInterface /* not final */ : public EffectDef
{
public:
using EffectDialogFactory = std::function<
wxDialog* ( wxWindow*, EffectHostInterface*, EffectUIClientInterface* )
wxDialog* ( wxWindow &parent,
EffectHostInterface*, EffectUIClientInterface* )
>;
virtual ~EffectClientInterface() {};
@ -179,7 +180,7 @@ public:
virtual bool RealtimeProcessEnd() = 0;
virtual bool ShowInterface(
wxWindow *parent, const EffectDialogFactory &factory,
wxWindow &parent, const EffectDialogFactory &factory,
bool forceModal = false
) = 0;
// Some effects will use define params to define what parameters they take.

View File

@ -218,7 +218,7 @@ void MacroCommandDialog::OnEditParams(wxCommandEvent & WXUNUSED(event))
auto command = mInternalCommandName;
wxString params = mParameters->GetValue();
params = MacroCommands::PromptForParamsFor(command, params, this).Trim();
params = MacroCommands::PromptForParamsFor(command, params, *this).Trim();
mParameters->SetValue(params);
mParameters->Refresh();

View File

@ -438,7 +438,8 @@ wxString MacroCommands::GetCurrentParamsFor(const CommandID & command)
return EffectManager::Get().GetEffectParameters(ID);
}
wxString MacroCommands::PromptForParamsFor(const CommandID & command, const wxString & params, wxWindow *parent)
wxString MacroCommands::PromptForParamsFor(
const CommandID & command, const wxString & params, wxWindow &parent)
{
const PluginID & ID =
EffectManager::Get().GetEffectByIdentifier(command);

View File

@ -95,7 +95,8 @@ class MacroCommands final {
static wxArrayStringEx GetNamesOfDefaultMacros();
static wxString GetCurrentParamsFor(const CommandID & command);
static wxString PromptForParamsFor(const CommandID & command, const wxString & params, wxWindow *parent);
static wxString PromptForParamsFor(
const CommandID & command, const wxString & params, wxWindow &parent);
static wxString PromptForPresetFor(const CommandID & command, const wxString & params, wxWindow *parent);
// These commands do depend on the command list.

View File

@ -1104,7 +1104,7 @@ void MacrosWindow::OnEditCommandParams(wxCommandEvent & WXUNUSED(event))
auto command = mMacroCommands.GetCommand(item);
wxString params = mMacroCommands.GetParams(item);
params = MacroCommands::PromptForParamsFor(command, params, this).Trim();
params = MacroCommands::PromptForParamsFor(command, params, *this).Trim();
Raise();
mMacroCommands.DeleteFromMacro(item);

View File

@ -215,7 +215,7 @@ bool EffectChangePitch::Process()
proxy.mProxyEffectName = XO("High Quality Pitch Change");
proxy.setParameters(1.0, pitchRatio);
return Delegate(proxy, mUIParent, nullptr);
return Delegate(proxy, *mUIParent, nullptr);
}
else
#endif

View File

@ -200,7 +200,7 @@ bool EffectChangeTempo::Process()
EffectSBSMS proxy;
proxy.mProxyEffectName = XO("High Quality Tempo Change");
proxy.setParameters(tempoRatio, 1.0);
success = Delegate(proxy, mUIParent, nullptr);
success = Delegate(proxy, *mUIParent, nullptr);
}
else
#endif

View File

@ -478,7 +478,7 @@ bool Effect::RealtimeProcessEnd()
return true;
}
bool Effect::ShowInterface(wxWindow *parent,
bool Effect::ShowInterface(wxWindow &parent,
const EffectDialogFactory &factory, bool forceModal)
{
if (!IsInteractive())
@ -1091,7 +1091,7 @@ void Effect::SetBatchProcessing(bool start)
}
}
bool Effect::DoEffect(wxWindow *parent,
bool Effect::DoEffect(wxWindow &parent,
double projectRate,
TrackList *list,
TrackFactory *factory,
@ -1214,7 +1214,7 @@ bool Effect::DoEffect(wxWindow *parent,
}
bool Effect::Delegate(
Effect &delegate, wxWindow *parent, const EffectDialogFactory &factory )
Effect &delegate, wxWindow &parent, const EffectDialogFactory &factory )
{
NotifyingSelectedRegion region;
region.setTimes( mT0, mT1 );

View File

@ -142,7 +142,7 @@ class AUDACITY_DLL_API Effect /* not final */ : public wxEvtHandler,
size_t numSamples) override;
bool RealtimeProcessEnd() override;
bool ShowInterface( wxWindow *parent,
bool ShowInterface( wxWindow &parent,
const EffectDialogFactory &factory, bool forceModal = false) override;
bool GetAutomationParameters(CommandParameters & parms) override;
@ -255,12 +255,12 @@ class AUDACITY_DLL_API Effect /* not final */ : public wxEvtHandler,
// have the "selected" flag set to true, which is consistent with
// Audacity's standard UI.
// Create a user interface only if the supplied function is not null.
/* not virtual */ bool DoEffect(wxWindow *parent, double projectRate, TrackList *list,
/* not virtual */ bool DoEffect(wxWindow &parent, double projectRate, TrackList *list,
TrackFactory *factory, NotifyingSelectedRegion &selectedRegion,
const EffectDialogFactory &dialogFactory );
bool Delegate( Effect &delegate,
wxWindow *parent, const EffectDialogFactory &factory );
wxWindow &parent, const EffectDialogFactory &factory );
virtual bool IsHidden();

View File

@ -326,7 +326,7 @@ bool EffectManager::SetEffectParameters(const PluginID & ID, const wxString & pa
bool EffectManager::PromptUser(
const PluginID & ID,
const EffectClientInterface::EffectDialogFactory &factory, wxWindow *parent)
const EffectClientInterface::EffectDialogFactory &factory, wxWindow &parent)
{
bool result = false;
Effect *effect = GetEffect(ID);
@ -342,7 +342,7 @@ bool EffectManager::PromptUser(
if (command)
{
result = command->PromptUser(parent);
result = command->PromptUser(&parent);
return result;
}

View File

@ -107,7 +107,7 @@ public:
bool SetEffectParameters(const PluginID & ID, const wxString & params);
bool PromptUser( const PluginID & ID,
const EffectClientInterface::EffectDialogFactory &factory,
wxWindow *parent );
wxWindow &parent );
bool HasPresets(const PluginID & ID);
wxString GetPreset(const PluginID & ID, const wxString & params, wxWindow * parent);
wxString GetDefaultPreset(const PluginID & ID);

View File

@ -19,6 +19,7 @@
#include "Effect.h"
#include "EffectManager.h"
#include "../ProjectHistory.h"
#include "../ProjectWindowBase.h"
#include "../TrackPanelAx.h"
#include "RealtimeEffectManager.h"
@ -377,7 +378,7 @@ void EffectRack::OnEditor(wxCommandEvent & evt)
}
auto pEffect = mEffects[index];
pEffect->ShowInterface( GetParent(), EffectUI::DialogFactory,
pEffect->ShowInterface( *GetParent(), EffectUI::DialogFactory,
pEffect->IsBatchProcessing() );
}
@ -1812,15 +1813,22 @@ void EffectUIHost::CleanupRealtime()
}
}
wxDialog *EffectUI::DialogFactory( wxWindow *parent, EffectHostInterface *pHost,
wxDialog *EffectUI::DialogFactory( wxWindow &parent, EffectHostInterface *pHost,
EffectUIClientInterface *client)
{
auto pEffect = dynamic_cast< Effect* >( pHost );
if ( ! pEffect )
return nullptr;
// Make sure there is an associated project, whose lifetime will
// govern the lifetime of the dialog, even when the dialog is
// non-modal, as for realtime effects
auto project = FindProjectFromWindow(&parent);
if ( !project )
return nullptr;
Destroy_ptr<EffectUIHost> dlg{
safenew EffectUIHost{ parent, pEffect, client} };
safenew EffectUIHost{ &parent, pEffect, client} };
if (dlg->Initialize())
{
@ -1913,7 +1921,7 @@ wxDialog *EffectUI::DialogFactory( wxWindow *parent, EffectHostInterface *pHost,
EffectRack::Get( context.project ).Add(effect);
}
#endif
success = effect->DoEffect(&window,
success = effect->DoEffect(window,
rate,
&tracks,
&trackFactory,

View File

@ -216,7 +216,7 @@ class CommandContext;
namespace EffectUI {
wxDialog *DialogFactory( wxWindow *parent, EffectHostInterface *pHost,
wxDialog *DialogFactory( wxWindow &parent, EffectHostInterface *pHost,
EffectUIClientInterface *client);
/** Run an effect given the plugin ID */

View File

@ -210,7 +210,7 @@ public:
~Settings() {}
bool PromptUser(EffectNoiseReduction *effect,
wxWindow *parent, bool bHasProfile, bool bAllowTwiddleSettings);
wxWindow &parent, bool bHasProfile, bool bAllowTwiddleSettings);
bool PrefsIO(bool read);
bool Validate(EffectNoiseReduction *effect) const;
@ -460,7 +460,7 @@ bool EffectNoiseReduction::CheckWhetherSkipEffect()
}
bool EffectNoiseReduction::ShowInterface(
wxWindow *parent, const EffectDialogFactory &, bool forceModal)
wxWindow &parent, const EffectDialogFactory &, bool forceModal)
{
// to do: use forceModal correctly
@ -474,11 +474,11 @@ bool EffectNoiseReduction::ShowInterface(
}
bool EffectNoiseReduction::Settings::PromptUser
(EffectNoiseReduction *effect, wxWindow *parent,
(EffectNoiseReduction *effect, wxWindow &parent,
bool bHasProfile, bool bAllowTwiddleSettings)
{
EffectNoiseReduction::Dialog dlog
(effect, this, parent, bHasProfile, bAllowTwiddleSettings);
(effect, this, &parent, bHasProfile, bAllowTwiddleSettings);
dlog.CentreOnParent();
dlog.ShowModal();

View File

@ -38,7 +38,7 @@ public:
// using Effect::TrackProgress;
bool ShowInterface( wxWindow *parent,
bool ShowInterface( wxWindow &parent,
const EffectDialogFactory &factory, bool forceModal = false) override;
bool Init() override;

View File

@ -150,10 +150,10 @@ bool EffectNoiseRemoval::CheckWhetherSkipEffect()
}
bool EffectNoiseRemoval::ShowInterface(
wxWindow *parent, const EffectDialogFactory &, bool forceModal /* forceModal */ )
wxWindow &parent, const EffectDialogFactory &, bool forceModal /* forceModal */ )
{
// to do: use forceModal correctly
NoiseRemovalDialog dlog(this, parent);
NoiseRemovalDialog dlog(this, &parent);
dlog.mSensitivity = mSensitivity;
dlog.mGain = -mNoiseGain;
dlog.mFreq = mFreqSmoothingHz;

View File

@ -53,7 +53,7 @@ public:
// Effect implementation
bool ShowInterface( wxWindow *parent,
bool ShowInterface( wxWindow &parent,
const EffectDialogFactory &factory, bool forceModal = false) override;
bool Init() override;
bool CheckWhetherSkipEffect() override;

View File

@ -1602,7 +1602,7 @@ bool VSTEffect::RealtimeProcessEnd()
/// all provide the information (kn0ck0ut is one).
///
bool VSTEffect::ShowInterface(
wxWindow *parent, const EffectDialogFactory &factory, bool forceModal)
wxWindow &parent, const EffectDialogFactory &factory, bool forceModal)
{
if (mDialog)
{

View File

@ -151,7 +151,7 @@ class VSTEffect final : public wxEvtHandler,
size_t numSamples) override;
bool RealtimeProcessEnd() override;
bool ShowInterface( wxWindow *parent,
bool ShowInterface( wxWindow &parent,
const EffectDialogFactory &factory, bool forceModal = false) override;
bool GetAutomationParameters(CommandParameters & parms) override;

View File

@ -1429,7 +1429,7 @@ bool AudioUnitEffect::RealtimeProcessEnd()
}
bool AudioUnitEffect::ShowInterface(
wxWindow *parent, const EffectDialogFactory &factory, bool forceModal)
wxWindow &parent, const EffectDialogFactory &factory, bool forceModal)
{
if (mDialog)
{

View File

@ -101,7 +101,7 @@ public:
size_t numSamples) override;
bool RealtimeProcessEnd() override;
bool ShowInterface( wxWindow *parent,
bool ShowInterface( wxWindow &parent,
const EffectDialogFactory &factory, bool forceModal = false) override;
bool GetAutomationParameters(CommandParameters & parms) override;

View File

@ -1071,7 +1071,7 @@ bool LadspaEffect::RealtimeProcessEnd()
}
bool LadspaEffect::ShowInterface(
wxWindow *parent, const EffectDialogFactory &factory, bool forceModal)
wxWindow &parent, const EffectDialogFactory &factory, bool forceModal)
{
if (mDialog)
{

View File

@ -99,7 +99,7 @@ public:
size_t numSamples) override;
bool RealtimeProcessEnd() override;
bool ShowInterface( wxWindow *parent,
bool ShowInterface( wxWindow &parent,
const EffectDialogFactory &factory, bool forceModal = false) override;
bool GetAutomationParameters(CommandParameters & parms) override;

View File

@ -1440,7 +1440,7 @@ bool LV2Effect::RealtimeProcessEnd()
}
bool LV2Effect::ShowInterface(
wxWindow *parent, const EffectDialogFactory &factory, bool forceModal)
wxWindow &parent, const EffectDialogFactory &factory, bool forceModal)
{
if (mDialog)
{

View File

@ -305,7 +305,7 @@ public:
size_t RealtimeProcess(int group, float **inbuf, float **outbuf, size_t numSamples) override;
bool RealtimeProcessEnd() override;
bool ShowInterface( wxWindow *parent,
bool ShowInterface( wxWindow &parent,
const EffectDialogFactory &factory, bool forceModal = false) override;
bool GetAutomationParameters(CommandParameters & parms) override;

View File

@ -977,7 +977,7 @@ finish:
}
bool NyquistEffect::ShowInterface(
wxWindow *parent, const EffectDialogFactory &factory, bool forceModal)
wxWindow &parent, const EffectDialogFactory &factory, bool forceModal)
{
// Show the normal (prompt or effect) interface
bool res = Effect::ShowInterface(parent, factory, forceModal);

View File

@ -99,7 +99,7 @@ public:
bool Init() override;
bool CheckWhetherSkipEffect() override;
bool Process() override;
bool ShowInterface( wxWindow *parent,
bool ShowInterface( wxWindow &parent,
const EffectDialogFactory &factory, bool forceModal = false) override;
void PopulateOrExchange(ShuttleGui & S) override;
bool TransferDataToWindow() override;