Tidy up monitoring slightly so that it matches oofus' truth

table for the various different states.  Should fix #4533.


git-svn-id: svn://localhost/ardour2/branches/3.0@11073 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2011-12-26 15:37:14 +00:00
parent 2adb3fb579
commit bda0f938fb
8 changed files with 94 additions and 131 deletions

BIN
doc/monitor_modes.pdf Normal file

Binary file not shown.

View File

@ -114,9 +114,6 @@ public:
protected:
XMLNode& state (bool full);
bool ardour_should_monitor () const;
bool send_silence () const;
void act_on_mute ();
private:

View File

@ -107,6 +107,9 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
bool is_master() const { return _flags & MasterOut; }
bool is_monitor() const { return _flags & MonitorOut; }
virtual MonitorState monitoring_state () const;
virtual MeterState metering_state () const;
/* these are the core of the API of a Route. see the protected sections as well */
virtual int roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame,
@ -494,7 +497,6 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
uint32_t pans_required() const;
ChanCount n_process_buffers ();
virtual bool ardour_should_monitor () const;
virtual void maybe_declick (BufferSet&, framecnt_t, int);
boost::shared_ptr<Amp> _amp;

View File

@ -50,9 +50,11 @@ class Track : public Route, public PublicDiskstream
virtual void set_monitoring (MonitorChoice);
MonitorChoice monitoring_choice() const { return _monitoring; }
MonitorState monitoring_state();
MonitorState monitoring_state () const;
PBD::Signal0<void> MonitoringChanged;
MeterState metering_state () const;
virtual int no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame,
bool state_changing);
@ -213,8 +215,6 @@ class Track : public Route, public PublicDiskstream
void maybe_declick (BufferSet&, framecnt_t, int);
virtual bool send_silence () const;
boost::shared_ptr<RecEnableControllable> _rec_enable_control;
framecnt_t check_initial_delay (framecnt_t nframes, framecnt_t&);

View File

@ -371,6 +371,11 @@ namespace ARDOUR {
MonitoringDisk = 0x4,
};
enum MeterState {
MeteringInput, ///< meter the input IO, regardless of what is going through the route
MeteringRoute ///< meter what is going through the route
};
enum PFLPosition {
/** PFL signals come from before pre-fader processors */
PFLFromBeforeProcessors,

View File

@ -652,18 +652,6 @@ MidiTrack::diskstream_data_recorded (boost::weak_ptr<MidiSource> src)
DataRecorded (src); /* EMIT SIGNAL */
}
bool
MidiTrack::ardour_should_monitor () const
{
return true;
}
bool
MidiTrack::send_silence () const
{
return false;
}
bool
MidiTrack::input_active () const
{

View File

@ -400,8 +400,6 @@ Route::process_output_buffers (BufferSet& bufs,
framepos_t start_frame, framepos_t end_frame, pframes_t nframes,
int declick, bool gain_automation_ok)
{
bool monitor = ardour_should_monitor ();
bufs.set_is_silent (false);
/* figure out if we're going to use gain automation */
@ -411,8 +409,11 @@ Route::process_output_buffers (BufferSet& bufs,
_amp->apply_gain_automation (false);
}
/* tell main outs what to do about monitoring */
_main_outs->no_outs_cuz_we_no_monitor (!monitor);
/* Tell main outs what to do about monitoring. We do this so that
on a transition between monitoring states we get a de-clicking gain
change in the _main_outs delivery.
*/
_main_outs->no_outs_cuz_we_no_monitor (monitoring_state () == MonitoringSilence);
/* -------------------------------------------------------------------------------------------
@ -478,12 +479,20 @@ Route::process_output_buffers (BufferSet& bufs,
and go ....
----------------------------------------------------------------------------------------- */
/* set this to be true if the meter will already have been ::run() earlier */
bool const meter_already_run = metering_state() == MeteringInput;
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
if (boost::dynamic_pointer_cast<UnknownProcessor> (*i)) {
break;
}
if (boost::dynamic_pointer_cast<PeakMeter> (*i) && meter_already_run) {
/* don't ::run() the meter, otherwise it will have its previous peak corrupted */
continue;
}
#ifndef NDEBUG
/* if it has any inputs, make sure they match */
if ((*i)->input_streams() != ChanCount::ZERO) {
@ -3846,22 +3855,6 @@ Route::setup_invisible_processors ()
}
}
/** @return true if Ardour should provide monitoring for this route */
bool
Route::ardour_should_monitor () const
{
switch (Config->get_monitoring_model()) {
case HardwareMonitoring:
case ExternalMonitoring:
return !record_enabled() || (_session.config.get_auto_input() && !_session.actively_recording());
break;
default:
break;
}
return true;
}
void
Route::unpan ()
{
@ -3919,3 +3912,21 @@ Route::processor_by_id (PBD::ID id) const
return boost::shared_ptr<Processor> ();
}
/** @return the monitoring state, or in other words what data we are pushing
* into the route (data from the inputs, data from disk or silence)
*/
MonitorState
Route::monitoring_state () const
{
return MonitoringInput;
}
/** @return what we should be metering; either the data coming from the input
* IO or the data that is flowing through the route.
*/
MeterState
Route::metering_state () const
{
return MeteringRoute;
}

View File

@ -375,25 +375,25 @@ Track::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame,
*/
be_silent = true;
} else {
be_silent = send_silence ();
MonitorState const s = monitoring_state ();
/* we are not rolling, so be silent even if we are monitoring disk, as there
will be no disk data coming in.
*/
be_silent = (s == MonitoringSilence || s == MonitoringDisk);
}
if (!_have_internal_generator && metering_state() == MeteringInput) {
_input->process_input (_meter, start_frame, end_frame, nframes);
}
_amp->apply_gain_automation(false);
/* if have_internal_generator, or .. */
//_input->process_input (_meter, start_frame, end_frame, nframes);
if (be_silent) {
/* 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);
}
passthru_silence (start_frame, end_frame, nframes, 0);
} else {
@ -774,101 +774,57 @@ Track::adjust_capture_buffering ()
}
}
bool
Track::send_silence () const
{
bool send_silence;
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)
&& ((_monitoring & MonitorInput) || (_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)
&& ((_monitoring & MonitorInput) ||
(!(_monitoring & MonitorDisk) && (_session.config.get_auto_input () || _diskstream->record_enabled())))){
DEBUG_TRACE (DEBUG::Monitor,
string_compose ("%1: no roll, use silence = FALSE, monitoring choice %2 recenable %3 sRA %4 autoinput %5\n",
name(), enum_2_string (_monitoring),
_diskstream->record_enabled(), _session.actively_recording(),
_session.config.get_auto_input()));
send_silence = false;
} else {
DEBUG_TRACE (DEBUG::Monitor,
string_compose ("%1: no roll, use silence = TRUE, monitoring choice %2 recenable %3 sRA %4 autoinput %5\n",
name(), enum_2_string (_monitoring),
_diskstream->record_enabled(), _session.actively_recording(),
_session.config.get_auto_input()));
send_silence = true;
}
}
return send_silence;
}
MonitorState
Track::monitoring_state ()
Track::monitoring_state () const
{
MonitorState ms = MonitoringSilence;
if (_session.transport_rolling()) {
/* Explicit requests */
if (_monitoring & MonitorInput) {
return MonitoringInput;
}
/* roll case */
if (_monitoring & MonitorInput) { // explicitly requested input monitoring
ms = MonitoringInput;
if (_monitoring & MonitorDisk) {
return MonitoringDisk;
}
} else if (_monitoring & MonitorDisk) { // explicitly requested disk monitoring
ms = MonitoringDisk;
/* This is an implementation of the truth table in doc/monitor_modes.pdf;
I don't think it's ever going to be too pretty too look at.
*/
} else if (_diskstream->record_enabled() && _session.actively_recording()) { // Track actually recording
ms = MonitoringInput;
bool const roll = _session.transport_rolling ();
bool const track_rec = _diskstream->record_enabled ();
bool const session_rec = _session.get_record_enabled ();
bool const auto_input = _session.config.get_auto_input ();
bool const software_monitor = Config->get_monitoring_model() == SoftwareMonitoring;
bool const tape_machine_mode = Config->get_tape_machine_mode ();
} else if (_diskstream->record_enabled() && !_session.actively_recording() && _session.config.get_auto_input()) { // Track armed but not recording, with auto input enabled
ms = MonitoringInput;
} else { // Every other state
ms = MonitoringDisk;
if (track_rec) {
if (!session_rec && roll && auto_input) {
return MonitoringDisk;
} else {
return software_monitor ? MonitoringInput : MonitoringSilence;
}
} else {
/* no-roll case */
if (tape_machine_mode) {
return MonitoringDisk;
if (send_silence()) {
ms = MonitoringSilence;
} else {
if (!roll && auto_input) {
return software_monitor ? MonitoringInput : MonitoringSilence;
} else {
return MonitoringDisk;
}
ms = MonitoringInput;
}
}
return ms;
/* NOTREACHED */
return MonitoringSilence;
}
void
@ -954,4 +910,8 @@ Track::parameter_changed (string p)
}
}
MeterState
Track::metering_state () const
{
return _diskstream->record_enabled() ? MeteringInput : MeteringRoute;
}