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