= boost::dynamic_pointer_cast<AutomationControl>(control (which));
if (c && s != Off) {
- _plugins[0]->set_parameter (which.id(), c->list()->eval (_session.transport_frame()));
+ _plugins[0]->set_parameter (which.id(), c->list()->eval (_session.transport_sample()));
}
}
return _plugins[0]->get_info()->n_inputs.n_audio() == 0;
}
-framecnt_t
+samplecnt_t
PluginInsert::plugin_latency () const {
return _plugins.front()->signal_latency ();
}
return ret;
}
+void
+PluginInsert::automation_run (samplepos_t start, pframes_t nframes)
+{
+ // XXX does not work when rolling backwards
+ if (_loop_location && nframes > 0) {
+ const samplepos_t loop_start = _loop_location->start ();
+ const samplepos_t loop_end = _loop_location->end ();
+ const samplecnt_t looplen = loop_end - loop_start;
+
+ samplecnt_t remain = nframes;
+ samplepos_t start_pos = start;
+
+ while (remain > 0) {
+ if (start_pos >= loop_end) {
+ sampleoffset_t start_off = (start_pos - loop_start) % looplen;
+ start_pos = loop_start + start_off;
+ }
+ samplecnt_t move = std::min ((samplecnt_t)nframes, loop_end - start_pos);
+
+ Automatable::automation_run (start_pos, move);
+ remain -= move;
+ start_pos += move;
+ }
+ return;
+ }
+ Automatable::automation_run (start, nframes);
+}
+
+bool
+PluginInsert::find_next_event (double now, double end, Evoral::ControlEvent& next_event, bool only_active) const
+{
+ bool rv = Automatable::find_next_event (now, end, next_event, only_active);
+
+ if (_loop_location && now < end) {
+ if (rv) {
+ end = ceil (next_event.when);
+ }
+ const samplepos_t loop_end = _loop_location->end ();
+ assert (now < loop_end); // due to map_loop_range ()
+ if (end > loop_end) {
+ next_event.when = loop_end;
+ rv = true;
+ }
+ }
+ return rv;
+}
+
void
PluginInsert::activate ()
{
BypassableChanged ();
}
+bool
+PluginInsert::write_immediate_event (size_t size, const uint8_t* buf)
+{
+ bool rv = true;
+ for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
+ if (!(*i)->write_immediate_event (size, buf)) {
+ rv = false;
+ }
+ }
+ return rv;
+}
+
void
PluginInsert::preset_load_set_value (uint32_t p, float v)
{
}
void
-PluginInsert::inplace_silence_unconnected (BufferSet& bufs, const PinMappings& out_map, framecnt_t nframes, framecnt_t offset) const
+PluginInsert::inplace_silence_unconnected (BufferSet& bufs, const PinMappings& out_map, samplecnt_t nframes, samplecnt_t offset) const
{
// TODO optimize: store "unconnected" in a fixed set.
// it only changes on reconfiguration.
}
void
-PluginInsert::connect_and_run (BufferSet& bufs, framepos_t start, framepos_t end, double speed, pframes_t nframes, framecnt_t offset, bool with_auto)
+PluginInsert::connect_and_run (BufferSet& bufs, samplepos_t start, samplepos_t end, double speed, pframes_t nframes, samplecnt_t offset, bool with_auto)
{
// TODO: atomically copy maps & _no_inplace
PinMappings in_map (_in_map);
}
}
- /* Calculate if, and how many frames we need to collect for analysis */
- framecnt_t collect_signal_nframes = (_signal_analysis_collect_nframes_max -
+ /* Calculate if, and how many samples we need to collect for analysis */
+ samplecnt_t collect_signal_nframes = (_signal_analysis_collect_nframes_max -
_signal_analysis_collected_nframes);
- if (nframes < collect_signal_nframes) { // we might not get all frames now
+ if (nframes < collect_signal_nframes) { // we might not get all samples now
collect_signal_nframes = nframes;
}
// collect input
//std::cerr << "collect input, bufs " << bufs.count().n_audio() << " count, " << bufs.available().n_audio() << " available" << std::endl;
//std::cerr << " streams " << internal_input_streams().n_audio() << std::endl;
- //std::cerr << "filling buffer with " << collect_signal_nframes << " frames at " << _signal_analysis_collected_nframes << std::endl;
+ //std::cerr << "filling buffer with " << collect_signal_nframes << " samples at " << _signal_analysis_collected_nframes << std::endl;
_signal_analysis_inputs.set_count(input_streams());
}
void
-PluginInsert::silence (framecnt_t nframes, framepos_t start_frame)
+PluginInsert::silence (samplecnt_t nframes, samplepos_t start_sample)
{
- automation_run (start_frame, nframes); // evaluate automation only
+ automation_run (start_sample, nframes); // evaluate automation only
if (!active ()) {
// XXX delaybuffers need to be offset by nframes
#ifdef MIXBUS
if (is_channelstrip ()) {
if (_configured_in.n_audio() > 0) {
- _plugins.front()->connect_and_run (_session.get_scratch_buffers (maxbuf, true), start_frame, start_frame + nframes, 1.0, in_map, out_map, nframes, 0);
+ _plugins.front()->connect_and_run (_session.get_scratch_buffers (maxbuf, true), start_sample, start_sample + nframes, 1.0, in_map, out_map, nframes, 0);
}
} else
#endif
for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
- (*i)->connect_and_run (_session.get_scratch_buffers (maxbuf, true), start_frame, start_frame + nframes, 1.0, in_map, out_map, nframes, 0);
+ (*i)->connect_and_run (_session.get_scratch_buffers (maxbuf, true), start_sample, start_sample + nframes, 1.0, in_map, out_map, nframes, 0);
}
}
void
-PluginInsert::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, double speed, pframes_t nframes, bool)
+PluginInsert::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool)
{
if (_sidechain) {
// collect sidechain input for complete cycle (!)
// TODO we need delaylines here for latency compensation
- _sidechain->run (bufs, start_frame, end_frame, speed, nframes, true);
+ _sidechain->run (bufs, start_sample, end_sample, speed, nframes, true);
}
if (_pending_active) {
/* run as normal if we are active or moving from inactive to active */
if (_session.transport_rolling() || _session.bounce_processing()) {
- automate_and_run (bufs, start_frame, end_frame, speed, nframes);
+ automate_and_run (bufs, start_sample, end_sample, speed, nframes);
} else {
Glib::Threads::Mutex::Lock lm (control_lock(), Glib::Threads::TRY_LOCK);
- connect_and_run (bufs, start_frame, end_frame, speed, nframes, 0, lm.locked());
+ connect_and_run (bufs, start_sample, end_sample, speed, nframes, 0, lm.locked());
}
} else {
// XXX should call ::silence() to run plugin(s) for consistent load.
// We'll need to change this anyway when bypass can be automated
bypass (bufs, nframes);
- automation_run (start_frame, nframes); // evaluate automation only
+ automation_run (start_sample, nframes); // evaluate automation only
_delaybuffers.flush ();
}
}
void
-PluginInsert::automate_and_run (BufferSet& bufs, framepos_t start, framepos_t end, double speed, pframes_t nframes)
+PluginInsert::automate_and_run (BufferSet& bufs, samplepos_t start, samplepos_t end, double speed, pframes_t nframes)
{
Evoral::ControlEvent next_event (0, 0.0f);
- framecnt_t offset = 0;
+ samplecnt_t offset = 0;
Glib::Threads::Mutex::Lock lm (control_lock(), Glib::Threads::TRY_LOCK);
return;
}
+ /* map start back into loop-range, adjust end */
+ map_loop_range (start, end);
+
if (!find_next_event (start, end, next_event) || _plugins.front()->requires_fixed_sized_buffers()) {
/* no events have a time within the relevant range */
while (nframes) {
- framecnt_t cnt = min (((framecnt_t) ceil (next_event.when) - start), (framecnt_t) nframes);
+ samplecnt_t cnt = min (((samplecnt_t) ceil (next_event.when) - start), (samplecnt_t) nframes);
connect_and_run (bufs, start, start + cnt, speed, cnt, offset, true); // XXX (start + cnt) * speed
offset += cnt;
start += cnt;
+ map_loop_range (start, end);
+
if (!find_next_event (start, end, next_event)) {
break;
}
XMLNode&
-PluginInsert::get_state ()
-{
- return state (true);
-}
-
-XMLNode&
-PluginInsert::state (bool full)
+PluginInsert::state ()
{
- XMLNode& node = Processor::state (full);
+ XMLNode& node = Processor::state ();
node.set_property("type", _plugins[0]->state_node_name());
node.set_property("unique-id", _plugins[0]->unique_id());
node.add_child_nocopy (* _thru_map.state ("ThruMap"));
if (_sidechain) {
- node.add_child_nocopy (_sidechain->state (full));
+ node.add_child_nocopy (_sidechain->get_state ());
}
_plugins[0]->set_insert_id(this->id());
return Automatable::describe_parameter(param);
}
-ARDOUR::framecnt_t
+ARDOUR::samplecnt_t
PluginInsert::signal_latency() const
{
if (!_pending_active) {
}
void
-PluginInsert::collect_signal_for_analysis (framecnt_t nframes)
+PluginInsert::collect_signal_for_analysis (samplecnt_t nframes)
{
// called from outside the audio thread, so this should be safe
// only do audio as analysis is (currently) only for audio plugins
{
boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id));
if (ac) {
- // ToDo subtract _plugin_signal_latency from audible_frame() when rolling, assert > 0
- ac->start_touch (session().audible_frame());
+ // ToDo subtract _plugin_signal_latency from audible_sample() when rolling, assert > 0
+ ac->start_touch (session().audible_sample());
}
}
{
boost::shared_ptr<AutomationControl> ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id));
if (ac) {
- // ToDo subtract _plugin_signal_latency from audible_frame() when rolling, assert > 0
- ac->stop_touch (session().audible_frame());
+ // ToDo subtract _plugin_signal_latency from audible_sample() when rolling, assert > 0
+ ac->stop_touch (session().audible_sample());
}
}