X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fdisk_writer.cc;h=e1997e0bbdb4ab926ecb27153879cda0f947b007;hb=9775c5c9f1b81340f3177ede038f02faed71c887;hp=b5dade0dc11f6c376aa900bfb51c35bda74cb7ca;hpb=7db12f6b128eef0d63dd6a8eda3d04f4dab1fc79;p=ardour.git diff --git a/libs/ardour/disk_writer.cc b/libs/ardour/disk_writer.cc index b5dade0dc1..e1997e0bbd 100644 --- a/libs/ardour/disk_writer.cc +++ b/libs/ardour/disk_writer.cc @@ -50,8 +50,6 @@ DiskWriter::DiskWriter (Session& s, string const & str, DiskIOProcessor::Flag f) , capture_start_sample (0) , capture_captured (0) , was_recording (false) - , adjust_capture_position (0) - , _capture_offset (0) , first_recordable_sample (max_samplepos) , last_recordable_sample (max_samplepos) , last_possibly_recording (0) @@ -88,89 +86,79 @@ DiskWriter::set_write_source_name (string const & str) } void -DiskWriter::check_record_status (samplepos_t transport_sample, bool can_record) +DiskWriter::check_record_status (samplepos_t transport_sample, double speed, bool can_record) { int possibly_recording; - int rolling; - int change; const int transport_rolling = 0x4; const int track_rec_enabled = 0x2; const int global_rec_enabled = 0x1; - const int fully_rec_enabled = (transport_rolling|track_rec_enabled|global_rec_enabled); + const int fully_rec_enabled = (transport_rolling |track_rec_enabled | global_rec_enabled); - /* merge together the 3 factors that affect record status, and compute - * what has changed. - */ + /* merge together the 3 factors that affect record status, and compute what has changed. */ - rolling = _session.transport_speed() != 0.0f; - possibly_recording = (rolling << 2) | ((int)record_enabled() << 1) | (int)can_record; - change = possibly_recording ^ last_possibly_recording; + possibly_recording = (speed != 0.0f ? 4 : 0) | (record_enabled() ? 2 : 0) | (can_record ? 1 : 0); if (possibly_recording == last_possibly_recording) { return; } - const samplecnt_t existing_material_offset = _session.worst_playback_latency(); - if (possibly_recording == fully_rec_enabled) { if (last_possibly_recording == fully_rec_enabled) { return; } - capture_start_sample = _session.transport_sample(); - first_recordable_sample = capture_start_sample + _capture_offset; - last_recordable_sample = max_samplepos; - - DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: @ %7 (%9) FRF = %2 CSF = %4 CO = %5, EMO = %6 RD = %8 WOL %10 WTL %11\n", - name(), first_recordable_sample, last_recordable_sample, capture_start_sample, - _capture_offset, - existing_material_offset, - transport_sample, - _session.transport_sample(), - _session.worst_output_latency(), - _session.worst_track_latency())); - - - if (_alignment_style == ExistingMaterial) { - first_recordable_sample += existing_material_offset; - DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("\tshift FRF by EMO %1\n", - first_recordable_sample)); - } - - prepare_record_status (capture_start_sample); - - } else { + Location* loc; + if (_session.config.get_punch_in () && 0 != (loc = _session.locations()->auto_punch_location ())) { + capture_start_sample = loc->start (); + } else { + capture_start_sample = _session.transport_sample (); + } - if (last_possibly_recording == fully_rec_enabled) { + first_recordable_sample = capture_start_sample; - /* we were recording last time */ + if (_alignment_style == ExistingMaterial) { + first_recordable_sample += _capture_offset + _playback_offset; + } - if (change & transport_rolling) { + if (_session.config.get_punch_out () && 0 != (loc = _session.locations()->auto_punch_location ())) { + /* this freezes the punch-out point when starting to record. + * + * We should allow to move it or at least allow to disable punch-out + * while rolling.. + */ + last_recordable_sample = loc->end (); + if (_alignment_style == ExistingMaterial) { + last_recordable_sample += _capture_offset + _playback_offset; + } + } else { + last_recordable_sample = max_samplepos; + } - /* transport-change (stopped rolling): last_recordable_sample was set in ::prepare_to_stop(). We - * had to set it there because we likely rolled past the stopping point to declick out, - * and then backed up. - */ + DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: @ %2 (STS: %3) CS:%4 FRS: %5 IL: %7, OL: %8 CO: %r9 PO: %10 WOL: %11 WIL: %12\n", + name(), + transport_sample, + _session.transport_sample(), + capture_start_sample, + first_recordable_sample, + last_recordable_sample, + _input_latency, + _output_latency, + _capture_offset, + _playback_offset, + _session.worst_output_latency(), + _session.worst_input_latency())); - } else { - /* punch out */ - last_recordable_sample = _session.transport_sample() + _capture_offset; + prepare_record_status (capture_start_sample); - if (_alignment_style == ExistingMaterial) { - last_recordable_sample += existing_material_offset; - } - } - } } last_possibly_recording = possibly_recording; } void -DiskWriter::calculate_record_range (Evoral::OverlapType ot, samplepos_t transport_sample, samplecnt_t nframes, - samplecnt_t & rec_nframes, samplecnt_t & rec_offset) +DiskWriter::calculate_record_range (Evoral::OverlapType ot, samplepos_t transport_sample, samplecnt_t nframes, samplecnt_t & rec_nframes, samplecnt_t & rec_offset) { switch (ot) { case Evoral::OverlapNone: @@ -212,32 +200,9 @@ DiskWriter::calculate_record_range (Evoral::OverlapType ot, samplepos_t transpor break; } - DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1 rec? %2 @ %3 (for %4) FRF %5 LRF %6 : rf %7 @ %8\n", - _name, enum_2_string (ot), transport_sample, nframes, - first_recordable_sample, last_recordable_sample, rec_nframes, rec_offset)); -} - -void -DiskWriter::prepare_to_stop (samplepos_t transport_sample, samplepos_t audible_sample) -{ - switch (_alignment_style) { - case ExistingMaterial: - last_recordable_sample = transport_sample + _capture_offset; - DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose("%1: prepare to stop sets last recordable sample to %2 + %3 = %4\n", _name, transport_sample, _capture_offset, last_recordable_sample)); - break; - - case CaptureTime: - last_recordable_sample = audible_sample; // note that capture_offset is zero - /* we may already have captured audio before the last_recordable_sample (audible sample), - so deal with this. - */ - if (last_recordable_sample > capture_start_sample) { - capture_captured = min (capture_captured, last_recordable_sample - capture_start_sample); - } - DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose("%1: prepare to stop sets last recordable sample to audible sample @ %2\n", _name, audible_sample)); - break; - } - + DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1 rec? %2 @ %3 (for %4) FRF %5 LRF %6 : rf %7 @ %8\n", + _name, enum_2_string (ot), transport_sample, nframes, + first_recordable_sample, last_recordable_sample, rec_nframes, rec_offset)); } void @@ -293,31 +258,6 @@ DiskWriter::get_captured_samples (uint32_t n) const } } -void -DiskWriter::set_input_latency (samplecnt_t l) -{ - Processor::set_input_latency (l); - set_capture_offset (); -} - -void -DiskWriter::set_capture_offset () -{ - switch (_alignment_style) { - case ExistingMaterial: - _capture_offset = _input_latency; - break; - - case CaptureTime: - default: - _capture_offset = 0; - break; - } - - DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: using input latency %4, capture offset set to %2 with style = %3\n", name(), _capture_offset, enum_2_string (_alignment_style), _input_latency)); -} - - void DiskWriter::set_align_style (AlignStyle a, bool force) { @@ -327,7 +267,6 @@ DiskWriter::set_align_style (AlignStyle a, bool force) if ((a != _alignment_style) || force) { _alignment_style = a; - set_capture_offset (); AlignmentStyleChanged (); } } @@ -369,10 +308,10 @@ DiskWriter::non_realtime_locate (samplepos_t position) void -DiskWriter::prepare_record_status(samplepos_t capture_start_sample) +DiskWriter::prepare_record_status (samplepos_t capture_start_sample) { if (recordable() && destructive()) { - boost::shared_ptr c = channels.reader(); + boost::shared_ptr c = channels.reader (); for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { RingBufferNPT::rw_vector transitions; @@ -404,31 +343,33 @@ void DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool result_required) { + if (!_active && !_pending_active) { + return; + } + _active = _pending_active; + uint32_t n; boost::shared_ptr c = channels.reader(); ChannelList::iterator chan; + samplecnt_t rec_offset = 0; samplecnt_t rec_nframes = 0; bool nominally_recording; + bool re = record_enabled (); + bool punch_in = _session.config.get_punch_in () && _session.locations()->auto_punch_location (); bool can_record = _session.actively_recording (); - - if (_active) { - if (!_pending_active) { - _active = false; - return; - } - } else { - if (_pending_active) { - _active = true; - } else { - return; - } - } + can_record |= speed != 0 && _session.get_record_enabled () && punch_in && _session.transport_sample () <= _session.locations()->auto_punch_location ()->start (); _need_butler = false; - check_record_status (start_sample, can_record); +#ifndef NDEBUG + if (speed != 0 && re) { + DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: run() start: %2 end: %3 NF: %4\n", _name, start_sample, end_sample, nframes)); + } +#endif + + check_record_status (start_sample, speed, can_record); if (nframes == 0) { return; @@ -444,17 +385,15 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp } const Location* const loop_loc = loop_location; - samplepos_t loop_start = 0; - samplepos_t loop_end = 0; - samplepos_t loop_length = 0; + samplepos_t loop_start = 0; + samplepos_t loop_end = 0; + samplepos_t loop_length = 0; if (loop_loc) { get_location_times (loop_loc, &loop_start, &loop_end, &loop_length); } - adjust_capture_position = 0; - - if (nominally_recording || (re && was_recording && _session.get_record_enabled() && (_session.config.get_punch_in() || _session.preroll_record_punch_enabled()))) { + if (nominally_recording || (re && was_recording && _session.get_record_enabled() && punch_in)) { Evoral::OverlapType ot = Evoral::coverage (first_recordable_sample, last_recordable_sample, start_sample, end_sample); // XXX should this be transport_sample + nframes - 1 ? coverage() expects its parameter ranges to include their end points @@ -472,7 +411,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp at the loop start and can handle time wrapping around. Otherwise, start the source right now as usual. */ - capture_captured = start_sample - loop_start; + capture_captured = start_sample - loop_start; capture_start_sample = loop_start; } @@ -480,8 +419,8 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp _midi_write_source->mark_write_starting_now (capture_start_sample, capture_captured, loop_length); } - g_atomic_int_set(const_cast (&_samples_pending_write), 0); - g_atomic_int_set(const_cast (&_num_captured_loops), 0); + g_atomic_int_set (const_cast (&_samples_pending_write), 0); + g_atomic_int_set (const_cast (&_num_captured_loops), 0); was_recording = true; @@ -499,7 +438,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp } - if (can_record && !_last_capture_sources.empty()) { + if (can_record && !_last_capture_sources.empty ()) { _last_capture_sources.clear (); } @@ -526,9 +465,9 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp samplecnt_t total = chaninfo->rw_vector.len[0] + chaninfo->rw_vector.len[1]; if (rec_nframes > total) { - DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 overrun in %2, rec_nframes = %3 total space = %4\n", - DEBUG_THREAD_SELF, name(), rec_nframes, total)); - Overrun (); + DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 overrun in %2, rec_nframes = %3 total space = %4\n", + DEBUG_THREAD_SELF, name(), rec_nframes, total)); + Overrun (); return; } @@ -551,7 +490,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp MidiChannelFilter* filter = mt ? &mt->capture_filter() : 0; for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) { - Evoral::Event ev(*i, false); + Evoral::Event ev (*i, false); if (ev.time() + rec_offset > rec_nframes) { break; } @@ -586,11 +525,25 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp continue; } + bool skip_event = false; + if (mt) { + /* skip injected immediate/out-of-band events */ + MidiBuffer const& ieb (mt->immediate_event_buffer()); + for (MidiBuffer::const_iterator j = ieb.begin(); j != ieb.end(); ++j) { + if (*j == ev) { + skip_event = true; + } + } + } + if (skip_event) { + continue; + } + if (!filter || !filter->filter(ev.buffer(), ev.size())) { _midi_buf->write (event_time, ev.event_type(), ev.size(), ev.buffer()); } } - g_atomic_int_add(const_cast(&_samples_pending_write), nframes); + g_atomic_int_add (const_cast(&_samples_pending_write), nframes); if (buf.size() != 0) { Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex, Glib::Threads::TRY_LOCK); @@ -695,6 +648,16 @@ DiskWriter::finish_capture (boost::shared_ptr c) first_recordable_sample = max_samplepos; } +boost::shared_ptr +DiskWriter::get_gui_feed_buffer () const +{ + boost::shared_ptr b (new MidiBuffer (AudioEngine::instance()->raw_buffer_size (DataType::MIDI))); + + Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex); + b->copy (_gui_feed_buffer); + return b; +} + void DiskWriter::set_record_enabled (bool yn) { @@ -1418,14 +1381,8 @@ DiskWriter::use_destructive_playlist () assert((*chan)->write_source); (*chan)->write_source->set_allow_remove_if_empty (false); - /* this might be false if we switched modes, so force it */ - -#ifdef XXX_OLD_DESTRUCTIVE_API_XXX - (*chan)->write_source->set_destructive (true); -#else // should be set when creating the source or loading the state assert ((*chan)->write_source->destructive()); -#endif } /* the source list will never be reset for a destructive track */