X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Ftrack.cc;h=1aa917ca9d0830a9e93ba9eb8c5af95aae95d6e6;hb=7d96960b162d25da87c388a3083775e8770bba56;hp=eac2ffd31abfb693fed059516e7ab8e945d81c0d;hpb=05bcdd1d4c583c68ed977164913ff47e94df7adb;p=ardour.git diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index eac2ffd31a..1aa917ca9d 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2006 Paul Davis + Copyright (C) 2006 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,22 +15,23 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "pbd/error.h" + +#include "ardour/amp.h" +#include "ardour/audioplaylist.h" +#include "ardour/audioregion.h" +#include "ardour/audiosource.h" +#include "ardour/debug.h" +#include "ardour/delivery.h" +#include "ardour/diskstream.h" +#include "ardour/io_processor.h" +#include "ardour/meter.h" +#include "ardour/port.h" +#include "ardour/processor.h" +#include "ardour/route_group_specialized.h" +#include "ardour/session.h" +#include "ardour/track.h" +#include "ardour/utils.h" #include "i18n.h" @@ -39,8 +40,8 @@ using namespace ARDOUR; using namespace PBD; Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type) - : Route (sess, name, 1, -1, -1, -1, flag, default_type) - , _rec_enable_control (*this) + : Route (sess, name, flag, default_type) + , _rec_enable_control (new RecEnableControllable(*this)) { _declickable = true; _freeze_record.state = NoFreeze; @@ -49,8 +50,8 @@ Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, Data } Track::Track (Session& sess, const XMLNode& node, DataType default_type) - : Route (sess, node) - , _rec_enable_control (*this) + : Route (sess, node, default_type) + , _rec_enable_control (new RecEnableControllable(*this)) { _freeze_record.state = NoFreeze; _declickable = true; @@ -59,12 +60,7 @@ Track::Track (Session& sess, const XMLNode& node, DataType default_type) Track::~Track () { -} - -void -Track::set_meter_point (MeterPoint p, void *src) -{ - Route::set_meter_point (p, src); + DEBUG_TRACE (DEBUG::Destruction, string_compose ("track %1 destructor\n", _name)); } XMLNode& @@ -82,7 +78,7 @@ Track::get_template () void Track::toggle_monitor_input () { - for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) { + for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end(); ++i) { i->ensure_monitor_input(!i->monitoring_input()); } } @@ -90,19 +86,29 @@ Track::toggle_monitor_input () ARDOUR::nframes_t Track::update_total_latency () { - _own_latency = 0; + nframes_t old = _output->effective_latency(); + nframes_t own_latency = _output->user_latency(); for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { if ((*i)->active ()) { - _own_latency += (*i)->latency (); + own_latency += (*i)->signal_latency (); } } - set_port_latency (_own_latency); +#undef DEBUG_LATENCY +#ifdef DEBUG_LATENCY + cerr << _name << ": internal redirect (final) latency = " << own_latency << endl; +#endif - return _own_latency; -} + _output->set_port_latency (own_latency); + + if (old != own_latency) { + _output->set_latency_delay (own_latency); + signal_latency_changed (); /* EMIT SIGNAL */ + } + return _output->effective_latency(); +} Track::FreezeRecord::~FreezeRecord () { @@ -139,30 +145,34 @@ Track::RecEnableControllable::get_value (void) const bool Track::record_enabled () const { - return _diskstream->record_enabled (); + return _diskstream && _diskstream->record_enabled (); } bool Track::can_record() { bool will_record = true; - for (PortSet::iterator i = _inputs.begin(); i != _inputs.end() && will_record; ++i) { + for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end() && will_record; ++i) { if (!i->connected()) will_record = false; } return will_record; } - + void Track::set_record_enable (bool yn, void *src) { + if (!_session.writable()) { + return; + } + if (_freeze_record.state == Frozen) { return; } - if (_mix_group && src != _mix_group && _mix_group->is_active()) { - _mix_group->apply (&Track::set_record_enable, yn, _mix_group); + if (_route_group && src != _route_group && _route_group->active_property (RouteGroup::RecEnable)) { + _route_group->apply (&Track::set_record_enable, yn, _route_group); return; } @@ -170,16 +180,18 @@ Track::set_record_enable (bool yn, void *src) if (!_diskstream->record_enabled()) { _saved_meter_point = _meter_point; } - + _diskstream->set_record_enabled (yn); if (_diskstream->record_enabled()) { - set_meter_point (MeterInput, this); + if (_meter_point != MeterCustom) { + set_meter_point (MeterInput, this); + } } else { set_meter_point (_saved_meter_point, this); } - _rec_enable_control.Changed (); + _rec_enable_control->Changed (); } @@ -199,7 +211,7 @@ Track::set_name (const string& str) /* save state so that the statefile fully reflects any filename changes */ - if ((ret = IO::set_name (str)) == 0) { + if ((ret = Route::set_name (str)) == 0) { _session.save_state (""); } @@ -213,3 +225,126 @@ Track::set_latency_delay (nframes_t longest_session_latency) _diskstream->set_roll_delay (_roll_delay); } +void +Track::zero_diskstream_id_in_xml (XMLNode& node) +{ + if (node.property ("diskstream-id")) { + node.add_property ("diskstream-id", "0"); + } +} + +int +Track::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, + bool session_state_changing, bool can_record, bool /*rec_monitors_input*/) +{ + if (n_outputs().n_total() == 0) { + return 0; + } + + if (!_active) { + silence (nframes); + return 0; + } + + if (session_state_changing) { + if (_session.transport_speed() != 0.0f) { + /* we're rolling but some state is changing (e.g. our diskstream contents) + so we cannot use them. Be silent till this is over. Don't declick. + + XXX note the absurdity of ::no_roll() being called when we ARE rolling! + */ + passthru_silence (start_frame, end_frame, nframes, 0); + return 0; + } + /* we're really not rolling, so we're either delivery silence or actually + monitoring, both of which are safe to do while session_state_changing is true. + */ + } + + diskstream()->check_record_status (start_frame, nframes, can_record); + + bool send_silence; + + if (_have_internal_generator) { + /* since the instrument has no input streams, + there is no reason to send any signal + into the route. + */ + send_silence = true; + } else { + if (!Config->get_tape_machine_mode()) { + /* + ADATs work in a strange way.. + they monitor input always when stopped.and auto-input is engaged. + */ + if ((Config->get_monitoring_model() == SoftwareMonitoring) + && (_session.config.get_auto_input () || _diskstream->record_enabled())) { + send_silence = false; + } else { + send_silence = true; + } + } else { + /* + Other machines switch to input on stop if the track is record enabled, + regardless of the auto input setting (auto input only changes the + monitoring state when the transport is rolling) + */ + if ((Config->get_monitoring_model() == SoftwareMonitoring) + && _diskstream->record_enabled()) { + send_silence = false; + } else { + send_silence = true; + } + } + } + + _amp->apply_gain_automation(false); + + if (send_silence) { + + /* if we're sending silence, but we want the meters to show levels for the signal, + meter right here. + */ + + if (_have_internal_generator) { + passthru_silence (start_frame, end_frame, nframes, 0); + } else { + if (_meter_point == MeterInput) { + _input->process_input (_meter, start_frame, end_frame, nframes); + } + passthru_silence (start_frame, end_frame, nframes, 0); + } + + } else { + + /* we're sending signal, but we may still want to meter the input. + */ + + passthru (start_frame, end_frame, nframes, false); + } + + _main_outs->flush (nframes, end_frame - start_frame - 1); + + return 0; +} + +int +Track::silent_roll (nframes_t nframes, sframes_t /*start_frame*/, sframes_t /*end_frame*/, + bool can_record, bool rec_monitors_input) +{ + if (n_outputs().n_total() == 0 && _processors.empty()) { + return 0; + } + + if (!_active) { + silence (nframes); + return 0; + } + + _silent = true; + _amp->apply_gain_automation(false); + + silence (nframes); + + return diskstream()->process (_session.transport_frame(), nframes, can_record, rec_monitors_input); +}