VST3: Prevent recursive calls to ::has_editor()
Some plugins call restartComponent(Vst::kParamTitlesChanged) when their GUI is created, from the call that creates the UI. This lead to a stack-overflow recursion in Ardour: ProcessorBox::redisplay_processors -> VST3Plugin::has_editor -> [plugin] -> VST3::restartComponent -> signal proc changed -> ProcessorBox::redisplay processors
This commit is contained in:
parent
bd1cf4e5cf
commit
7227407aa6
@ -725,11 +725,12 @@ enum AppleNSGLViewMode {
|
||||
*/
|
||||
struct RouteProcessorChange {
|
||||
enum Type {
|
||||
MeterPointChange = 0x1,
|
||||
RealTimeChange = 0x2,
|
||||
GeneralChange = 0x4,
|
||||
SendReturnChange = 0x8,
|
||||
CustomPinChange = 0x10
|
||||
NoProcessorChange = 0x0,
|
||||
MeterPointChange = 0x1,
|
||||
RealTimeChange = 0x2,
|
||||
GeneralChange = 0x4,
|
||||
SendReturnChange = 0x8,
|
||||
CustomPinChange = 0x10
|
||||
};
|
||||
|
||||
RouteProcessorChange () : type (GeneralChange), meter_visibly_changed (true)
|
||||
|
@ -212,6 +212,22 @@ public:
|
||||
bool add_slave (Vst::IEditController*, bool);
|
||||
bool remove_slave (Vst::IEditController*);
|
||||
|
||||
class RouteProcessorChangeBlock
|
||||
{
|
||||
public:
|
||||
RouteProcessorChangeBlock (VST3PI* p) : _impl (p)
|
||||
{
|
||||
_impl->block_notifications ();
|
||||
}
|
||||
|
||||
~RouteProcessorChangeBlock ()
|
||||
{
|
||||
_impl->resume_notifications ();
|
||||
}
|
||||
private:
|
||||
VST3PI* _impl;
|
||||
};
|
||||
|
||||
private:
|
||||
/* prevent copy construction */
|
||||
VST3PI (const VST3PI&);
|
||||
@ -246,6 +262,10 @@ private:
|
||||
void psl_subscribe_to (std::shared_ptr<ARDOUR::AutomationControl>, FIDString);
|
||||
void psl_stripable_property_changed (PBD::PropertyChange const&);
|
||||
|
||||
void block_notifications ();
|
||||
void resume_notifications ();
|
||||
void send_processors_changed (ARDOUR::RouteProcessorChange const&);
|
||||
|
||||
void forward_signal (Presonus::IContextInfoHandler2*, FIDString) const;
|
||||
|
||||
std::shared_ptr<ARDOUR::VST3PluginModule> _module;
|
||||
@ -333,6 +353,9 @@ private:
|
||||
int _n_midi_outputs;
|
||||
int _n_factory_presets;
|
||||
|
||||
mutable std::atomic<int> _block_rpc;
|
||||
ARDOUR::RouteProcessorChange _rpc_queue;
|
||||
|
||||
/* work around UADx plugin crash */
|
||||
bool _no_kMono;
|
||||
};
|
||||
|
@ -341,6 +341,8 @@ VST3Plugin::possible_output () const
|
||||
bool
|
||||
VST3Plugin::has_editor () const
|
||||
{
|
||||
VST3PI::RouteProcessorChangeBlock rpcb (_plug);
|
||||
|
||||
std::shared_ptr<VST3PluginInfo> nfo = std::dynamic_pointer_cast<VST3PluginInfo> (get_info ());
|
||||
if (nfo->has_editor.has_value ()) {
|
||||
return nfo->has_editor.value ();
|
||||
@ -1168,6 +1170,8 @@ VST3PI::VST3PI (std::shared_ptr<ARDOUR::VST3PluginModule> m, std::string unique_
|
||||
, _owner (0)
|
||||
, _add_to_selection (false)
|
||||
, _n_factory_presets (0)
|
||||
, _block_rpc (0)
|
||||
, _rpc_queue (RouteProcessorChange::NoProcessorChange, false)
|
||||
, _no_kMono (false)
|
||||
{
|
||||
using namespace std;
|
||||
@ -1595,10 +1599,7 @@ VST3PI::restartComponent (int32 flags)
|
||||
p.normal = pi.defaultNormalizedValue;
|
||||
}
|
||||
}
|
||||
Route* r = dynamic_cast<Route*> (_owner);
|
||||
if (r) {
|
||||
r->processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
|
||||
}
|
||||
send_processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
|
||||
}
|
||||
if (flags & Vst::kIoChanged) {
|
||||
warning << "VST3: Vst::kIoChanged (not implemented)" << endmsg;
|
||||
@ -3221,3 +3222,38 @@ VST3PI::resizeView (IPlugView* view, ViewRect* new_size)
|
||||
OnResizeView (new_size->getWidth (), new_size->getHeight ()); /* EMIT SIGNAL */
|
||||
return view->onSize (new_size);
|
||||
}
|
||||
|
||||
void
|
||||
VST3PI::block_notifications ()
|
||||
{
|
||||
_block_rpc.fetch_add (1);
|
||||
}
|
||||
|
||||
void
|
||||
VST3PI::resume_notifications ()
|
||||
{
|
||||
if (!PBD::atomic_dec_and_test (_block_rpc)) {
|
||||
return;
|
||||
}
|
||||
Route* r = dynamic_cast<Route*> (_owner);
|
||||
if (r && _rpc_queue.type != RouteProcessorChange::NoProcessorChange) {
|
||||
r->processors_changed (_rpc_queue); /* EMIT SIGNAL */
|
||||
}
|
||||
_rpc_queue.type = RouteProcessorChange::NoProcessorChange;
|
||||
_rpc_queue.meter_visibly_changed = false;
|
||||
}
|
||||
|
||||
void
|
||||
VST3PI::send_processors_changed (RouteProcessorChange const& rpc)
|
||||
{
|
||||
if (_block_rpc.load () != 0) {
|
||||
_rpc_queue.type = ARDOUR::RouteProcessorChange::Type (_rpc_queue.type | rpc.type);
|
||||
_rpc_queue.meter_visibly_changed |= rpc.meter_visibly_changed;
|
||||
return;
|
||||
}
|
||||
|
||||
Route* r = dynamic_cast<Route*> (_owner);
|
||||
if (r) {
|
||||
r->processors_changed (rpc); /* EMIT SIGNAL */
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user