1 /*
2  * Copyright (C) 1999-2019 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2005-2009 Taybin Rutkin <taybin@taybin.com>
4  * Copyright (C) 2006-2007 Jesse Chappell <jesse@essej.net>
5  * Copyright (C) 2006-2012 David Robillard <d@drobilla.net>
6  * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
7  * Copyright (C) 2008-2009 Hans Baier <hansfbaier@googlemail.com>
8  * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
9  * Copyright (C) 2014-2018 Ben Loftis <ben@harrisonconsoles.com>
10  * Copyright (C) 2015 GZharun <grygoriiz@wavesglobal.com>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with this program; if not, write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26 
27 #ifdef WAF_BUILD
28 #include "libardour-config.h"
29 #endif
30 
31 #include <cmath>
32 #include <cerrno>
33 #include <unistd.h>
34 
35 #include <boost/algorithm/string/erase.hpp>
36 
37 #include "pbd/error.h"
38 #include "pbd/enumwriter.h"
39 #include "pbd/i18n.h"
40 #include "pbd/memento_command.h"
41 #include "pbd/pthread_utils.h"
42 #include "pbd/stacktrace.h"
43 #include "pbd/undo.h"
44 
45 #include "midi++/mmc.h"
46 #include "midi++/port.h"
47 
48 #include "ardour/audio_backend.h"
49 #include "ardour/audioengine.h"
50 #include "ardour/auditioner.h"
51 #include "ardour/automation_watch.h"
52 #include "ardour/butler.h"
53 #include "ardour/click.h"
54 #include "ardour/debug.h"
55 #include "ardour/disk_reader.h"
56 #include "ardour/location.h"
57 #include "ardour/playlist.h"
58 #include "ardour/profile.h"
59 #include "ardour/scene_changer.h"
60 #include "ardour/session.h"
61 #include "ardour/transport_fsm.h"
62 #include "ardour/transport_master.h"
63 #include "ardour/transport_master_manager.h"
64 #include "ardour/tempo.h"
65 #include "ardour/operations.h"
66 #include "ardour/vca.h"
67 #include "ardour/vca_manager.h"
68 
69 using namespace std;
70 using namespace ARDOUR;
71 using namespace PBD;
72 
73 
74 #ifdef NDEBUG
75 # define ENSURE_PROCESS_THREAD do {} while (0)
76 #else
77 # define ENSURE_PROCESS_THREAD                           \
78   do {                                                   \
79     if (!AudioEngine::instance()->in_process_thread()) { \
80       PBD::stacktrace (std::cerr, 30);                   \
81     }                                                    \
82   } while (0)
83 #endif
84 
85 
86 #define TFSM_EVENT(evtype) { _transport_fsm->enqueue (new TransportFSM::Event (evtype)); }
87 #define TFSM_STOP(abort,clear) { _transport_fsm->enqueue (new TransportFSM::Event (TransportFSM::StopTransport,abort,clear)); }
88 #define TFSM_LOCATE(target,ltd,loop,force) { _transport_fsm->enqueue (new TransportFSM::Event (TransportFSM::Locate,target,ltd,loop,force)); }
89 #define TFSM_SPEED(speed,as_default) { _transport_fsm->enqueue (new TransportFSM::Event (speed,as_default)); }
90 
91 /* *****************************************************************************
92  * REALTIME ACTIONS (to be called on state transitions)
93  * ****************************************************************************/
94 
95 void
realtime_stop(bool abort,bool clear_state)96 Session::realtime_stop (bool abort, bool clear_state)
97 {
98 	ENSURE_PROCESS_THREAD;
99 
100 	DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1 speed = %2\n", _transport_sample, _transport_fsm->transport_speed()));
101 	PostTransportWork todo = PostTransportStop;
102 
103 	/* we are rolling and we want to stop */
104 
105 	if (Config->get_monitoring_model() == HardwareMonitoring) {
106 		set_track_monitor_input_status (true);
107 	}
108 
109 	if (synced_to_engine ()) {
110 		if (clear_state) {
111 			/* do this here because our response to the slave won't
112 			   take care of it.
113 			*/
114 			_play_range = false;
115 			_count_in_once = false;
116 			unset_play_loop ();
117 		}
118 	}
119 
120 	/* call routes */
121 
122 	boost::shared_ptr<RouteList> r = routes.reader ();
123 
124 	for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
125 		(*i)->realtime_handle_transport_stopped ();
126 	}
127 
128 	DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_sample));
129 
130 	if (abort) {
131 		todo = PostTransportWork (todo | PostTransportAbort);
132 	}
133 
134 	if (clear_state) {
135 		todo = PostTransportWork (todo | PostTransportClearSubstate);
136 	}
137 
138 	if (todo) {
139 		add_post_transport_work (todo);
140 	}
141 
142 	_clear_event_type (SessionEvent::RangeStop);
143 	_clear_event_type (SessionEvent::RangeLocate);
144 
145 	/* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
146 	disable_record (true, (!Config->get_latched_record_enable() && clear_state));
147 
148 	if (clear_state && !Config->get_loop_is_mode()) {
149 		unset_play_loop ();
150 	}
151 
152 	reset_punch_loop_constraint ();
153 
154 	g_atomic_int_set (&_playback_load, 100);
155 	g_atomic_int_set (&_capture_load, 100);
156 
157 	if (config.get_use_video_sync()) {
158 		waiting_for_sync_offset = true;
159 	}
160 
161 	if (todo) {
162 		TFSM_EVENT (TransportFSM::ButlerRequired);
163 	}
164 }
165 
166 /** @param with_mmc true to send a MMC locate command when the locate is done */
167 void
locate(samplepos_t target_sample,bool for_loop_end,bool force,bool with_mmc)168 Session::locate (samplepos_t target_sample, bool for_loop_end, bool force, bool with_mmc)
169 {
170 	ENSURE_PROCESS_THREAD;
171 
172 	if (target_sample < 0) {
173 		error << _("Locate called for negative sample position - ignored") << endmsg;
174 		return;
175 	}
176 
177 	bool need_butler = false;
178 
179 	/* Locates for seamless looping are fairly different from other
180 	 * locates. They assume that the diskstream buffers for each track
181 	 * already have the correct data in them, and thus there is no need to
182 	 * actually tell the tracks to locate. What does need to be done,
183 	 * though, is all the housekeeping that is associated with non-linear
184 	 * changes in the value of _transport_sample.
185 	 */
186 
187 	DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1 ts = %7, for loop end %2 force %3 mmc %4\n",
188 	                                               target_sample, for_loop_end, force, with_mmc, _transport_sample));
189 
190 	if (!force && (_transport_sample == target_sample) && !for_loop_end) {
191 		TFSM_EVENT (TransportFSM::LocateDone);
192 		Located (); /* EMIT SIGNAL */
193 		return;
194 	}
195 
196 	// Update Timecode time
197 	_transport_sample = target_sample;
198 	_nominal_jack_transport_sample = boost::none;
199 	// Bump seek counter so that any in-process locate in the butler
200 	// thread(s?) can restart.
201 	g_atomic_int_inc (&_seek_counter);
202 	_last_roll_or_reversal_location = target_sample;
203 	if (!for_loop_end) {
204 		_remaining_latency_preroll = worst_latency_preroll_buffer_size_ceil ();
205 	}
206 	timecode_time(_transport_sample, transmitting_timecode_time); // XXX here?
207 
208 	assert (_transport_fsm->locating() || _transport_fsm->declicking_for_locate());
209 
210 	/* Tell all routes to do the RT part of locate */
211 
212 	boost::shared_ptr<RouteList> r = routes.reader ();
213 	for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
214 		(*i)->realtime_locate (for_loop_end);
215 	}
216 
217 	if (force || !for_loop_end) {
218 
219 		PostTransportWork todo = PostTransportLocate;
220 		add_post_transport_work (todo);
221 		need_butler = true;
222 
223 	} else {
224 
225 		/* this is functionally what clear_clicks() does but with a tentative lock */
226 
227 		Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
228 
229 		if (clickm.locked()) {
230 
231 			for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
232 				delete *i;
233 			}
234 
235 			clicks.clear ();
236 		}
237 	}
238 
239 	/* cancel looped playback if transport pos outside of loop range */
240 	if (get_play_loop ()) {
241 
242 		Location* al = _locations->auto_loop_location();
243 
244 		if (al) {
245 			if (_transport_sample < al->start() || _transport_sample >= al->end()) {
246 
247 				// located outside the loop: cancel looping directly, this is called from event handling context
248 
249 				have_looped = false;
250 
251 				if (!Config->get_loop_is_mode()) {
252 					set_play_loop (false, false);
253 				} else {
254 					/* this will make the non_realtime_locate() in the butler
255 					   which then causes seek() in tracks actually do the right
256 					   thing.
257 					*/
258 					set_track_loop (false);
259 				}
260 
261 			} else if (_transport_sample == al->start()) {
262 
263 				// located to start of loop - this is looping, basically
264 
265 				boost::shared_ptr<RouteList> rl = routes.reader();
266 
267 				for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
268 					boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
269 
270 					if (tr && tr->rec_enable_control()->get_value()) {
271 						// tell it we've looped, so it can deal with the record state
272 						tr->transport_looped (_transport_sample);
273 					}
274 				}
275 
276 				if (for_loop_end) {
277 					have_looped = true;
278 					TransportLooped(); // EMIT SIGNAL
279 				}
280 			}
281 		}
282 	}
283 
284 	if (need_butler) {
285 		TFSM_EVENT (TransportFSM::ButlerRequired);
286 	} else {
287 		TFSM_EVENT (TransportFSM::LocateDone);
288 	}
289 
290 	_send_timecode_update = true;
291 
292 	if (with_mmc) {
293 		send_mmc_locate (_transport_sample);
294 	}
295 
296 	_last_roll_location = _last_roll_or_reversal_location =  _transport_sample;
297 
298 	Located (); /* EMIT SIGNAL */
299 }
300 
301 void
post_locate()302 Session::post_locate ()
303 {
304 	if (transport_master_is_external() && !synced_to_engine()) {
305 		const samplepos_t current_master_position = TransportMasterManager::instance().get_current_position_in_process_context();
306 		if (abs (current_master_position - _transport_sample) > TransportMasterManager::instance().current()->resolution()) {
307 			_last_roll_location = _last_roll_or_reversal_location =  _transport_sample;
308 		}
309 	}
310 }
311 
312 /** Set the transport speed.
313  *  Called from the process thread.
314  *  @param speed New speed
315  */
316 void
set_transport_speed(double speed)317 Session::set_transport_speed (double speed)
318 {
319 	ENSURE_PROCESS_THREAD;
320 	DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %1 Set transport speed to %2 from %3 (es = %4)\n", _transport_sample, speed, _transport_fsm->transport_speed(), _engine_speed));
321 
322 	assert (speed != 0.0);
323 
324 	/* the logic:
325 
326 	   a) engine speed is not 1.0 (normal speed)
327 	   b) engine speed matches the requested speed (sign ignored)
328 	   c) speed and transport speed have the same sign (no direction change)
329 
330 	   For (c) the correct arithmetical test is >= 0, but we care about the
331 	   case where at least one of them is zero. That would generate an
332 	   equality with zero, but if only one of them is zero, we still need
333 	   to change speed. So we check that the product is > 0, which implies
334 	   that neither of them are zero, and they have the same sign.
335 
336 	*/
337 
338 	if ((_engine_speed != 1) && (_engine_speed == fabs (speed)) && ((speed * _transport_fsm->transport_speed()) > 0)) {
339 		/* engine speed is not changing and no direction change, do nothing */
340 		DEBUG_TRACE (DEBUG::Transport, "no reason to change speed, do nothing\n");
341 		return;
342 	}
343 
344 	/* max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
345 	   and user needs. XXX We really need CD-style "skip" playback for ffwd and rewind.
346 	*/
347 
348 	if (speed > 0) {
349 		speed = min ((double) Config->get_max_transport_speed(), speed);
350 	} else if (speed < 0) {
351 		speed = max ((double) -Config->get_max_transport_speed(), speed);
352 	}
353 
354 	double new_engine_speed = fabs (speed);
355 	// double new_transport_speed = (speed < 0) ? -1 : 1;
356 
357 	if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
358 		warning << string_compose (
359 			_("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
360 			PROGRAM_NAME)
361 		        << endmsg;
362 		return;
363 	}
364 
365 	clear_clicks ();
366 	_engine_speed = new_engine_speed;
367 
368 	if (!Config->get_auto_return_after_rewind_ffwd() && fabs (speed) != 1.0 && _transport_fsm->default_speed() == 1.0) {
369 		/* varispeed of any sort cancels auto-return */
370 		_requested_return_sample = -1;
371 		_last_roll_location = -1;
372 		_last_roll_or_reversal_location = -1;
373 	}
374 
375 
376 	/* throttle signal emissions.
377 	 * when slaved [_last]_transport_fsm->transport_speed()
378 	 * usually changes every cycle (tiny amounts due to DLL).
379 	 * Emitting a signal every cycle is overkill and unwarranted.
380 	 *
381 	 * Using _transport_fsm->transport_speed() is not acceptable,
382 	 * since it allows for large changes over a long period
383 	 * of time. Hence we introduce a dedicated variable to keep track
384 	 *
385 	 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
386 	 * for TransportStateChange() here is the ShuttleControl display.
387 	 */
388 
389 	const double act_speed = actual_speed ();
390 
391 	if (fabs (_signalled_varispeed - act_speed) > .002
392 	    // still, signal hard changes to 1.0 and 0.0:
393 	    || (act_speed == 1.0 && _signalled_varispeed != 1.0)
394 	    || (act_speed == 0.0 && _signalled_varispeed != 0.0)
395 		)
396 	{
397 		DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_fsm->transport_speed()));
398 		TransportStateChange (); /* EMIT SIGNAL */
399 		_signalled_varispeed = act_speed;
400 	}
401 
402 }
403 
404 /** Stop the transport.  */
405 void
stop_transport(bool abort,bool clear_state)406 Session::stop_transport (bool abort, bool clear_state)
407 {
408 	ENSURE_PROCESS_THREAD;
409 
410 	_count_in_once = false;
411 
412 	DEBUG_TRACE (DEBUG::Transport, string_compose ("time to actually stop with TS @ %1\n", _transport_sample));
413 
414 	realtime_stop (abort, clear_state);
415 }
416 
417 /** Called from the process thread */
418 void
start_transport()419 Session::start_transport ()
420 {
421 	ENSURE_PROCESS_THREAD;
422 	DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
423 
424 	if (Config->get_loop_is_mode() && get_play_loop ()) {
425 
426 		Location *location = _locations->auto_loop_location();
427 
428 		if (location != 0) {
429 			if (_transport_sample != location->start()) {
430 
431 				/* force tracks to do their thing */
432 				set_track_loop (true);
433 
434 				/* jump to start and then roll from there */
435 
436 				request_locate (location->start(), MustRoll);
437 				return;
438 			}
439 		}
440 	}
441 
442 	if (Config->get_monitoring_model() == HardwareMonitoring) {
443 		set_track_monitor_input_status (!config.get_auto_input());
444 	}
445 
446 	_last_roll_location = _transport_sample;
447 	_last_roll_or_reversal_location = _transport_sample;
448 	if (!have_looped && !_exporting) {
449 		_remaining_latency_preroll = worst_latency_preroll_buffer_size_ceil ();
450 	}
451 
452 	have_looped = false;
453 
454 	/* if record status is Enabled, move it to Recording. if its
455 	   already Recording, move it to Disabled.
456 	*/
457 
458 	switch (record_status()) {
459 	case Enabled:
460 		if (!config.get_punch_in()) {
461 			/* This is only for UIs (keep blinking rec-en before
462 			 * punch-in, don't show rec-region etc). The UI still
463 			 * depends on SessionEvent::PunchIn and ensuing signals.
464 			 *
465 			 * The disk-writers handle punch in/out internally
466 			 * in their local delay-compensated timeframe.
467 			 */
468 			enable_record ();
469 		}
470 		break;
471 
472 	case Recording:
473 		if (!get_play_loop ()) {
474 			disable_record (false);
475 		}
476 		break;
477 
478 	default:
479 		break;
480 	}
481 
482 	maybe_allow_only_loop ();
483 	maybe_allow_only_punch ();
484 
485 	clear_clicks ();
486 
487 	if (!_engine.freewheeling()) {
488 		Timecode::Time time;
489 		timecode_time_subframes (_transport_sample, time);
490 		if (transport_master()->type() != MTC) { // why not when slaved to MTC?
491 			send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
492 		}
493 
494 		if ((actively_recording () || (config.get_punch_in () && get_record_enabled ()))
495 		    && click_data && (config.get_count_in () || _count_in_once)) {
496 			_count_in_once = false;
497 			/* calculate count-in duration (in audio samples)
498 			 * - use [fixed] tempo/meter at _transport_sample
499 			 * - calc duration of 1 bar + time-to-beat before or at transport_sample
500 			 */
501 			const Tempo& tempo = _tempo_map->tempo_at_sample (_transport_sample);
502 			const Meter& meter = _tempo_map->meter_at_sample (_transport_sample);
503 
504 			const double num = meter.divisions_per_bar ();
505 			const double den = meter.note_divisor ();
506 			const double barbeat = _tempo_map->exact_qn_at_sample (_transport_sample, 0) * den / (4. * num);
507 			const double bar_fract = fmod (barbeat, 1.0); // fraction of bar elapsed.
508 
509 			_count_in_samples = meter.samples_per_bar (tempo, _current_sample_rate);
510 
511 			double dt = _count_in_samples / num;
512 			if (bar_fract == 0) {
513 				/* at bar boundary, count-in 2 bars before start. */
514 				_count_in_samples *= 2;
515 			} else {
516 				/* beats left after full bar until roll position */
517 				_count_in_samples *= 1. + bar_fract;
518 			}
519 
520 			if (_count_in_samples > _remaining_latency_preroll) {
521 				_remaining_latency_preroll = _count_in_samples;
522 			}
523 
524 			int clickbeat = 0;
525 			samplepos_t cf = _transport_sample - _count_in_samples;
526 			samplecnt_t offset = _click_io->connected_latency (true);
527 			clear_clicks ();
528 			_clicks_cleared = cf;
529 			while (cf < _transport_sample + offset) {
530 				add_click (cf, clickbeat == 0);
531 				cf += dt;
532 				clickbeat = fmod (clickbeat + 1, num);
533 			}
534 
535 			if (_count_in_samples < _remaining_latency_preroll) {
536 				_count_in_samples = _remaining_latency_preroll;
537 			}
538 		}
539 	}
540 
541 	DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", transport_speed()));
542 	TransportStateChange (); /* EMIT SIGNAL */
543 }
544 
545 bool
need_declick_before_locate() const546 Session::need_declick_before_locate () const
547 {
548 	/* At this time (July 2020) only audio playback from disk readers is
549 	   de-clicked. MIDI tracks with audio output really need it too.
550 	*/
551 	return naudiotracks() > 0;
552 }
553 
554 bool
should_stop_before_locate() const555 Session::should_stop_before_locate () const
556 {
557 	/* do "stopped" stuff if:
558 	 *
559 	 * we are rolling AND
560 	 * no autoplay in effect AND
561 	 * we're not synced to an external transport master
562 	 *
563 	 */
564 
565 	if ((!auto_play_legal || !config.get_auto_play()) &&
566 	    !(config.get_external_sync() && !synced_to_engine())) {
567 
568 		return true;
569 	}
570 	return false;
571 }
572 
573 bool
user_roll_after_locate() const574 Session::user_roll_after_locate () const
575 {
576 	return auto_play_legal && config.get_auto_play();
577 }
578 
579 bool
should_roll_after_locate() const580 Session::should_roll_after_locate () const
581 {
582 	/* a locate must previously have been requested and completed before
583 	 * this answer can be considered correct
584 	 */
585 
586 	return ((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting);
587 
588 }
589 
590 /** Do any transport work in the audio thread that needs to be done after the
591  * butler thread is finished.  Audio thread, realtime safe.
592  */
593 void
butler_completed_transport_work()594 Session::butler_completed_transport_work ()
595 {
596 	ENSURE_PROCESS_THREAD;
597 	PostTransportWork ptw = post_transport_work ();
598 
599 	DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler done, RT cleanup for %1\n", enum_2_string (ptw)));
600 
601 	if (ptw & PostTransportAudition) {
602 		if (auditioner && auditioner->auditioning()) {
603 			_remaining_latency_preroll = 0;
604 			process_function = &Session::process_audition;
605 		} else {
606 			process_function = &Session::process_with_events;
607 		}
608 		ptw = PostTransportWork (ptw & ~PostTransportAudition);
609 		set_post_transport_work (ptw);
610 	}
611 
612 	if (ptw & PostTransportLocate) {
613 		post_locate ();
614 		ptw = PostTransportWork (ptw & ~PostTransportLocate);
615 		set_post_transport_work (ptw);
616 		TFSM_EVENT (TransportFSM::LocateDone);
617 	}
618 
619 	/* the butler finished its work so clear all PostTransportWork flags
620 	 */
621 
622 	set_post_transport_work (PostTransportWork (0));
623 
624 	set_next_event ();
625 
626 	if (_transport_fsm->waiting_for_butler()) {
627 		TFSM_EVENT (TransportFSM::ButlerDone);
628 	}
629 }
630 
631 void
schedule_butler_for_transport_work()632 Session::schedule_butler_for_transport_work ()
633 {
634 	assert (_transport_fsm->waiting_for_butler ());
635 	DEBUG_TRACE (DEBUG::Butler, string_compose ("summon butler for transport work (%1)\n", enum_2_string (post_transport_work())));
636 	_butler->schedule_transport_work ();
637 }
638 
639 bool
maybe_stop(samplepos_t limit)640 Session::maybe_stop (samplepos_t limit)
641 {
642 	ENSURE_PROCESS_THREAD;
643 	if ((_transport_fsm->transport_speed() > 0.0f && _transport_sample >= limit) || (_transport_fsm->transport_speed() < 0.0f && _transport_sample == 0)) {
644 		if (synced_to_engine ()) {
645 			_engine.transport_stop ();
646 		} else {
647 			TFSM_STOP (false, false);
648 		}
649 		return true;
650 	}
651 	return false;
652 }
653 
654 int
micro_locate(samplecnt_t distance)655 Session::micro_locate (samplecnt_t distance)
656 {
657 	ENSURE_PROCESS_THREAD;
658 
659 	boost::shared_ptr<RouteList> rl = routes.reader();
660 	for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
661 		boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
662 		if (tr && !tr->can_internal_playback_seek (distance)) {
663 			return -1;
664 		}
665 	}
666 
667 	DEBUG_TRACE (DEBUG::Transport, string_compose ("micro-locate by %1\n", distance));
668 
669 	for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
670 		boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
671 		if (tr) {
672 			tr->internal_playback_seek (distance);
673 		}
674 	}
675 
676 	_transport_sample += distance;
677 	return 0;
678 }
679 
680 void
flush_all_inserts()681 Session::flush_all_inserts ()
682 {
683 	ENSURE_PROCESS_THREAD;
684 	boost::shared_ptr<RouteList> r = routes.reader ();
685 
686 	for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
687 		(*i)->flush_processors ();
688 	}
689 }
690 
691 /* *****************************************************************************
692  * END REALTIME ACTIONS
693  * ****************************************************************************/
694 
695 void
add_post_transport_work(PostTransportWork ptw)696 Session::add_post_transport_work (PostTransportWork ptw)
697 {
698 	PostTransportWork oldval;
699 	PostTransportWork newval;
700 	int tries = 0;
701 
702 	while (tries < 8) {
703 		oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
704 		newval = PostTransportWork (oldval | ptw);
705 		if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
706 			/* success */
707 			return;
708 		}
709 	}
710 
711 	error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
712 }
713 
714 bool
should_ignore_transport_request(TransportRequestSource src,TransportRequestType type)715 Session::should_ignore_transport_request (TransportRequestSource src, TransportRequestType type)
716 {
717 	if (config.get_external_sync()) {
718 		if (TransportMasterManager::instance().current()->allow_request (src, type)) {
719 			/* accepting a command means dropping external sync first */
720 			config.set_external_sync (false);
721 			return true;
722 		}
723 	}
724 	return false;
725 }
726 
727 bool
synced_to_engine() const728 Session::synced_to_engine() const
729 {
730 	return config.get_external_sync() && TransportMasterManager::instance().current()->type() == Engine;
731 }
732 
733 void
request_sync_source(boost::shared_ptr<TransportMaster> tm)734 Session::request_sync_source (boost::shared_ptr<TransportMaster> tm)
735 {
736 	SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportMaster, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
737 	ev->transport_master = tm;
738 	DEBUG_TRACE (DEBUG::Slave, "sent request for new transport master\n");
739 	queue_event (ev);
740 }
741 
742 void
reset_transport_speed(TransportRequestSource origin)743 Session::reset_transport_speed (TransportRequestSource origin)
744 {
745 	request_transport_speed (1.0, true, origin);
746 }
747 
748 void
request_transport_speed(double speed,bool as_default,TransportRequestSource origin)749 Session::request_transport_speed (double speed, bool as_default, TransportRequestSource origin)
750 {
751 	if (synced_to_engine()) {
752 		if (speed != 0) {
753 			_engine.transport_start ();
754 		} else {
755 			_engine.transport_stop ();
756 		}
757 		return;
758 	}
759 
760 	if (speed == 1. || speed == 0. || speed == -1.) {
761 		if (should_ignore_transport_request (origin, TR_StartStop)) {
762 			return;
763 		}
764 	} else {
765 		if (should_ignore_transport_request (origin, TR_Speed)) {
766 			return;
767 		}
768 	}
769 
770 	SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
771 	ev->yes_or_no = as_default; // as_default
772 	DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
773 	queue_event (ev);
774 }
775 
776 /** Request a new transport speed, but if the speed parameter is exactly zero then use
777  *  a very small +ve value to prevent the transport actually stopping.  This method should
778  *  be used by callers who are varying transport speed but don't ever want to stop it.
779  */
780 void
request_transport_speed_nonzero(double speed,bool as_default,TransportRequestSource origin)781 Session::request_transport_speed_nonzero (double speed, bool as_default, TransportRequestSource origin)
782 {
783 	if (speed == 0) {
784 		speed = DBL_EPSILON;
785 	}
786 
787 	request_transport_speed (speed, as_default);
788 }
789 
790 void
request_roll(TransportRequestSource origin)791 Session::request_roll (TransportRequestSource origin)
792 {
793 	if (synced_to_engine()) {
794 		_engine.transport_start ();
795 		return;
796 	}
797 
798 	if (should_ignore_transport_request (origin, TR_StartStop)) {
799 		return;
800 	}
801 
802 	SessionEvent* ev = new SessionEvent (SessionEvent::StartRoll, SessionEvent::Add, SessionEvent::Immediate, 0, false); /* final 2 argumment do not matter */
803 	DEBUG_TRACE (DEBUG::Transport, "Request transport roll\n");
804 	queue_event (ev);
805 }
806 
807 void
request_stop(bool abort,bool clear_state,TransportRequestSource origin)808 Session::request_stop (bool abort, bool clear_state, TransportRequestSource origin)
809 {
810 	if (synced_to_engine()) {
811 		_engine.transport_stop ();
812 		return;
813 	}
814 
815 	if (should_ignore_transport_request (origin, TR_StartStop)) {
816 		return;
817 	}
818 
819 	/* clear our solo-selection, if there is one */
820 	if ( solo_selection_active() ) {
821 		solo_selection ( _soloSelection, false );
822 	}
823 
824 	SessionEvent* ev = new SessionEvent (SessionEvent::EndRoll, SessionEvent::Add, SessionEvent::Immediate, audible_sample(), 0.0, abort, clear_state);
825 	DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, audible %3 transport %4 abort = %1, clear state = %2\n", abort, clear_state, audible_sample(), _transport_sample));
826 	queue_event (ev);
827 }
828 
829 void
request_locate(samplepos_t target_sample,LocateTransportDisposition ltd,TransportRequestSource origin)830 Session::request_locate (samplepos_t target_sample, LocateTransportDisposition ltd, TransportRequestSource origin)
831 {
832 	if (synced_to_engine()) {
833 		_engine.transport_locate (target_sample);
834 		return;
835 	}
836 
837 	if (should_ignore_transport_request (origin, TR_Locate)) {
838 		return;
839 	}
840 
841 	SessionEvent::Type type;
842 
843 	switch (ltd) {
844 	case MustRoll:
845 		type = SessionEvent::LocateRoll;
846 		break;
847 	case MustStop:
848 		type = SessionEvent::Locate;
849 		break;
850 	case RollIfAppropriate:
851 		if (config.get_auto_play()) {
852 			type = SessionEvent::LocateRoll;
853 		} else {
854 			type = SessionEvent::Locate;
855 		}
856 		break;
857 	}
858 
859 	SessionEvent *ev = new SessionEvent (type, SessionEvent::Add, SessionEvent::Immediate, target_sample, 0, false);
860 	ev->locate_transport_disposition = ltd;
861 	DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1 ltd = %2\n", target_sample, enum_2_string (ltd)));
862 	queue_event (ev);
863 }
864 
865 void
force_locate(samplepos_t target_sample,LocateTransportDisposition ltd)866 Session::force_locate (samplepos_t target_sample, LocateTransportDisposition ltd)
867 {
868 	SessionEvent *ev = new SessionEvent (SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_sample, 0, true);
869 	ev->locate_transport_disposition = ltd;
870 	DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1 roll %2\n", target_sample, enum_2_string (ltd)));
871 	queue_event (ev);
872 }
873 
874 void
unset_preroll_record_trim()875 Session::unset_preroll_record_trim ()
876 {
877 	_preroll_record_trim_len = 0;
878 }
879 
880 void
request_preroll_record_trim(samplepos_t rec_in,samplecnt_t preroll)881 Session::request_preroll_record_trim (samplepos_t rec_in, samplecnt_t preroll)
882 {
883 	if (actively_recording ()) {
884 		return;
885 	}
886 	unset_preroll_record_trim ();
887 
888 	config.set_punch_in (false);
889 	config.set_punch_out (false);
890 
891 	samplepos_t pos = std::max ((samplepos_t)0, rec_in - preroll);
892 	_preroll_record_trim_len = preroll;
893 	maybe_enable_record ();
894 	request_locate (pos, MustRoll);
895 	set_requested_return_sample (rec_in);
896 }
897 
898 void
request_count_in_record()899 Session::request_count_in_record ()
900 {
901 	if (actively_recording ()) {
902 		return;
903 	}
904 	if (transport_rolling()) {
905 		return;
906 	}
907 	maybe_enable_record ();
908 	_count_in_once = true;
909 	request_transport_speed (1.0, true);
910 }
911 
912 void
request_play_loop(bool yn,bool change_transport_roll)913 Session::request_play_loop (bool yn, bool change_transport_roll)
914 {
915 	if (transport_master_is_external() && yn) {
916 		// don't attempt to loop when not using Internal Transport
917 		// see also gtk2_ardour/ardour_ui_options.cc parameter_changed()
918 		return;
919 	}
920 
921 	SessionEvent* ev;
922 	Location *location = _locations->auto_loop_location();
923 	double target_speed;
924 
925 	if (location == 0 && yn) {
926 		error << _("Cannot loop - no loop range defined")
927 		      << endmsg;
928 		return;
929 	}
930 
931 	if (change_transport_roll) {
932 		if (transport_rolling()) {
933 			/* start looping at current speed */
934 			target_speed = transport_speed ();
935 		} else {
936 			/* currently stopped */
937 			if (yn) {
938 				/* start looping at normal speed */
939 				target_speed = 1.0;
940 			} else {
941 				target_speed = 0.0;
942 			}
943 		}
944 	} else {
945 		/* leave the speed alone */
946 		target_speed = transport_speed ();
947 	}
948 
949 	ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn, change_transport_roll);
950 	DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
951 	queue_event (ev);
952 }
953 
954 void
request_play_range(list<AudioRange> * range,bool leave_rolling)955 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
956 {
957 	SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
958 	if (range) {
959 		ev->audio_range = *range;
960 	} else {
961 		ev->audio_range.clear ();
962 	}
963 	DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
964 	queue_event (ev);
965 }
966 
967 void
request_cancel_play_range()968 Session::request_cancel_play_range ()
969 {
970 	SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
971 	queue_event (ev);
972 }
973 
974 
975 bool
solo_selection_active()976 Session::solo_selection_active ()
977 {
978 	if (_soloSelection.empty()) {
979 		return false;
980 	}
981 	return true;
982 }
983 
984 void
solo_selection(StripableList & list,bool new_state)985 Session::solo_selection (StripableList &list, bool new_state)
986 {
987 	boost::shared_ptr<ControlList> solo_list (new ControlList);
988 	boost::shared_ptr<ControlList> unsolo_list (new ControlList);
989 
990 	boost::shared_ptr<RouteList> rl = get_routes();
991 
992 	for (ARDOUR::RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
993 
994 		if ( !(*i)->is_track() ) {
995 			continue;
996 		}
997 
998 		boost::shared_ptr<Stripable> s (*i);
999 
1000 		bool found = (std::find(list.begin(), list.end(), s) != list.end());
1001 		if ( found ) {
1002 			/* must invalidate playlists on selected track, so disk reader
1003 			 * will re-fill with the new selection state for solo_selection */
1004 			boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (*i);
1005 			if (track) {
1006 				boost::shared_ptr<Playlist> playlist = track->playlist();
1007 				if (playlist) {
1008 					playlist->ContentsChanged();
1009 				}
1010 			}
1011 		}
1012 
1013 		if ( found & new_state ) {
1014 			solo_list->push_back (s->solo_control());
1015 		} else {
1016 			unsolo_list->push_back (s->solo_control());
1017 		}
1018 	}
1019 
1020 	/* set/unset solos of the associated tracks */
1021 	set_controls (solo_list, 1.0, Controllable::NoGroup);
1022 	set_controls (unsolo_list, 0.0, Controllable::NoGroup);
1023 
1024 	if (new_state)
1025 		_soloSelection = list;
1026 	else
1027 		_soloSelection.clear();
1028 }
1029 
1030 
1031 void
butler_transport_work(bool have_process_lock)1032 Session::butler_transport_work (bool have_process_lock)
1033 {
1034 	/* Note: this function executes in the butler thread context */
1035 
1036   restart:
1037 	boost::shared_ptr<RouteList> r = routes.reader ();
1038 	int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
1039 	bool finished = true;
1040 	PostTransportWork ptw = post_transport_work();
1041 #ifndef NDEBUG
1042 	uint64_t before;
1043 #endif
1044 
1045 	DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = [%1] (0x%3%4%5) at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time()), std::hex, ptw, std::dec));
1046 
1047 	if (ptw & PostTransportLocate) {
1048 
1049 		if (get_play_loop()) {
1050 
1051 			DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
1052 
1053 			/* this locate might be happening while we are
1054 			 * loop recording.
1055 			 *
1056 			 * Non-seamless looping will require a locate (below) that
1057 			 * will reset capture buffers and throw away data.
1058 			 *
1059 			 * Rather than first find all tracks and see if they
1060 			 * have outstanding data, just do a flush anyway. It
1061 			 * may be cheaper this way anyway, and is certainly
1062 			 * more accurate.
1063 			 */
1064 
1065 			bool more_disk_io_to_do = false;
1066 			uint32_t errors = 0;
1067 
1068 			do {
1069 				more_disk_io_to_do = _butler->flush_tracks_to_disk_after_locate (r, errors);
1070 
1071 				if (errors) {
1072 					break;
1073 				}
1074 
1075 				if (more_disk_io_to_do) {
1076 					continue;
1077 				}
1078 
1079 			} while (false);
1080 
1081 		}
1082 	}
1083 
1084 	if (ptw & PostTransportAdjustPlaybackBuffering) {
1085 		/* need to prevent concurrency with ARDOUR::Reader::run(),
1086 		 * DiskWriter::adjust_buffering() re-allocates the ringbuffer */
1087 		Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock (), Glib::Threads::NOT_LOCK);
1088 		if (!have_process_lock) {
1089 			lx.acquire ();
1090 		}
1091 		for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1092 			boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1093 			if (tr) {
1094 				tr->adjust_playback_buffering ();
1095 				/* and refill those buffers ... */
1096 			}
1097 			(*i)->non_realtime_locate (_transport_sample);
1098 		}
1099 		VCAList v = _vca_manager->vcas ();
1100 		for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1101 			(*i)->non_realtime_locate (_transport_sample);
1102 		}
1103 	}
1104 
1105 	if (ptw & PostTransportAdjustCaptureBuffering) {
1106 		/* need to prevent concurrency with ARDOUR::DiskWriter::run(),
1107 		 * DiskWriter::adjust_buffering() re-allocates the ringbuffer */
1108 		Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock (), Glib::Threads::NOT_LOCK);
1109 		if (!have_process_lock) {
1110 			lx.acquire ();
1111 		}
1112 		for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1113 			boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1114 			if (tr) {
1115 				tr->adjust_capture_buffering ();
1116 			}
1117 		}
1118 	}
1119 
1120 	const int butler = g_atomic_int_get (&_butler_seek_counter);
1121 	const int rtlocates = g_atomic_int_get (&_seek_counter);
1122 
1123 	if (butler != rtlocates) {
1124 		DEBUG_TRACE (DEBUG::Transport, string_compose ("nonrealtime locate invoked from BTW (butler has done %1, rtlocs %2)\n", butler, rtlocates));
1125 		non_realtime_locate ();
1126 	}
1127 
1128 	if (ptw & PostTransportStop) {
1129 		non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
1130 		if (!finished) {
1131 			g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1132 			goto restart;
1133 		}
1134 	}
1135 
1136 	if (ptw & PostTransportOverWrite) {
1137 		non_realtime_overwrite (on_entry, finished, (ptw & PostTransportLoopChanged));
1138 		if (!finished) {
1139 			g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1140 			goto restart;
1141 		}
1142 	}
1143 
1144 	if (ptw & PostTransportAudition) {
1145 		non_realtime_set_audition ();
1146 	}
1147 
1148 	g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1149 
1150 	DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs @ %2 ptw %3 trw = %4\n"), g_get_monotonic_time() - before, _transport_sample, enum_2_string (post_transport_work()), _butler->transport_work_requested()));
1151 }
1152 
1153 void
non_realtime_overwrite(int on_entry,bool & finished,bool update_loop_declicks)1154 Session::non_realtime_overwrite (int on_entry, bool& finished, bool update_loop_declicks)
1155 {
1156 	if (update_loop_declicks) {
1157 		DiskReader::reset_loop_declick (_locations->auto_loop_location(), sample_rate());
1158 	}
1159 
1160 	boost::shared_ptr<RouteList> rl = routes.reader();
1161 	for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1162 		boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1163 		if (tr && tr->pending_overwrite ()) {
1164 			tr->overwrite_existing_buffers ();
1165 		}
1166 		if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
1167 			finished = false;
1168 			return;
1169 		}
1170 	}
1171 }
1172 
1173 void
non_realtime_locate()1174 Session::non_realtime_locate ()
1175 {
1176 	DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_sample));
1177 
1178 	if (Config->get_loop_is_mode() && get_play_loop()) {
1179 
1180 		Location *loc  = _locations->auto_loop_location();
1181 
1182 		if (!loc || (_transport_sample < loc->start() || _transport_sample >= loc->end())) {
1183 			/* jumped out of loop range: stop tracks from looping,
1184 			   but leave loop (mode) enabled.
1185 			 */
1186 			set_track_loop (false);
1187 
1188 		} else if (loc && ((loc->start() <= _transport_sample) || (loc->end() > _transport_sample))) {
1189 
1190 			/* jumping to start of loop. This  might have been done before but it is
1191 			 * idempotent and cheap. Doing it here ensures that when we start playback
1192 			 * outside the loop we still flip tracks into the magic seamless mode
1193 			 * when needed.
1194 			 */
1195 			set_track_loop (true);
1196 
1197 		} else if (loc) {
1198 			set_track_loop (false);
1199 		}
1200 
1201 	} else {
1202 
1203 		/* no more looping .. should have been noticed elsewhere */
1204 	}
1205 
1206 	microseconds_t start;
1207 	uint32_t nt = 0;
1208 
1209 	samplepos_t tf;
1210 	gint sc;
1211 
1212 	{
1213 		boost::shared_ptr<RouteList> rl = routes.reader();
1214 
1215 	  restart:
1216 		sc = g_atomic_int_get (&_seek_counter);
1217 		tf = _transport_sample;
1218 		start = get_microseconds ();
1219 
1220 		for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i, ++nt) {
1221 			(*i)->non_realtime_locate (tf);
1222 			if (sc != g_atomic_int_get (&_seek_counter)) {
1223 				goto restart;
1224 			}
1225 		}
1226 
1227 		microseconds_t end = get_microseconds ();
1228 		int usecs_per_track = lrintf ((end - start) / (double) nt);
1229 #ifndef NDEBUG
1230 		std::cerr << "locate to " << tf << " took " << (end - start) << " usecs for " << nt << " tracks = " << usecs_per_track << " per track\n";
1231 #endif
1232 		if (usecs_per_track > g_atomic_int_get (&_current_usecs_per_track)) {
1233 			g_atomic_int_set (&_current_usecs_per_track, usecs_per_track);
1234 		}
1235 	}
1236 
1237 	/* we've caught up with whatever the _seek_counter was when we did the
1238 	   non-realtime locates.
1239 	*/
1240 	g_atomic_int_set (&_butler_seek_counter, sc);
1241 
1242 	{
1243 		/* VCAs are quick to locate because they have no data (except
1244 		   automation) associated with them. Don't bother with a
1245 		   restart mechanism here, but do use the same transport sample
1246 		   that the Routes used.
1247 		*/
1248 		VCAList v = _vca_manager->vcas ();
1249 		for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1250 			(*i)->non_realtime_locate (tf);
1251 		}
1252 	}
1253 
1254 	_scene_changer->locate (_transport_sample);
1255 
1256 	/* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
1257 	   rather than clearing them so that the RT thread has to spend time constructing
1258 	   them (in Session::click).
1259 	 */
1260 	clear_clicks ();
1261 }
1262 
1263 bool
select_playhead_priority_target(samplepos_t & jump_to)1264 Session::select_playhead_priority_target (samplepos_t& jump_to)
1265 {
1266 	if (!transport_master_no_external_or_using_engine() || !config.get_auto_return()) {
1267 		return false;
1268 	}
1269 
1270 	jump_to = _last_roll_location;
1271 	return jump_to >= 0;
1272 }
1273 
1274 void
follow_playhead_priority()1275 Session::follow_playhead_priority ()
1276 {
1277 	samplepos_t target;
1278 
1279 	if (select_playhead_priority_target (target)) {
1280 		request_locate (target);
1281 	}
1282 }
1283 
1284 void
non_realtime_stop(bool abort,int on_entry,bool & finished)1285 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
1286 {
1287 	struct tm* now;
1288 	time_t     xnow;
1289 	bool       did_record;
1290 	bool       saved;
1291 	PostTransportWork ptw = post_transport_work();
1292 
1293 	did_record = false;
1294 	saved = false;
1295 
1296 	boost::shared_ptr<RouteList> rl = routes.reader();
1297 	for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1298 		boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1299 		if (tr && tr->get_captured_samples () != 0) {
1300 			did_record = true;
1301 			break;
1302 		}
1303 	}
1304 
1305 	/* stop and locate are merged here because they share a lot of common stuff */
1306 
1307 	time (&xnow);
1308 	now = localtime (&xnow);
1309 
1310 	if (auditioner) {
1311 		auditioner->cancel_audition ();
1312 	}
1313 
1314 	if (did_record) {
1315 		begin_reversible_command (Operations::capture);
1316 		_have_captured = true;
1317 	}
1318 
1319 	DEBUG_TRACE (DEBUG::Transport, X_("Butler post-transport-work, non realtime stop\n"));
1320 
1321 	if (abort && did_record) {
1322 		/* no reason to save the session file when we remove sources
1323 		 */
1324 		_state_of_the_state = StateOfTheState (_state_of_the_state | InCleanup);
1325 	}
1326 
1327 	for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1328 		boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1329 		if (tr) {
1330 			tr->transport_stopped_wallclock (*now, xnow, abort);
1331 		}
1332 	}
1333 
1334 	if (abort && did_record) {
1335 		_state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1336 	}
1337 
1338 	boost::shared_ptr<RouteList> r = routes.reader ();
1339 
1340 	if (did_record) {
1341 		commit_reversible_command ();
1342 		/* increase take name */
1343 		if (config.get_track_name_take () && !config.get_take_name ().empty()) {
1344 			string newname = config.get_take_name();
1345 			config.set_take_name(bump_name_number (newname));
1346 		}
1347 	}
1348 
1349 	if (_engine.running()) {
1350 		PostTransportWork ptw = post_transport_work ();
1351 
1352 		for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1353 			(*i)->non_realtime_transport_stop (_transport_sample, !(ptw & PostTransportLocate));
1354 		}
1355 		VCAList v = _vca_manager->vcas ();
1356 		for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1357 			(*i)->non_realtime_transport_stop (_transport_sample, !(ptw & PostTransportLocate));
1358 		}
1359 	}
1360 
1361 	/* If we are not synced to a "true" external master, and we're not
1362 	 * handling an explicit locate, we should consider whether or not to
1363 	 * "auto-return". This could mean going to a specifically requested
1364 	 * location, or just back to the start of the last roll.
1365 	 */
1366 
1367 	if (transport_master_no_external_or_using_engine() && !locate_initiated()) {
1368 
1369 		bool do_locate = false;
1370 
1371 		if (_requested_return_sample >= 0) {
1372 
1373 			/* explicit return request pre-queued in event list. overrides everything else */
1374 
1375 			_transport_sample = _requested_return_sample;
1376 
1377 			/* cancel this request */
1378 			_requested_return_sample = -1;
1379 			do_locate = true;
1380 
1381 		} else if (Config->get_auto_return_target_list()) {
1382 
1383 			samplepos_t jump_to;
1384 
1385 			if (select_playhead_priority_target (jump_to)) {
1386 
1387 				/* there's a valid target (we don't care how it
1388 				 * was derived here)
1389 				 */
1390 
1391 				_transport_sample = jump_to;
1392 				do_locate = true;
1393 
1394 			} else if (abort) {
1395 
1396 				/* roll aborted (typically capture) with
1397 				 * auto-return enabled
1398 				 */
1399 
1400 				if (_last_roll_location >= 0) {
1401 					_transport_sample = _last_roll_location;
1402 					do_locate = true;
1403 				}
1404 			}
1405 		}
1406 
1407 
1408 		if (do_locate && synced_to_engine()) {
1409 
1410 			/* We will unconditionally locate to _transport_sample
1411 			 * below, which will refill playback buffers based on
1412 			 * _transport_sample, and maximises the buffering they
1413 			 * represent.
1414 			 *
1415 			 * But if we are synced to engine (JACK), we should
1416 			 * locate the engine (JACK) as well. We would follow
1417 			 * the engine (JACK) on the next process cycle, but
1418 			 * since we're going to do a locate below anyway,
1419 			 * it seems pointless to not use just do it ourselves
1420 			 * right now, rather than wait for the engine (JACK) to
1421 			 * provide the new position on the next cycle.
1422 			 *
1423 			 * Despite the generic name of the called method
1424 			 * (::transport_locate()) this method only does
1425 			 * anything if the audio/MIDI backend is JACK.
1426 			 */
1427 
1428 			_engine.transport_locate (_transport_sample);
1429 
1430 		}
1431 	}
1432 
1433 	clear_clicks();
1434 	unset_preroll_record_trim ();
1435 
1436 	/* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
1437 	*/
1438 
1439 	if (ptw & (PostTransportClearSubstate|PostTransportStop)) {
1440 		unset_play_range ();
1441 		if (!Config->get_loop_is_mode() && get_play_loop() && !loop_changing) {
1442 			unset_play_loop ();
1443 		}
1444 	}
1445 
1446 	/* reset loop_changing so it does not affect next transport action */
1447 	loop_changing = false;
1448 
1449 	if (!_transport_fsm->declicking_for_locate()) {
1450 
1451 		DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
1452 
1453 		for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1454 			DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
1455 			(*i)->non_realtime_locate (_transport_sample);
1456 
1457 			if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
1458 				finished = false;
1459 				/* we will be back */
1460 				return;
1461 			}
1462 		}
1463 
1464 		VCAList v = _vca_manager->vcas ();
1465 		for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1466 			(*i)->non_realtime_locate (_transport_sample);
1467 		}
1468 	}
1469 
1470 	have_looped = false;
1471 
1472 	/* don't bother with this stuff if we're disconnected from the engine,
1473 	   because there will be no process callbacks to deliver stuff from
1474 	*/
1475 
1476 	if (_engine.running() && !_engine.freewheeling()) {
1477 		// need to queue this in the next RT cycle
1478 		_send_timecode_update = true;
1479 
1480 		if (transport_master()->type() != MTC) { // why?
1481 			send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
1482 
1483 			/* This (::non_realtime_stop()) gets called by main
1484 			   process thread, which will lead to confusion
1485 			   when calling AsyncMIDIPort::write().
1486 
1487 			   Something must be done. XXX
1488 			*/
1489 			send_mmc_locate (_transport_sample);
1490 		}
1491 	}
1492 
1493 	if ((ptw & PostTransportLocate) && get_record_enabled()) {
1494 		/* This is scheduled by realtime_stop(), which is also done
1495 		 * when a slave requests /locate/ for an initial sync.
1496 		 * We can't hold up the slave for long with a save() here,
1497 		 * without breaking its initial sync cycle.
1498 		 *
1499 		 * save state only if there's no slave or if it's not yet locked.
1500 		 */
1501 		if (!transport_master_is_external() || !transport_master()->locked()) {
1502 			DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
1503 			SaveSessionRequested (_current_snapshot_name);
1504 			saved = true;
1505 		}
1506 	}
1507 
1508 	/* save the current state of things if appropriate */
1509 
1510 	if (did_record && !saved) {
1511 		SaveSessionRequested (_current_snapshot_name);
1512 	}
1513 
1514 	PositionChanged (_transport_sample); /* EMIT SIGNAL */
1515 	DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_fsm->transport_speed()));
1516 	TransportStateChange (); /* EMIT SIGNAL */
1517 	AutomationWatch::instance().transport_stop_automation_watches (_transport_sample);
1518 }
1519 
1520 void
set_play_loop(bool yn,bool change_transport_state)1521 Session::set_play_loop (bool yn, bool change_transport_state)
1522 {
1523 	ENSURE_PROCESS_THREAD;
1524 	/* Called from event-handling context */
1525 
1526 	DEBUG_TRACE (DEBUG::Transport, string_compose ("set_play_loop (%1)\n", yn));
1527 
1528 	Location *loc;
1529 
1530 	if (yn == get_play_loop () || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
1531 		/* nothing to do, or can't change loop status while recording */
1532 		return;
1533 	}
1534 
1535 	if (yn && synced_to_engine()) {
1536 		warning << string_compose (
1537 			_("Looping cannot be supported while %1 is using JACK transport.\n"
1538 			  "Recommend changing the configured options"), PROGRAM_NAME)
1539 			<< endmsg;
1540 		return;
1541 	}
1542 
1543 	if (yn && !maybe_allow_only_loop (true)) {
1544 		return;
1545 	}
1546 
1547 	if (yn) {
1548 
1549 		play_loop = true;
1550 		have_looped = false;
1551 
1552 		unset_play_range ();
1553 		/* set all tracks to use internal looping */
1554 		set_track_loop (true);
1555 
1556 		merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
1557 
1558 		if (!Config->get_loop_is_mode()) {
1559 			if (transport_rolling()) {
1560 				/* set loop_changing to ensure that non_realtime_stop does not unset_play_loop */
1561 				loop_changing = true;
1562 			}
1563 			/* args: position, disposition, for_loop_end=false, force=true */
1564 			TFSM_LOCATE (loc->start(), MustRoll, false, true);
1565 		} else {
1566 			if (!transport_rolling()) {
1567 				/* loop-is-mode: not rolling, just locate to loop start */
1568 				TFSM_LOCATE (loc->start(), MustStop, false, true);
1569 			}
1570 		}
1571 		TransportStateChange (); /* EMIT SIGNAL */
1572 	} else {
1573 		unset_play_loop ();
1574 	}
1575 
1576 	DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_fsm->transport_speed()));
1577 }
1578 
1579 void
unset_play_loop(bool change_transport_state)1580 Session::unset_play_loop (bool change_transport_state)
1581 {
1582 	if (!get_play_loop()) {
1583 		return;
1584 	}
1585 
1586 	play_loop = false;
1587 	clear_events (SessionEvent::AutoLoop);
1588 	set_track_loop (false);
1589 
1590 	/* likely need to flush track buffers: this will locate us to wherever we are */
1591 
1592 	if (change_transport_state && transport_rolling ()) {
1593 		TFSM_STOP (false, false);
1594 	}
1595 
1596 	overwrite_some_buffers (boost::shared_ptr<Route>(), LoopDisabled);
1597 	TransportStateChange (); /* EMIT SIGNAL */
1598 }
1599 
1600 void
set_track_loop(bool yn)1601 Session::set_track_loop (bool yn)
1602 {
1603 	Location* loc = _locations->auto_loop_location ();
1604 
1605 	if (!loc) {
1606 		yn = false;
1607 	}
1608 
1609 	boost::shared_ptr<RouteList> rl = routes.reader ();
1610 
1611 	for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1612 		if (*i && !(*i)->is_private_route()) {
1613 			(*i)->set_loop (yn ? loc : 0);
1614 		}
1615 	}
1616 
1617 	DiskReader::reset_loop_declick (loc, nominal_sample_rate());
1618 }
1619 
1620 samplecnt_t
worst_latency_preroll() const1621 Session::worst_latency_preroll () const
1622 {
1623 	return _worst_output_latency + _worst_input_latency;
1624 }
1625 
1626 samplecnt_t
worst_latency_preroll_buffer_size_ceil() const1627 Session::worst_latency_preroll_buffer_size_ceil () const
1628 {
1629 	return lrintf (ceil ((_worst_output_latency + _worst_input_latency) / (float) current_block_size) * current_block_size);
1630 }
1631 
1632 void
unset_play_range()1633 Session::unset_play_range ()
1634 {
1635 	_play_range = false;
1636 	_clear_event_type (SessionEvent::RangeStop);
1637 	_clear_event_type (SessionEvent::RangeLocate);
1638 }
1639 
1640 void
set_play_range(list<AudioRange> & range,bool leave_rolling)1641 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1642 {
1643 	SessionEvent* ev;
1644 
1645 	/* Called from event-processing context */
1646 
1647 	unset_play_range ();
1648 
1649 	if (range.empty()) {
1650 		/* _play_range set to false in unset_play_range()
1651 		 */
1652 		if (!leave_rolling) {
1653 			/* stop transport */
1654 			SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1655 			merge_event (ev);
1656 		}
1657 		return;
1658 	}
1659 
1660 	_play_range = true;
1661 
1662 	/* cancel loop play */
1663 	unset_play_loop ();
1664 
1665 	list<AudioRange>::size_type sz = range.size();
1666 
1667 	if (sz > 1) {
1668 
1669 		list<AudioRange>::iterator i = range.begin();
1670 		list<AudioRange>::iterator next;
1671 
1672 		while (i != range.end()) {
1673 
1674 			next = i;
1675 			++next;
1676 
1677 			/* locating/stopping is subject to delays for declicking.
1678 			 */
1679 
1680 			samplepos_t requested_sample = i->end;
1681 
1682 			if (requested_sample > current_block_size) {
1683 				requested_sample -= current_block_size;
1684 			} else {
1685 				requested_sample = 0;
1686 			}
1687 
1688 			if (next == range.end()) {
1689 				ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_sample, 0, 0.0f);
1690 			} else {
1691 				ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_sample, (*next).start, 0.0f);
1692 			}
1693 
1694 			merge_event (ev);
1695 
1696 			i = next;
1697 		}
1698 
1699 	} else if (sz == 1) {
1700 
1701 		ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1702 		merge_event (ev);
1703 
1704 	}
1705 
1706 	/* save range so we can do auto-return etc. */
1707 
1708 	current_audio_range = range;
1709 
1710 	/* now start rolling at the right place */
1711 
1712 	ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1713 	merge_event (ev);
1714 
1715 	DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_fsm->transport_speed()));
1716 	TransportStateChange (); /* EMIT SIGNAL */
1717 }
1718 
1719 void
request_bounded_roll(samplepos_t start,samplepos_t end)1720 Session::request_bounded_roll (samplepos_t start, samplepos_t end)
1721 {
1722 	AudioRange ar (start, end, 0);
1723 	list<AudioRange> lar;
1724 
1725 	lar.push_back (ar);
1726 	request_play_range (&lar, true);
1727 }
1728 
1729 void
set_requested_return_sample(samplepos_t return_to)1730 Session::set_requested_return_sample (samplepos_t return_to)
1731 {
1732 	_requested_return_sample = return_to;
1733 }
1734 
1735 void
request_roll_at_and_return(samplepos_t start,samplepos_t return_to)1736 Session::request_roll_at_and_return (samplepos_t start, samplepos_t return_to)
1737 {
1738 	SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1739 	ev->target2_sample = start;
1740 	queue_event (ev);
1741 }
1742 
1743 void
engine_halted()1744 Session::engine_halted ()
1745 {
1746 	/* there will be no more calls to process(), so
1747 	   we'd better clean up for ourselves, right now.
1748 
1749 	   We can't queue SessionEvents because they only get
1750 	   handled from within a process callback.
1751 	*/
1752 
1753 	/* this just stops the FSM engine ... it doesn't change the state of
1754 	 * the FSM directly or anything else ... but the FSM will be
1755 	 * reinitialized when we call its ::start() method from
1756 	 * ::engine_running() (if we ever get there)
1757 	 */
1758 
1759 	_transport_fsm->stop ();
1760 
1761 	/* Synchronously do the realtime part of a transport stop.
1762 	 *
1763 	 * Calling this will cause the butler to asynchronously run
1764 	 * ::non_realtime_stop() where the rest of the "stop" work will be
1765 	 * done.
1766 	 */
1767 
1768 	realtime_stop (false, true);
1769 }
1770 
1771 void
engine_running()1772 Session::engine_running ()
1773 {
1774 	_transport_fsm->start ();
1775 	reset_xrun_count ();
1776 }
1777 
1778 void
xrun_recovery()1779 Session::xrun_recovery ()
1780 {
1781 	++_xrun_count;
1782 
1783 	Xrun (_transport_sample); /* EMIT SIGNAL */
1784 
1785 	if (actively_recording ()) {
1786 		++_capture_xruns;
1787 
1788 		if (Config->get_stop_recording_on_xrun()) {
1789 
1790 			/* it didn't actually halt, but we need
1791 			 * to handle things in the same way.
1792 			 */
1793 
1794 			engine_halted();
1795 
1796 			/* ..and start the FSM engine again */
1797 			_transport_fsm->start ();
1798 		} else {
1799 			boost::shared_ptr<RouteList> rl = routes.reader();
1800 			for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1801 				boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1802 				if (tr) {
1803 					tr->mark_capture_xrun ();
1804 				}
1805 			}
1806 
1807 		}
1808 	}
1809 	else if (_exporting && _realtime_export && _export_rolling) {
1810 		++_export_xruns;
1811 	}
1812 }
1813 
1814 void
reset_xrun_count()1815 Session::reset_xrun_count ()
1816 {
1817 	_xrun_count = 0;
1818 	ARDOUR::reset_performance_meters (this);
1819 	Xrun (-1); /* EMIT SIGNAL */
1820 }
1821 
1822 void
route_processors_changed(RouteProcessorChange c)1823 Session::route_processors_changed (RouteProcessorChange c)
1824 {
1825 	if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
1826 		g_atomic_int_set (&_ignored_a_processor_change, 1);
1827 		return;
1828 	}
1829 
1830 	if (c.type == RouteProcessorChange::MeterPointChange) {
1831 		set_dirty ();
1832 		return;
1833 	}
1834 
1835 	if (c.type == RouteProcessorChange::RealTimeChange) {
1836 		set_dirty ();
1837 		return;
1838 	}
1839 
1840 	resort_routes ();
1841 	update_latency_compensation (false, false);
1842 
1843 	set_dirty ();
1844 }
1845 
1846 void
allow_auto_play(bool yn)1847 Session::allow_auto_play (bool yn)
1848 {
1849 	auto_play_legal = yn;
1850 }
1851 
1852 
1853 void
send_mmc_locate(samplepos_t t)1854 Session::send_mmc_locate (samplepos_t t)
1855 {
1856 	if (t < 0) {
1857 		return;
1858 	}
1859 
1860 	if (!_engine.freewheeling()) {
1861 		Timecode::Time time;
1862 		timecode_time_subframes (t, time);
1863 		send_immediate_mmc (MIDI::MachineControlCommand (time));
1864 	}
1865 }
1866 
1867 /** Ask the transport to not send timecode until further notice.  The suspension
1868  *  will come into effect some finite time after this call, and timecode_transmission_suspended()
1869  *  should be checked by the caller to find out when.
1870  */
1871 void
request_suspend_timecode_transmission()1872 Session::request_suspend_timecode_transmission ()
1873 {
1874 	SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
1875 	queue_event (ev);
1876 }
1877 
1878 void
request_resume_timecode_transmission()1879 Session::request_resume_timecode_transmission ()
1880 {
1881 	SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
1882 	queue_event (ev);
1883 }
1884 
1885 bool
timecode_transmission_suspended() const1886 Session::timecode_transmission_suspended () const
1887 {
1888 	return g_atomic_int_get (&_suspend_timecode_transmission) == 1;
1889 }
1890 
1891 boost::shared_ptr<TransportMaster>
transport_master() const1892 Session::transport_master() const
1893 {
1894 	return TransportMasterManager::instance().current();
1895 }
1896 
1897 bool
transport_master_is_external() const1898 Session::transport_master_is_external () const
1899 {
1900 	return TransportMasterManager::instance().current() && config.get_external_sync();
1901 }
1902 
1903 bool
transport_master_no_external_or_using_engine() const1904 Session::transport_master_no_external_or_using_engine () const
1905 {
1906 	return !TransportMasterManager::instance().current() || !config.get_external_sync() || (TransportMasterManager::instance().current()->type() == Engine);
1907 }
1908 
1909 void
sync_source_changed(SyncSource type,samplepos_t pos,pframes_t cycle_nframes)1910 Session::sync_source_changed (SyncSource type, samplepos_t pos, pframes_t cycle_nframes)
1911 {
1912 	/* Runs in process() context */
1913 
1914 	boost::shared_ptr<TransportMaster> master = TransportMasterManager::instance().current();
1915 
1916 	if (master->can_loop()) {
1917 		request_play_loop (false);
1918 	} else if (master->has_loop()) {
1919 		request_play_loop (true);
1920 	}
1921 
1922 	/* slave change, reset any DiskIO block on disk output because it is no
1923 	   longer valid with a new slave.
1924 	*/
1925 
1926 	TransportMasterManager::instance().unblock_disk_output ();
1927 
1928 #if 0
1929 	we should not be treating specific transport masters as special cases because there maybe > 1 of a particular type
1930 
1931 	boost::shared_ptr<MTC_TransportMaster> mtc_master = boost::dynamic_pointer_cast<MTC_TransportMaster> (master);
1932 
1933 	if (mtc_master) {
1934 		mtc_master->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1935 		MTCSyncStateChanged(mtc_master->locked() );
1936 	} else {
1937 		if (g_atomic_int_compare_and_exchange (&_mtc_active, 1, 0)) {
1938 			MTCSyncStateChanged( false );
1939 		}
1940 		mtc_status_connection.disconnect ();
1941 	}
1942 
1943 	boost::shared_ptr<LTC_TransportMaster> ltc_master = boost::dynamic_pointer_cast<LTC_TransportMaster> (master);
1944 
1945 	if (ltc_master) {
1946 		ltc_master->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1947 		LTCSyncStateChanged (ltc_master->locked() );
1948 	} else {
1949 		if (g_atomic_int_compare_and_exchange (&_ltc_active, 1, 0)) {
1950 			LTCSyncStateChanged( false );
1951 		}
1952 		ltc_status_connection.disconnect ();
1953 	}
1954 #endif
1955 
1956 	DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", master));
1957 
1958 	// need to queue this for next process() cycle
1959 	_send_timecode_update = true;
1960 
1961 	boost::shared_ptr<RouteList> rl = routes.reader();
1962 	const bool externally_slaved = transport_master_is_external();
1963 
1964 	for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1965 		boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1966 		if (tr && !tr->is_private_route()) {
1967 			tr->set_slaved (externally_slaved);
1968 		}
1969 	}
1970 
1971 	set_dirty();
1972 }
1973 
1974 bool
transport_stopped() const1975 Session::transport_stopped() const
1976 {
1977 	return _transport_fsm->stopped();
1978 }
1979 
1980 bool
transport_stopped_or_stopping() const1981 Session::transport_stopped_or_stopping() const
1982 {
1983 	return _transport_fsm->stopped() || _transport_fsm->stopping();
1984 }
1985 
1986 bool
transport_state_rolling() const1987 Session::transport_state_rolling() const
1988 {
1989 	return _transport_fsm->rolling();
1990 }
1991 
1992 bool
transport_rolling() const1993 Session::transport_rolling() const
1994 {
1995 	return _transport_fsm->transport_speed() != 0.0 && _count_in_samples == 0 && _remaining_latency_preroll == 0;
1996 }
1997 
1998 bool
locate_pending() const1999 Session::locate_pending () const
2000 {
2001 	return _transport_fsm->locating();
2002 }
2003 
2004 bool
locate_initiated() const2005 Session::locate_initiated() const
2006 {
2007 	return _transport_fsm->declicking_for_locate() || _transport_fsm->locating();
2008 }
2009 
2010 bool
declick_in_progress() const2011 Session::declick_in_progress () const
2012 {
2013 	return _transport_fsm->declick_in_progress();
2014 }
2015 
2016 bool
transport_will_roll_forwards() const2017 Session::transport_will_roll_forwards () const
2018 {
2019 	return _transport_fsm->will_roll_fowards ();
2020 }
2021 
2022 double
transport_speed() const2023 Session::transport_speed() const
2024 {
2025 	if (_transport_fsm->transport_speed() != _transport_fsm->transport_speed()) {
2026 		// cerr << "\n\n!!TS " << _transport_fsm->transport_speed() << " TFSM::speed " << _transport_fsm->transport_speed() << " via " << _transport_fsm->current_state() << endl;
2027 	}
2028 	return _count_in_samples > 0 ? 0. : _transport_fsm->transport_speed();
2029 }
2030 
2031 double
actual_speed() const2032 Session::actual_speed() const
2033 {
2034 	if (_transport_fsm->transport_speed() > 0) return _engine_speed;
2035 	if (_transport_fsm->transport_speed() < 0) return - _engine_speed;
2036 	return 0;
2037 }
2038