assert (!AudioEngine::instance()->process_lock().trylock());
Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
- assert(lm.locked());
+ if (!lm.locked()) {
+ bufs.silence (nframes, 0);
+ return;
+ }
/* figure out if we're going to use gain automation */
if (gain_automation_ok) {
return;
}
+ if (is_master() || is_monitor() || is_auditioner()) {
+ DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 ignore solo change (master, monitor or auditioner)\n", name()));
+ return;
+ }
+
if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_solo()) {
_route_group->foreach_route (boost::bind (&Route::set_solo, _1, yn, _route_group));
return;
if (processor->set_state (node, version)) {
return false;
}
+
+ //A2 uses the "active" flag in the toplevel redirect node, not in the child plugin/IO
+ if (i != children.end()) {
+ if ((prop = (*i)->property (X_("active"))) != 0) {
+ if ( string_is_affirmative (prop->value()) && !_session.get_disable_all_loaded_plugins() )
+ processor->activate();
+ else
+ processor->deactivate();
+ }
+ }
- return (add_processor (processor, placement) == 0);
+ return (add_processor (processor, placement, 0, false) == 0);
}
catch (failed_constructor &err) {
node->add_child_nocopy (_mute_control->get_state ());
node->add_child_nocopy (_mute_master->get_state ());
+ if (full_state) {
+ node->add_child_nocopy (Automatable::get_automation_xml_state ());
+ }
+
XMLNode* remote_control_node = new XMLNode (X_("RemoteControl"));
snprintf (buf, sizeof (buf), "%d", _remote_control_id);
remote_control_node->add_property (X_("id"), buf);
} else if (child->name() == X_("MuteMaster")) {
_mute_master->set_state (*child, version);
+
+ } else if (child->name() == Automatable::xml_node_name) {
+ set_automation_xml_state (*child, Evoral::Parameter(NullAutomation));
}
}
int
Route::set_state_2X (const XMLNode& node, int version)
{
+ LocaleGuard lg (X_("C"));
XMLNodeList nlist;
XMLNodeConstIterator niter;
XMLNode *child;
}
Route::SoloControllable::SoloControllable (std::string name, boost::shared_ptr<Route> r)
- : AutomationControl (r->session(), Evoral::Parameter (SoloAutomation),
- boost::shared_ptr<AutomationList>(), name)
+ : AutomationControl (r->session(),
+ Evoral::Parameter (SoloAutomation),
+ ParameterDescriptor(Evoral::Parameter (SoloAutomation)),
+ boost::shared_ptr<AutomationList>(), name)
, _route (r)
{
boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(SoloAutomation)));
+ gl->set_interpolation(Evoral::ControlList::Discrete);
set_list (gl);
}
void
Route::SoloControllable::set_value (double val)
{
- bool bval = ((val >= 0.5f) ? true: false);
+ const bool bval = ((val >= 0.5) ? true : false);
boost::shared_ptr<RouteList> rl (new RouteList);
}
Route::MuteControllable::MuteControllable (std::string name, boost::shared_ptr<Route> r)
- : AutomationControl (r->session(), Evoral::Parameter (MuteAutomation),
- boost::shared_ptr<AutomationList>(), name)
+ : AutomationControl (r->session(),
+ Evoral::Parameter (MuteAutomation),
+ ParameterDescriptor (Evoral::Parameter (MuteAutomation)),
+ boost::shared_ptr<AutomationList>(),
+ name)
, _route (r)
{
boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(MuteAutomation)));
+ gl->set_interpolation(Evoral::ControlList::Discrete);
set_list (gl);
}
void
-Route::MuteControllable::set_value (double val)
+Route::MuteControllable::set_superficial_value(bool muted)
{
- bool bval = ((val >= 0.5f) ? true: false);
+ /* Note we can not use AutomationControl::set_value here since it will emit
+ Changed(), but the value will not be correct to the observer. */
- boost::shared_ptr<RouteList> rl (new RouteList);
+ bool to_list = _list && ((AutomationList*)_list.get())->automation_write();
+
+ Control::set_double (muted, _session.transport_frame(), to_list);
+}
+
+void
+Route::MuteControllable::set_value (double val)
+{
+ const bool bval = ((val >= 0.5) ? true : false);
boost::shared_ptr<Route> r = _route.lock ();
if (!r) {
return;
}
- rl->push_back (r);
- _session.set_mute (rl, bval);
+ if (_list && ((AutomationList*)_list.get())->automation_playback()) {
+ // Playing back automation, set route mute directly
+ r->set_mute (bval, this);
+ } else {
+ // Set from user, queue mute event
+ boost::shared_ptr<RouteList> rl (new RouteList);
+ rl->push_back (r);
+ _session.set_mute (rl, bval, Session::rt_cleanup);
+ }
+
+ // Set superficial/automation value to drive controller (and possibly record)
+ set_superficial_value(bval);
}
double
Route::MuteControllable::get_value () const
{
- boost::shared_ptr<Route> r = _route.lock ();
- if (!r) {
- return 0;
+ if (_list && ((AutomationList*)_list.get())->automation_playback()) {
+ // Playing back automation, get the value from the list
+ return AutomationControl::get_value();
}
- return r->muted() ? 1.0f : 0.0f;
+ // Not playing back automation, get the actual route mute value
+ boost::shared_ptr<Route> r = _route.lock ();
+ return (r && r->muted()) ? 1.0 : 0.0;
}
void
void
Route::meter ()
{
- Glib::Threads::RWLock::ReaderLock rm (_processor_lock, Glib::Threads::TRY_LOCK);
+ Glib::Threads::RWLock::ReaderLock rm (_processor_lock);
assert (_meter);
/* maybe one of our processors does or ... */
- Glib::Threads::RWLock::ReaderLock rm (_processor_lock, Glib::Threads::TRY_LOCK);
+ Glib::Threads::RWLock::ReaderLock rm (_processor_lock);
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
if ((c = boost::dynamic_pointer_cast<AutomationControl>((*i)->control (param))) != 0) {
break;