Make sure CapturingProcessors write a type to their state node so that they can be...
[ardour.git] / libs / ardour / route.cc
index 56fc0905764f0d541562fbdfb42ad4ce6284478b..4277bea0226a190ac957974e9118acb8416a38a2 100644 (file)
@@ -97,8 +97,6 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type)
         , _recordable (true)
         , _silent (false)
         , _declickable (false)
-       , _solo_control (new SoloControllable (X_("solo"), *this))
-       , _mute_control (new MuteControllable (X_("mute"), *this))
        , _mute_master (new MuteMaster (sess, name))
         , _have_internal_generator (false)
         , _solo_safe (false)
@@ -115,6 +113,9 @@ Route::init ()
 {
         /* add standard controls */
 
+       _solo_control.reset (new SoloControllable (X_("solo"), shared_from_this ()));
+       _mute_control.reset (new MuteControllable (X_("mute"), shared_from_this ()));
+
        _solo_control->set_flags (Controllable::Flag (_solo_control->flags() | Controllable::Toggle));
        _mute_control->set_flags (Controllable::Flag (_mute_control->flags() | Controllable::Toggle));
 
@@ -502,13 +503,17 @@ Route::process_output_buffers (BufferSet& bufs,
                        break;
                }
 
-               if (bufs.count() != (*i)->input_streams()) {
-                       cerr << _name << " bufs = " << bufs.count()
-                            << " input for " << (*i)->name() << " = " << (*i)->input_streams()
-                            << endl;
-               }
-               assert (bufs.count() == (*i)->input_streams());
-                
+#ifndef NDEBUG
+                /* if it has any inputs, make sure they match */
+                if ((*i)->input_streams() != ChanCount::ZERO) {
+                        if (bufs.count() != (*i)->input_streams()) {
+                                cerr << _name << " bufs = " << bufs.count()
+                                     << " input for " << (*i)->name() << " = " << (*i)->input_streams()
+                                     << endl;
+                                abort ();
+                        }
+                }
+#endif                
                 /* should we NOT run plugins here if the route is inactive?
                    do we catch route != active somewhere higher?
                 */
@@ -865,6 +870,8 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorList::ite
 {
        assert (processor != _meter);
        assert (processor != _main_outs);
+
+        DEBUG_TRACE (DEBUG::Processors, string_compose ("%1 adding processor %2\n", name(), processor->name()));
        
        ChanCount old_pms = processor_max_streams;
 
@@ -911,7 +918,6 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorList::ite
                        if (configure_processors_unlocked (err)) {
                                pstate.restore ();
                                configure_processors_unlocked (0); // it worked before we tried to add it ...
-                               cerr << "configure failed\n";
                                return -1;
                        }
                }
@@ -2342,6 +2348,8 @@ Route::set_processor_state (const XMLNode& node)
                                 must_configure = true;
                         }
                         _monitor_control->set_state (**niter, Stateful::current_state_version);
+               } else if (prop->value() == "capture") {
+                       _capturing_processor.reset (new CapturingProcessor (_session));
                 } else {
                         ProcessorList::iterator o;
 
@@ -2363,7 +2371,6 @@ 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" ||
@@ -2389,6 +2396,14 @@ Route::set_processor_state (const XMLNode& node)
                                        processor.reset (new UnknownProcessor (_session, **niter));
                                }
 
+                               /* we have to note the monitor send here, otherwise a new one will be created
+                                  and the state of this one will be lost.
+                               */
+                               boost::shared_ptr<InternalSend> isend = boost::dynamic_pointer_cast<InternalSend> (processor);
+                               if (isend && isend->role() == Delivery::Listen) {
+                                       _monitor_send = isend;
+                               }
+
                                /* it doesn't matter if invisible processors are added here, as they
                                   will be sorted out by setup_invisible_processors () shortly.
                                */
@@ -2465,8 +2480,8 @@ Route::add_internal_return ()
        }
 }
 
-BufferSet*
-Route::get_return_buffer () const
+void
+Route::add_send_to_internal_return (InternalSend* send)
 {
        Glib::RWLock::ReaderLock rm (_processor_lock);
 
@@ -2474,16 +2489,13 @@ Route::get_return_buffer () const
                boost::shared_ptr<InternalReturn> d = boost::dynamic_pointer_cast<InternalReturn>(*x);
 
                if (d) {
-                       BufferSet* bs = d->get_buffers ();
-                       return bs;
+                       return d->add_send (send);
                }
        }
-
-       return 0;
 }
 
 void
-Route::release_return_buffer () const
+Route::remove_send_from_internal_return (InternalSend* send)
 {
        Glib::RWLock::ReaderLock rm (_processor_lock);
 
@@ -2491,12 +2503,12 @@ Route::release_return_buffer () const
                boost::shared_ptr<InternalReturn> d = boost::dynamic_pointer_cast<InternalReturn>(*x);
 
                if (d) {
-                       return d->release_buffers ();
+                       return d->remove_send (send);
                }
        }
 }
 
-/** Add a monitor send, if we don't already have one */
+/** Add a monitor send (if we don't already have one) but don't activate it */
 int
 Route::listen_via_monitor ()
 {
@@ -2506,7 +2518,6 @@ Route::listen_via_monitor ()
        /* make sure we have one */
        if (!_monitor_send) {
                _monitor_send.reset (new InternalSend (_session, _pannable, _mute_master, _session.monitor_out(), Delivery::Listen));
-               _monitor_send->activate ();
                _monitor_send->set_display_to_user (false);
        }
        
@@ -3093,10 +3104,10 @@ Route::automation_snapshot (framepos_t now, bool force)
        }
 }
 
-Route::SoloControllable::SoloControllable (std::string name, Route& r)
-       : AutomationControl (r.session(), Evoral::Parameter (SoloAutomation),
+Route::SoloControllable::SoloControllable (std::string name, boost::shared_ptr<Route> r)
+       : AutomationControl (r->session(), Evoral::Parameter (SoloAutomation),
                             boost::shared_ptr<AutomationList>(), name)
-       , route (r)
+       , _route (r)
 {
        boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(SoloAutomation)));
        set_list (gl);
@@ -3106,36 +3117,42 @@ void
 Route::SoloControllable::set_value (double val)
 {
        bool bval = ((val >= 0.5f) ? true: false);
-# if 0
-       this is how it should be done 
 
        boost::shared_ptr<RouteList> rl (new RouteList);
-       rl->push_back (route);
+
+       boost::shared_ptr<Route> r = _route.lock ();
+       if (!r) {
+               return;
+       }
+       
+       rl->push_back (r);
 
        if (Config->get_solo_control_is_listen_control()) {
                _session.set_listen (rl, bval);
        } else {
                _session.set_solo (rl, bval);
        }
-#else
-       route.set_solo (bval, this);
-#endif
 }
 
 double
-Route::SoloControllable::get_value (void) const
+Route::SoloControllable::get_value () const
 {
+       boost::shared_ptr<Route> r = _route.lock ();
+       if (!r) {
+               return 0;
+       }
+       
        if (Config->get_solo_control_is_listen_control()) {
-               return route.listening_via_monitor() ? 1.0f : 0.0f;
+               return r->listening_via_monitor() ? 1.0f : 0.0f;
        } else {
-               return route.self_soloed() ? 1.0f : 0.0f;
+               return r->self_soloed() ? 1.0f : 0.0f;
        }
 }
 
-Route::MuteControllable::MuteControllable (std::string name, Route& r)
-       : AutomationControl (r.session(), Evoral::Parameter (MuteAutomation),
+Route::MuteControllable::MuteControllable (std::string name, boost::shared_ptr<Route> r)
+       : AutomationControl (r->session(), Evoral::Parameter (MuteAutomation),
                             boost::shared_ptr<AutomationList>(), name)
-       , route (r)
+       , _route (r)
 {
        boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(MuteAutomation)));
        set_list (gl);
@@ -3145,21 +3162,27 @@ void
 Route::MuteControllable::set_value (double val)
 {
        bool bval = ((val >= 0.5f) ? true: false);
-# if 0
-       this is how it should be done 
 
        boost::shared_ptr<RouteList> rl (new RouteList);
-       rl->push_back (route);
+
+       boost::shared_ptr<Route> r = _route.lock ();
+       if (!r) {
+               return;
+       }
+       
+       rl->push_back (r);
        _session.set_mute (rl, bval);
-#else
-       route.set_mute (bval, this);
-#endif
 }
 
 double
-Route::MuteControllable::get_value (void) const
+Route::MuteControllable::get_value () const
 {
-       return route.muted() ? 1.0f : 0.0f;
+       boost::shared_ptr<Route> r = _route.lock ();
+       if (!r) {
+               return 0;
+       }
+       
+       return r->muted() ? 1.0f : 0.0f;
 }
 
 void
@@ -3637,11 +3660,16 @@ Route::update_port_latencies (const PortSet& operands, const PortSet& feeders, b
 void
 Route::setup_invisible_processors ()
 {
-#ifdef NDEBUG
-       Glib::RWLock::WriterLock lm (_processor_lock, Glib::TryLock);
+#ifndef NDEBUG
+       Glib::RWLock::WriterLock lm (_processor_lock, Glib::TRY_LOCK);
        assert (!lm.locked ());
 #endif
 
+        if (!_main_outs) {
+                /* too early to be doing this stuff */
+                return;
+        }
+
        /* we'll build this new list here and then use it */
        
        ProcessorList new_processors;
@@ -3681,8 +3709,10 @@ Route::setup_invisible_processors ()
                        new_processors.insert (amp, _meter);
                        break;
                case MeterPostFader:
-                       assert (!_meter->display_to_user ());
-                       new_processors.insert (after_amp, _meter);
+                        /* do nothing here */
+                       break;
+               case MeterOutput:
+                        /* do nothing here */
                        break;
                case MeterCustom:
                        /* the meter is visible, so we don't touch it here */
@@ -3690,33 +3720,62 @@ Route::setup_invisible_processors ()
                }
        }
 
-
        /* MAIN OUTS */
 
-       if (_main_outs) {
-               assert (!_main_outs->display_to_user ());
-               new_processors.push_back (_main_outs);
-       }
+        assert (_main_outs);
+        assert (!_main_outs->display_to_user ());
+        new_processors.push_back (_main_outs);
+
+        /* iterator for the main outs */
+        
+        ProcessorList::iterator main = new_processors.end();
+        --main;
+
+        /* OUTPUT METERING */
+
+        if (_meter && (_meter_point == MeterOutput || _meter_point == MeterPostFader)) {
+                assert (!_meter->display_to_user ());
+
+                /* add the processor just before or just after the main outs */
+                
+                ProcessorList::iterator meter_point = main;
+
+                if (_meter_point == MeterOutput) {
+                        ++meter_point;
+                }
+                new_processors.insert (meter_point, _meter);                        
+        }
 
        /* MONITOR SEND */
 
        if (_monitor_send && !is_monitor ()) {
                assert (!_monitor_send->display_to_user ());
-               switch (Config->get_listen_position ()) {
-               case PreFaderListen:
-                       switch (Config->get_pfl_position ()) {
-                       case PFLFromBeforeProcessors:
-                               new_processors.push_front (_monitor_send);
-                               break;
-                       case PFLFromAfterProcessors:
-                               new_processors.insert (amp, _monitor_send);
-                               break;
-                       }
-                       break;
-               case AfterFaderListen:
-                       new_processors.insert (after_amp, _monitor_send);
-                       break;
-               }
+                if (Config->get_solo_control_is_listen_control()) {
+                        switch (Config->get_listen_position ()) {
+                        case PreFaderListen:
+                                switch (Config->get_pfl_position ()) {
+                                case PFLFromBeforeProcessors:
+                                        new_processors.push_front (_monitor_send);
+                                        break;
+                                case PFLFromAfterProcessors:
+                                        new_processors.insert (amp, _monitor_send);
+                                        break;
+                                }
+                                break;
+                        case AfterFaderListen:
+                                switch (Config->get_afl_position ()) {
+                                case AFLFromBeforeProcessors:
+                                        new_processors.insert (after_amp, _monitor_send);
+                                        break;
+                                case AFLFromAfterProcessors:
+                                        new_processors.insert (new_processors.end(), _monitor_send);
+                                        break;
+                                }
+                                break;
+                        }
+                }  else {
+                        new_processors.insert (new_processors.end(), _monitor_send);
+                }
        }
 
        /* MONITOR CONTROL */