Add a null check to ports when loading an export channel from xml + fix indentation...
[ardour.git] / libs / ardour / route.cc
index 97b1402d3053542389fc7836a4bf18271cd3a5e4..51ea1960cb96c1b386143ac974427f540cfb250c 100644 (file)
@@ -382,8 +382,9 @@ Route::set_gain (gain_t val, void *src)
  */
 void
 Route::process_output_buffers (BufferSet& bufs,
-                              framepos_t start_frame, framepos_t end_frame, nframes_t nframes,
-                              bool /*with_processors*/, int declick)
+                              framepos_t start_frame, framepos_t end_frame, pframes_t nframes,
+                              bool /*with_processors*/, int declick,
+                               bool gain_automation_ok)
 {
        bool monitor;
 
@@ -403,9 +404,12 @@ Route::process_output_buffers (BufferSet& bufs,
        }
 
        /* figure out if we're going to use gain automation */
-       _amp->setup_gain_automation (start_frame, end_frame, nframes);
-
-
+        if (gain_automation_ok) {
+                _amp->setup_gain_automation (start_frame, end_frame, nframes);
+        } else {
+                _amp->apply_gain_automation (false);
+        }
+        
        /* tell main outs what to do about monitoring */
        _main_outs->no_outs_cuz_we_no_monitor (!monitor);
 
@@ -436,12 +440,12 @@ Route::process_output_buffers (BufferSet& bufs,
                                Sample* const sp = i->data();
 
                                if (_phase_invert[chn]) {
-                                       for (nframes_t nx = 0; nx < nframes; ++nx) {
+                                       for (pframes_t nx = 0; nx < nframes; ++nx) {
                                                sp[nx]  = -sp[nx];
                                                sp[nx] += 1.0e-27f;
                                        }
                                } else {
-                                       for (nframes_t nx = 0; nx < nframes; ++nx) {
+                                       for (pframes_t nx = 0; nx < nframes; ++nx) {
                                                sp[nx] += 1.0e-27f;
                                        }
                                }
@@ -453,7 +457,7 @@ Route::process_output_buffers (BufferSet& bufs,
                                Sample* const sp = i->data();
 
                                if (_phase_invert[chn]) {
-                                       for (nframes_t nx = 0; nx < nframes; ++nx) {
+                                       for (pframes_t nx = 0; nx < nframes; ++nx) {
                                                sp[nx] = -sp[nx];
                                        }
                                }
@@ -466,7 +470,7 @@ Route::process_output_buffers (BufferSet& bufs,
 
                        for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
                                Sample* const sp = i->data();
-                               for (nframes_t nx = 0; nx < nframes; ++nx) {
+                               for (pframes_t nx = 0; nx < nframes; ++nx) {
                                        sp[nx] += 1.0e-27f;
                                }
                        }
@@ -507,7 +511,7 @@ Route::n_process_buffers ()
 }
 
 void
-Route::passthru (framepos_t start_frame, framepos_t end_frame, nframes_t nframes, int declick)
+Route::passthru (framepos_t start_frame, framepos_t end_frame, pframes_t nframes, int declick)
 {
        BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
 
@@ -543,16 +547,16 @@ Route::passthru (framepos_t start_frame, framepos_t end_frame, nframes_t nframes
        }
 
        write_out_of_band_data (bufs, start_frame, end_frame, nframes);
-       process_output_buffers (bufs, start_frame, end_frame, nframes, true, declick);
+       process_output_buffers (bufs, start_frame, end_frame, nframes, true, declick, true);
 }
 
 void
-Route::passthru_silence (framepos_t start_frame, framepos_t end_frame, nframes_t nframes, int declick)
+Route::passthru_silence (framepos_t start_frame, framepos_t end_frame, pframes_t nframes, int declick)
 {
        BufferSet& bufs (_session.get_silent_buffers (n_process_buffers()));
        bufs.set_count (_input->n_ports());
        write_out_of_band_data (bufs, start_frame, end_frame, nframes);
-       process_output_buffers (bufs, start_frame, end_frame, nframes, true, declick);
+       process_output_buffers (bufs, start_frame, end_frame, nframes, true, declick, false);
 }
 
 void
@@ -1832,6 +1836,7 @@ Route::state(bool full_state)
        node->add_child_nocopy (_input->state (full_state));
        node->add_child_nocopy (_output->state (full_state));
        node->add_child_nocopy (_solo_control->get_state ());
+       node->add_child_nocopy (_mute_control->get_state ());
        node->add_child_nocopy (_mute_master->get_state ());
 
        XMLNode* remote_control_node = new XMLNode (X_("RemoteControl"));
@@ -2013,11 +2018,9 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/)
 
                        _extra_xml = new XMLNode (*child);
 
-               } else if (child->name() == X_("Controllable") && (prop = child->property("name")) != 0) {
-
+               } else if (child->name() == Controllable::xml_node_name && (prop = child->property("name")) != 0) {
                        if (prop->value() == "solo") {
                                _solo_control->set_state (*child, version);
-                               _session.add_controllable (_solo_control);
                        }
 
                } else if (child->name() == X_("RemoteControl")) {
@@ -2264,13 +2267,13 @@ Route::_set_state_2X (const XMLNode& node, int version)
 
                        _extra_xml = new XMLNode (*child);
 
-               } else if (child->name() == X_("Controllable") && (prop = child->property("name")) != 0) {
-
-                       if (prop->value() == "solo") {
+               } else if (child->name() == Controllable::xml_node_name && (prop = child->property("name")) != 0) {
+                       if (prop->value() == X_("solo")) {
                                _solo_control->set_state (*child, version);
-                               _session.add_controllable (_solo_control);
-                       }
-
+                       } else if (prop->value() == X_("mute")) {
+                               _mute_control->set_state (*child, version);
+                        }
+                                
                } else if (child->name() == X_("RemoteControl")) {
                        if ((prop = child->property (X_("id"))) != 0) {
                                int32_t x;
@@ -2418,7 +2421,7 @@ Route::curve_reallocate ()
 }
 
 void
-Route::silence (nframes_t nframes)
+Route::silence (framecnt_t nframes)
 {
        Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
        if (!lm.locked()) {
@@ -2429,7 +2432,7 @@ Route::silence (nframes_t nframes)
 }
 
 void
-Route::silence_unlocked (nframes_t nframes)
+Route::silence_unlocked (framecnt_t nframes)
 {
        /* Must be called with the processor lock held */
        
@@ -2687,8 +2690,9 @@ Route::direct_feeds (boost::shared_ptr<Route> other, bool* only_send)
        return false;
 }
 
+/** Called from the (non-realtime) butler thread when the transport is stopped */
 void
-Route::handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool can_flush_processors)
+Route::nonrealtime_handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool can_flush_processors)
 {
        framepos_t now = _session.transport_frame();
 
@@ -2714,7 +2718,7 @@ Route::handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool c
        _roll_delay = _initial_delay;
 }
 
-/** Called with the process lock held */
+/** Called with the process lock held if change contains ConfigurationChanged */
 void
 Route::input_change_handler (IOChange change, void * /*src*/)
 {
@@ -2725,7 +2729,7 @@ Route::input_change_handler (IOChange change, void * /*src*/)
        }
 }
 
-/** Called with the process lock held */
+/** Called with the process lock held if change contains ConfigurationChanged */
 void
 Route::output_change_handler (IOChange change, void * /*src*/)
 {
@@ -2775,7 +2779,7 @@ Route::pans_required () const
 }
 
 int
-Route::no_roll (nframes_t nframes, framepos_t start_frame, framepos_t end_frame,
+Route::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame,
                bool session_state_changing, bool /*can_record*/, bool /*rec_monitors_input*/)
 {
        Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
@@ -2812,8 +2816,8 @@ Route::no_roll (nframes_t nframes, framepos_t start_frame, framepos_t end_frame,
        return 0;
 }
 
-nframes_t
-Route::check_initial_delay (nframes_t nframes, nframes_t& transport_frame)
+framecnt_t
+Route::check_initial_delay (framecnt_t nframes, framecnt_t& transport_frame)
 {
        if (_roll_delay > nframes) {
 
@@ -2840,7 +2844,7 @@ Route::check_initial_delay (nframes_t nframes, nframes_t& transport_frame)
 }
 
 int
-Route::roll (nframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick,
+Route::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick,
             bool /*can_record*/, bool /*rec_monitors_input*/, bool& /* need_butler */)
 {
        Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
@@ -2859,7 +2863,7 @@ Route::roll (nframes_t nframes, framepos_t start_frame, framepos_t end_frame, in
                return 0;
        }
 
-       nframes_t unused = 0;
+       framecnt_t unused = 0;
 
        if ((nframes = check_initial_delay (nframes, unused)) == 0) {
                return 0;
@@ -2873,7 +2877,7 @@ Route::roll (nframes_t nframes, framepos_t start_frame, framepos_t end_frame, in
 }
 
 int
-Route::silent_roll (nframes_t nframes, framepos_t /*start_frame*/, framepos_t /*end_frame*/,
+Route::silent_roll (pframes_t nframes, framepos_t /*start_frame*/, framepos_t /*end_frame*/,
                    bool /*can_record*/, bool /*rec_monitors_input*/, bool& /* need_butler */)
 {
        silence (nframes);
@@ -3042,11 +3046,11 @@ Route::put_monitor_send_at (Placement p)
        _session.set_dirty ();
 }
 
-nframes_t
+framecnt_t
 Route::update_total_latency ()
 {
-       nframes_t old = _output->effective_latency();
-       nframes_t own_latency = _output->user_latency();
+       framecnt_t old = _output->effective_latency();
+       framecnt_t own_latency = _output->user_latency();
 
        for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
                if ((*i)->active ()) {
@@ -3081,16 +3085,16 @@ Route::update_total_latency ()
 }
 
 void
-Route::set_user_latency (nframes_t nframes)
+Route::set_user_latency (framecnt_t nframes)
 {
        _output->set_user_latency (nframes);
        _session.update_latency_compensation (false, false);
 }
 
 void
-Route::set_latency_delay (nframes_t longest_session_latency)
+Route::set_latency_delay (framecnt_t longest_session_latency)
 {
-       nframes_t old = _initial_delay;
+       framecnt_t old = _initial_delay;
 
        if (_output->effective_latency() < longest_session_latency) {
                _initial_delay = longest_session_latency - _output->effective_latency();
@@ -3108,7 +3112,7 @@ Route::set_latency_delay (nframes_t longest_session_latency)
 }
 
 void
-Route::automation_snapshot (nframes_t now, bool force)
+Route::automation_snapshot (framepos_t now, bool force)
 {
        panner()->automation_snapshot (now, force);
        
@@ -3187,7 +3191,7 @@ Route::MuteControllable::get_value (void) const
 }
 
 void
-Route::set_block_size (nframes_t nframes)
+Route::set_block_size (pframes_t nframes)
 {
        for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
                (*i)->set_block_size (nframes);
@@ -3226,44 +3230,54 @@ Route::set_pending_declick (int declick)
  */
 
 void
-Route::shift (framepos_t /*pos*/, framecnt_t /*frames*/)
+Route::shift (framepos_t pos, framecnt_t frames)
 {
-#ifdef THIS_NEEDS_FIXING_FOR_V3
-
        /* gain automation */
-       XMLNode &before = _gain_control->get_state ();
-       _gain_control->shift (pos, frames);
-       XMLNode &after = _gain_control->get_state ();
-       _session.add_command (new MementoCommand<AutomationList> (_gain_automation_curve, &before, &after));
+        {
+                boost::shared_ptr<AutomationControl> gc = _amp->gain_control();
+                
+                XMLNode &before = gc->alist()->get_state ();
+                gc->alist()->shift (pos, frames);
+                XMLNode &after = gc->alist()->get_state ();
+                _session.add_command (new MementoCommand<AutomationList> (*gc->alist().get(), &before, &after));
+        }
 
        /* pan automation */
-       for (std::vector<StreamPanner*>::iterator i = _panner->begin (); i != _panner->end (); ++i) {
-               Curve & c = (*i)->automation ();
-               XMLNode &before = c.get_state ();
-               c.shift (pos, frames);
-               XMLNode &after = c.get_state ();
-               _session.add_command (new MementoCommand<AutomationList> (c, &before, &after));
-       }
+        {
+                boost::shared_ptr<AutomationControl> pc;
+                uint32_t npans = _main_outs->panner()->npanners();
+
+                for (uint32_t p = 0; p < npans; ++p) {
+                        pc = _main_outs->panner()->pan_control (0, p);
+                        if (pc) {
+                                boost::shared_ptr<AutomationList> al = pc->alist();
+                                XMLNode& before = al->get_state ();
+                                al->shift (pos, frames);
+                                XMLNode& after = al->get_state ();
+                                _session.add_command (new MementoCommand<AutomationList> (*al.get(), &before, &after));
+                        }
+                }
+        }
 
        /* redirect automation */
        {
-               Glib::RWLock::ReaderLock lm (redirect_lock);
-               for (RedirectList::iterator i = _redirects.begin (); i != _redirects.end (); ++i) {
-
-                       set<uint32_t> a;
-                       (*i)->what_has_automation (a);
-
-                       for (set<uint32_t>::const_iterator j = a.begin (); j != a.end (); ++j) {
-                               AutomationList & al = (*i)->automation_list (*j);
-                               XMLNode &before = al.get_state ();
-                               al.shift (pos, frames);
-                               XMLNode &after = al.get_state ();
-                               _session.add_command (new MementoCommand<AutomationList> (al, &before, &after));
-                       }
-               }
+               Glib::RWLock::ReaderLock lm (_processor_lock);
+               for (ProcessorList::iterator i = _processors.begin (); i != _processors.end (); ++i) {
+
+                       set<Evoral::Parameter> parameters = (*i)->what_can_be_automated();
+
+                       for (set<Evoral::Parameter>::const_iterator p = parameters.begin (); p != parameters.end (); ++p) {
+                                boost::shared_ptr<AutomationControl> ac = (*i)->automation_control (*p);
+                                if (ac) {
+                                        boost::shared_ptr<AutomationList> al = ac->alist();
+                                        XMLNode &before = al->get_state ();
+                                        al->shift (pos, frames);
+                                        XMLNode &after = al->get_state ();
+                                        _session.add_command (new MementoCommand<AutomationList> (*al.get(), &before, &after));
+                                }
+                        }
+                }
        }
-#endif
-
 }