add virtual Delivery::pan_outs() so that internal sends correctly configure their...
[ardour.git] / libs / ardour / route.cc
index 0e8c93d75e0b364f74b3bc00a5afe40a5e624808..8d1c1c8397764513d28f67def554df53b1090c51 100644 (file)
@@ -125,11 +125,13 @@ Route::init ()
 
        /* panning */
 
-        Pannable* p = new Pannable (_session);
+       if (!(_flags & Route::MonitorOut)) {
+               Pannable* p = new Pannable (_session);
 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
-       boost_debug_shared_ptr_mark_interesting (p, "Pannable");
+               boost_debug_shared_ptr_mark_interesting (p, "Pannable");
 #endif
-       _pannable.reset (p);
+               _pannable.reset (p);
+       }
 
        /* input and output objects */
 
@@ -568,6 +570,11 @@ Route::set_listen (bool yn, void* src)
                return;
        }
 
+       if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_solo()) {
+               _route_group->foreach_route (boost::bind (&Route::set_listen, _1, yn, _route_group));
+               return;
+       }
+
        if (_monitor_send) {
                if (yn != _monitor_send->active()) {
                        if (yn) {
@@ -819,7 +826,7 @@ dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& p
        cerr << name << " {" << endl;
        for (list<boost::shared_ptr<Processor> >::const_iterator p = procs.begin();
                        p != procs.end(); ++p) {
-               cerr << "\t" << (*p)->name() << " ID = " << (*p)->id() << endl;
+               cerr << "\t" << (*p)->name() << " ID = " << (*p)->id() << " @ " << (*p) << endl;
        }
        cerr << "}" << endl;
 }
@@ -858,8 +865,6 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorList::ite
        DEBUG_TRACE (DEBUG::Processors, string_compose (
                             "%1 adding processor %2\n", name(), processor->name()));
 
-       ChanCount old_pms = processor_max_streams;
-
        if (!_session.engine().connected() || !processor) {
                return 1;
        }
@@ -909,7 +914,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorList::ite
 
                if ((pi = boost::dynamic_pointer_cast<PluginInsert>(processor)) != 0) {
 
-                       if (pi->natural_input_streams() == ChanCount::ZERO) {
+                       if (pi->has_no_inputs ()) {
                                /* generator plugin */
                                _have_internal_generator = true;
                        }
@@ -1016,8 +1021,6 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
                loc = _processors.end ();
        }
 
-       ChanCount old_pms = processor_max_streams;
-
        if (!_session.engine().connected()) {
                return 1;
        }
@@ -1042,7 +1045,7 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
                                pi->set_count (1);
                        }
 
-                       ProcessorList::iterator inserted = _processors.insert (loc, *i);
+                       _processors.insert (loc, *i);
 
                        if ((*i)->active()) {
                                (*i)->activate ();
@@ -1064,7 +1067,7 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
                        boost::shared_ptr<PluginInsert> pi;
 
                        if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
-                               if (pi->is_generator()) {
+                               if (pi->has_no_inputs ()) {
                                        _have_internal_generator = true;
                                        break;
                                }
@@ -1214,8 +1217,6 @@ Route::ab_plugins (bool forward)
 void
 Route::clear_processors (Placement p)
 {
-       const ChanCount old_pms = processor_max_streams;
-
        if (!_session.engine().connected()) {
                return;
        }
@@ -1296,8 +1297,6 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
                return 0;
        }
 
-       ChanCount old_pms = processor_max_streams;
-
        if (!_session.engine().connected()) {
                return 1;
        }
@@ -1367,7 +1366,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
                        boost::shared_ptr<PluginInsert> pi;
 
                        if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
-                               if (pi->is_generator()) {
+                               if (pi->has_no_inputs ()) {
                                        _have_internal_generator = true;
                                        break;
                                }
@@ -1457,7 +1456,7 @@ Route::remove_processors (const ProcessorList& to_be_deleted, ProcessorStreams*
                        boost::shared_ptr<PluginInsert> pi;
 
                        if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
-                               if (pi->is_generator()) {
+                               if (pi->has_no_inputs ()) {
                                        _have_internal_generator = true;
                                        break;
                                }
@@ -1589,7 +1588,8 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
        }
 
        /* make sure we have sufficient scratch buffers to cope with the new processor
-          configuration */
+          configuration 
+       */
        _session.ensure_buffers (n_process_buffers ());
 
        DEBUG_TRACE (DEBUG::Processors, string_compose ("%1: configuration complete\n", _name));
@@ -1843,7 +1843,9 @@ Route::state(bool full_state)
                cmt->add_content (_comment);
        }
 
-       node->add_child_nocopy (_pannable->state (full_state));
+       if (_pannable) {
+               node->add_child_nocopy (_pannable->state (full_state));
+       }
 
        for (i = _processors.begin(); i != _processors.end(); ++i) {
                node->add_child_nocopy((*i)->state (full_state));
@@ -1897,11 +1899,21 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/)
                _mute_master->set_solo_ignore (true);
        }
 
+       if (is_monitor()) {
+               /* monitor bus does not get a panner, but if (re)created
+                  via XML, it will already have one by the time we
+                  call ::set_state(). so ... remove it.
+               */
+               unpan ();
+       }
+
        /* add all processors (except amp, which is always present) */
 
        nlist = node.children();
        XMLNode processor_state (X_("processor_state"));
 
+       Stateful::save_extra_xml (node);
+
        for (niter = nlist.begin(); niter != nlist.end(); ++niter){
 
                child = *niter;
@@ -1924,7 +1936,11 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/)
 
 
                if (child->name() == X_("Pannable")) {
-                       _pannable->set_state (*child, version);
+                       if (_pannable) {
+                               _pannable->set_state (*child, version);
+                       } else {
+                               warning << string_compose (_("Pannable state found for route (%1) without a panner!"), name()) << endmsg;
+                       }
                }
        }
 
@@ -2015,10 +2031,6 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/)
                        XMLNode *cmt = *(child->children().begin());
                        _comment = cmt->content();
 
-               } else if (child->name() == X_("Extra")) {
-
-                       _extra_xml = new XMLNode (*child);
-
                } else if (child->name() == Controllable::xml_node_name && (prop = child->property("name")) != 0) {
                        if (prop->value() == "solo") {
                                _solo_control->set_state (*child, version);
@@ -2255,6 +2267,8 @@ Route::_set_state_2X (const XMLNode& node, int version)
 
        set_processor_state_2X (redirect_nodes, version);
 
+       Stateful::save_extra_xml (node);
+
        for (niter = nlist.begin(); niter != nlist.end(); ++niter){
                child = *niter;
 
@@ -2265,10 +2279,6 @@ Route::_set_state_2X (const XMLNode& node, int version)
                        XMLNode *cmt = *(child->children().begin());
                        _comment = cmt->content();
 
-               } else if (child->name() == X_("extra")) {
-
-                       _extra_xml = new XMLNode (*child);
-
                } else if (child->name() == Controllable::xml_node_name && (prop = child->property("name")) != 0) {
                        if (prop->value() == X_("solo")) {
                                _solo_control->set_state (*child, version);
@@ -2368,6 +2378,7 @@ Route::set_processor_state (const XMLNode& node)
                                if (prop->value() == "intsend") {
 
                                        processor.reset (new InternalSend (_session, _pannable, _mute_master, boost::shared_ptr<Route>(), Delivery::Role (0)));
+
                                } else if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
                                           prop->value() == "lv2" ||
                                           prop->value() == "vst" ||
@@ -2427,7 +2438,7 @@ Route::set_processor_state (const XMLNode& node)
                        boost::shared_ptr<PluginInsert> pi;
 
                        if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
-                               if (pi->is_generator()) {
+                               if (pi->has_no_inputs ()) {
                                        _have_internal_generator = true;
                                        break;
                                }
@@ -3068,7 +3079,10 @@ Route::set_latency_compensation (framecnt_t longest_session_latency)
 void
 Route::automation_snapshot (framepos_t now, bool force)
 {
-       _pannable->automation_snapshot (now, force);
+       if (_pannable) {
+               _pannable->automation_snapshot (now, force);
+       }
+
        for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
                (*i)->automation_snapshot (now, force);
        }
@@ -3208,7 +3222,7 @@ Route::shift (framepos_t pos, framecnt_t frames)
        }
 
        /* pan automation */
-       {
+       if (_pannable) {
                ControlSet::Controls& c (_pannable->controls());
 
                for (ControlSet::Controls::const_iterator ci = c.begin(); ci != c.end(); ++ci) {
@@ -3764,6 +3778,7 @@ Route::setup_invisible_processors ()
                                        new_processors.insert (amp, _monitor_send);
                                        break;
                                }
+                               _monitor_send->set_can_pan (false);
                                break;
                        case AfterFaderListen:
                                switch (Config->get_afl_position ()) {
@@ -3774,10 +3789,12 @@ Route::setup_invisible_processors ()
                                        new_processors.insert (new_processors.end(), _monitor_send);
                                        break;
                                }
+                               _monitor_send->set_can_pan (true);
                                break;
                        }
                }  else {
                        new_processors.insert (new_processors.end(), _monitor_send);
+                       _monitor_send->set_can_pan (false);
                }
        }
 
@@ -3829,3 +3846,18 @@ Route::should_monitor () const
        return true;
 }
 
+void
+Route::unpan ()
+{
+       Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+       Glib::RWLock::ReaderLock lp (_processor_lock);
+
+       _pannable.reset ();
+
+       for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+               boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery>(*i);
+               if (d) {
+                       d->unpan ();
+               }
+       }
+}