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