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>
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.
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.
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.
28 #include "libardour-config.h"
36 #include "pbd/error.h"
37 #include "pbd/enumwriter.h"
38 #include "pbd/pthread_utils.h"
39 #include "pbd/memento_command.h"
40 #include "pbd/stacktrace.h"
42 #include "midi++/mmc.h"
43 #include "midi++/port.h"
45 #include "ardour/audioengine.h"
46 #include "ardour/auditioner.h"
47 #include "ardour/automation_watch.h"
48 #include "ardour/butler.h"
49 #include "ardour/click.h"
50 #include "ardour/debug.h"
51 #include "ardour/disk_reader.h"
52 #include "ardour/location.h"
53 #include "ardour/playlist.h"
54 #include "ardour/profile.h"
55 #include "ardour/scene_changer.h"
56 #include "ardour/session.h"
57 #include "ardour/transport_master.h"
58 #include "ardour/transport_master_manager.h"
59 #include "ardour/tempo.h"
60 #include "ardour/operations.h"
61 #include "ardour/vca.h"
62 #include "ardour/vca_manager.h"
67 using namespace ARDOUR;
72 # define ENSURE_PROCESS_THREAD do {} while (0)
74 # define ENSURE_PROCESS_THREAD \
76 if (!AudioEngine::instance()->in_process_thread()) { \
77 PBD::stacktrace (std::cerr, 10); \
83 /* *****************************************************************************
84 * REALTIME ACTIONS (to be called on state transtion
85 * ****************************************************************************/
88 Session::realtime_stop (bool abort, bool clear_state)
90 ENSURE_PROCESS_THREAD;
92 DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_sample));
93 PostTransportWork todo = PostTransportWork (0);
95 /* assume that when we start, we'll be moving forwards */
97 if (_transport_speed < 0.0f) {
98 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
99 _default_transport_speed = 1.0;
101 todo = PostTransportWork (todo | PostTransportStop);
106 boost::shared_ptr<RouteList> r = routes.reader ();
108 for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
109 (*i)->realtime_handle_transport_stopped ();
112 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_sample));
114 /* the duration change is not guaranteed to have happened, but is likely */
116 todo = PostTransportWork (todo | PostTransportDuration);
119 todo = PostTransportWork (todo | PostTransportAbort);
123 todo = PostTransportWork (todo | PostTransportClearSubstate);
127 add_post_transport_work (todo);
130 _clear_event_type (SessionEvent::StopOnce);
131 _clear_event_type (SessionEvent::RangeStop);
132 _clear_event_type (SessionEvent::RangeLocate);
134 //clear our solo-selection, if there is one
135 if ( solo_selection_active() ) {
136 solo_selection ( _soloSelection, false );
139 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
140 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
142 if (clear_state && !Config->get_loop_is_mode()) {
146 reset_slave_state ();
148 _transport_speed = 0;
149 _target_transport_speed = 0;
152 g_atomic_int_set (&_playback_load, 100);
153 g_atomic_int_set (&_capture_load, 100);
155 if (config.get_use_video_sync()) {
156 waiting_for_sync_offset = true;
159 transport_sub_state = 0;
163 Session::realtime_locate ()
165 ENSURE_PROCESS_THREAD;
167 boost::shared_ptr<RouteList> r = routes.reader ();
168 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
169 (*i)->realtime_locate ();
174 Session::start_locate (samplepos_t target_sample, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
176 ENSURE_PROCESS_THREAD;
178 if (target_sample < 0) {
179 error << _("Locate called for negative sample position - ignored") << endmsg;
183 if (synced_to_engine()) {
187 samplepos_t ignore1, ignore2;
189 transport_master()->speed_and_position (sp, pos, ignore1, ignore2, 0);
191 if (target_sample != pos) {
193 if (config.get_jack_time_master()) {
194 /* actually locate now, since otherwise jack_timebase_callback
195 will use the incorrect _transport_sample and report an old
196 and incorrect time to Jack transport
198 locate (target_sample, with_roll, with_flush, for_loop_enabled, force);
201 /* tell JACK to change transport position, and we will
202 follow along later in ::follow_slave()
205 _engine.transport_locate (target_sample);
207 if (sp != 1.0f && with_roll) {
208 _engine.transport_start ();
214 locate (target_sample, with_roll, with_flush, for_loop_enabled, force);
218 /** @param with_mmc true to send a MMC locate command when the locate is done */
220 Session::locate (samplepos_t target_sample, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
222 ENSURE_PROCESS_THREAD;
224 bool need_butler = false;
226 /* Locates for seamless looping are fairly different from other
227 * locates. They assume that the diskstream buffers for each track
228 * already have the correct data in them, and thus there is no need to
229 * actually tell the tracks to locate. What does need to be done,
230 * though, is all the housekeeping that is associated with non-linear
231 * changes in the value of _transport_sample.
234 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
235 target_sample, with_roll, with_flush, for_loop_enabled, force, with_mmc));
237 if (!force && _transport_sample == target_sample && !loop_changing && !for_loop_enabled) {
239 /* already at the desired position. Not forced to locate,
240 the loop isn't changing, so unless we're told to
241 start rolling also, there's nothing to do but
242 tell the world where we are (again).
246 set_transport_speed (1.0, 0, false);
248 loop_changing = false;
249 Located (); /* EMIT SIGNAL */
253 cerr << "... now doing the actual locate to " << target_sample << " from " << _transport_sample << endl;
255 // Update Timecode time
256 _transport_sample = target_sample;
257 // Bump seek counter so that any in-process locate in the butler
258 // thread(s?) can restart.
259 g_atomic_int_inc (&_seek_counter);
260 _last_roll_or_reversal_location = target_sample;
261 _remaining_latency_preroll = worst_latency_preroll ();
262 timecode_time(_transport_sample, transmitting_timecode_time); // XXX here?
264 /* do "stopped" stuff if:
267 * no autoplay in effect AND
268 * we're not going to keep rolling after the locate AND
269 * !(playing a loop with JACK sync)
273 bool transport_was_stopped = !transport_rolling();
275 if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
276 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
277 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
278 transport_was_stopped = true;
280 /* otherwise tell the world that we located */
284 if (force || !for_loop_enabled || loop_changing) {
286 PostTransportWork todo = PostTransportLocate;
288 if (with_roll && transport_was_stopped) {
289 todo = PostTransportWork (todo | PostTransportRoll);
292 add_post_transport_work (todo);
297 /* this is functionally what clear_clicks() does but with a tentative lock */
299 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
301 if (clickm.locked()) {
303 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
312 /* switch from input if we're going to roll */
313 if (Config->get_monitoring_model() == HardwareMonitoring) {
314 set_track_monitor_input_status (!config.get_auto_input());
317 /* otherwise we're going to stop, so do the opposite */
318 if (Config->get_monitoring_model() == HardwareMonitoring) {
319 set_track_monitor_input_status (true);
323 /* cancel looped playback if transport pos outside of loop range */
326 Location* al = _locations->auto_loop_location();
329 if (_transport_sample < al->start() || _transport_sample >= al->end()) {
331 // located outside the loop: cancel looping directly, this is called from event handling context
335 if (!Config->get_loop_is_mode()) {
336 set_play_loop (false, _transport_speed);
338 if (Config->get_seamless_loop()) {
339 /* this will make the non_realtime_locate() in the butler
340 which then causes seek() in tracks actually do the right
343 set_track_loop (false);
347 } else if (_transport_sample == al->start()) {
349 // located to start of loop - this is looping, basically
353 if (_last_roll_location != al->start()) {
354 /* didn't start at loop start - playback must have
355 * started before loop since we've now hit the loop
358 add_post_transport_work (PostTransportLocate);
364 boost::shared_ptr<RouteList> rl = routes.reader();
366 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
367 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
369 if (tr && tr->rec_enable_control()->get_value()) {
370 // tell it we've looped, so it can deal with the record state
371 tr->transport_looped (_transport_sample);
376 TransportLooped(); // EMIT SIGNAL
382 _butler->schedule_transport_work ();
385 loop_changing = false;
387 _send_timecode_update = true;
390 send_mmc_locate (_transport_sample);
393 _last_roll_location = _last_roll_or_reversal_location = _transport_sample;
394 if (!synced_to_engine () || _transport_sample == _engine.transport_sample ()) {
395 Located (); /* EMIT SIGNAL */
399 /** Set the transport speed.
400 * Called from the process thread.
401 * @param speed New speed
404 Session::set_transport_speed (double speed, samplepos_t destination_sample, bool abort, bool clear_state, bool as_default)
406 ENSURE_PROCESS_THREAD;
407 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
408 speed, abort, clear_state, _transport_speed, _transport_sample, as_default));
410 /* max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
411 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
415 speed = min ((double) Config->get_max_transport_speed(), speed);
416 } else if (speed < 0) {
417 speed = max ((double) -Config->get_max_transport_speed(), speed);
420 double new_engine_speed = 1.0;
422 new_engine_speed = fabs (speed);
423 if (speed < 0) speed = -1;
424 if (speed > 0) speed = 1;
427 if (_transport_speed == speed && new_engine_speed == _engine_speed) {
428 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
429 _default_transport_speed = 1.0;
434 #if 0 // TODO pref: allow vari-speed recording
435 if (actively_recording() && speed != 1.0 && speed != 0.0) {
436 /* no varispeed during recording */
437 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, sample %2\n",
438 _transport_speed, _transport_sample));
443 _target_transport_speed = fabs(speed);
444 _engine_speed = new_engine_speed;
446 if (transport_rolling() && speed == 0.0) {
448 /* we are rolling and we want to stop */
450 if (Config->get_monitoring_model() == HardwareMonitoring) {
451 set_track_monitor_input_status (true);
454 if (synced_to_engine ()) {
456 /* do this here because our response to the slave won't
460 _count_in_once = false;
463 _engine.transport_stop ();
465 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
467 if (!auto_return_enabled) {
468 _requested_return_sample = destination_sample;
471 stop_transport (abort);
474 } else if (transport_stopped() && speed == 1.0) {
476 _default_transport_speed = speed;
478 /* we are stopped and we want to start rolling at speed 1 */
480 if (Config->get_loop_is_mode() && play_loop) {
482 Location *location = _locations->auto_loop_location();
485 if (_transport_sample != location->start()) {
487 if (Config->get_seamless_loop()) {
488 /* force tracks to do their thing */
489 set_track_loop (true);
492 /* jump to start and then roll from there */
494 request_locate (location->start(), true);
500 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
501 set_track_monitor_input_status (false);
504 if (synced_to_engine()) {
505 _engine.transport_start ();
506 _count_in_once = false;
513 /* not zero, not 1.0 ... varispeed */
515 // TODO handled transport start.. _remaining_latency_preroll
516 // and reversal of playback direction.
518 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
519 warning << string_compose (
520 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
527 if (actively_recording()) {
532 if (speed > 0.0 && _transport_sample == current_end_sample()) {
536 if (speed < 0.0 && _transport_sample == 0) {
542 /* if we are reversing relative to the current speed, or relative to the speed
543 before the last stop, then we have to do extra work.
546 PostTransportWork todo = PostTransportWork (0);
548 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
549 todo = PostTransportWork (todo | PostTransportReverse);
550 _last_roll_or_reversal_location = _transport_sample;
553 _last_transport_speed = _transport_speed;
554 _transport_speed = speed;
557 _default_transport_speed = speed;
561 add_post_transport_work (todo);
562 _butler->schedule_transport_work ();
565 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
567 /* throttle signal emissions.
568 * when slaved [_last]_transport_speed
569 * usually changes every cycle (tiny amounts due to DLL).
570 * Emitting a signal every cycle is overkill and unwarranted.
572 * Using _last_transport_speed is not acceptable,
573 * since it allows for large changes over a long period
574 * of time. Hence we introduce a dedicated variable to keep track
576 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
577 * for TransportStateChange() here is the ShuttleControl display.
579 if (fabs (_signalled_varispeed - actual_speed ()) > .002
580 // still, signal hard changes to 1.0 and 0.0:
581 || (actual_speed () == 1.0 && _signalled_varispeed != 1.0)
582 || (actual_speed () == 0.0 && _signalled_varispeed != 0.0)
585 TransportStateChange (); /* EMIT SIGNAL */
586 _signalled_varispeed = actual_speed ();
591 /** Stop the transport. */
593 Session::stop_transport (bool abort, bool clear_state)
595 ENSURE_PROCESS_THREAD;
597 _count_in_once = false;
598 if (_transport_speed == 0.0f) {
602 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
604 realtime_stop (abort, clear_state);
605 _butler->schedule_transport_work ();
608 /** Called from the process thread */
610 Session::start_transport ()
612 ENSURE_PROCESS_THREAD;
613 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
615 _last_roll_location = _transport_sample;
616 _last_roll_or_reversal_location = _transport_sample;
617 _remaining_latency_preroll = worst_latency_preroll ();
621 /* if record status is Enabled, move it to Recording. if its
622 already Recording, move it to Disabled.
625 switch (record_status()) {
627 if (!config.get_punch_in()) {
628 /* This is only for UIs (keep blinking rec-en before
629 * punch-in, don't show rec-region etc). The UI still
630 * depends on SessionEvent::PunchIn and ensuing signals.
632 * The disk-writers handle punch in/out internally
633 * in their local delay-compensated timeframe.
641 disable_record (false);
649 _transport_speed = _default_transport_speed;
650 _target_transport_speed = _transport_speed;
652 if (!_engine.freewheeling()) {
654 timecode_time_subframes (_transport_sample, time);
655 if (transport_master()->type() == MTC) {
656 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
659 if ((actively_recording () || (config.get_punch_in () && get_record_enabled ()))
660 && click_data && (config.get_count_in () || _count_in_once)) {
661 _count_in_once = false;
662 /* calculate count-in duration (in audio samples)
663 * - use [fixed] tempo/meter at _transport_sample
664 * - calc duration of 1 bar + time-to-beat before or at transport_sample
666 const Tempo& tempo = _tempo_map->tempo_at_sample (_transport_sample);
667 const Meter& meter = _tempo_map->meter_at_sample (_transport_sample);
669 const double num = meter.divisions_per_bar ();
670 const double den = meter.note_divisor ();
671 const double barbeat = _tempo_map->exact_qn_at_sample (_transport_sample, 0) * den / (4. * num);
672 const double bar_fract = fmod (barbeat, 1.0); // fraction of bar elapsed.
674 _count_in_samples = meter.samples_per_bar (tempo, _current_sample_rate);
676 double dt = _count_in_samples / num;
677 if (bar_fract == 0) {
678 /* at bar boundary, count-in 2 bars before start. */
679 _count_in_samples *= 2;
681 /* beats left after full bar until roll position */
682 _count_in_samples *= 1. + bar_fract;
685 if (_count_in_samples > _remaining_latency_preroll) {
686 _remaining_latency_preroll = _count_in_samples;
690 samplepos_t cf = _transport_sample - _count_in_samples;
691 samplecnt_t offset = _click_io->connected_latency (true);
692 while (cf < _transport_sample + offset) {
693 add_click (cf, clickbeat == 0);
695 clickbeat = fmod (clickbeat + 1, num);
698 if (_count_in_samples < _remaining_latency_preroll) {
699 _count_in_samples = _remaining_latency_preroll;
704 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
705 TransportStateChange (); /* EMIT SIGNAL */
708 /** Do any transport work in the audio thread that needs to be done after the
709 * transport thread is finished. Audio thread, realtime safe.
712 Session::post_transport ()
714 ENSURE_PROCESS_THREAD;
715 PostTransportWork ptw = post_transport_work ();
717 if (ptw & PostTransportAudition) {
718 if (auditioner && auditioner->auditioning()) {
719 process_function = &Session::process_audition;
721 process_function = &Session::process_with_events;
725 if (ptw & PostTransportStop) {
727 transport_sub_state = 0;
730 if (ptw & PostTransportLocate) {
732 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
733 _count_in_once = false;
736 transport_sub_state = 0;
741 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
744 set_post_transport_work (PostTransportWork (0));
748 Session::maybe_stop (samplepos_t limit)
750 ENSURE_PROCESS_THREAD;
751 if ((_transport_speed > 0.0f && _transport_sample >= limit) || (_transport_speed < 0.0f && _transport_sample == 0)) {
752 if (synced_to_engine () && config.get_jack_time_master ()) {
753 _engine.transport_stop ();
754 } else if (!synced_to_engine ()) {
763 Session::micro_locate (samplecnt_t distance)
765 ENSURE_PROCESS_THREAD;
767 boost::shared_ptr<RouteList> rl = routes.reader();
768 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
769 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
770 if (tr && !tr->can_internal_playback_seek (distance)) {
775 DEBUG_TRACE (DEBUG::Transport, string_compose ("micro-locate by %1\n", distance));
777 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
778 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
780 tr->internal_playback_seek (distance);
784 _transport_sample += distance;
789 Session::flush_all_inserts ()
791 ENSURE_PROCESS_THREAD;
792 boost::shared_ptr<RouteList> r = routes.reader ();
794 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
795 (*i)->flush_processors ();
800 Session::set_play_loop (bool yn, double speed)
802 ENSURE_PROCESS_THREAD;
803 /* Called from event-handling context */
807 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
808 /* nothing to do, or can't change loop status while recording */
812 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
813 warning << string_compose (
814 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
815 "Recommend changing the configured options"), PROGRAM_NAME)
829 if (Config->get_seamless_loop()) {
830 if (!Config->get_loop_is_mode()) {
831 /* set all tracks to use internal looping */
832 set_track_loop (true);
834 /* we will do this in the locate to the start OR when we hit the end
835 * of the loop for the first time
839 /* set all tracks to NOT use internal looping */
840 set_track_loop (false);
843 /* Put the delick and loop events in into the event list. The declick event will
844 cause a de-clicking fade-out just before the end of the loop, and it will also result
845 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
850 auto_loop_declick_range (loc, dcp, dcl);
851 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
853 /* if requested to roll, locate to start of loop and
854 * roll but ONLY if we're not already rolling.
856 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
859 if (Config->get_loop_is_mode()) {
860 /* loop IS a transport mode: if already
861 rolling, do not locate to loop start.
863 if (!transport_rolling() && (speed != 0.0)) {
864 start_locate (loc->start(), true, true, false, true);
868 start_locate (loc->start(), true, true, false, true);
878 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
879 TransportStateChange ();
882 /* *****************************************************************************
883 * END REALTIME ACTIONS
884 * ****************************************************************************/
888 Session::add_post_transport_work (PostTransportWork ptw)
890 PostTransportWork oldval;
891 PostTransportWork newval;
895 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
896 newval = PostTransportWork (oldval | ptw);
897 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
903 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
907 Session::should_ignore_transport_request (TransportRequestSource src, TransportRequestType type) const
909 if (config.get_external_sync()) {
910 if (TransportMasterManager::instance().current()->allow_request (src, type)) {
920 Session::synced_to_engine() const {
921 return config.get_external_sync() && TransportMasterManager::instance().current()->type() == Engine;
925 Session::request_sync_source (boost::shared_ptr<TransportMaster> tm)
927 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportMaster, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
928 ev->transport_master = tm;
929 DEBUG_TRACE (DEBUG::Slave, "sent request for new transport master\n");
934 Session::request_transport_speed (double speed, bool as_default, TransportRequestSource origin)
936 if (should_ignore_transport_request (origin, TR_Speed)) {
939 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
940 ev->third_yes_or_no = as_default; // as_default
941 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
945 /** Request a new transport speed, but if the speed parameter is exactly zero then use
946 * a very small +ve value to prevent the transport actually stopping. This method should
947 * be used by callers who are varying transport speed but don't ever want to stop it.
950 Session::request_transport_speed_nonzero (double speed, bool as_default, TransportRequestSource origin)
952 if (should_ignore_transport_request (origin, TransportRequestType (TR_Speed|TR_Start))) {
960 request_transport_speed (speed, as_default);
964 Session::request_stop (bool abort, bool clear_state, TransportRequestSource origin)
966 if (should_ignore_transport_request (origin, TR_Stop)) {
970 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_sample(), 0.0, abort, clear_state);
971 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));
976 Session::request_locate (samplepos_t target_sample, bool with_roll, TransportRequestSource origin)
978 if (should_ignore_transport_request (origin, TR_Locate)) {
982 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_sample, 0, false);
983 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_sample));
988 Session::force_locate (samplepos_t target_sample, bool with_roll)
990 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_sample, 0, true);
991 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_sample));
996 Session::unset_preroll_record_trim ()
998 _preroll_record_trim_len = 0;
1002 Session::request_preroll_record_trim (samplepos_t rec_in, samplecnt_t preroll)
1004 if (actively_recording ()) {
1007 unset_preroll_record_trim ();
1009 config.set_punch_in (false);
1010 config.set_punch_out (false);
1012 samplepos_t pos = std::max ((samplepos_t)0, rec_in - preroll);
1013 _preroll_record_trim_len = preroll;
1014 maybe_enable_record ();
1015 request_locate (pos, true);
1016 set_requested_return_sample (rec_in);
1020 Session::request_count_in_record ()
1022 if (actively_recording ()) {
1025 if (transport_rolling()) {
1028 maybe_enable_record ();
1029 _count_in_once = true;
1030 request_transport_speed (1.0, true);
1034 Session::request_play_loop (bool yn, bool change_transport_roll)
1036 if (transport_master_is_external() && yn) {
1037 // don't attempt to loop when not using Internal Transport
1038 // see also gtk2_ardour/ardour_ui_options.cc parameter_changed()
1043 Location *location = _locations->auto_loop_location();
1044 double target_speed;
1046 if (location == 0 && yn) {
1047 error << _("Cannot loop - no loop range defined")
1052 if (change_transport_roll) {
1053 if (transport_rolling()) {
1054 /* start looping at current speed */
1055 target_speed = transport_speed ();
1057 /* currently stopped */
1059 /* start looping at normal speed */
1066 /* leave the speed alone */
1067 target_speed = transport_speed ();
1070 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
1071 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
1075 if (!change_transport_roll) {
1076 if (!transport_rolling()) {
1077 /* we're not changing transport state, but we do want
1078 to set up position for the new loop. Don't
1079 do this if we're rolling already.
1081 request_locate (location->start(), false);
1085 if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
1086 // request an immediate locate to refresh the tracks
1087 // after disabling looping
1088 request_locate (_transport_sample-1, false);
1094 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
1096 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
1098 ev->audio_range = *range;
1100 ev->audio_range.clear ();
1102 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
1107 Session::request_cancel_play_range ()
1109 SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
1115 Session::solo_selection_active ()
1117 if ( _soloSelection.empty() ) {
1124 Session::solo_selection ( StripableList &list, bool new_state )
1126 boost::shared_ptr<ControlList> solo_list (new ControlList);
1127 boost::shared_ptr<ControlList> unsolo_list (new ControlList);
1130 _soloSelection = list;
1132 _soloSelection.clear();
1134 boost::shared_ptr<RouteList> rl = get_routes();
1136 for (ARDOUR::RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1138 if ( !(*i)->is_track() ) {
1142 boost::shared_ptr<Stripable> s (*i);
1144 bool found = (std::find(list.begin(), list.end(), s) != list.end());
1145 if ( new_state && found ) {
1147 solo_list->push_back (s->solo_control());
1149 //must invalidate playlists on selected tracks, so only selected regions get heard
1150 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (*i);
1152 boost::shared_ptr<Playlist> playlist = track->playlist();
1154 playlist->ContentsChanged();
1158 unsolo_list->push_back (s->solo_control());
1162 set_controls (solo_list, 1.0, Controllable::NoGroup);
1163 set_controls (unsolo_list, 0.0, Controllable::NoGroup);
1168 Session::butler_transport_work ()
1170 /* Note: this function executes in the butler thread context */
1173 boost::shared_ptr<RouteList> r = routes.reader ();
1174 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
1175 bool finished = true;
1176 PostTransportWork ptw = post_transport_work();
1179 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
1181 if (ptw & PostTransportLocate) {
1183 if (get_play_loop() && !Config->get_seamless_loop()) {
1185 DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
1187 /* this locate might be happening while we are
1190 * Non-seamless looping will require a locate (below) that
1191 * will reset capture buffers and throw away data.
1193 * Rather than first find all tracks and see if they
1194 * have outstanding data, just do a flush anyway. It
1195 * may be cheaper this way anyway, and is certainly
1199 bool more_disk_io_to_do = false;
1200 uint32_t errors = 0;
1203 more_disk_io_to_do = _butler->flush_tracks_to_disk_after_locate (r, errors);
1209 if (more_disk_io_to_do) {
1218 if (ptw & PostTransportAdjustPlaybackBuffering) {
1219 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1220 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1222 tr->adjust_playback_buffering ();
1223 /* and refill those buffers ... */
1225 (*i)->non_realtime_locate (_transport_sample);
1227 VCAList v = _vca_manager->vcas ();
1228 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1229 (*i)->non_realtime_locate (_transport_sample);
1233 if (ptw & PostTransportAdjustCaptureBuffering) {
1234 /* need to prevent concurrency with ARDOUR::DiskWriter::run(),
1235 * DiskWriter::adjust_buffering() re-allocates the ringbuffer */
1236 Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
1237 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1238 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1240 tr->adjust_capture_buffering ();
1245 if (ptw & PostTransportReverse) {
1249 /* don't seek if locate will take care of that in non_realtime_stop() */
1251 if (!(ptw & PostTransportLocate)) {
1252 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1253 (*i)->non_realtime_locate (_transport_sample);
1255 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
1256 /* new request, stop seeking, and start again */
1257 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1261 VCAList v = _vca_manager->vcas ();
1262 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1263 (*i)->non_realtime_locate (_transport_sample);
1268 if (ptw & PostTransportLocate) {
1269 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
1270 non_realtime_locate ();
1273 if (ptw & PostTransportStop) {
1274 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
1276 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1281 if (ptw & PostTransportOverWrite) {
1282 non_realtime_overwrite (on_entry, finished);
1284 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1289 if (ptw & PostTransportAudition) {
1290 non_realtime_set_audition ();
1293 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1295 DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs @ %2 trw = %3\n"), g_get_monotonic_time() - before, _transport_sample, _butler->transport_work_requested()));
1299 Session::non_realtime_overwrite (int on_entry, bool& finished)
1301 boost::shared_ptr<RouteList> rl = routes.reader();
1302 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1303 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1304 if (tr && tr->pending_overwrite ()) {
1305 tr->overwrite_existing_buffers ();
1307 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
1315 Session::declick_in_progress () const
1317 boost::shared_ptr<RouteList> rl = routes.reader();
1318 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1319 if ((*i)->declick_in_progress ()) {
1327 Session::non_realtime_locate ()
1329 DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_sample));
1331 if (Config->get_loop_is_mode() && get_play_loop()) {
1333 Location *loc = _locations->auto_loop_location();
1335 if (!loc || (_transport_sample < loc->start() || _transport_sample >= loc->end())) {
1336 /* jumped out of loop range: stop tracks from looping,
1337 but leave loop (mode) enabled.
1339 set_track_loop (false);
1341 } else if (loc && Config->get_seamless_loop() &&
1342 ((loc->start() <= _transport_sample) || (loc->end() > _transport_sample))) {
1344 /* jumping to start of loop. This might have been done before but it is
1345 * idempotent and cheap. Doing it here ensures that when we start playback
1346 * outside the loop we still flip tracks into the magic seamless mode
1349 set_track_loop (true);
1352 set_track_loop (false);
1357 /* no more looping .. should have been noticed elsewhere */
1364 boost::shared_ptr<RouteList> rl = routes.reader();
1367 gint sc = g_atomic_int_get (&_seek_counter);
1368 tf = _transport_sample;
1370 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1371 (*i)->non_realtime_locate (tf);
1372 if (sc != g_atomic_int_get (&_seek_counter)) {
1379 /* VCAs are quick to locate because they have no data (except
1380 automation) associated with them. Don't bother with a
1381 restart mechanism here, but do use the same transport sample
1382 that the Routes used.
1384 VCAList v = _vca_manager->vcas ();
1385 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1386 (*i)->non_realtime_locate (tf);
1390 _scene_changer->locate (_transport_sample);
1392 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
1393 rather than clearing them so that the RT thread has to spend time constructing
1394 them (in Session::click).
1399 #ifdef USE_TRACKS_CODE_FEATURES
1401 Session::select_playhead_priority_target (samplepos_t& jump_to)
1405 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
1411 if (Profile->get_trx() && transport_rolling() ) {
1412 // We're playing, so do nothing.
1413 // Next stop will put us where we need to be.
1417 /* Note that the order of checking each AutoReturnTarget flag defines
1418 the priority each flag.
1420 Ardour/Mixbus: Last Locate
1425 Tracks: Range Selection
1431 if (autoreturn & RangeSelectionStart) {
1432 if (!_range_selection.empty()) {
1433 jump_to = _range_selection.from;
1435 if (transport_rolling ()) {
1436 /* Range selection no longer exists, but we're playing,
1437 so do nothing. Next stop will put us where
1445 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
1446 /* don't try to handle loop play when synced to JACK */
1448 if (!synced_to_engine()) {
1449 Location *location = _locations->auto_loop_location();
1452 jump_to = location->start();
1454 if (Config->get_seamless_loop()) {
1455 /* need to get track buffers reloaded */
1456 set_track_loop (true);
1462 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
1463 if (!_object_selection.empty()) {
1464 jump_to = _object_selection.from;
1468 if (jump_to < 0 && (autoreturn & LastLocate)) {
1469 jump_to = _last_roll_location;
1472 return jump_to >= 0;
1477 Session::select_playhead_priority_target (samplepos_t& jump_to)
1479 if (!transport_master_no_external_or_using_engine() || !config.get_auto_return()) {
1483 jump_to = _last_roll_location;
1484 return jump_to >= 0;
1490 Session::follow_playhead_priority ()
1494 if (select_playhead_priority_target (target)) {
1495 request_locate (target);
1500 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
1506 PostTransportWork ptw = post_transport_work();
1511 boost::shared_ptr<RouteList> rl = routes.reader();
1512 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1513 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1514 if (tr && tr->get_captured_samples () != 0) {
1520 /* stop and locate are merged here because they share a lot of common stuff */
1523 now = localtime (&xnow);
1526 auditioner->cancel_audition ();
1530 begin_reversible_command (Operations::capture);
1531 _have_captured = true;
1534 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
1536 if (abort && did_record) {
1537 /* no reason to save the session file when we remove sources
1539 _state_of_the_state = StateOfTheState (_state_of_the_state | InCleanup);
1542 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1543 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1545 tr->transport_stopped_wallclock (*now, xnow, abort);
1549 if (abort && did_record) {
1550 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1553 boost::shared_ptr<RouteList> r = routes.reader ();
1556 commit_reversible_command ();
1557 /* increase take name */
1558 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
1559 string newname = config.get_take_name();
1560 config.set_take_name(bump_name_number (newname));
1564 if (_engine.running()) {
1565 PostTransportWork ptw = post_transport_work ();
1567 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1568 (*i)->non_realtime_transport_stop (_transport_sample, !(ptw & PostTransportLocate));
1570 VCAList v = _vca_manager->vcas ();
1571 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1572 (*i)->non_realtime_transport_stop (_transport_sample, !(ptw & PostTransportLocate));
1575 update_latency_compensation ();
1578 /* If we are not synced to a "true" external master, and we're not
1579 * handling an explicit locate, we should consider whether or not to
1580 * "auto-return". This could mean going to a specifically requested
1581 * location, or just back to the start of the last roll.
1584 if (transport_master_no_external_or_using_engine() && !(ptw & PostTransportLocate)) {
1586 bool do_locate = false;
1588 if (_requested_return_sample >= 0) {
1590 /* explicit return request pre-queued in event list. overrides everything else */
1592 _transport_sample = _requested_return_sample;
1594 /* cancel this request */
1595 _requested_return_sample = -1;
1598 } else if (Config->get_auto_return_target_list()) {
1600 samplepos_t jump_to;
1602 if (select_playhead_priority_target (jump_to)) {
1604 /* there's a valid target (we don't care how it
1608 _transport_sample = jump_to;
1613 /* roll aborted (typically capture) with
1614 * auto-return enabled
1617 _transport_sample = _last_roll_location;
1624 if (do_locate && synced_to_engine()) {
1626 /* We will unconditionally locate to _transport_sample
1627 * below, which will refill playback buffers based on
1628 * _transport_sample, and maximises the buffering they
1631 * But if we are synced to engine (JACK), we should
1632 * locate the engine (JACK) as well. We would follow
1633 * the engine (JACK) on the next process cycle, but
1634 * since we're going to do a locate below anyway,
1635 * it seems pointless to not use just do it ourselves
1636 * right now, rather than wait for the engine (JACK) to
1637 * provide the new position on the next cycle.
1639 * Despite the generic name of the called method
1640 * (::transport_locate()) this method only does
1641 * anything if the audio/MIDI backend is JACK.
1644 _engine.transport_locate (_transport_sample);
1650 unset_preroll_record_trim ();
1652 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
1655 if (ptw & PostTransportClearSubstate) {
1656 unset_play_range ();
1657 if (!Config->get_loop_is_mode()) {
1662 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
1665 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
1666 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1667 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
1668 (*i)->non_realtime_locate (_transport_sample);
1670 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
1672 /* we will be back */
1679 VCAList v = _vca_manager->vcas ();
1680 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1681 (*i)->non_realtime_locate (_transport_sample);
1685 have_looped = false;
1687 /* don't bother with this stuff if we're disconnected from the engine,
1688 because there will be no process callbacks to deliver stuff from
1691 if (_engine.running() && !_engine.freewheeling()) {
1692 // need to queue this in the next RT cycle
1693 _send_timecode_update = true;
1695 if (transport_master()->type() == MTC) {
1696 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
1698 /* This (::non_realtime_stop()) gets called by main
1699 process thread, which will lead to confusion
1700 when calling AsyncMIDIPort::write().
1702 Something must be done. XXX
1704 send_mmc_locate (_transport_sample);
1708 if ((ptw & PostTransportLocate) && get_record_enabled()) {
1709 /* This is scheduled by realtime_stop(), which is also done
1710 * when a slave requests /locate/ for an initial sync.
1711 * We can't hold up the slave for long with a save() here,
1712 * without breaking its initial sync cycle.
1714 * save state only if there's no slave or if it's not yet locked.
1716 if (!transport_master_is_external() || !transport_master()->locked()) {
1717 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
1718 SaveSessionRequested (_current_snapshot_name);
1723 /* save the current state of things if appropriate */
1725 if (did_record && !saved) {
1726 SaveSessionRequested (_current_snapshot_name);
1729 if (ptw & PostTransportStop) {
1730 unset_play_range ();
1731 if (!Config->get_loop_is_mode()) {
1736 PositionChanged (_transport_sample); /* EMIT SIGNAL */
1737 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
1738 TransportStateChange (); /* EMIT SIGNAL */
1739 AutomationWatch::instance().transport_stop_automation_watches (_transport_sample);
1741 /* and start it up again if relevant */
1743 if ((ptw & PostTransportLocate) && !config.get_external_sync()) {
1744 request_transport_speed (1.0);
1749 Session::unset_play_loop ()
1753 clear_events (SessionEvent::AutoLoop);
1754 set_track_loop (false);
1757 if (Config->get_seamless_loop()) {
1758 /* likely need to flush track buffers: this will locate us to wherever we are */
1759 add_post_transport_work (PostTransportLocate);
1760 _butler->schedule_transport_work ();
1762 TransportStateChange (); /* EMIT SIGNAL */
1767 Session::set_track_loop (bool yn)
1769 Location* loc = _locations->auto_loop_location ();
1775 boost::shared_ptr<RouteList> rl = routes.reader ();
1777 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1778 if (*i && !(*i)->is_private_route()) {
1779 (*i)->set_loop (yn ? loc : 0);
1785 Session::worst_latency_preroll () const
1787 return _worst_output_latency + _worst_input_latency;
1791 Session::unset_play_range ()
1793 _play_range = false;
1794 _clear_event_type (SessionEvent::RangeStop);
1795 _clear_event_type (SessionEvent::RangeLocate);
1799 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1803 /* Called from event-processing context */
1805 unset_play_range ();
1807 if (range.empty()) {
1808 /* _play_range set to false in unset_play_range()
1810 if (!leave_rolling) {
1811 /* stop transport */
1812 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1820 /* cancel loop play */
1823 list<AudioRange>::size_type sz = range.size();
1827 list<AudioRange>::iterator i = range.begin();
1828 list<AudioRange>::iterator next;
1830 while (i != range.end()) {
1835 /* locating/stopping is subject to delays for declicking.
1838 samplepos_t requested_sample = i->end;
1840 if (requested_sample > current_block_size) {
1841 requested_sample -= current_block_size;
1843 requested_sample = 0;
1846 if (next == range.end()) {
1847 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_sample, 0, 0.0f);
1849 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_sample, (*next).start, 0.0f);
1857 } else if (sz == 1) {
1859 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1864 /* save range so we can do auto-return etc. */
1866 current_audio_range = range;
1868 /* now start rolling at the right place */
1870 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1873 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
1874 TransportStateChange ();
1878 Session::request_bounded_roll (samplepos_t start, samplepos_t end)
1880 AudioRange ar (start, end, 0);
1881 list<AudioRange> lar;
1884 request_play_range (&lar, true);
1888 Session::set_requested_return_sample (samplepos_t return_to)
1890 _requested_return_sample = return_to;
1894 Session::request_roll_at_and_return (samplepos_t start, samplepos_t return_to)
1896 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1897 ev->target2_sample = start;
1902 Session::engine_halted ()
1906 /* there will be no more calls to process(), so
1907 we'd better clean up for ourselves, right now.
1909 but first, make sure the butler is out of
1917 realtime_stop (false, true);
1918 non_realtime_stop (false, 0, ignored);
1919 transport_sub_state = 0;
1921 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
1922 TransportStateChange (); /* EMIT SIGNAL */
1927 Session::xrun_recovery ()
1931 Xrun (_transport_sample); /* EMIT SIGNAL */
1933 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1935 /* it didn't actually halt, but we need
1936 to handle things in the same way.
1944 Session::route_processors_changed (RouteProcessorChange c)
1946 if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
1950 if (c.type == RouteProcessorChange::MeterPointChange) {
1955 if (c.type == RouteProcessorChange::RealTimeChange) {
1960 update_latency_compensation ();
1967 Session::allow_auto_play (bool yn)
1969 auto_play_legal = yn;
1974 Session::send_mmc_locate (samplepos_t t)
1980 if (!_engine.freewheeling()) {
1981 Timecode::Time time;
1982 timecode_time_subframes (t, time);
1983 send_immediate_mmc (MIDI::MachineControlCommand (time));
1987 /** Ask the transport to not send timecode until further notice. The suspension
1988 * will come into effect some finite time after this call, and timecode_transmission_suspended()
1989 * should be checked by the caller to find out when.
1992 Session::request_suspend_timecode_transmission ()
1994 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
1999 Session::request_resume_timecode_transmission ()
2001 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2006 Session::timecode_transmission_suspended () const
2008 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;
2011 boost::shared_ptr<TransportMaster>
2012 Session::transport_master() const
2014 return TransportMasterManager::instance().current();
2018 Session::transport_master_is_external () const
2020 return TransportMasterManager::instance().current() && config.get_external_sync();
2024 Session::transport_master_no_external_or_using_engine () const
2026 return !TransportMasterManager::instance().current() || !config.get_external_sync() || (TransportMasterManager::instance().current()->type() == Engine);
2030 Session::sync_source_changed (SyncSource type, samplepos_t pos, pframes_t cycle_nframes)
2032 /* Runs in process() context */
2034 boost::shared_ptr<TransportMaster> master = TransportMasterManager::instance().current();
2036 /* save value of seamless from before the switch */
2037 _was_seamless = Config->get_seamless_loop ();
2039 if (type == Engine) {
2040 /* JACK cannot support seamless looping at present */
2041 Config->set_seamless_loop (false);
2043 /* reset to whatever the value was before we last switched slaves */
2044 Config->set_seamless_loop (_was_seamless);
2047 if (master->can_loop()) {
2048 request_play_loop (false);
2049 } else if (master->has_loop()) {
2050 request_play_loop (true);
2053 /* slave change, reset any DiskIO block on disk output because it is no
2054 longer valid with a new slave.
2057 DiskReader::set_no_disk_output (false);
2060 we should not be treating specific transport masters as special cases because there maybe > 1 of a particular type
2062 boost::shared_ptr<MTC_TransportMaster> mtc_master = boost::dynamic_pointer_cast<MTC_TransportMaster> (master);
2065 mtc_master->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
2066 MTCSyncStateChanged(mtc_master->locked() );
2068 if (g_atomic_int_compare_and_exchange (&_mtc_active, 1, 0)) {
2069 MTCSyncStateChanged( false );
2071 mtc_status_connection.disconnect ();
2074 boost::shared_ptr<LTC_TransportMaster> ltc_master = boost::dynamic_pointer_cast<LTC_TransportMaster> (master);
2077 ltc_master->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
2078 LTCSyncStateChanged (ltc_master->locked() );
2080 if (g_atomic_int_compare_and_exchange (&_ltc_active, 1, 0)) {
2081 LTCSyncStateChanged( false );
2083 ltc_status_connection.disconnect ();
2087 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", master));
2089 // need to queue this for next process() cycle
2090 _send_timecode_update = true;
2092 boost::shared_ptr<RouteList> rl = routes.reader();
2093 const bool externally_slaved = transport_master_is_external();
2095 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2096 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2097 if (tr && !tr->is_private_route()) {
2098 tr->set_slaved (externally_slaved);