diff options
author | Carl Hetherington <carl@carlh.net> | 2010-12-07 14:44:47 +0000 |
---|---|---|
committer | Carl Hetherington <carl@carlh.net> | 2010-12-07 14:44:47 +0000 |
commit | 94b4c264d156d79efc687a98f17514b128960118 (patch) | |
tree | 97847ecdb68b1da8ea482b5e4de54fcc058dcf4a /libs/ardour | |
parent | 40c162d6096f9bb338b602fb7845234133285411 (diff) |
Send note-offs to VST instrument plugins on transport stop. Fixes #3583.
git-svn-id: svn://localhost/ardour2/branches/3.0@8203 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r-- | libs/ardour/ardour/midi_track.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/plugin.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/plugin_insert.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/processor.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/route.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/vst_plugin.h | 7 | ||||
-rw-r--r-- | libs/ardour/midi_track.cc | 11 | ||||
-rw-r--r-- | libs/ardour/plugin_insert.cc | 8 | ||||
-rw-r--r-- | libs/ardour/route.cc | 3 | ||||
-rw-r--r-- | libs/ardour/session_transport.cc | 10 | ||||
-rw-r--r-- | libs/ardour/vst_plugin.cc | 27 |
11 files changed, 70 insertions, 7 deletions
diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 554f5b3385..60d2567c21 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -42,7 +42,7 @@ public: int roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool can_record, bool rec_monitors_input, bool& need_butler); - void handle_transport_stopped (bool abort, bool did_locate, bool flush_processors); + void realtime_handle_transport_stopped (); void use_new_diskstream (); void set_diskstream (boost::shared_ptr<Diskstream>); diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h index 828e532c6a..d917ef85af 100644 --- a/libs/ardour/ardour/plugin.h +++ b/libs/ardour/ardour/plugin.h @@ -128,6 +128,8 @@ class Plugin : public PBD::StatefulDestructible, public Latent virtual bool parameter_is_input(uint32_t) const = 0; virtual bool parameter_is_output(uint32_t) const = 0; + virtual void realtime_handle_transport_stopped () {} + bool save_preset (std::string); void remove_preset (std::string); virtual bool load_preset (const std::string& uri) = 0; diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h index e4a42d8165..a83f75ed3e 100644 --- a/libs/ardour/ardour/plugin_insert.h +++ b/libs/ardour/ardour/plugin_insert.h @@ -74,6 +74,8 @@ class PluginInsert : public Processor bool is_generator() const; + void realtime_handle_transport_stopped (); + struct PluginControl : public AutomationControl { PluginControl (PluginInsert* p, const Evoral::Parameter ¶m, diff --git a/libs/ardour/ardour/processor.h b/libs/ardour/ardour/processor.h index 182208e560..9038088cf0 100644 --- a/libs/ardour/ardour/processor.h +++ b/libs/ardour/ardour/processor.h @@ -84,6 +84,8 @@ class Processor : public SessionObject, public Automatable, public Latent virtual ChanCount input_streams () const { return _configured_input; } virtual ChanCount output_streams() const { return _configured_output; } + virtual void realtime_handle_transport_stopped () {} + /* note: derived classes should implement state(), NOT get_state(), to allow us to merge C++ inheritance and XML lack-of-inheritance reasonably smoothly. diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index afa6c0e527..7f2f5dc719 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -116,7 +116,8 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember, virtual void set_record_enabled (bool /*yn*/, void * /*src*/) {} virtual bool record_enabled() const { return false; } - virtual void handle_transport_stopped (bool abort, bool did_locate, bool flush_processors); + virtual void nonrealtime_handle_transport_stopped (bool abort, bool did_locate, bool flush_processors); + virtual void realtime_handle_transport_stopped () {} virtual void set_pending_declick (int); /* end of vfunc-based API */ diff --git a/libs/ardour/ardour/vst_plugin.h b/libs/ardour/ardour/vst_plugin.h index 332872e9bd..24af13c053 100644 --- a/libs/ardour/ardour/vst_plugin.h +++ b/libs/ardour/ardour/vst_plugin.h @@ -28,8 +28,8 @@ #include <dlfcn.h> #include "pbd/stateful.h" -#include <jack/types.h> #include "ardour/plugin.h" +#include "ardour/midi_state_tracker.h" struct _FSTHandle; struct _FST; @@ -79,6 +79,8 @@ class VSTPlugin : public ARDOUR::Plugin bool parameter_is_input(uint32_t i) const { return true; } bool parameter_is_output(uint32_t i) const { return false; } + void realtime_handle_transport_stopped (); + bool load_preset (const std::string& preset_label); virtual std::vector<PresetRecord> get_presets (); int first_user_preset_index () const; @@ -103,6 +105,9 @@ private: FST* _fst; AEffect* _plugin; bool been_resumed; + MidiStateTracker _tracker; + BufferSet _pending_stop_events; + bool _have_pending_stop_events; }; class VSTPluginInfo : public PluginInfo diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index c994350ebc..fa406adfa0 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -403,9 +403,16 @@ MidiTrack::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_fr } void -MidiTrack::handle_transport_stopped (bool abort, bool did_locate, bool flush_processors) +MidiTrack::realtime_handle_transport_stopped () { - Route::handle_transport_stopped (abort, did_locate, flush_processors); + Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK); + if (!lm.locked ()) { + return; + } + + for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { + (*i)->realtime_handle_transport_stopped (); + } } void diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index ecaca5cc50..25c885f5a6 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -1060,3 +1060,11 @@ PluginInsert::add_plugin_with_activation (boost::shared_ptr<Plugin> plugin) plugin->activate (); } } + +void +PluginInsert::realtime_handle_transport_stopped () +{ + for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) { + (*i)->realtime_handle_transport_stopped (); + } +} diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 3577d3a659..dba087c61d 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -2686,8 +2686,9 @@ Route::direct_feeds (boost::shared_ptr<Route> other, bool* only_send) return false; } +/** Called from the (non-realtime) butler thread when the transport is stopped */ void -Route::handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool can_flush_processors) +Route::nonrealtime_handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool can_flush_processors) { framepos_t now = _session.transport_frame(); diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index bb20fe97ac..d0e927dbab 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -188,6 +188,14 @@ Session::realtime_stop (bool abort, bool clear_state) todo = PostTransportWork (todo | PostTransportStop); } + /* call routes */ + + boost::shared_ptr<RouteList> r = routes.reader (); + + for (RouteList::iterator i = r->begin (); i != r->end(); ++i) { + (*i)->realtime_handle_transport_stopped (); + } + if (actively_recording()) { /* move the transport position back to where the @@ -1487,7 +1495,7 @@ Session::update_latency_compensation (bool with_stop, bool abort) for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { if (with_stop) { - (*i)->handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush)); + (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush)); } framecnt_t old_latency = (*i)->output()->signal_latency (); diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc index 333b7d893a..8f30ff98e9 100644 --- a/libs/ardour/vst_plugin.cc +++ b/libs/ardour/vst_plugin.cc @@ -63,6 +63,7 @@ using std::max; VSTPlugin::VSTPlugin (AudioEngine& e, Session& session, FSTHandle* h) : Plugin (e, session) + , _have_pending_stop_events (false) { handle = h; @@ -89,6 +90,7 @@ VSTPlugin::VSTPlugin (AudioEngine& e, Session& session, FSTHandle* h) VSTPlugin::VSTPlugin (const VSTPlugin &other) : Plugin (other) + , _have_pending_stop_events (false) { handle = other.handle; @@ -514,6 +516,18 @@ VSTPlugin::connect_and_run (BufferSet& bufs, if (bufs.count().n_midi() > 0) { + + /* Track notes that we are sending to the plugin */ + MidiBuffer& b = bufs.get_midi (0); + bool looped; + _tracker.track (b.begin(), b.end(), looped); + + if (_have_pending_stop_events) { + /* Transmit note-offs that are pending from the last transport stop */ + bufs.merge_from (_pending_stop_events, 0); + _have_pending_stop_events = false; + } + VstEvents* v = bufs.get_vst_midi (0); _plugin->dispatcher (_plugin, effProcessEvents, 0, 0, v, 0); } @@ -721,6 +735,19 @@ VSTPlugin::first_user_preset_index () const return _plugin->numPrograms; } +void +VSTPlugin::realtime_handle_transport_stopped () +{ + /* Create note-offs for any active notes and put them in _pending_stop_events, to be picked + up on the next call to connect_and_run (). + */ + + _pending_stop_events.ensure_buffers (DataType::MIDI, 1, 4096); + _pending_stop_events.get_midi(0).clear (); + _tracker.resolve_notes (_pending_stop_events.get_midi (0), 0); + _have_pending_stop_events = true; +} + VSTPluginInfo::VSTPluginInfo() { type = ARDOUR::VST; |