summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2010-12-07 14:44:47 +0000
committerCarl Hetherington <carl@carlh.net>2010-12-07 14:44:47 +0000
commit94b4c264d156d79efc687a98f17514b128960118 (patch)
tree97847ecdb68b1da8ea482b5e4de54fcc058dcf4a
parent40c162d6096f9bb338b602fb7845234133285411 (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
-rw-r--r--libs/ardour/ardour/midi_track.h2
-rw-r--r--libs/ardour/ardour/plugin.h2
-rw-r--r--libs/ardour/ardour/plugin_insert.h2
-rw-r--r--libs/ardour/ardour/processor.h2
-rw-r--r--libs/ardour/ardour/route.h3
-rw-r--r--libs/ardour/ardour/vst_plugin.h7
-rw-r--r--libs/ardour/midi_track.cc11
-rw-r--r--libs/ardour/plugin_insert.cc8
-rw-r--r--libs/ardour/route.cc3
-rw-r--r--libs/ardour/session_transport.cc10
-rw-r--r--libs/ardour/vst_plugin.cc27
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 &param,
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;