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