1 /*
2  * Copyright (C) 2005-2017 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2006-2012 David Robillard <d@drobilla.net>
4  * Copyright (C) 2008-2013 Sakari Bergen <sakari.bergen@beatwaves.net>
5  * Copyright (C) 2010-2012 Carl Hetherington <carl@carlh.net>
6  * Copyright (C) 2015-2018 Robin Gareus <robin@gareus.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 
23 
24 #include "pbd/error.h"
25 #include <glibmm/threads.h>
26 #include <glibmm/timer.h>
27 
28 #include <midi++/mmc.h>
29 
30 #include "ardour/audioengine.h"
31 #include "ardour/butler.h"
32 #include "ardour/export_handler.h"
33 #include "ardour/export_status.h"
34 #include "ardour/process_thread.h"
35 #include "ardour/session.h"
36 #include "ardour/track.h"
37 #include "ardour/transport_fsm.h"
38 
39 #include "pbd/i18n.h"
40 
41 using namespace std;
42 using namespace ARDOUR;
43 using namespace PBD;
44 
45 #define TFSM_ROLL() { _transport_fsm->enqueue (new TransportFSM::Event (TransportFSM::StartTransport)); }
46 #define TFSM_SPEED(speed,as_default) { _transport_fsm->enqueue (new TransportFSM::Event (speed,as_default)); }
47 
48 boost::shared_ptr<ExportHandler>
get_export_handler()49 Session::get_export_handler ()
50 {
51 	if (!export_handler) {
52 		export_handler.reset (new ExportHandler (*this));
53 	}
54 
55 	return export_handler;
56 }
57 
58 boost::shared_ptr<ExportStatus>
get_export_status()59 Session::get_export_status ()
60 {
61 	if (!export_status) {
62 		export_status.reset (new ExportStatus ());
63 	}
64 
65 	return export_status;
66 }
67 
68 
69 int
pre_export()70 Session::pre_export ()
71 {
72 	get_export_status (); // Init export_status
73 
74 	/* take everyone out of awrite to avoid disasters */
75 
76 	{
77 		boost::shared_ptr<RouteList> r = routes.reader ();
78 
79 		for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
80 			(*i)->protect_automation ();
81 		}
82 	}
83 
84 	/* prepare transport */
85 
86 	realtime_stop (true, true);
87 
88 	if (get_record_enabled()) {
89 		disable_record (false, true);
90 	}
91 
92 	unset_play_loop ();
93 
94 	/* no slaving */
95 
96 	post_export_sync = config.get_external_sync ();
97 	post_export_position = _transport_sample;
98 
99 	config.set_external_sync (false);
100 
101 	_export_xruns = 0;
102 	_exporting = true;
103 	export_status->set_running (true);
104 	export_status->Finished.connect_same_thread (*this, boost::bind (&Session::finalize_audio_export, this, _1));
105 
106 	/* disable MMC output early */
107 
108 	_pre_export_mmc_enabled = _mmc->send_enabled ();
109 	_mmc->enable_send (false);
110 
111 	return 0;
112 }
113 
114 /** Called for each range that is being exported */
115 int
start_audio_export(samplepos_t position,bool realtime,bool region_export)116 Session::start_audio_export (samplepos_t position, bool realtime, bool region_export)
117 {
118 	assert (!engine().in_process_thread ());
119 
120 	if (!_exporting) {
121 		pre_export ();
122 	} else if (_transport_fsm->transport_speed() != 0) {
123 		realtime_stop (true, true);
124 	}
125 
126 	_region_export = region_export;
127 
128 	if (region_export) {
129 		_export_preroll = 0;
130 	}
131 	else if (realtime) {
132 		_export_preroll = nominal_sample_rate ();
133 	} else {
134 		_export_preroll = Config->get_export_preroll() * nominal_sample_rate ();
135 	}
136 
137 	if (_export_preroll == 0) {
138 		// must be > 0 so that transport is started in sync.
139 		_export_preroll = 1;
140 	}
141 
142 	/* realtime_stop will have queued butler work (and TSFM),
143 	 * but the butler may not run immediately, so well have
144 	 * to wait for it to wake up and call
145 	 * non_realtime_stop ().
146 	 */
147 	int sleeptm = std::max (40000, engine().usecs_per_cycle ());
148 	int timeout = std::max (100, 8000000 / sleeptm);
149 	do {
150 		Glib::usleep (sleeptm);
151 		sched_yield ();
152 	} while (_transport_fsm->waiting_for_butler() && --timeout > 0);
153 
154 	if (timeout == 0) {
155 		error << _("Cannot prepare transport for export") << endmsg;
156 		return -1;
157 	}
158 
159 	/* We're about to call Track::seek, so the butler must have finished everything
160 	   up otherwise it could be doing do_refill in its thread while we are doing
161 	   it here.
162 	*/
163 
164 	{
165 		Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
166 		_butler->wait_until_finished ();
167 
168 	/* get everyone to the right position */
169 
170 		boost::shared_ptr<RouteList> rl = routes.reader();
171 
172 		for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
173 			boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
174 			if (tr && tr->seek (position, true)) {
175 				error << string_compose (_("%1: cannot seek to %2 for export"),
176 						  (*i)->name(), position)
177 				      << endmsg;
178 				return -1;
179 			}
180 		}
181 	}
182 
183 	/* we just did the core part of a locate call above, but
184 	   for the sake of any GUI, put the _transport_sample in
185 	   the right place too.
186 	*/
187 
188 	_transport_sample = position;
189 
190 	if (!region_export) {
191 		_remaining_latency_preroll = worst_latency_preroll_buffer_size_ceil ();
192 	} else {
193 		_remaining_latency_preroll = 0;
194 	}
195 
196 	/* get transport ready. note how this is calling butler functions
197 	   from a non-butler thread. we waited for the butler to stop
198 	   what it was doing earlier in Session::pre_export() and nothing
199 	   since then has re-awakened it.
200 	 */
201 
202 	/* we are ready to go ... */
203 
204 	if (!_engine.running()) {
205 		return -1;
206 	}
207 
208 	assert (!_engine.freewheeling ());
209 	assert (!_engine.in_process_thread ());
210 
211 	if (realtime) {
212 		Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
213 		_export_rolling = true;
214 		_realtime_export = true;
215 		export_status->stop = false;
216 		process_function = &Session::process_export_fw;
217 		/* this is required for ExportGraphBuilder::Intermediate::start_post_processing */
218 		_engine.Freewheel.connect_same_thread (export_freewheel_connection, boost::bind (&Session::process_export_fw, this, _1));
219 		reset_xrun_count ();
220 		return 0;
221 	} else {
222 		if (_realtime_export) {
223 			Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
224 			process_function = &Session::process_with_events;
225 		}
226 		_realtime_export = false;
227 		_export_rolling = true;
228 		export_status->stop = false;
229 		_engine.Freewheel.connect_same_thread (export_freewheel_connection, boost::bind (&Session::process_export_fw, this, _1));
230 		reset_xrun_count ();
231 		return _engine.freewheel (true);
232 	}
233 }
234 
235 void
process_export(pframes_t nframes)236 Session::process_export (pframes_t nframes)
237 {
238 	if (_export_rolling && export_status->stop) {
239 		stop_audio_export ();
240 	}
241 
242 	/* for Region Raw or Fades, we can skip this
243 	 * RegionExportChannelFactory::update_buffers() does not care
244 	 * about anything done here
245 	 */
246 	if (!_region_export) {
247 		if (_export_rolling) {
248 			if (!_realtime_export)  {
249 				/* make sure we've caught up with disk i/o, since
250 				 * we're running faster than realtime c/o JACK.
251 				 */
252 				_butler->wait_until_finished ();
253 			}
254 
255 			/* do the usual stuff */
256 
257 			process_without_events (nframes);
258 
259 		} else if (_realtime_export) {
260 			fail_roll (nframes); // somehow we need to silence _ALL_ output buffers
261 		}
262 	}
263 
264 	try {
265 		/* handle export - XXX what about error handling? */
266 
267 		if (ProcessExport (nframes).value_or (0) > 0) {
268 			/* last cycle completed */
269 			assert (_export_rolling);
270 			stop_audio_export ();
271 		}
272 
273 	} catch (std::exception & e) {
274 		error << string_compose (_("Export ended unexpectedly: %1"), e.what()) << endmsg;
275 		export_status->abort (true);
276 	}
277 }
278 
279 void
process_export_fw(pframes_t nframes)280 Session::process_export_fw (pframes_t nframes)
281 {
282 	if (!_export_rolling) {
283 		try {
284 			ProcessExport (0);
285 		} catch (std::exception & e) {
286 			/* pre-roll export must not throw */
287 			assert (0);
288 			export_status->abort (true);
289 		}
290 		return;
291 	}
292 
293 	const bool need_buffers = _engine.freewheeling ();
294 	if (_export_preroll > 0) {
295 
296 		if (need_buffers) {
297 			_engine.main_thread()->get_buffers ();
298 		}
299 		fail_roll (nframes);
300 		if (need_buffers) {
301 			_engine.main_thread()->drop_buffers ();
302 		}
303 
304 		_export_preroll -= std::min ((samplepos_t)nframes, _export_preroll);
305 
306 		if (_export_preroll > 0) {
307 			// clear out buffers (reverb tails etc).
308 			return;
309 		}
310 
311 		TFSM_SPEED (1.0, false);
312 		TFSM_ROLL ();
313 		_butler->schedule_transport_work ();
314 
315 		/* Session::process_with_events () sets _remaining_latency_preroll = 0
316 		 * when being called with _transport_fsm->transport_speed() == 0.
317 		 *
318 		 * This can happen wit JACK, there is a process-callback before
319 		 * freewheeling becomes active, after Session::start_audio_export().
320 		 */
321 		if (!_region_export) {
322 			_remaining_latency_preroll = worst_latency_preroll_buffer_size_ceil ();
323 		}
324 
325 		return;
326 	}
327 
328 	/* wait for butler to complete schedule_transport_work(),
329 	 * compare to Session::process */
330 	if (non_realtime_work_pending ()) {
331 		if (_butler->transport_work_requested ()) {
332 			/* butler is still processing */
333 			return;
334 		}
335 		butler_completed_transport_work ();
336 	}
337 
338 	if (_remaining_latency_preroll > 0) {
339 		samplepos_t remain = std::min ((samplepos_t)nframes, _remaining_latency_preroll);
340 
341 		if (need_buffers) {
342 			_engine.main_thread()->get_buffers ();
343 		}
344 
345 		assert (_count_in_samples == 0);
346 		while (remain > 0) {
347 			samplecnt_t ns = calc_preroll_subcycle (remain);
348 
349 			bool session_needs_butler = false;
350 			if (process_routes (ns, session_needs_butler)) {
351 				fail_roll (ns);
352 			}
353 
354 			try {
355 				ProcessExport (ns);
356 			} catch (std::exception & e) {
357 				/* pre-roll export must not throw */
358 				assert (0);
359 				export_status->abort (true);
360 			}
361 
362 			_remaining_latency_preroll -= ns;
363 			remain -= ns;
364 			nframes -= ns;
365 
366 			if (remain != 0) {
367 				_engine.split_cycle (ns);
368 			}
369 		}
370 
371 		if (need_buffers) {
372 			_engine.main_thread()->drop_buffers ();
373 		}
374 
375 		if (nframes == 0) {
376 			return;
377 		}
378 	}
379 
380 	if (need_buffers) {
381 		_engine.main_thread()->get_buffers ();
382 	}
383 	process_export (nframes);
384 	if (need_buffers) {
385 		_engine.main_thread()->drop_buffers ();
386 	}
387 
388 	return;
389 }
390 
391 int
stop_audio_export()392 Session::stop_audio_export ()
393 {
394 	/* can't use stop_transport() here because we need
395 	   an synchronous halt and don't require all the declick
396 	   stuff that stop_transport() implements.
397 	*/
398 
399 	realtime_stop (true, true);
400 	flush_all_inserts ();
401 	_export_rolling = false;
402 	_butler->schedule_transport_work ();
403 	reset_xrun_count ();
404 
405 	return 0;
406 }
407 
408 void
finalize_audio_export(TransportRequestSource trs)409 Session::finalize_audio_export (TransportRequestSource trs)
410 {
411 	/* This is called as a handler for the Finished signal, which is
412 	   emitted by a UI component once the ExportStatus object associated
413 	   with this export indicates that it has finished. It runs in the UI
414 	   thread that emits the signal.
415 	*/
416 
417 	_exporting = false;
418 
419 	if (_export_rolling) {
420 		stop_audio_export ();
421 	}
422 
423 	/* Clean up */
424 
425 	if (_realtime_export) {
426 		Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
427 		process_function = &Session::process_with_events;
428 	}
429 	_engine.freewheel (false);
430 	export_freewheel_connection.disconnect();
431 
432 	_mmc->enable_send (_pre_export_mmc_enabled);
433 
434 	/* maybe write CUE/TOC */
435 
436 	export_handler.reset();
437 	export_status.reset();
438 
439 	/* restart slaving */
440 
441 	if (post_export_sync) {
442 		config.set_external_sync (true);
443 	} else {
444 		request_locate (post_export_position, MustStop, trs);
445 	}
446 }
447