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
This commit is contained in:
parent
40c162d609
commit
94b4c264d1
@ -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>);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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 ();
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user