Disk I/O: only allocate midi-buffer if needed
[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                 assert (buf.size() == 0 || _midi_buf);
521
522                 for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
523                         Evoral::Event<MidiBuffer::TimeType> ev (*i, false);
524                         if (ev.time() + rec_offset > rec_nframes) {
525                                 break;
526                         }
527 #ifndef NDEBUG
528                         if (DEBUG_ENABLED(DEBUG::MidiIO)) {
529                                 const uint8_t* __data = ev.buffer();
530                                 DEBUG_STR_DECL(a);
531                                 DEBUG_STR_APPEND(a, string_compose ("mididiskstream %1 capture event @ %2 + %3 sz %4 ", this, ev.time(), start_sample, ev.size()));
532                                 for (size_t i=0; i < ev.size(); ++i) {
533                                         DEBUG_STR_APPEND(a,hex);
534                                         DEBUG_STR_APPEND(a,"0x");
535                                         DEBUG_STR_APPEND(a,(int)__data[i]);
536                                         DEBUG_STR_APPEND(a,' ');
537                                 }
538                                 DEBUG_STR_APPEND(a,'\n');
539                                 DEBUG_TRACE (DEBUG::MidiIO, DEBUG_STR(a).str());
540                         }
541 #endif
542                         /* Write events to the capture buffer in samples from session start,
543                            but ignoring looping so event time progresses monotonically.
544                            The source knows the loop length so it knows exactly where the
545                            event occurs in the series of recorded loops and can implement
546                            any desirable behaviour.  We don't want to send event with
547                            transport time here since that way the source can not
548                            reconstruct their actual time; future clever MIDI looping should
549                            probably be implemented in the source instead of here.
550                         */
551                         const samplecnt_t loop_offset = _num_captured_loops * loop_length;
552                         const samplepos_t event_time = start_sample + loop_offset - _accumulated_capture_offset + ev.time();
553                         if (event_time < 0 || event_time < first_recordable_sample) {
554                                 /* Event out of range, skip */
555                                 continue;
556                         }
557
558                         bool skip_event = false;
559                         if (mt) {
560                                 /* skip injected immediate/out-of-band events */
561                                 MidiBuffer const& ieb (mt->immediate_event_buffer());
562                                 for (MidiBuffer::const_iterator j = ieb.begin(); j != ieb.end(); ++j) {
563                                         if (*j == ev) {
564                                                 skip_event = true;
565                                         }
566                                 }
567                         }
568                         if (skip_event) {
569                                 continue;
570                         }
571
572                         if (!filter || !filter->filter(ev.buffer(), ev.size())) {
573                                 _midi_buf->write (event_time, ev.event_type(), ev.size(), ev.buffer());
574                         }
575                 }
576
577                 g_atomic_int_add (const_cast<gint*>(&_samples_pending_write), nframes);
578
579                 if (buf.size() != 0) {
580                         Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex, Glib::Threads::TRY_LOCK);
581
582                         if (lm.locked ()) {
583                                 /* Copy this data into our GUI feed buffer and tell the GUI
584                                    that it can read it if it likes.
585                                 */
586                                 _gui_feed_buffer.clear ();
587
588                                 for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
589                                         /* This may fail if buf is larger than _gui_feed_buffer, but it's not really
590                                            the end of the world if it does.
591                                         */
592                                         _gui_feed_buffer.push_back ((*i).time() + start_sample, (*i).size(), (*i).buffer());
593                                 }
594                         }
595
596                         DataRecorded (_midi_write_source); /* EMIT SIGNAL */
597                 }
598
599                 capture_captured += rec_nframes;
600                 DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1 now captured %2 (by %3)\n", name(), capture_captured, rec_nframes));
601
602         } else {
603
604                 /* not recording this time, but perhaps we were before .. */
605
606                 if (was_recording) {
607                         finish_capture (c);
608                         _accumulated_capture_offset = 0;
609                 }
610         }
611
612         /* AUDIO BUTLER REQUIRED CODE */
613
614         if (_playlists[DataType::AUDIO] && !c->empty()) {
615                 if (((samplecnt_t) c->front()->wbuf->read_space() >= _chunk_samples)) {
616                         _need_butler = true;
617                 }
618         }
619
620         /* MIDI BUTLER REQUIRED CODE */
621
622         if (_playlists[DataType::MIDI] && (_midi_buf->read_space() < _midi_buf->bufsize() / 2)) {
623                 _need_butler = true;
624         }
625
626         // DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 writer run, needs butler = %2\n", name(), _need_butler));
627 }
628
629 void
630 DiskWriter::finish_capture (boost::shared_ptr<ChannelList> c)
631 {
632         was_recording = false;
633         first_recordable_sample = max_samplepos;
634         last_recordable_sample = max_samplepos;
635
636         if (capture_captured == 0) {
637                 return;
638         }
639
640         if (recordable() && destructive()) {
641                 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
642
643                         RingBufferNPT<CaptureTransition>::rw_vector transvec;
644                         (*chan)->capture_transition_buf->get_write_vector(&transvec);
645
646                         if (transvec.len[0] > 0) {
647                                 transvec.buf[0]->type = CaptureEnd;
648                                 transvec.buf[0]->capture_val = capture_captured;
649                                 (*chan)->capture_transition_buf->increment_write_ptr(1);
650                         }
651                         else {
652                                 // bad!
653                                 fatal << string_compose (_("programmer error: %1"), X_("capture_transition_buf is full when stopping record!  inconceivable!")) << endmsg;
654                         }
655                 }
656         }
657
658
659         CaptureInfo* ci = new CaptureInfo;
660
661         ci->start =  capture_start_sample;
662         ci->samples = capture_captured;
663
664         DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("Finish capture, add new CI, %1 + %2\n", ci->start, ci->samples));
665
666         /* XXX theoretical race condition here. Need atomic exchange ?
667            However, the circumstances when this is called right
668            now (either on record-disable or transport_stopped)
669            mean that no actual race exists. I think ...
670            We now have a capture_info_lock, but it is only to be used
671            to synchronize in the transport_stop and the capture info
672            accessors, so that invalidation will not occur (both non-realtime).
673         */
674
675         capture_info.push_back (ci);
676         capture_captured = 0;
677
678         /* now we've finished a capture, reset first_recordable_sample for next time */
679         first_recordable_sample = max_samplepos;
680 }
681
682 boost::shared_ptr<MidiBuffer>
683 DiskWriter::get_gui_feed_buffer () const
684 {
685         boost::shared_ptr<MidiBuffer> b (new MidiBuffer (AudioEngine::instance()->raw_buffer_size (DataType::MIDI)));
686
687         Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex);
688         b->copy (_gui_feed_buffer);
689         return b;
690 }
691
692 void
693 DiskWriter::set_record_enabled (bool yn)
694 {
695         if (!recordable() || !_session.record_enabling_legal() || record_safe ()) {
696                 return;
697         }
698
699         /* can't rec-enable in destructive mode if transport is before start */
700
701         if (destructive() && yn && _session.transport_sample() < _session.current_start_sample()) {
702                 return;
703         }
704
705         /* yes, i know that this not proof against race conditions, but its
706            good enough. i think.
707         */
708
709         if (record_enabled() != yn) {
710                 if (yn) {
711                         engage_record_enable ();
712                 } else {
713                         disengage_record_enable ();
714                 }
715
716                 RecordEnableChanged (); /* EMIT SIGNAL */
717         }
718 }
719
720 void
721 DiskWriter::set_record_safe (bool yn)
722 {
723         if (!recordable() || !_session.record_enabling_legal() || channels.reader()->empty()) {
724                 return;
725         }
726
727         /* can't rec-safe in destructive mode if transport is before start ????
728          REQUIRES REVIEW */
729
730         if (destructive() && yn && _session.transport_sample() < _session.current_start_sample()) {
731                 return;
732         }
733
734         /* yes, i know that this not proof against race conditions, but its
735          good enough. i think.
736          */
737
738         if (record_safe () != yn) {
739                 if (yn) {
740                         engage_record_safe ();
741                 } else {
742                         disengage_record_safe ();
743                 }
744
745                 RecordSafeChanged (); /* EMIT SIGNAL */
746         }
747 }
748
749 bool
750 DiskWriter::prep_record_enable ()
751 {
752         if (!recordable() || !_session.record_enabling_legal() || channels.reader()->empty() || record_safe ()) { // REQUIRES REVIEW "|| record_safe ()"
753                 return false;
754         }
755
756         /* can't rec-enable in destructive mode if transport is before start */
757
758         if (destructive() && _session.transport_sample() < _session.current_start_sample()) {
759                 return false;
760         }
761
762         boost::shared_ptr<ChannelList> c = channels.reader();
763
764         capturing_sources.clear ();
765
766         for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
767                 capturing_sources.push_back ((*chan)->write_source);
768                 Source::Lock lock((*chan)->write_source->mutex());
769                 (*chan)->write_source->mark_streaming_write_started (lock);
770         }
771
772         return true;
773 }
774
775 bool
776 DiskWriter::prep_record_disable ()
777 {
778         capturing_sources.clear ();
779         return true;
780 }
781
782 float
783 DiskWriter::buffer_load () const
784 {
785         boost::shared_ptr<ChannelList> c = channels.reader();
786
787         if (c->empty ()) {
788                 return 1.0;
789         }
790
791         return (float) ((double) c->front()->wbuf->write_space()/
792                         (double) c->front()->wbuf->bufsize());
793 }
794
795 void
796 DiskWriter::set_note_mode (NoteMode m)
797 {
798         _note_mode = m;
799
800         boost::shared_ptr<MidiPlaylist> mp = boost::dynamic_pointer_cast<MidiPlaylist> (_playlists[DataType::MIDI]);
801
802         if (mp) {
803                 mp->set_note_mode (m);
804         }
805
806         if (_midi_write_source && _midi_write_source->model())
807                 _midi_write_source->model()->set_note_mode(m);
808 }
809
810 int
811 DiskWriter::seek (samplepos_t sample, bool complete_refill)
812 {
813         uint32_t n;
814         ChannelList::iterator chan;
815         boost::shared_ptr<ChannelList> c = channels.reader();
816
817         for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
818                 (*chan)->wbuf->reset ();
819         }
820
821         if (_midi_buf) {
822                 _midi_buf->reset ();
823         }
824         g_atomic_int_set(&_samples_read_from_ringbuffer, 0);
825         g_atomic_int_set(&_samples_written_to_ringbuffer, 0);
826
827         /* can't rec-enable in destructive mode if transport is before start */
828
829         if (destructive() && record_enabled() && sample < _session.current_start_sample()) {
830                 disengage_record_enable ();
831         }
832
833         playback_sample = sample;
834
835         return 0;
836 }
837
838 int
839 DiskWriter::do_flush (RunContext ctxt, bool force_flush)
840 {
841         uint32_t to_write;
842         int32_t ret = 0;
843         RingBufferNPT<Sample>::rw_vector vector;
844         RingBufferNPT<CaptureTransition>::rw_vector transvec;
845         samplecnt_t total;
846
847         transvec.buf[0] = 0;
848         transvec.buf[1] = 0;
849         vector.buf[0] = 0;
850         vector.buf[1] = 0;
851
852         boost::shared_ptr<ChannelList> c = channels.reader();
853         for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
854
855                 (*chan)->wbuf->get_read_vector (&vector);
856
857                 total = vector.len[0] + vector.len[1];
858
859                 if (total == 0 || (total < _chunk_samples && !force_flush && was_recording)) {
860                         goto out;
861                 }
862
863                 /* if there are 2+ chunks of disk i/o possible for
864                    this track, let the caller know so that it can arrange
865                    for us to be called again, ASAP.
866
867                    if we are forcing a flush, then if there is* any* extra
868                    work, let the caller know.
869
870                    if we are no longer recording and there is any extra work,
871                    let the caller know too.
872                 */
873
874                 if (total >= 2 * _chunk_samples || ((force_flush || !was_recording) && total > _chunk_samples)) {
875                         ret = 1;
876                 }
877
878                 to_write = min (_chunk_samples, (samplecnt_t) vector.len[0]);
879
880                 // check the transition buffer when recording destructive
881                 // important that we get this after the capture buf
882
883                 if (destructive()) {
884                         (*chan)->capture_transition_buf->get_read_vector(&transvec);
885                         size_t transcount = transvec.len[0] + transvec.len[1];
886                         size_t ti;
887
888                         for (ti=0; ti < transcount; ++ti) {
889                                 CaptureTransition & captrans = (ti < transvec.len[0]) ? transvec.buf[0][ti] : transvec.buf[1][ti-transvec.len[0]];
890
891                                 if (captrans.type == CaptureStart) {
892                                         // by definition, the first data we got above represents the given capture pos
893
894                                         (*chan)->write_source->mark_capture_start (captrans.capture_val);
895                                         (*chan)->curr_capture_cnt = 0;
896
897                                 } else if (captrans.type == CaptureEnd) {
898
899                                         // capture end, the capture_val represents total samples in capture
900
901                                         if (captrans.capture_val <= (*chan)->curr_capture_cnt + to_write) {
902
903                                                 // shorten to make the write a perfect fit
904                                                 uint32_t nto_write = (captrans.capture_val - (*chan)->curr_capture_cnt);
905
906                                                 if (nto_write < to_write) {
907                                                         ret = 1; // should we?
908                                                 }
909                                                 to_write = nto_write;
910
911                                                 (*chan)->write_source->mark_capture_end ();
912
913                                                 // increment past this transition, but go no further
914                                                 ++ti;
915                                                 break;
916                                         }
917                                         else {
918                                                 // actually ends just beyond this chunk, so force more work
919                                                 ret = 1;
920                                                 break;
921                                         }
922                                 }
923                         }
924
925                         if (ti > 0) {
926                                 (*chan)->capture_transition_buf->increment_read_ptr(ti);
927                         }
928                 }
929
930                 if ((!(*chan)->write_source) || (*chan)->write_source->write (vector.buf[0], to_write) != to_write) {
931                         error << string_compose(_("AudioDiskstream %1: cannot write to disk"), id()) << endmsg;
932                         return -1;
933                 }
934
935                 (*chan)->wbuf->increment_read_ptr (to_write);
936                 (*chan)->curr_capture_cnt += to_write;
937
938                 if ((to_write == vector.len[0]) && (total > to_write) && (to_write < _chunk_samples) && !destructive()) {
939
940                         /* we wrote all of vector.len[0] but it wasn't an entire
941                            disk_write_chunk_samples of data, so arrange for some part
942                            of vector.len[1] to be flushed to disk as well.
943                         */
944
945                         to_write = min ((samplecnt_t)(_chunk_samples - to_write), (samplecnt_t) vector.len[1]);
946
947                         DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 additional write of %2\n", name(), to_write));
948
949                         if ((*chan)->write_source->write (vector.buf[1], to_write) != to_write) {
950                                 error << string_compose(_("AudioDiskstream %1: cannot write to disk"), id()) << endmsg;
951                                 return -1;
952                         }
953
954                         (*chan)->wbuf->increment_read_ptr (to_write);
955                         (*chan)->curr_capture_cnt += to_write;
956                 }
957         }
958
959         /* MIDI*/
960
961         if (_midi_write_source && _midi_buf) {
962
963                 const samplecnt_t total = g_atomic_int_get(const_cast<gint*> (&_samples_pending_write));
964
965                 if (total == 0 ||
966                     _midi_buf->read_space() == 0 ||
967                     (!force_flush && (total < _chunk_samples) && was_recording)) {
968                         goto out;
969                 }
970
971                 /* if there are 2+ chunks of disk i/o possible for
972                    this track), let the caller know so that it can arrange
973                    for us to be called again, ASAP.
974
975                    if we are forcing a flush, then if there is* any* extra
976                    work, let the caller know.
977
978                    if we are no longer recording and there is any extra work,
979                    let the caller know too.
980                 */
981
982                 if (total >= 2 * _chunk_samples || ((force_flush || !was_recording) && total > _chunk_samples)) {
983                         ret = 1;
984                 }
985
986                 if (force_flush) {
987                         /* push out everything we have, right now */
988                         to_write = UINT32_MAX;
989                 } else {
990                         to_write = _chunk_samples;
991                 }
992
993                 if (record_enabled() && ((total > _chunk_samples) || force_flush)) {
994                         Source::Lock lm(_midi_write_source->mutex());
995                         if (_midi_write_source->midi_write (lm, *_midi_buf, get_capture_start_sample (0), to_write) != to_write) {
996                                 error << string_compose(_("MidiDiskstream %1: cannot write to disk"), id()) << endmsg;
997                                 return -1;
998                         }
999                         g_atomic_int_add(const_cast<gint*> (&_samples_pending_write), -to_write);
1000                 }
1001         }
1002
1003   out:
1004         return ret;
1005
1006 }
1007
1008 void
1009 DiskWriter::reset_write_sources (bool mark_write_complete, bool /*force*/)
1010 {
1011         ChannelList::iterator chan;
1012         boost::shared_ptr<ChannelList> c = channels.reader();
1013         uint32_t n;
1014
1015         if (!_session.writable() || !recordable()) {
1016                 return;
1017         }
1018
1019         capturing_sources.clear ();
1020
1021         for (chan = c->begin(), n = 0; chan != c->end(); ++chan, ++n) {
1022
1023                 if (!destructive()) {
1024
1025                         if ((*chan)->write_source) {
1026
1027                                 if (mark_write_complete) {
1028                                         Source::Lock lock((*chan)->write_source->mutex());
1029                                         (*chan)->write_source->mark_streaming_write_completed (lock);
1030                                         (*chan)->write_source->done_with_peakfile_writes ();
1031                                 }
1032
1033                                 if ((*chan)->write_source->removable()) {
1034                                         (*chan)->write_source->mark_for_remove ();
1035                                         (*chan)->write_source->drop_references ();
1036                                 }
1037
1038                                 (*chan)->write_source.reset ();
1039                         }
1040
1041                         use_new_write_source (DataType::AUDIO, n);
1042
1043                         if (record_enabled()) {
1044                                 capturing_sources.push_back ((*chan)->write_source);
1045                         }
1046
1047                 } else {
1048
1049                         if ((*chan)->write_source == 0) {
1050                                 use_new_write_source (DataType::AUDIO, n);
1051                         }
1052                 }
1053         }
1054
1055         if (_midi_write_source) {
1056                 if (mark_write_complete) {
1057                         Source::Lock lm(_midi_write_source->mutex());
1058                         _midi_write_source->mark_streaming_write_completed (lm);
1059                 }
1060         }
1061
1062         if (_playlists[DataType::MIDI]) {
1063                 use_new_write_source (DataType::MIDI);
1064         }
1065
1066         if (destructive() && !c->empty ()) {
1067
1068                 /* we now have all our write sources set up, so create the
1069                    playlist's single region.
1070                 */
1071
1072                 if (_playlists[DataType::MIDI]->empty()) {
1073                         setup_destructive_playlist ();
1074                 }
1075         }
1076 }
1077
1078 int
1079 DiskWriter::use_new_write_source (DataType dt, uint32_t n)
1080 {
1081         if (dt == DataType::MIDI) {
1082
1083                 _accumulated_capture_offset = 0;
1084                 _midi_write_source.reset();
1085
1086                 try {
1087                         _midi_write_source = boost::dynamic_pointer_cast<SMFSource>(
1088                                 _session.create_midi_source_for_session (write_source_name ()));
1089
1090                         if (!_midi_write_source) {
1091                                 throw failed_constructor();
1092                         }
1093                 }
1094
1095                 catch (failed_constructor &err) {
1096                         error << string_compose (_("%1:%2 new capture file not initialized correctly"), _name, n) << endmsg;
1097                         _midi_write_source.reset();
1098                         return -1;
1099                 }
1100         } else {
1101                 boost::shared_ptr<ChannelList> c = channels.reader();
1102
1103                 if (!recordable()) {
1104                         return 1;
1105                 }
1106
1107                 if (n >= c->size()) {
1108                         error << string_compose (_("AudioDiskstream: channel %1 out of range"), n) << endmsg;
1109                         return -1;
1110                 }
1111
1112                 ChannelInfo* chan = (*c)[n];
1113
1114                 try {
1115                         if ((chan->write_source = _session.create_audio_source_for_session (
1116                                      c->size(), write_source_name(), n, destructive())) == 0) {
1117                                 throw failed_constructor();
1118                         }
1119                 }
1120
1121                 catch (failed_constructor &err) {
1122                         error << string_compose (_("%1:%2 new capture file not initialized correctly"), _name, n) << endmsg;
1123                         chan->write_source.reset ();
1124                         return -1;
1125                 }
1126
1127                 /* do not remove destructive files even if they are empty */
1128
1129                 chan->write_source->set_allow_remove_if_empty (!destructive());
1130         }
1131
1132         return 0;
1133 }
1134
1135 void
1136 DiskWriter::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abort_capture)
1137 {
1138         bool more_work = true;
1139         int err = 0;
1140         samplecnt_t total_capture;
1141         SourceList audio_srcs;
1142         SourceList midi_srcs;
1143         ChannelList::iterator chan;
1144         vector<CaptureInfo*>::iterator ci;
1145         boost::shared_ptr<ChannelList> c = channels.reader();
1146         uint32_t n = 0;
1147         bool mark_write_completed = false;
1148
1149         finish_capture (c);
1150
1151
1152         /* butler is already stopped, but there may be work to do
1153            to flush remaining data to disk.
1154         */
1155
1156         while (more_work && !err) {
1157                 switch (do_flush (TransportContext, true)) {
1158                 case 0:
1159                         more_work = false;
1160                         break;
1161                 case 1:
1162                         break;
1163                 case -1:
1164                         error << string_compose(_("AudioDiskstream \"%1\": cannot flush captured data to disk!"), _name) << endmsg;
1165                         err++;
1166                 }
1167         }
1168
1169         /* XXX is there anything we can do if err != 0 ? */
1170         Glib::Threads::Mutex::Lock lm (capture_info_lock);
1171
1172         if (capture_info.empty()) {
1173                 return;
1174         }
1175
1176         if (abort_capture) {
1177
1178                 if (destructive()) {
1179                         goto outout;
1180                 }
1181
1182                 for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
1183
1184                         if ((*chan)->write_source) {
1185
1186                                 (*chan)->write_source->mark_for_remove ();
1187                                 (*chan)->write_source->drop_references ();
1188                                 (*chan)->write_source.reset ();
1189                         }
1190
1191                         /* new source set up in "out" below */
1192                 }
1193
1194                 if (_midi_write_source) {
1195                         _midi_write_source->mark_for_remove ();
1196                         _midi_write_source->drop_references ();
1197                         _midi_write_source.reset();
1198                 }
1199
1200                 goto out;
1201         }
1202
1203         for (total_capture = 0, ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
1204                 total_capture += (*ci)->samples;
1205         }
1206
1207         /* figure out the name for this take */
1208
1209         for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
1210
1211                 boost::shared_ptr<AudioFileSource> as = (*chan)->write_source;
1212
1213                 if (as) {
1214                         audio_srcs.push_back (as);
1215                         as->update_header (capture_info.front()->start, when, twhen);
1216                         as->set_captured_for (_name.val());
1217                         as->mark_immutable ();
1218
1219                         if (Config->get_auto_analyse_audio()) {
1220                                 Analyser::queue_source_for_analysis (as, true);
1221                         }
1222
1223                         DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("newly captured source %1 length %2\n", as->path(), as->length (0)));
1224                 }
1225
1226                 if (_midi_write_source) {
1227                         midi_srcs.push_back (_midi_write_source);
1228                 }
1229         }
1230
1231
1232         /* MIDI */
1233
1234         if (_midi_write_source) {
1235
1236                 if (_midi_write_source->length (capture_info.front()->start) == 0) {
1237                         /* No data was recorded, so this capture will
1238                            effectively be aborted; do the same as we
1239                            do for an explicit abort.
1240                         */
1241                         if (_midi_write_source) {
1242                                 _midi_write_source->mark_for_remove ();
1243                                 _midi_write_source->drop_references ();
1244                                 _midi_write_source.reset();
1245                         }
1246
1247                         goto out;
1248                 }
1249
1250                 /* phew, we have data */
1251
1252                 Source::Lock source_lock(_midi_write_source->mutex());
1253
1254                 /* figure out the name for this take */
1255
1256                 midi_srcs.push_back (_midi_write_source);
1257
1258                 _midi_write_source->set_timeline_position (capture_info.front()->start);
1259                 _midi_write_source->set_captured_for (_name);
1260
1261                 /* set length in beats to entire capture length */
1262
1263                 BeatsSamplesConverter converter (_session.tempo_map(), capture_info.front()->start);
1264                 const Temporal::Beats total_capture_beats = converter.from (total_capture);
1265                 _midi_write_source->set_length_beats (total_capture_beats);
1266
1267                 /* flush to disk: this step differs from the audio path,
1268                    where all the data is already on disk.
1269                 */
1270
1271                 _midi_write_source->mark_midi_streaming_write_completed (source_lock, Evoral::Sequence<Temporal::Beats>::ResolveStuckNotes, total_capture_beats);
1272         }
1273
1274         _last_capture_sources.insert (_last_capture_sources.end(), audio_srcs.begin(), audio_srcs.end());
1275         _last_capture_sources.insert (_last_capture_sources.end(), midi_srcs.begin(), midi_srcs.end());
1276
1277
1278         if (_route) {
1279                 _route->use_captured_sources (audio_srcs, capture_info);
1280                 _route->use_captured_sources (midi_srcs, capture_info);
1281         }
1282
1283         mark_write_completed = true;
1284
1285   out:
1286         reset_write_sources (mark_write_completed);
1287
1288   outout:
1289
1290         for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
1291                 delete *ci;
1292         }
1293
1294         capture_info.clear ();
1295         capture_start_sample = 0;
1296 }
1297
1298 void
1299 DiskWriter::transport_looped (samplepos_t transport_sample)
1300 {
1301         if (was_recording) {
1302                 // all we need to do is finish this capture, with modified capture length
1303                 boost::shared_ptr<ChannelList> c = channels.reader();
1304
1305                 finish_capture (c);
1306
1307                 // the next region will start recording via the normal mechanism
1308                 // we'll set the start position to the current transport pos
1309                 // no latency adjustment or capture offset needs to be made, as that already happened the first time
1310                 capture_start_sample = transport_sample;
1311                 first_recordable_sample = transport_sample; // mild lie
1312                 last_recordable_sample = max_samplepos;
1313                 was_recording = true;
1314
1315                 if (recordable() && destructive()) {
1316                         for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
1317
1318                                 RingBufferNPT<CaptureTransition>::rw_vector transvec;
1319                                 (*chan)->capture_transition_buf->get_write_vector(&transvec);
1320
1321                                 if (transvec.len[0] > 0) {
1322                                         transvec.buf[0]->type = CaptureStart;
1323                                         transvec.buf[0]->capture_val = capture_start_sample;
1324                                         (*chan)->capture_transition_buf->increment_write_ptr(1);
1325                                 }
1326                                 else {
1327                                         // bad!
1328                                         fatal << X_("programming error: capture_transition_buf is full on rec loop!  inconceivable!")
1329                                               << endmsg;
1330                                 }
1331                         }
1332                 }
1333
1334         }
1335
1336         /* Here we only keep track of the number of captured loops so monotonic
1337            event times can be delivered to the write source in process().  Trying
1338            to be clever here is a world of trouble, it is better to simply record
1339            the input in a straightforward non-destructive way.  In the future when
1340            we want to implement more clever MIDI looping modes it should be done in
1341            the Source and/or entirely after the capture is finished.
1342         */
1343         if (was_recording) {
1344                 g_atomic_int_add(const_cast<gint*> (&_num_captured_loops), 1);
1345         }
1346 }
1347
1348 void
1349 DiskWriter::setup_destructive_playlist ()
1350 {
1351         SourceList srcs;
1352         boost::shared_ptr<ChannelList> c = channels.reader();
1353
1354         for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
1355                 srcs.push_back ((*chan)->write_source);
1356         }
1357
1358         /* a single full-sized region */
1359
1360         assert (!srcs.empty ());
1361
1362         PropertyList plist;
1363         plist.add (Properties::name, _name.val());
1364         plist.add (Properties::start, 0);
1365         plist.add (Properties::length, max_samplepos - srcs.front()->natural_position());
1366
1367         boost::shared_ptr<Region> region (RegionFactory::create (srcs, plist));
1368         _playlists[DataType::AUDIO]->add_region (region, srcs.front()->natural_position());
1369
1370         /* apply region properties and update write sources */
1371         use_destructive_playlist();
1372 }
1373
1374 void
1375 DiskWriter::use_destructive_playlist ()
1376 {
1377         /* this is called from the XML-based constructor or ::set_destructive. when called,
1378            we already have a playlist and a region, but we need to
1379            set up our sources for write. we use the sources associated
1380            with the (presumed single, full-extent) region.
1381         */
1382
1383         boost::shared_ptr<Region> rp;
1384         {
1385                 const RegionList& rl (_playlists[DataType::AUDIO]->region_list_property().rlist());
1386                 if (rl.size() > 0) {
1387                         /* this can happen when dragging a region onto a tape track */
1388                         assert((rl.size() == 1));
1389                         rp = rl.front();
1390                 }
1391         }
1392
1393         if (!rp) {
1394                 reset_write_sources (false, true);
1395                 return;
1396         }
1397
1398         boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (rp);
1399
1400         if (region == 0) {
1401                 throw failed_constructor();
1402         }
1403
1404         /* be sure to stretch the region out to the maximum length (non-musical)*/
1405
1406         region->set_length (max_samplepos - region->position(), 0);
1407
1408         uint32_t n;
1409         ChannelList::iterator chan;
1410         boost::shared_ptr<ChannelList> c = channels.reader();
1411
1412         for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
1413                 (*chan)->write_source = boost::dynamic_pointer_cast<AudioFileSource>(region->source (n));
1414                 assert((*chan)->write_source);
1415                 (*chan)->write_source->set_allow_remove_if_empty (false);
1416
1417                 // should be set when creating the source or loading the state
1418                 assert ((*chan)->write_source->destructive());
1419         }
1420
1421         /* the source list will never be reset for a destructive track */
1422 }
1423
1424 void
1425 DiskWriter::adjust_buffering ()
1426 {
1427         boost::shared_ptr<ChannelList> c = channels.reader();
1428
1429         for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
1430                 (*chan)->resize (_session.butler()->audio_diskstream_capture_buffer_size());
1431         }
1432 }
1433
1434 void
1435 DiskWriter::realtime_handle_transport_stopped ()
1436 {
1437 }
1438
1439 bool
1440 DiskWriter::set_name (string const & str)
1441 {
1442         string my_name = X_("recorder:");
1443         my_name += str;
1444
1445         if (_name != my_name) {
1446                 SessionObject::set_name (my_name);
1447         }
1448
1449         return true;
1450 }
1451
1452 std::string
1453 DiskWriter::steal_write_source_name ()
1454 {
1455         if (_playlists[DataType::MIDI]) {
1456                 string our_old_name = _midi_write_source->name();
1457
1458                 /* this will bump the name of the current write source to the next one
1459                  * (e.g. "MIDI 1-1" gets renamed to "MIDI 1-2"), thus leaving the
1460                  * current write source name (e.g. "MIDI 1-1" available). See the
1461                  * comments in Session::create_midi_source_by_stealing_name() about why
1462                  * we do this.
1463                  */
1464
1465                 try {
1466                         string new_path = _session.new_midi_source_path (name());
1467
1468                         if (_midi_write_source->rename (new_path)) {
1469                                 return string();
1470                         }
1471                 } catch (...) {
1472                         return string ();
1473                 }
1474
1475                 return our_old_name;
1476         }
1477
1478         return std::string();
1479 }
1480
1481 bool
1482 DiskWriter::configure_io (ChanCount in, ChanCount out)
1483 {
1484         if (!DiskIOProcessor::configure_io (in, out)) {
1485                 return false;
1486         }
1487
1488         reset_write_sources (false, true);
1489
1490         return true;
1491 }