if (session->transport_rolling()) {
session->request_stop ();
- usleep (2500000);
+ usleep (250000);
}
if (session->dirty()) {
#include <limits.h>
+#include "ardour/amp.h"
#include "ardour/io.h"
#include "ardour/route.h"
#include "ardour/route_group.h"
void
GainMeterBase::set_controls (boost::shared_ptr<Route> r,
boost::shared_ptr<PeakMeter> pm,
- boost::shared_ptr<AutomationControl> gc,
- boost::shared_ptr<Automatable> gc_owner)
+ boost::shared_ptr<Amp> amp)
{
connections.clear ();
- if (!pm && !gc) {
+ if (!pm && !amp) {
level_meter->set_meter (0);
gain_slider->set_controllable (boost::shared_ptr<PBD::Controllable>());
_meter.reset ();
- _gain_control.reset ();
+ _amp.reset ();
_route.reset ();
return;
}
_meter = pm;
- _gain_control = gc;
+ _amp = amp;
_route = r;
level_meter->set_meter (pm.get());
- gain_slider->set_controllable (gc);
-
+ gain_slider->set_controllable (amp->gain_control());
+
if (!_route || !_route->is_hidden()) {
using namespace Menu_Helpers;
gain_astate_menu.items().clear ();
gain_astate_menu.items().push_back (MenuElem (_("Manual"),
- bind (mem_fun (*(gc_owner.get()), &Automatable::set_parameter_automation_state),
+ bind (mem_fun (*(amp.get()), &Automatable::set_parameter_automation_state),
Evoral::Parameter(GainAutomation), (AutoState) Off)));
gain_astate_menu.items().push_back (MenuElem (_("Play"),
- bind (mem_fun (*(gc_owner.get()), &Automatable::set_parameter_automation_state),
+ bind (mem_fun (*(amp.get()), &Automatable::set_parameter_automation_state),
Evoral::Parameter(GainAutomation), (AutoState) Play)));
gain_astate_menu.items().push_back (MenuElem (_("Write"),
- bind (mem_fun (*(gc_owner.get()), &Automatable::set_parameter_automation_state),
+ bind (mem_fun (*(amp.get()), &Automatable::set_parameter_automation_state),
Evoral::Parameter(GainAutomation), (AutoState) Write)));
gain_astate_menu.items().push_back (MenuElem (_("Touch"),
- bind (mem_fun (*(gc_owner.get()), &Automatable::set_parameter_automation_state),
+ bind (mem_fun (*(amp.get()), &Automatable::set_parameter_automation_state),
Evoral::Parameter(GainAutomation), (AutoState) Touch)));
connections.push_back (gain_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_style_button_event), false));
connections.push_back (gain_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_state_button_event), false));
-
+
+ boost::shared_ptr<AutomationControl> gc = amp->gain_control();
+
connections.push_back (gc->alist()->automation_state_changed.connect (mem_fun(*this, &GainMeter::gain_automation_state_changed)));
connections.push_back (gc->alist()->automation_style_changed.connect (mem_fun(*this, &GainMeter::gain_automation_style_changed)));
gain_automation_state_changed ();
}
- connections.push_back (gc->Changed.connect (mem_fun (*this, &GainMeterBase::gain_changed)));
+ connections.push_back (amp->gain_control()->Changed.connect (mem_fun (*this, &GainMeterBase::gain_changed)));
gain_changed ();
show_gain ();
f = min (f, 6.0f);
- _gain_control->set_value (dB_to_coefficient(f));
+ _amp->set_gain (dB_to_coefficient(f), this);
if (gain_display.has_focus()) {
PublicEditor::instance().reset_focus();
GainMeterBase::gain_adjusted ()
{
if (!ignore_toggle) {
- _gain_control->set_value (slider_position_to_gain (gain_adjustment.get_value()));
+ if (_route) {
+ if (_route->amp() == _amp) {
+ _route->set_gain (slider_position_to_gain (gain_adjustment.get_value()), this);
+ } else {
+ _amp->set_gain (slider_position_to_gain (gain_adjustment.get_value()), this);
+ }
+ }
}
show_gain ();
void
GainMeterBase::effective_gain_display ()
{
- gfloat value = gain_to_slider_position (_gain_control->get_value());
+ gfloat value = gain_to_slider_position (_amp->gain());
//cerr << this << " for " << _io->name() << " EGAIN = " << value
// << " AGAIN = " << gain_adjustment.get_value () << endl;
void
GainMeterBase::update_gain_sensitive ()
{
- bool x = !(_gain_control->alist()->automation_state() & Play);
+ bool x = !(_amp->gain_control()->alist()->automation_state() & Play);
static_cast<Gtkmm2ext::SliderController*>(gain_slider)->set_sensitive (x);
}
gint
GainMeterBase::start_gain_touch (GdkEventButton* ev)
{
- _gain_control->start_touch ();
+ _amp->gain_control()->start_touch ();
return FALSE;
}
gint
GainMeterBase::end_gain_touch (GdkEventButton* ev)
{
- _gain_control->stop_touch ();
+ _amp->gain_control()->stop_touch ();
return FALSE;
}
{
switch (_width) {
case Wide:
- gain_automation_style_button.set_label (astyle_string(_gain_control->alist()->automation_style()));
+ gain_automation_style_button.set_label (astyle_string(_amp->gain_control()->alist()->automation_style()));
break;
case Narrow:
- gain_automation_style_button.set_label (short_astyle_string(_gain_control->alist()->automation_style()));
+ gain_automation_style_button.set_label (short_astyle_string(_amp->gain_control()->alist()->automation_style()));
break;
}
}
switch (_width) {
case Wide:
- gain_automation_state_button.set_label (astate_string(_gain_control->alist()->automation_state()));
+ gain_automation_state_button.set_label (astate_string(_amp->gain_control()->alist()->automation_state()));
break;
case Narrow:
- gain_automation_state_button.set_label (short_astate_string(_gain_control->alist()->automation_state()));
+ gain_automation_state_button.set_label (short_astate_string(_amp->gain_control()->alist()->automation_state()));
break;
}
- x = (_gain_control->alist()->automation_state() != Off);
+ x = (_amp->gain_control()->alist()->automation_state() != Off);
if (gain_automation_state_button.get_active() != x) {
ignore_toggle = true;
void
GainMeter::set_controls (boost::shared_ptr<Route> r,
boost::shared_ptr<PeakMeter> meter,
- boost::shared_ptr<AutomationControl> gain_control,
- boost::shared_ptr<Automatable> gc_owner)
+ boost::shared_ptr<Amp> amp)
{
if (level_meter->get_parent()) {
hbox.remove (*level_meter);
fader_vbox->remove (gain_automation_state_button);
}
- GainMeterBase::set_controls (r, meter, gain_control, gc_owner);
+ GainMeterBase::set_controls (r, meter, amp);
/*
if we have a non-hidden route (ie. we're not the click or the auditioner),
boost::shared_ptr<PBD::Controllable>
GainMeterBase::get_controllable()
{
- return _gain_control;
+ if (_amp) {
+ return _amp->gain_control();
+ } else {
+ return boost::shared_ptr<PBD::Controllable>();
+ }
}
class Route;
class RouteGroup;
class PeakMeter;
+ class Amp;
class Automatable;
}
namespace Gtkmm2ext {
virtual void set_controls (boost::shared_ptr<ARDOUR::Route> route,
boost::shared_ptr<ARDOUR::PeakMeter> meter,
- boost::shared_ptr<ARDOUR::AutomationControl> gain_control,
- boost::shared_ptr<ARDOUR::Automatable> gc_owner);
+ boost::shared_ptr<ARDOUR::Amp> amp);
void update_gain_sensitive ();
void update_meters ();
friend class MixerStrip;
boost::shared_ptr<ARDOUR::Route> _route;
boost::shared_ptr<ARDOUR::PeakMeter> _meter;
- boost::shared_ptr<ARDOUR::AutomationControl> _gain_control;
+ boost::shared_ptr<ARDOUR::Amp> _amp;
ARDOUR::Session& _session;
std::vector<sigc::connection> connections;
virtual void set_controls (boost::shared_ptr<ARDOUR::Route> route,
boost::shared_ptr<ARDOUR::PeakMeter> meter,
- boost::shared_ptr<ARDOUR::AutomationControl> gain_control,
- boost::shared_ptr<ARDOUR::Automatable> gc_owner);
+ boost::shared_ptr<ARDOUR::Amp> amp);
int get_gm_width ();
void setup_meters (int len=0);
_current_delivery = _route->main_outs ();
panners.set_panner (rt->main_outs()->panner());
- gpm.set_controls (rt, rt->shared_peak_meter(), rt->gain_control(), rt->amp());
+ gpm.set_controls (rt, rt->shared_peak_meter(), rt->amp());
processor_box.set_route (rt);
if (set_color_from_route()) {
send = boost::dynamic_pointer_cast<Send>(_current_delivery);
send->set_metering (true);
_current_delivery->GoingAway.connect (mem_fun (*this, &MixerStrip::revert_to_default_display));
- gain_meter().set_controls (_route, send->meter(), send->amp()->gain_control(), send->amp());
+ gain_meter().set_controls (_route, send->meter(), send->amp());
panner_ui().set_panner (_current_delivery->panner());
} else {
_current_delivery = _route->main_outs ();
- gain_meter().set_controls (_route, _route->shared_peak_meter(), _route->gain_control(), _route->amp());
+ gain_meter().set_controls (_route, _route->shared_peak_meter(), _route->amp());
panner_ui().set_panner (_route->main_outs()->panner());
}
_current_delivery = _route->main_outs();
- gain_meter().set_controls (_route, _route->shared_peak_meter(), _route->gain_control(), _route->amp());
+ gain_meter().set_controls (_route, _route->shared_peak_meter(), _route->amp());
gain_meter().setup_meters ();
panner_ui().set_panner (_route->main_outs()->panner());
panner_ui().setup_pan ();
gidget = send_ui;
#else
if (_parent_strip) {
- _parent_strip->gain_meter().set_controls (_route, send->meter(), send->amp()->gain_control(), send->amp());
+ _parent_strip->gain_meter().set_controls (_route, send->meter(), send->amp());
_parent_strip->panner_ui().set_panner (send->panner());
}
#endif
, _session (se)
, _gpm (se)
{
- _gpm.set_controls (boost::shared_ptr<Route>(), r->meter(), r->amp()->gain_control(), r->amp());
+ _gpm.set_controls (boost::shared_ptr<Route>(), r->meter(), r->amp());
_hbox.pack_start (_gpm, true, true);
set_name ("ReturnUIFrame");
{
set_button_names ();
- gm.set_controls (_route, _route->shared_peak_meter(), _route->gain_control(), _route->amp());
+ gm.set_controls (_route, _route->shared_peak_meter(), _route->amp());
gm.get_level_meter().set_no_show_all();
gm.get_level_meter().setup_meters(50);
, _panners (se)
{
_panners.set_panner (s->panner());
- _gpm.set_controls (boost::shared_ptr<Route>(), s->meter(), s->amp()->gain_control(), s->amp());
+ _gpm.set_controls (boost::shared_ptr<Route>(), s->meter(), s->amp());
_hbox.pack_start (_gpm, true, true);
set_name ("SendUIFrame");
boost::shared_ptr<Route> r = session->the_auditioner ();
- gm->set_controls (r, r->shared_peak_meter(), r->gain_control(), r->amp());
+ gm->set_controls (r, r->shared_peak_meter(), r->amp());
meter_packer.set_border_width (12);
meter_packer.pack_start (*gm, false, true);
{
gain_t mute_gain;
- if (!_active) {
+ if (!_active && !_pending_active) {
return;
}
}
}
}
+
+ _active = _pending_active;
}
void
virtual bool visible() const { return true; }
virtual void set_visible (bool) {}
- bool active () const { return _active; }
+ bool active () const { return _pending_active; }
bool get_next_ab_is_active () const { return _next_ab_is_active; }
void set_next_ab_is_active (bool yn) { _next_ab_is_active = yn; }
virtual void run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes) {}
virtual void silence (nframes_t nframes) {}
- virtual void activate () { _active = true; ActiveChanged(); }
- virtual void deactivate () { _active = false; ActiveChanged(); }
+ virtual void activate () { _pending_active = true; ActiveChanged(); }
+ virtual void deactivate () { _pending_active = false; ActiveChanged(); }
virtual bool configure_io (ChanCount in, ChanCount out);
{
assert (_output);
- if (!_active || _output->n_ports ().get (_output->default_type()) == 0) {
- return;
+ PortSet& ports (_output->ports());
+ gain_t tgain;
+
+ if (_output->n_ports ().get (_output->default_type()) == 0) {
+ goto out;
+ }
+
+ if (!_active && !_pending_active) {
+ _output->silence (nframes);
+ goto out;
}
/* this setup is not just for our purposes, but for anything that comes after us in the
processing pathway that wants to use this->output_buffers() for some reason.
*/
- PortSet& ports (_output->ports());
output_buffers().attach_buffers (ports, nframes, _output_offset);
// this Delivery processor is not a derived type, and thus we assume
// the main output stage of a Route). Contrast with Send::run()
// which cannot do this.
- gain_t tgain = target_gain ();
+ tgain = target_gain ();
if (tgain != _current_gain) {
/* we were quiet last time, and we're still supposed to be quiet.
Silence the outputs, and make sure the buffers are quiet too,
*/
-
+
_output->silence (nframes);
Amp::apply_simple_gain (bufs, nframes, 0.0);
-
- return;
+ goto out;
} else if (tgain != 1.0) {
_output->copy_to_outputs (bufs, DataType::MIDI, nframes, _output_offset);
}
}
+
+ out:
+ _active = _pending_active;
}
XMLNode&
gain_t
Delivery::target_gain ()
{
+ /* if we've been requested to deactivate, our target gain is zero */
+
+ if (!_pending_active) {
+ return 0.0;
+ }
+
/* if we've been told not to output because its a monitoring situation and
we're not monitoring, then be quiet.
*/
void
InternalReturn::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
- /* XXX no lock here, just atomic fetch */
+ if (!_active && !_pending_active) {
+ return;
+ }
+
+ /* no lock here, just atomic fetch */
if (g_atomic_int_get(&user_count) == 0) {
/* nothing to do - nobody is feeding us anything */
}
bufs.merge_from (buffers, nframes);
+ _active = _pending_active;
}
bool
void
InternalSend::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
- if (!_active || !target || !_send_to) {
+ if ((!_active && !_pending_active) || !target || !_send_to) {
_meter->reset ();
return;
}
_meter->reset ();
Amp::apply_simple_gain (sendbufs, nframes, 0.0);
- return;
+ goto out;
} else if (tgain != 1.0) {
/* deliver to target */
target->merge_from (sendbufs, nframes);
+
+ out:
+ _active = _pending_active;
}
bool
void
PeakMeter::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
- if (!_active) {
+ if (!_active && !_pending_active) {
return;
}
for (uint32_t i = n; i < _peak_power.size(); ++i) {
_peak_power[i] = 0.0f;
}
+
+ _active = _pending_active;
}
PeakMeter::PeakMeter (Session& s, const XMLNode& node)
void
PluginInsert::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
- if (active()) {
+ if (_active || _pending_active) {
if (_session.transport_rolling()) {
automation_run (bufs, nframes);
} else {
connect_and_run (bufs, nframes, 0, false);
}
+
} else {
/* FIXME: type, audio only */
bufs.count().set_audio(out);
}
+
+ _active = _pending_active;
}
void
return;
}
- if (!active()) {
+ if (!_active && !_pending_active) {
/* deliver silence */
silence (nframes);
- return;
+ goto out;
}
_out->run (bufs, start_frame, end_frame, nframes);
_input->collect_input (bufs, nframes, ChanCount::ZERO);
+
+ out:
+ _active = _pending_active;
}
XMLNode&
Processor::Processor(Session& session, const string& name)
: SessionObject(session, name)
, AutomatableControls(session)
+ , _pending_active(false)
, _active(false)
, _next_ab_is_active(false)
, _configured(false)
Processor::Processor (Session& session, const XMLNode& node)
: SessionObject(session, "renameMe")
, AutomatableControls(session)
+ , _pending_active(false)
, _active(false)
, _next_ab_is_active(false)
, _configured(false)
, _gui(0)
{
set_state (node);
+ _pending_active = _active;
}
XMLNode&
void
Return::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
- if (!active() || _input->n_ports() == ChanCount::ZERO) {
+ if ((!_active && !_pending_active) || _input->n_ports() == ChanCount::ZERO) {
return;
}
_meter->run (bufs, start_frame, end_frame, nframes);
}
}
+
+ _active = _pending_active;
}
bool
void
Send::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
- if (!_active || _output->n_ports() == ChanCount::ZERO) {
+ if (_output->n_ports() == ChanCount::ZERO) {
_meter->reset ();
+ _active = _pending_active;
+ return;
+ }
+
+ if (!_active && !_pending_active) {
+ _meter->reset ();
+ _output->silence (nframes);
+ _active = _pending_active;
return;
}
_meter->run (*_output_buffers, start_frame, end_frame, nframes);
}
}
+
+ /* _active was set to _pending_active by Delivery::run() */
}
XMLNode&