1 /*
2 * Copyright (C) 2017-2018 Robin Gareus <robin@gareus.org>
3 * Copyright (C) 2017 Paul Davis <paul@linuxaudiosystems.com>
4 * Copyright (C) 2018 Ben Loftis <ben@harrisonconsoles.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include <glibmm/datetime.h>
22
23 #include "ardour/analyser.h"
24 #include "ardour/audioengine.h"
25 #include "ardour/audiofilesource.h"
26 #include "ardour/audio_buffer.h"
27 #include "ardour/audioplaylist.h"
28 #include "ardour/audioregion.h"
29 #include "ardour/butler.h"
30 #include "ardour/debug.h"
31 #include "ardour/disk_writer.h"
32 #include "ardour/midi_playlist.h"
33 #include "ardour/midi_source.h"
34 #include "ardour/midi_track.h"
35 #include "ardour/port.h"
36 #include "ardour/region_factory.h"
37 #include "ardour/session.h"
38 #include "ardour/smf_source.h"
39
40 #include "pbd/i18n.h"
41
42 using namespace ARDOUR;
43 using namespace PBD;
44 using namespace std;
45
46 ARDOUR::samplecnt_t DiskWriter::_chunk_samples = DiskWriter::default_chunk_samples ();
47 PBD::Signal0<void> DiskWriter::Overrun;
48
DiskWriter(Session & s,Track & t,string const & str,DiskIOProcessor::Flag f)49 DiskWriter::DiskWriter (Session& s, Track& t, string const & str, DiskIOProcessor::Flag f)
50 : DiskIOProcessor (s, t, X_("recorder:") + str, f)
51 , _capture_start_sample (0)
52 , _capture_captured (0)
53 , _was_recording (false)
54 , _xrun_flag (false)
55 , _first_recordable_sample (max_samplepos)
56 , _last_recordable_sample (max_samplepos)
57 , _last_possibly_recording (0)
58 , _alignment_style (ExistingMaterial)
59 , _note_mode (Sustained)
60 , _accumulated_capture_offset (0)
61 , _transport_looped (false)
62 , _transport_loop_sample (0)
63 , _gui_feed_buffer(AudioEngine::instance()->raw_buffer_size (DataType::MIDI))
64 {
65 DiskIOProcessor::init ();
66 _xruns.reserve (128);
67
68 g_atomic_int_set (&_record_enabled, 0);
69 g_atomic_int_set (&_record_safe, 0);
70 g_atomic_int_set (&_samples_pending_write, 0);
71 g_atomic_int_set (&_num_captured_loops, 0);
72 }
73
~DiskWriter()74 DiskWriter::~DiskWriter ()
75 {
76 DEBUG_TRACE (DEBUG::Destruction, string_compose ("DiskWriter %1 @ %2 deleted\n", _name, this));
77
78 boost::shared_ptr<ChannelList> c = channels.reader();
79
80 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
81 (*chan)->write_source.reset ();
82 }
83 }
84
85 samplecnt_t
default_chunk_samples()86 DiskWriter::default_chunk_samples ()
87 {
88 return 65536;
89 }
90
91 std::string
display_name() const92 DiskWriter::display_name () const
93 {
94 return std::string (_("Recorder"));
95 }
96
97 void
resize(samplecnt_t bufsize)98 DiskWriter::WriterChannelInfo::resize (samplecnt_t bufsize)
99 {
100 if (!capture_transition_buf) {
101 capture_transition_buf = new RingBufferNPT<CaptureTransition> (256);
102 }
103 delete wbuf;
104 wbuf = new RingBufferNPT<Sample> (bufsize);
105 /* touch memory to lock it */
106 memset (wbuf->buffer(), 0, sizeof (Sample) * wbuf->bufsize());
107 }
108
109 int
add_channel_to(boost::shared_ptr<ChannelList> c,uint32_t how_many)110 DiskWriter::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
111 {
112 while (how_many--) {
113 c->push_back (new WriterChannelInfo (_session.butler()->audio_capture_buffer_size()));
114 DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: new writer channel, write space = %2 read = %3\n",
115 name(),
116 c->back()->wbuf->write_space(),
117 c->back()->wbuf->read_space()));
118 }
119
120 return 0;
121 }
122
123 bool
set_write_source_name(string const & str)124 DiskWriter::set_write_source_name (string const & str)
125 {
126 _write_source_name = str;
127
128 reset_write_sources (false);
129
130 return true;
131 }
132
133 std::string
write_source_name() const134 DiskWriter::write_source_name () const
135 {
136 if (!_write_source_name.empty ()) {
137 return _write_source_name;
138 }
139
140 std::string const& n (name ());
141 if (n.find (X_("recorder:")) == 0 && n.size () > 9) {
142 return n.substr (9);
143 }
144 return n;
145 }
146
147 void
check_record_status(samplepos_t transport_sample,double speed,bool can_record)148 DiskWriter::check_record_status (samplepos_t transport_sample, double speed, bool can_record)
149 {
150 int possibly_recording;
151 const int transport_rolling = 0x4;
152 const int track_rec_enabled = 0x2;
153 const int global_rec_enabled = 0x1;
154 const int fully_rec_enabled = (transport_rolling |track_rec_enabled | global_rec_enabled);
155
156 /* merge together the 3 factors that affect record status, and compute what has changed. */
157
158 possibly_recording = (speed != 0.0f ? 4 : 0) | (record_enabled() ? 2 : 0) | (can_record ? 1 : 0);
159
160 if (possibly_recording == _last_possibly_recording) {
161 return;
162 }
163
164 if (possibly_recording == fully_rec_enabled) {
165
166 if (_last_possibly_recording == fully_rec_enabled) {
167 return;
168 }
169
170 Location* loc;
171 if (_session.config.get_punch_in () && 0 != (loc = _session.locations()->auto_punch_location ())) {
172 _capture_start_sample = loc->start ();
173 } else {
174 _capture_start_sample = _session.transport_sample ();
175 }
176
177 _first_recordable_sample = _capture_start_sample;
178
179 if (_alignment_style == ExistingMaterial) {
180 _first_recordable_sample += _capture_offset + _playback_offset;
181 }
182
183 if (_session.config.get_punch_out () && 0 != (loc = _session.locations()->auto_punch_location ())) {
184 /* this freezes the punch-out point when starting to record.
185 *
186 * We should allow to move it or at least allow to disable punch-out
187 * while rolling..
188 */
189 _last_recordable_sample = loc->end ();
190 if (_alignment_style == ExistingMaterial) {
191 _last_recordable_sample += _capture_offset + _playback_offset;
192 }
193 } else {
194 _last_recordable_sample = max_samplepos;
195 }
196
197 DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: @ %2 (STS: %3) CS:%4 FRS: %5 IL: %7, OL: %8 CO: %9 PO: %10 WOL: %11 WIL: %12\n",
198 name(),
199 transport_sample,
200 _session.transport_sample(),
201 _capture_start_sample,
202 _first_recordable_sample,
203 _last_recordable_sample,
204 _input_latency,
205 _output_latency,
206 _capture_offset,
207 _playback_offset,
208 _session.worst_output_latency(),
209 _session.worst_input_latency()));
210
211
212 prepare_record_status (_capture_start_sample);
213
214 }
215
216 _last_possibly_recording = possibly_recording;
217 }
218
219 void
calculate_record_range(Evoral::OverlapType ot,samplepos_t transport_sample,samplecnt_t nframes,samplecnt_t & rec_nframes,samplecnt_t & rec_offset)220 DiskWriter::calculate_record_range (Evoral::OverlapType ot, samplepos_t transport_sample, samplecnt_t nframes, samplecnt_t & rec_nframes, samplecnt_t & rec_offset)
221 {
222 switch (ot) {
223 case Evoral::OverlapNone:
224 rec_nframes = 0;
225 break;
226
227 case Evoral::OverlapInternal:
228 /* ---------- recrange
229 * |---| transrange
230 */
231 rec_nframes = nframes;
232 rec_offset = 0;
233 break;
234
235 case Evoral::OverlapStart:
236 /* |--------| recrange
237 * -----| transrange
238 */
239 rec_nframes = transport_sample + nframes - _first_recordable_sample;
240 if (rec_nframes) {
241 rec_offset = _first_recordable_sample - transport_sample;
242 }
243 break;
244
245 case Evoral::OverlapEnd:
246 /* |--------| recrange
247 * |-------- transrange
248 */
249 rec_nframes = _last_recordable_sample - transport_sample;
250 rec_offset = 0;
251 break;
252
253 case Evoral::OverlapExternal:
254 /* |--------| recrange
255 * -------------- transrange
256 */
257 rec_nframes = _last_recordable_sample - _first_recordable_sample;
258 rec_offset = _first_recordable_sample - transport_sample;
259 break;
260 }
261
262 DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1 rec? %2 @ %3 (for %4) FRF %5 LRF %6 : rf %7 @ %8\n",
263 _name, enum_2_string (ot), transport_sample, nframes,
264 _first_recordable_sample, _last_recordable_sample, rec_nframes, rec_offset));
265 }
266
267 void
engage_record_enable()268 DiskWriter::engage_record_enable ()
269 {
270 g_atomic_int_set (&_record_enabled, 1);
271 }
272
273 void
disengage_record_enable()274 DiskWriter::disengage_record_enable ()
275 {
276 g_atomic_int_set (&_record_enabled, 0);
277 }
278
279 void
engage_record_safe()280 DiskWriter::engage_record_safe ()
281 {
282 g_atomic_int_set (&_record_safe, 1);
283 }
284
285 void
disengage_record_safe()286 DiskWriter::disengage_record_safe ()
287 {
288 g_atomic_int_set (&_record_safe, 0);
289 }
290
291 /** Get the start position (in session samples) of the nth capture in the current pass */
292 ARDOUR::samplepos_t
get_capture_start_sample(uint32_t n) const293 DiskWriter::get_capture_start_sample (uint32_t n) const
294 {
295 Glib::Threads::Mutex::Lock lm (capture_info_lock);
296
297 if (capture_info.size() > n) {
298 /* this is a completed capture */
299 return capture_info[n]->start;
300 } else {
301 /* this is the currently in-progress capture */
302 return _capture_start_sample;
303 }
304 }
305
306 ARDOUR::samplecnt_t
get_captured_samples(uint32_t n) const307 DiskWriter::get_captured_samples (uint32_t n) const
308 {
309 Glib::Threads::Mutex::Lock lm (capture_info_lock);
310
311 if (capture_info.size() > n) {
312 /* this is a completed capture */
313 return capture_info[n]->samples;
314 } else {
315 /* this is the currently in-progress capture */
316 return _capture_captured;
317 }
318 }
319
320 void
set_align_style(AlignStyle a,bool force)321 DiskWriter::set_align_style (AlignStyle a, bool force)
322 {
323 if (record_enabled() && _session.actively_recording()) {
324 return;
325 }
326
327 if ((a != _alignment_style) || force) {
328 _alignment_style = a;
329 AlignmentStyleChanged ();
330 }
331 }
332
333 XMLNode&
state()334 DiskWriter::state ()
335 {
336 XMLNode& node (DiskIOProcessor::state ());
337 node.set_property (X_("type"), X_("diskwriter"));
338 node.set_property (X_("record-safe"), record_safe ());
339 return node;
340 }
341
342 int
set_state(const XMLNode & node,int version)343 DiskWriter::set_state (const XMLNode& node, int version)
344 {
345 if (DiskIOProcessor::set_state (node, version)) {
346 return -1;
347 }
348
349 int rec_safe = 0;
350 node.get_property (X_("record-safe"), rec_safe);
351 g_atomic_int_set (&_record_safe, rec_safe);
352
353 reset_write_sources (false, true);
354
355 return 0;
356 }
357
358 void
non_realtime_locate(samplepos_t position)359 DiskWriter::non_realtime_locate (samplepos_t position)
360 {
361 if (_midi_write_source) {
362 _midi_write_source->set_natural_position (position);
363 }
364
365 DiskIOProcessor::non_realtime_locate (position);
366 }
367
368
369 void
prepare_record_status(samplepos_t _capture_start_sample)370 DiskWriter::prepare_record_status (samplepos_t _capture_start_sample)
371 {
372 }
373
374 /** Do some record stuff [not described in this comment!]
375 *
376 * Also:
377 * - Setup playback_distance with the nframes, or nframes adjusted
378 * for current varispeed, if appropriate.
379 * - Setup current_playback_buffer in each ChannelInfo to point to data
380 * that someone can read playback_distance worth of data from.
381 */
382 void
run(BufferSet & bufs,samplepos_t start_sample,samplepos_t end_sample,double speed,pframes_t nframes,bool result_required)383 DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample,
384 double speed, pframes_t nframes, bool result_required)
385 {
386 if (!_active && !_pending_active) {
387 _xrun_flag = false;
388 return;
389 }
390 _active = _pending_active;
391
392 uint32_t n;
393 boost::shared_ptr<ChannelList> c = channels.reader();
394 ChannelList::iterator chan;
395
396 samplecnt_t rec_offset = 0;
397 samplecnt_t rec_nframes = 0;
398 bool nominally_recording;
399
400 bool re = record_enabled ();
401 bool punch_in = _session.config.get_punch_in () && _session.locations()->auto_punch_location ();
402 bool can_record = _session.actively_recording ();
403 can_record |= speed != 0 && _session.get_record_enabled () && punch_in && _session.transport_sample () <= _session.locations()->auto_punch_location ()->start ();
404
405 _need_butler = false;
406
407 const Location* const loop_loc = _loop_location;
408 samplepos_t loop_start = 0;
409 samplepos_t loop_end = 0;
410 samplepos_t loop_length = 0;
411
412 if (_transport_looped && _capture_captured == 0) {
413 _transport_looped = false;
414 }
415
416 if (loop_loc) {
417 get_location_times (loop_loc, &loop_start, &loop_end, &loop_length);
418
419 if (_was_recording && _transport_looped && _capture_captured >= loop_length) {
420 samplecnt_t remain = _capture_captured - loop_length;
421 _capture_captured = loop_length;
422 loop (_transport_loop_sample);
423 _capture_captured = remain;
424 }
425
426 } else {
427 _transport_looped = false;
428 }
429
430 #ifndef NDEBUG
431 if (speed != 0 && re) {
432 DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: run() start: %2 end: %3 NF: %4\n", _name, start_sample, end_sample, nframes));
433 }
434 #endif
435
436 check_record_status (start_sample, speed, can_record);
437
438 if (nframes == 0) {
439 _xrun_flag = false;
440 return;
441 }
442
443 nominally_recording = (can_record && re);
444
445 // Safeguard against situations where process() goes haywire when autopunching
446 // and last_recordable_sample < first_recordable_sample
447
448 if (_last_recordable_sample < _first_recordable_sample) {
449 _last_recordable_sample = max_samplepos;
450 }
451
452 if (nominally_recording || (re && _was_recording && _session.get_record_enabled() && punch_in)) {
453
454 Evoral::OverlapType ot = Evoral::coverage (_first_recordable_sample, _last_recordable_sample, start_sample, end_sample);
455 // XXX should this be transport_sample + nframes - 1 ? coverage() expects its parameter ranges to include their end points
456 // XXX also, first_recordable_sample & last_recordable_sample may both be == max_samplepos: coverage() will return OverlapNone in that case. Is thak OK?
457 calculate_record_range (ot, start_sample, nframes, rec_nframes, rec_offset);
458
459 DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: this time record %2 of %3 samples, offset %4\n", _name, rec_nframes, nframes, rec_offset));
460
461 if (rec_nframes && !_was_recording) {
462 _capture_captured = 0;
463 _xrun_flag = false;
464
465 if (loop_loc) {
466 /* Loop recording, so pretend the capture started at the loop
467 start rgardless of what time it is now, so the source starts
468 at the loop start and can handle time wrapping around.
469 Otherwise, start the source right now as usual.
470 */
471 _capture_captured = start_sample - loop_start;
472 _capture_start_sample = loop_start;
473 _first_recordable_sample = loop_start;
474 if (_capture_captured > 0) {
475 /* when enabling record while already looping,
476 * zero fill region back to loop-start.
477 */
478 for (chan = c->begin(), n = 0; chan != c->end(); ++chan, ++n) {
479 ChannelInfo* chaninfo (*chan);
480 for (samplecnt_t s = 0; s < _capture_captured; ++s) {
481 chaninfo->wbuf->write_one (0); // TODO: optimize
482 }
483 }
484 }
485 }
486
487 if (_midi_write_source) {
488 _midi_write_source->mark_write_starting_now (_capture_start_sample, _capture_captured, loop_length);
489 }
490
491 g_atomic_int_set (&_samples_pending_write, 0);
492 g_atomic_int_set (&_num_captured_loops, 0);
493
494 _was_recording = true;
495
496 }
497
498 /* For audio: not writing samples to the capture ringbuffer offsets
499 * the recording. For midi: we need to keep track of the record range
500 * and subtract the accumulated difference from the event time.
501 */
502 if (rec_nframes) {
503 _accumulated_capture_offset += rec_offset;
504 } else if (start_sample >= _capture_start_sample) {
505 _accumulated_capture_offset += nframes;
506 }
507
508 }
509
510 if (can_record && !_last_capture_sources.empty ()) {
511 _last_capture_sources.clear ();
512 }
513
514 if (rec_nframes) {
515
516 /* AUDIO */
517
518 const size_t n_buffers = bufs.count().n_audio();
519
520 for (chan = c->begin(), n = 0; chan != c->end(); ++chan, ++n) {
521
522 ChannelInfo* chaninfo (*chan);
523 AudioBuffer& buf (bufs.get_audio (n%n_buffers));
524
525 chaninfo->wbuf->get_write_vector (&chaninfo->rw_vector);
526
527 if (rec_nframes <= (samplecnt_t) chaninfo->rw_vector.len[0]) {
528
529 Sample *incoming = buf.data (rec_offset);
530 memcpy (chaninfo->rw_vector.buf[0], incoming, sizeof (Sample) * rec_nframes);
531
532 } else {
533
534 samplecnt_t total = chaninfo->rw_vector.len[0] + chaninfo->rw_vector.len[1];
535
536 if (rec_nframes > total) {
537 DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 overrun in %2, rec_nframes = %3 total space = %4\n",
538 DEBUG_THREAD_SELF, name(), rec_nframes, total));
539 Overrun ();
540 _xruns.push_back (_capture_captured);
541 _xrun_flag = false;
542 return;
543 }
544
545 Sample *incoming = buf.data (rec_offset);
546 samplecnt_t first = chaninfo->rw_vector.len[0];
547
548 memcpy (chaninfo->rw_vector.buf[0], incoming, sizeof (Sample) * first);
549 memcpy (chaninfo->rw_vector.buf[1], incoming + first, sizeof (Sample) * (rec_nframes - first));
550 }
551
552 chaninfo->wbuf->increment_write_ptr (rec_nframes);
553
554 }
555
556 /* MIDI */
557
558 if (_midi_buf) {
559
560 // Pump entire port buffer into the ring buffer (TODO: split cycles?)
561 MidiBuffer& buf = bufs.get_midi (0);
562 MidiTrack* mt = dynamic_cast<MidiTrack*>(&_track);
563 MidiChannelFilter* filter = mt ? &mt->capture_filter() : 0;
564
565 assert (buf.size() == 0 || _midi_buf);
566
567 for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
568 Evoral::Event<MidiBuffer::TimeType> ev (*i, false);
569 if (ev.time() + rec_offset > rec_nframes) {
570 break;
571 }
572 #ifndef NDEBUG
573 if (DEBUG_ENABLED(DEBUG::MidiIO)) {
574 const uint8_t* __data = ev.buffer();
575 DEBUG_STR_DECL(a);
576 DEBUG_STR_APPEND(a, string_compose ("mididiskstream %1 capture event @ %2 + %3 sz %4 ", this, ev.time(), start_sample, ev.size()));
577 for (size_t i=0; i < ev.size(); ++i) {
578 DEBUG_STR_APPEND(a,hex);
579 DEBUG_STR_APPEND(a,"0x");
580 DEBUG_STR_APPEND(a,(int)__data[i]);
581 DEBUG_STR_APPEND(a,' ');
582 }
583 DEBUG_STR_APPEND(a,'\n');
584 DEBUG_TRACE (DEBUG::MidiIO, DEBUG_STR(a).str());
585 }
586 #endif
587 /* Write events to the capture buffer in samples from session start,
588 but ignoring looping so event time progresses monotonically.
589 The source knows the loop length so it knows exactly where the
590 event occurs in the series of recorded loops and can implement
591 any desirable behaviour. We don't want to send event with
592 transport time here since that way the source can not
593 reconstruct their actual time; future clever MIDI looping should
594 probably be implemented in the source instead of here.
595 */
596 const samplecnt_t loop_offset = g_atomic_int_get (&_num_captured_loops) * loop_length;
597 const samplepos_t event_time = start_sample + loop_offset - _accumulated_capture_offset + ev.time();
598 if (event_time < 0 || event_time < _first_recordable_sample) {
599 /* Event out of range, skip */
600 continue;
601 }
602
603 bool skip_event = false;
604 if (mt) {
605 /* skip injected immediate/out-of-band events */
606 MidiBuffer const& ieb (mt->immediate_event_buffer());
607 for (MidiBuffer::const_iterator j = ieb.begin(); j != ieb.end(); ++j) {
608 if (*j == ev) {
609 skip_event = true;
610 }
611 }
612 }
613 if (skip_event) {
614 continue;
615 }
616
617 if (!filter || !filter->filter(ev.buffer(), ev.size())) {
618 _midi_buf->write (event_time, ev.event_type(), ev.size(), ev.buffer());
619 }
620 }
621
622 g_atomic_int_add (&_samples_pending_write, nframes);
623
624 if (buf.size() != 0) {
625 Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex, Glib::Threads::TRY_LOCK);
626
627 if (lm.locked ()) {
628 /* Copy this data into our GUI feed buffer and tell the GUI
629 that it can read it if it likes.
630 */
631 _gui_feed_buffer.clear ();
632
633 for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
634 /* This may fail if buf is larger than _gui_feed_buffer, but it's not really
635 the end of the world if it does.
636 */
637 _gui_feed_buffer.push_back ((*i).time() + start_sample, Evoral::MIDI_EVENT, (*i).size(), (*i).buffer());
638 }
639 }
640
641 DataRecorded (_midi_write_source); /* EMIT SIGNAL */
642 }
643 }
644
645 if (_xrun_flag) {
646 /* There still are `Port::resampler_quality () -1` samples in the resampler
647 * buffer from before the xrun. */
648 _xruns.push_back (_capture_captured + Port::resampler_quality () - 1);
649 }
650
651 _capture_captured += rec_nframes;
652 DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1 now captured %2 (by %3)\n", name(), _capture_captured, rec_nframes));
653
654 } else {
655
656 /* not recording this time, but perhaps we were before .. */
657
658 if (_was_recording) {
659 finish_capture (c);
660 _accumulated_capture_offset = 0;
661 }
662 }
663
664 /* clear xrun flag */
665 _xrun_flag = false;
666
667 /* AUDIO BUTLER REQUIRED CODE */
668
669 if (_playlists[DataType::AUDIO] && !c->empty()) {
670 if (((samplecnt_t) c->front()->wbuf->read_space() >= _chunk_samples)) {
671 _need_butler = true;
672 }
673 }
674
675 /* MIDI BUTLER REQUIRED CODE */
676
677 if (_playlists[DataType::MIDI] && _midi_buf && (_midi_buf->read_space() >= _midi_buf->bufsize() / 2)) {
678 _need_butler = true;
679 }
680
681 // DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 writer run, needs butler = %2\n", name(), _need_butler));
682 }
683
684 void
finish_capture(boost::shared_ptr<ChannelList> c)685 DiskWriter::finish_capture (boost::shared_ptr<ChannelList> c)
686 {
687 _was_recording = false;
688 _xrun_flag = false;
689 _first_recordable_sample = max_samplepos;
690 _last_recordable_sample = max_samplepos;
691
692 if (_capture_captured == 0) {
693 return;
694 }
695
696 CaptureInfo* ci = new CaptureInfo ();
697
698 ci->start = _capture_start_sample;
699 ci->samples = _capture_captured;
700 ci->xruns = _xruns;
701 _xruns.clear ();
702
703 if (_loop_location) {
704 samplepos_t loop_start = 0;
705 samplepos_t loop_end = 0;
706 samplepos_t loop_length = 0;
707 get_location_times (_loop_location, &loop_start, &loop_end, &loop_length);
708 ci->loop_offset = g_atomic_int_get (&_num_captured_loops) * loop_length;
709 } else {
710 ci->loop_offset = 0;
711 }
712
713 DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("Finish capture, add new CI, %1 + %2\n", ci->start, ci->samples));
714
715 /* XXX theoretical race condition here. Need atomic exchange ?
716 However, the circumstances when this is called right
717 now (either on record-disable or transport_stopped)
718 mean that no actual race exists. I think ...
719 We now have a capture_info_lock, but it is only to be used
720 to synchronize in the transport_stop and the capture info
721 accessors, so that invalidation will not occur (both non-realtime).
722 */
723
724 capture_info.push_back (ci);
725 _capture_captured = 0;
726
727 /* now we've finished a capture, reset first_recordable_sample for next time */
728 _first_recordable_sample = max_samplepos;
729 }
730
731 boost::shared_ptr<MidiBuffer>
get_gui_feed_buffer() const732 DiskWriter::get_gui_feed_buffer () const
733 {
734 boost::shared_ptr<MidiBuffer> b (new MidiBuffer (AudioEngine::instance()->raw_buffer_size (DataType::MIDI)));
735
736 Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex);
737 b->copy (_gui_feed_buffer);
738 return b;
739 }
740
741 void
mark_capture_xrun()742 DiskWriter::mark_capture_xrun ()
743 {
744 _xrun_flag = true;
745 }
746
747 void
set_record_enabled(bool yn)748 DiskWriter::set_record_enabled (bool yn)
749 {
750 if (!recordable() || !_session.record_enabling_legal() || record_safe ()) {
751 return;
752 }
753
754 /* yes, i know that this not proof against race conditions, but its
755 good enough. i think.
756 */
757
758 if (record_enabled() != yn) {
759 if (yn) {
760 engage_record_enable ();
761 } else {
762 disengage_record_enable ();
763 }
764
765 RecordEnableChanged (); /* EMIT SIGNAL */
766 }
767 }
768
769 void
set_record_safe(bool yn)770 DiskWriter::set_record_safe (bool yn)
771 {
772 if (!recordable() || !_session.record_enabling_legal() || channels.reader()->empty()) {
773 return;
774 }
775
776 /* yes, i know that this not proof against race conditions, but its
777 good enough. i think.
778 */
779
780 if (record_safe () != yn) {
781 if (yn) {
782 engage_record_safe ();
783 } else {
784 disengage_record_safe ();
785 }
786
787 RecordSafeChanged (); /* EMIT SIGNAL */
788 }
789 }
790
791 bool
prep_record_enable()792 DiskWriter::prep_record_enable ()
793 {
794 if (!recordable() || !_session.record_enabling_legal() || (channels.reader()->empty() && !_midi_buf) || record_safe ()) { // REQUIRES REVIEW "|| record_safe ()"
795 return false;
796 }
797
798 boost::shared_ptr<ChannelList> c = channels.reader();
799
800 capturing_sources.clear ();
801
802 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
803 capturing_sources.push_back ((*chan)->write_source);
804 Source::Lock lock((*chan)->write_source->mutex());
805 (*chan)->write_source->mark_streaming_write_started (lock);
806 }
807
808 return true;
809 }
810
811 bool
prep_record_disable()812 DiskWriter::prep_record_disable ()
813 {
814 capturing_sources.clear ();
815 return true;
816 }
817
818 float
buffer_load() const819 DiskWriter::buffer_load () const
820 {
821 boost::shared_ptr<ChannelList> c = channels.reader();
822
823 if (c->empty ()) {
824 return 1.0;
825 }
826
827 return (float) ((double) c->front()->wbuf->write_space()/
828 (double) c->front()->wbuf->bufsize());
829 }
830
831 void
set_note_mode(NoteMode m)832 DiskWriter::set_note_mode (NoteMode m)
833 {
834 _note_mode = m;
835
836 boost::shared_ptr<MidiPlaylist> mp = boost::dynamic_pointer_cast<MidiPlaylist> (_playlists[DataType::MIDI]);
837
838 if (mp) {
839 mp->set_note_mode (m);
840 }
841
842 if (_midi_write_source && _midi_write_source->model())
843 _midi_write_source->model()->set_note_mode(m);
844 }
845
846 void
configuration_changed()847 DiskWriter::configuration_changed ()
848 {
849 seek (_session.transport_sample(), false);
850 }
851
852 int
seek(samplepos_t sample,bool)853 DiskWriter::seek (samplepos_t sample, bool /*complete_refill*/)
854 {
855 uint32_t n;
856 ChannelList::iterator chan;
857 boost::shared_ptr<ChannelList> c = channels.reader();
858
859 for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
860 (*chan)->wbuf->reset ();
861 }
862
863 if (_midi_buf) {
864 _midi_buf->reset ();
865 }
866 g_atomic_int_set(&_samples_read_from_ringbuffer, 0);
867 g_atomic_int_set(&_samples_written_to_ringbuffer, 0);
868
869 playback_sample = sample;
870
871 return 0;
872 }
873
874 int
do_flush(RunContext ctxt,bool force_flush)875 DiskWriter::do_flush (RunContext ctxt, bool force_flush)
876 {
877 uint32_t to_write;
878 int32_t ret = 0;
879 RingBufferNPT<Sample>::rw_vector vector;
880 samplecnt_t total;
881
882 vector.buf[0] = 0;
883 vector.buf[1] = 0;
884
885 boost::shared_ptr<ChannelList> c = channels.reader();
886 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
887
888 (*chan)->wbuf->get_read_vector (&vector);
889
890 total = vector.len[0] + vector.len[1];
891
892 if (total == 0 || (total < _chunk_samples && !force_flush && _was_recording)) {
893 goto out;
894 }
895
896 /* if there are 2+ chunks of disk i/o possible for
897 this track, let the caller know so that it can arrange
898 for us to be called again, ASAP.
899
900 if we are forcing a flush, then if there is* any* extra
901 work, let the caller know.
902
903 if we are no longer recording and there is any extra work,
904 let the caller know too.
905 */
906
907 if (total >= 2 * _chunk_samples || ((force_flush || !_was_recording) && total > _chunk_samples)) {
908 ret = 1;
909 }
910
911 to_write = min (_chunk_samples, (samplecnt_t) vector.len[0]);
912
913 if ((!(*chan)->write_source) || (*chan)->write_source->write (vector.buf[0], to_write) != to_write) {
914 error << string_compose(_("AudioDiskstream %1: cannot write to disk"), id()) << endmsg;
915 return -1;
916 }
917
918 (*chan)->wbuf->increment_read_ptr (to_write);
919 (*chan)->curr_capture_cnt += to_write;
920
921 if ((to_write == vector.len[0]) && (total > to_write) && (to_write < _chunk_samples)) {
922
923 /* we wrote all of vector.len[0] but it wasn't an entire
924 disk_write_chunk_samples of data, so arrange for some part
925 of vector.len[1] to be flushed to disk as well.
926 */
927
928 to_write = min ((samplecnt_t)(_chunk_samples - to_write), (samplecnt_t) vector.len[1]);
929
930 DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 additional write of %2\n", name(), to_write));
931
932 if ((*chan)->write_source->write (vector.buf[1], to_write) != to_write) {
933 error << string_compose(_("AudioDiskstream %1: cannot write to disk"), id()) << endmsg;
934 return -1;
935 }
936
937 (*chan)->wbuf->increment_read_ptr (to_write);
938 (*chan)->curr_capture_cnt += to_write;
939 }
940 }
941
942 /* MIDI*/
943
944 if (_midi_write_source && _midi_buf) {
945
946 const samplecnt_t total = g_atomic_int_get(&_samples_pending_write);
947
948 if (total == 0 ||
949 _midi_buf->read_space() == 0 ||
950 (!force_flush && (total < _chunk_samples) && _was_recording)) {
951 goto out;
952 }
953
954 /* if there are 2+ chunks of disk i/o possible for
955 this track), let the caller know so that it can arrange
956 for us to be called again, ASAP.
957
958 if we are forcing a flush, then if there is* any* extra
959 work, let the caller know.
960
961 if we are no longer recording and there is any extra work,
962 let the caller know too.
963 */
964
965 if (total >= 2 * _chunk_samples || ((force_flush || !_was_recording) && total > _chunk_samples)) {
966 ret = 1;
967 }
968
969 if (force_flush) {
970 /* push out everything we have, right now */
971 to_write = UINT32_MAX;
972 } else {
973 to_write = _chunk_samples;
974 }
975
976 if ((total > _chunk_samples) || force_flush) {
977 Source::Lock lm(_midi_write_source->mutex());
978 if (_midi_write_source->midi_write (lm, *_midi_buf, get_capture_start_sample (0), to_write) != to_write) {
979 error << string_compose(_("MidiDiskstream %1: cannot write to disk"), id()) << endmsg;
980 return -1;
981 }
982 g_atomic_int_add(&_samples_pending_write, -to_write);
983 }
984 }
985
986 out:
987 return ret;
988
989 }
990
991 void
reset_write_sources(bool mark_write_complete,bool)992 DiskWriter::reset_write_sources (bool mark_write_complete, bool /*force*/)
993 {
994 ChannelList::iterator chan;
995 boost::shared_ptr<ChannelList> c = channels.reader();
996 uint32_t n;
997
998 if (!_session.writable() || !recordable()) {
999 return;
1000 }
1001
1002 capturing_sources.clear ();
1003
1004 for (chan = c->begin(), n = 0; chan != c->end(); ++chan, ++n) {
1005
1006 if ((*chan)->write_source) {
1007
1008 if (mark_write_complete) {
1009 Source::Lock lock((*chan)->write_source->mutex());
1010 (*chan)->write_source->mark_streaming_write_completed (lock);
1011 (*chan)->write_source->done_with_peakfile_writes ();
1012 }
1013
1014 if ((*chan)->write_source->removable()) {
1015 (*chan)->write_source->mark_for_remove ();
1016 (*chan)->write_source->drop_references ();
1017 }
1018
1019 (*chan)->write_source.reset ();
1020 }
1021
1022 use_new_write_source (DataType::AUDIO, n);
1023
1024 if (record_enabled()) {
1025 capturing_sources.push_back ((*chan)->write_source);
1026 }
1027 }
1028
1029 if (_midi_write_source) {
1030 if (mark_write_complete) {
1031 Source::Lock lm(_midi_write_source->mutex());
1032 _midi_write_source->mark_streaming_write_completed (lm);
1033 }
1034 }
1035
1036 if (_playlists[DataType::MIDI]) {
1037 use_new_write_source (DataType::MIDI);
1038 }
1039 }
1040
1041 int
use_new_write_source(DataType dt,uint32_t n)1042 DiskWriter::use_new_write_source (DataType dt, uint32_t n)
1043 {
1044 _accumulated_capture_offset = 0;
1045
1046 if (dt == DataType::MIDI) {
1047 _midi_write_source.reset();
1048
1049 try {
1050 _midi_write_source = boost::dynamic_pointer_cast<SMFSource>(
1051 _session.create_midi_source_for_session (write_source_name ()));
1052
1053 if (!_midi_write_source) {
1054 throw failed_constructor();
1055 }
1056 }
1057
1058 catch (failed_constructor &err) {
1059 error << string_compose (_("%1:%2 new capture file not initialized correctly"), _name, n) << endmsg;
1060 _midi_write_source.reset();
1061 return -1;
1062 }
1063 } else {
1064 boost::shared_ptr<ChannelList> c = channels.reader();
1065
1066 if (!recordable()) {
1067 return 1;
1068 }
1069
1070 if (n >= c->size()) {
1071 error << string_compose (_("AudioDiskstream: channel %1 out of range"), n) << endmsg;
1072 return -1;
1073 }
1074
1075 ChannelInfo* chan = (*c)[n];
1076
1077 try {
1078 if ((chan->write_source = _session.create_audio_source_for_session (
1079 c->size(), write_source_name(), n)) == 0) {
1080 throw failed_constructor();
1081 }
1082 }
1083
1084 catch (failed_constructor &err) {
1085 error << string_compose (_("%1:%2 new capture file not initialized correctly"), _name, n) << endmsg;
1086 chan->write_source.reset ();
1087 return -1;
1088 }
1089
1090 chan->write_source->set_allow_remove_if_empty (true);
1091 }
1092
1093 return 0;
1094 }
1095
1096 void
transport_stopped_wallclock(struct tm & when,time_t twhen,bool abort_capture)1097 DiskWriter::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abort_capture)
1098 {
1099 bool more_work = true;
1100 int err = 0;
1101 samplecnt_t total_capture;
1102 SourceList audio_srcs;
1103 SourceList midi_srcs;
1104 ChannelList::iterator chan;
1105 vector<CaptureInfo*>::iterator ci;
1106 boost::shared_ptr<ChannelList> c = channels.reader();
1107 uint32_t n = 0;
1108 bool mark_write_completed = false;
1109
1110 finish_capture (c);
1111
1112
1113 /* butler is already stopped, but there may be work to do
1114 to flush remaining data to disk.
1115 */
1116
1117 while (more_work && !err) {
1118 switch (do_flush (TransportContext, true)) {
1119 case 0:
1120 more_work = false;
1121 break;
1122 case 1:
1123 break;
1124 case -1:
1125 error << string_compose(_("AudioDiskstream \"%1\": cannot flush captured data to disk!"), _name) << endmsg;
1126 err++;
1127 }
1128 }
1129
1130 /* XXX is there anything we can do if err != 0 ? */
1131 Glib::Threads::Mutex::Lock lm (capture_info_lock);
1132
1133 if (capture_info.empty()) {
1134 return;
1135 }
1136
1137 if (abort_capture) {
1138 _xruns.clear ();
1139
1140 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
1141
1142 if ((*chan)->write_source) {
1143
1144 (*chan)->write_source->mark_for_remove ();
1145 (*chan)->write_source->drop_references ();
1146 (*chan)->write_source.reset ();
1147 }
1148
1149 /* new source set up in "out" below */
1150 }
1151
1152 if (_midi_write_source) {
1153 _midi_write_source->mark_for_remove ();
1154 _midi_write_source->drop_references ();
1155 _midi_write_source.reset();
1156 }
1157
1158 goto out;
1159 }
1160
1161 for (total_capture = 0, ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
1162 total_capture += (*ci)->samples;
1163 }
1164
1165 /* figure out the name for this take */
1166
1167 for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
1168
1169 boost::shared_ptr<AudioFileSource> as = (*chan)->write_source;
1170
1171 if (as) {
1172 audio_srcs.push_back (as);
1173 as->update_header (capture_info.front()->start, when, twhen);
1174 as->set_captured_for (_track.name());
1175 as->mark_immutable ();
1176
1177 Glib::DateTime tm (Glib::DateTime::create_now_local (mktime (&when)));
1178 as->set_take_id (tm.format ("%F %H.%M.%S"));
1179
1180 if (Config->get_auto_analyse_audio()) {
1181 Analyser::queue_source_for_analysis (as, true);
1182 }
1183
1184 DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("newly captured source %1 length %2\n", as->path(), as->length (0)));
1185 }
1186
1187 if (_midi_write_source) {
1188 midi_srcs.push_back (_midi_write_source);
1189 _midi_write_source->set_captured_for (_track.name());
1190 }
1191
1192 (*chan)->write_source->stamp (twhen);
1193 (*chan)->write_source->set_captured_xruns (capture_info.front()->xruns);
1194 }
1195
1196
1197 /* MIDI */
1198
1199 if (_midi_write_source) {
1200
1201 if (_midi_write_source->length (capture_info.front()->start) == 0) {
1202 /* No data was recorded, so this capture will
1203 effectively be aborted; do the same as we
1204 do for an explicit abort.
1205 */
1206 if (_midi_write_source) {
1207 _midi_write_source->mark_for_remove ();
1208 _midi_write_source->drop_references ();
1209 _midi_write_source.reset();
1210 }
1211
1212 goto out;
1213 }
1214
1215 /* phew, we have data */
1216
1217 Source::Lock source_lock(_midi_write_source->mutex());
1218
1219 /* figure out the name for this take */
1220
1221 midi_srcs.push_back (_midi_write_source);
1222
1223 _midi_write_source->set_natural_position (capture_info.front()->start);
1224 _midi_write_source->set_captured_for (_track.name ());
1225
1226 Glib::DateTime tm (Glib::DateTime::create_now_local (mktime (&when)));
1227 _midi_write_source->set_take_id (tm.format ("%F %H.%M.%S"));
1228
1229 /* set length in beats to entire capture length */
1230
1231 BeatsSamplesConverter converter (_session.tempo_map(), capture_info.front()->start);
1232 const Temporal::Beats total_capture_beats = converter.from (total_capture);
1233 _midi_write_source->set_length_beats (total_capture_beats);
1234
1235 /* flush to disk: this step differs from the audio path,
1236 where all the data is already on disk.
1237 */
1238
1239 _midi_write_source->mark_midi_streaming_write_completed (source_lock, Evoral::Sequence<Temporal::Beats>::ResolveStuckNotes, total_capture_beats);
1240 }
1241
1242 _last_capture_sources.insert (_last_capture_sources.end(), audio_srcs.begin(), audio_srcs.end());
1243 _last_capture_sources.insert (_last_capture_sources.end(), midi_srcs.begin(), midi_srcs.end());
1244
1245
1246 _track.use_captured_sources (audio_srcs, capture_info);
1247 _track.use_captured_sources (midi_srcs, capture_info);
1248
1249 mark_write_completed = true;
1250
1251 out:
1252 reset_write_sources (mark_write_completed);
1253
1254 for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
1255 delete *ci;
1256 }
1257
1258 capture_info.clear ();
1259 _capture_start_sample = 0;
1260 }
1261
1262 void
transport_looped(samplepos_t transport_sample)1263 DiskWriter::transport_looped (samplepos_t transport_sample)
1264 {
1265 if (_capture_captured) {
1266 _transport_looped = true;
1267 _transport_loop_sample = transport_sample;
1268 }
1269 }
1270
1271 void
loop(samplepos_t transport_sample)1272 DiskWriter::loop (samplepos_t transport_sample)
1273 {
1274 _transport_looped = false;
1275 if (_was_recording) {
1276 // all we need to do is finish this capture, with modified capture length
1277 boost::shared_ptr<ChannelList> c = channels.reader();
1278
1279 finish_capture (c);
1280
1281 // the next region will start recording via the normal mechanism
1282 // we'll set the start position to the current transport pos
1283 // no latency adjustment or capture offset needs to be made, as that already happened the first time
1284 _capture_start_sample = transport_sample;
1285 _first_recordable_sample = transport_sample; // mild lie
1286 _last_recordable_sample = max_samplepos;
1287 _was_recording = true;
1288 }
1289
1290 /* Here we only keep track of the number of captured loops so monotonic
1291 event times can be delivered to the write source in process(). Trying
1292 to be clever here is a world of trouble, it is better to simply record
1293 the input in a straightforward non-destructive way. In the future when
1294 we want to implement more clever MIDI looping modes it should be done in
1295 the Source and/or entirely after the capture is finished.
1296 */
1297 if (_was_recording) {
1298 g_atomic_int_add (&_num_captured_loops, 1);
1299 }
1300 }
1301
1302 void
adjust_buffering()1303 DiskWriter::adjust_buffering ()
1304 {
1305 boost::shared_ptr<ChannelList> c = channels.reader();
1306
1307 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
1308 (*chan)->resize (_session.butler()->audio_capture_buffer_size());
1309 }
1310 }
1311
1312 void
realtime_handle_transport_stopped()1313 DiskWriter::realtime_handle_transport_stopped ()
1314 {
1315 }
1316
1317 bool
set_name(string const & str)1318 DiskWriter::set_name (string const & str)
1319 {
1320 string my_name = X_("recorder:");
1321 my_name += str;
1322
1323 if (_name != my_name) {
1324 SessionObject::set_name (my_name);
1325 }
1326
1327 return true;
1328 }
1329
1330 std::string
steal_write_source_name()1331 DiskWriter::steal_write_source_name ()
1332 {
1333 if (_playlists[DataType::MIDI]) {
1334 string our_old_name = _midi_write_source->name();
1335
1336 /* this will bump the name of the current write source to the next one
1337 * (e.g. "MIDI 1-1" gets renamed to "MIDI 1-2"), thus leaving the
1338 * current write source name (e.g. "MIDI 1-1" available). See the
1339 * comments in Session::create_midi_source_by_stealing_name() about why
1340 * we do this.
1341 */
1342
1343 try {
1344 string new_path = _session.new_midi_source_path (write_source_name ());
1345
1346 if (_midi_write_source->rename (new_path)) {
1347 return string();
1348 }
1349 } catch (...) {
1350 return string ();
1351 }
1352
1353 return our_old_name;
1354 }
1355
1356 return std::string();
1357 }
1358
1359 bool
configure_io(ChanCount in,ChanCount out)1360 DiskWriter::configure_io (ChanCount in, ChanCount out)
1361 {
1362 bool changed = false;
1363 {
1364 boost::shared_ptr<ChannelList> c = channels.reader();
1365 if (in.n_audio() != c->size()) {
1366 changed = true;
1367 }
1368 if ((0 == in.n_midi ()) != (0 == _midi_buf)) {
1369 changed = true;
1370 }
1371 }
1372
1373
1374 if (!DiskIOProcessor::configure_io (in, out)) {
1375 return false;
1376 }
1377
1378 if (record_enabled() || changed) {
1379 reset_write_sources (false, true);
1380 }
1381
1382 return true;
1383 }
1384
1385 int
use_playlist(DataType dt,boost::shared_ptr<Playlist> playlist)1386 DiskWriter::use_playlist (DataType dt, boost::shared_ptr<Playlist> playlist)
1387 {
1388 bool reset_ws = _playlists[dt] != playlist;
1389
1390 if (DiskIOProcessor::use_playlist (dt, playlist)) {
1391 return -1;
1392 }
1393 if (reset_ws) {
1394 reset_write_sources (false, true);
1395 }
1396 return 0;
1397 }
1398