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