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 (8.0, speed);
416 } else if (speed < 0) {
417 speed = max (-8.0, 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 */
1174 PostTransportWork ptw;
1175 boost::shared_ptr<RouteList> r = routes.reader ();
1178 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
1180 ptw = post_transport_work();
1182 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
1185 if (ptw & PostTransportLocate) {
1187 if (get_play_loop() && !Config->get_seamless_loop()) {
1189 DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
1191 /* this locate might be happening while we are
1194 * Non-seamless looping will require a locate (below) that
1195 * will reset capture buffers and throw away data.
1197 * Rather than first find all tracks and see if they
1198 * have outstanding data, just do a flush anyway. It
1199 * may be cheaper this way anyway, and is certainly
1203 bool more_disk_io_to_do = false;
1204 uint32_t errors = 0;
1207 more_disk_io_to_do = _butler->flush_tracks_to_disk_after_locate (r, errors);
1213 if (more_disk_io_to_do) {
1222 if (ptw & PostTransportAdjustPlaybackBuffering) {
1223 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1224 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1226 tr->adjust_playback_buffering ();
1227 /* and refill those buffers ... */
1229 (*i)->non_realtime_locate (_transport_sample);
1231 VCAList v = _vca_manager->vcas ();
1232 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1233 (*i)->non_realtime_locate (_transport_sample);
1237 if (ptw & PostTransportAdjustCaptureBuffering) {
1238 /* need to prevent concurrency with ARDOUR::DiskWriter::run(),
1239 * DiskWriter::adjust_buffering() re-allocates the ringbuffer */
1240 Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
1241 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1242 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1244 tr->adjust_capture_buffering ();
1249 if (ptw & PostTransportReverse) {
1253 /* don't seek if locate will take care of that in non_realtime_stop() */
1255 if (!(ptw & PostTransportLocate)) {
1256 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1257 (*i)->non_realtime_locate (_transport_sample);
1259 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
1260 /* new request, stop seeking, and start again */
1261 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1265 VCAList v = _vca_manager->vcas ();
1266 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1267 (*i)->non_realtime_locate (_transport_sample);
1272 if (ptw & PostTransportLocate) {
1273 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
1274 non_realtime_locate ();
1277 if (ptw & PostTransportStop) {
1278 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
1280 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1285 if (ptw & PostTransportOverWrite) {
1286 non_realtime_overwrite (on_entry, finished);
1288 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1293 if (ptw & PostTransportAudition) {
1294 non_realtime_set_audition ();
1297 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
1299 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()));
1303 Session::non_realtime_overwrite (int on_entry, bool& finished)
1305 boost::shared_ptr<RouteList> rl = routes.reader();
1306 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1307 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1308 if (tr && tr->pending_overwrite ()) {
1309 tr->overwrite_existing_buffers ();
1311 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
1319 Session::declick_in_progress () const
1321 boost::shared_ptr<RouteList> rl = routes.reader();
1322 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1323 if ((*i)->declick_in_progress ()) {
1331 Session::non_realtime_locate ()
1333 DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_sample));
1335 if (Config->get_loop_is_mode() && get_play_loop()) {
1337 Location *loc = _locations->auto_loop_location();
1339 if (!loc || (_transport_sample < loc->start() || _transport_sample >= loc->end())) {
1340 /* jumped out of loop range: stop tracks from looping,
1341 but leave loop (mode) enabled.
1343 set_track_loop (false);
1345 } else if (loc && Config->get_seamless_loop() &&
1346 ((loc->start() <= _transport_sample) || (loc->end() > _transport_sample))) {
1348 /* jumping to start of loop. This might have been done before but it is
1349 * idempotent and cheap. Doing it here ensures that when we start playback
1350 * outside the loop we still flip tracks into the magic seamless mode
1353 set_track_loop (true);
1356 set_track_loop (false);
1361 /* no more looping .. should have been noticed elsewhere */
1368 boost::shared_ptr<RouteList> rl = routes.reader();
1371 gint sc = g_atomic_int_get (&_seek_counter);
1372 tf = _transport_sample;
1374 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1375 (*i)->non_realtime_locate (tf);
1376 if (sc != g_atomic_int_get (&_seek_counter)) {
1383 /* VCAs are quick to locate because they have no data (except
1384 automation) associated with them. Don't bother with a
1385 restart mechanism here, but do use the same transport sample
1386 that the Routes used.
1388 VCAList v = _vca_manager->vcas ();
1389 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1390 (*i)->non_realtime_locate (tf);
1394 _scene_changer->locate (_transport_sample);
1396 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
1397 rather than clearing them so that the RT thread has to spend time constructing
1398 them (in Session::click).
1403 #ifdef USE_TRACKS_CODE_FEATURES
1405 Session::select_playhead_priority_target (samplepos_t& jump_to)
1409 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
1415 if (Profile->get_trx() && transport_rolling() ) {
1416 // We're playing, so do nothing.
1417 // Next stop will put us where we need to be.
1421 /* Note that the order of checking each AutoReturnTarget flag defines
1422 the priority each flag.
1424 Ardour/Mixbus: Last Locate
1429 Tracks: Range Selection
1435 if (autoreturn & RangeSelectionStart) {
1436 if (!_range_selection.empty()) {
1437 jump_to = _range_selection.from;
1439 if (transport_rolling ()) {
1440 /* Range selection no longer exists, but we're playing,
1441 so do nothing. Next stop will put us where
1449 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
1450 /* don't try to handle loop play when synced to JACK */
1452 if (!synced_to_engine()) {
1453 Location *location = _locations->auto_loop_location();
1456 jump_to = location->start();
1458 if (Config->get_seamless_loop()) {
1459 /* need to get track buffers reloaded */
1460 set_track_loop (true);
1466 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
1467 if (!_object_selection.empty()) {
1468 jump_to = _object_selection.from;
1472 if (jump_to < 0 && (autoreturn & LastLocate)) {
1473 jump_to = _last_roll_location;
1476 return jump_to >= 0;
1481 Session::select_playhead_priority_target (samplepos_t& jump_to)
1483 if (!transport_master_no_external_or_using_engine() || !config.get_auto_return()) {
1487 jump_to = _last_roll_location;
1488 return jump_to >= 0;
1494 Session::follow_playhead_priority ()
1498 if (select_playhead_priority_target (target)) {
1499 request_locate (target);
1504 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
1510 PostTransportWork ptw = post_transport_work();
1515 boost::shared_ptr<RouteList> rl = routes.reader();
1516 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1517 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1518 if (tr && tr->get_captured_samples () != 0) {
1524 /* stop and locate are merged here because they share a lot of common stuff */
1527 now = localtime (&xnow);
1530 auditioner->cancel_audition ();
1534 begin_reversible_command (Operations::capture);
1535 _have_captured = true;
1538 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
1540 if (abort && did_record) {
1541 /* no reason to save the session file when we remove sources
1543 _state_of_the_state = StateOfTheState (_state_of_the_state | InCleanup);
1546 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1547 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1549 tr->transport_stopped_wallclock (*now, xnow, abort);
1553 if (abort && did_record) {
1554 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1557 boost::shared_ptr<RouteList> r = routes.reader ();
1560 commit_reversible_command ();
1561 /* increase take name */
1562 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
1563 string newname = config.get_take_name();
1564 config.set_take_name(bump_name_number (newname));
1568 if (_engine.running()) {
1569 PostTransportWork ptw = post_transport_work ();
1571 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1572 (*i)->non_realtime_transport_stop (_transport_sample, !(ptw & PostTransportLocate));
1574 VCAList v = _vca_manager->vcas ();
1575 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1576 (*i)->non_realtime_transport_stop (_transport_sample, !(ptw & PostTransportLocate));
1579 update_latency_compensation ();
1582 /* If we are not synced to a "true" external master, and we're not
1583 * handling an explicit locate, we should consider whether or not to
1584 * "auto-return". This could mean going to a specifically requested
1585 * location, or just back to the start of the last roll.
1588 if (transport_master_no_external_or_using_engine() && !(ptw & PostTransportLocate)) {
1590 bool do_locate = false;
1592 if (_requested_return_sample >= 0) {
1594 /* explicit return request pre-queued in event list. overrides everything else */
1596 _transport_sample = _requested_return_sample;
1598 /* cancel this request */
1599 _requested_return_sample = -1;
1602 } else if (Config->get_auto_return_target_list()) {
1604 samplepos_t jump_to;
1606 if (select_playhead_priority_target (jump_to)) {
1608 /* there's a valid target (we don't care how it
1612 _transport_sample = jump_to;
1617 /* roll aborted (typically capture) with
1618 * auto-return enabled
1621 _transport_sample = _last_roll_location;
1628 if (do_locate && synced_to_engine()) {
1630 /* We will unconditionally locate to _transport_sample
1631 * below, which will refill playback buffers based on
1632 * _transport_sample, and maximises the buffering they
1635 * But if we are synced to engine (JACK), we should
1636 * locate the engine (JACK) as well. We would follow
1637 * the engine (JACK) on the next process cycle, but
1638 * since we're going to do a locate below anyway,
1639 * it seems pointless to not use just do it ourselves
1640 * right now, rather than wait for the engine (JACK) to
1641 * provide the new position on the next cycle.
1643 * Despite the generic name of the called method
1644 * (::transport_locate()) this method only does
1645 * anything if the audio/MIDI backend is JACK.
1648 _engine.transport_locate (_transport_sample);
1654 unset_preroll_record_trim ();
1656 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
1659 if (ptw & PostTransportClearSubstate) {
1660 unset_play_range ();
1661 if (!Config->get_loop_is_mode()) {
1666 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
1669 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
1670 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1671 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
1672 (*i)->non_realtime_locate (_transport_sample);
1674 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
1676 /* we will be back */
1683 VCAList v = _vca_manager->vcas ();
1684 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
1685 (*i)->non_realtime_locate (_transport_sample);
1689 have_looped = false;
1691 /* don't bother with this stuff if we're disconnected from the engine,
1692 because there will be no process callbacks to deliver stuff from
1695 if (_engine.running() && !_engine.freewheeling()) {
1696 // need to queue this in the next RT cycle
1697 _send_timecode_update = true;
1699 if (transport_master()->type() == MTC) {
1700 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
1702 /* This (::non_realtime_stop()) gets called by main
1703 process thread, which will lead to confusion
1704 when calling AsyncMIDIPort::write().
1706 Something must be done. XXX
1708 send_mmc_locate (_transport_sample);
1712 if ((ptw & PostTransportLocate) && get_record_enabled()) {
1713 /* This is scheduled by realtime_stop(), which is also done
1714 * when a slave requests /locate/ for an initial sync.
1715 * We can't hold up the slave for long with a save() here,
1716 * without breaking its initial sync cycle.
1718 * save state only if there's no slave or if it's not yet locked.
1720 if (!transport_master_is_external() || !transport_master()->locked()) {
1721 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
1722 SaveSessionRequested (_current_snapshot_name);
1727 /* save the current state of things if appropriate */
1729 if (did_record && !saved) {
1730 SaveSessionRequested (_current_snapshot_name);
1733 if (ptw & PostTransportStop) {
1734 unset_play_range ();
1735 if (!Config->get_loop_is_mode()) {
1740 PositionChanged (_transport_sample); /* EMIT SIGNAL */
1741 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
1742 TransportStateChange (); /* EMIT SIGNAL */
1743 AutomationWatch::instance().transport_stop_automation_watches (_transport_sample);
1745 /* and start it up again if relevant */
1747 if ((ptw & PostTransportLocate) && !config.get_external_sync()) {
1748 request_transport_speed (1.0);
1753 Session::unset_play_loop ()
1757 clear_events (SessionEvent::AutoLoop);
1758 set_track_loop (false);
1761 if (Config->get_seamless_loop()) {
1762 /* likely need to flush track buffers: this will locate us to wherever we are */
1763 add_post_transport_work (PostTransportLocate);
1764 _butler->schedule_transport_work ();
1766 TransportStateChange (); /* EMIT SIGNAL */
1771 Session::set_track_loop (bool yn)
1773 Location* loc = _locations->auto_loop_location ();
1779 boost::shared_ptr<RouteList> rl = routes.reader ();
1781 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1782 if (*i && !(*i)->is_private_route()) {
1783 (*i)->set_loop (yn ? loc : 0);
1789 Session::worst_latency_preroll () const
1791 return _worst_output_latency + _worst_input_latency;
1795 Session::unset_play_range ()
1797 _play_range = false;
1798 _clear_event_type (SessionEvent::RangeStop);
1799 _clear_event_type (SessionEvent::RangeLocate);
1803 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1807 /* Called from event-processing context */
1809 unset_play_range ();
1811 if (range.empty()) {
1812 /* _play_range set to false in unset_play_range()
1814 if (!leave_rolling) {
1815 /* stop transport */
1816 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1824 /* cancel loop play */
1827 list<AudioRange>::size_type sz = range.size();
1831 list<AudioRange>::iterator i = range.begin();
1832 list<AudioRange>::iterator next;
1834 while (i != range.end()) {
1839 /* locating/stopping is subject to delays for declicking.
1842 samplepos_t requested_sample = i->end;
1844 if (requested_sample > current_block_size) {
1845 requested_sample -= current_block_size;
1847 requested_sample = 0;
1850 if (next == range.end()) {
1851 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_sample, 0, 0.0f);
1853 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_sample, (*next).start, 0.0f);
1861 } else if (sz == 1) {
1863 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1868 /* save range so we can do auto-return etc. */
1870 current_audio_range = range;
1872 /* now start rolling at the right place */
1874 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1877 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
1878 TransportStateChange ();
1882 Session::request_bounded_roll (samplepos_t start, samplepos_t end)
1884 AudioRange ar (start, end, 0);
1885 list<AudioRange> lar;
1888 request_play_range (&lar, true);
1892 Session::set_requested_return_sample (samplepos_t return_to)
1894 _requested_return_sample = return_to;
1898 Session::request_roll_at_and_return (samplepos_t start, samplepos_t return_to)
1900 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1901 ev->target2_sample = start;
1906 Session::engine_halted ()
1910 /* there will be no more calls to process(), so
1911 we'd better clean up for ourselves, right now.
1913 but first, make sure the butler is out of
1921 realtime_stop (false, true);
1922 non_realtime_stop (false, 0, ignored);
1923 transport_sub_state = 0;
1925 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
1926 TransportStateChange (); /* EMIT SIGNAL */
1931 Session::xrun_recovery ()
1935 Xrun (_transport_sample); /* EMIT SIGNAL */
1937 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1939 /* it didn't actually halt, but we need
1940 to handle things in the same way.
1948 Session::route_processors_changed (RouteProcessorChange c)
1950 if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
1954 if (c.type == RouteProcessorChange::MeterPointChange) {
1959 if (c.type == RouteProcessorChange::RealTimeChange) {
1964 update_latency_compensation ();
1971 Session::allow_auto_play (bool yn)
1973 auto_play_legal = yn;
1978 Session::send_mmc_locate (samplepos_t t)
1984 if (!_engine.freewheeling()) {
1985 Timecode::Time time;
1986 timecode_time_subframes (t, time);
1987 send_immediate_mmc (MIDI::MachineControlCommand (time));
1991 /** Ask the transport to not send timecode until further notice. The suspension
1992 * will come into effect some finite time after this call, and timecode_transmission_suspended()
1993 * should be checked by the caller to find out when.
1996 Session::request_suspend_timecode_transmission ()
1998 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2003 Session::request_resume_timecode_transmission ()
2005 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2010 Session::timecode_transmission_suspended () const
2012 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;
2015 boost::shared_ptr<TransportMaster>
2016 Session::transport_master() const
2018 return TransportMasterManager::instance().current();
2022 Session::transport_master_is_external () const
2024 return TransportMasterManager::instance().current() && config.get_external_sync();
2028 Session::transport_master_no_external_or_using_engine () const
2030 return !TransportMasterManager::instance().current() || !config.get_external_sync() || (TransportMasterManager::instance().current()->type() == Engine);
2034 Session::sync_source_changed (SyncSource type, samplepos_t pos, pframes_t cycle_nframes)
2036 /* Runs in process() context */
2038 boost::shared_ptr<TransportMaster> master = TransportMasterManager::instance().current();
2040 /* save value of seamless from before the switch */
2041 _was_seamless = Config->get_seamless_loop ();
2043 if (type == Engine) {
2044 /* JACK cannot support seamless looping at present */
2045 Config->set_seamless_loop (false);
2047 /* reset to whatever the value was before we last switched slaves */
2048 Config->set_seamless_loop (_was_seamless);
2051 if (master->can_loop()) {
2052 request_play_loop (false);
2053 } else if (master->has_loop()) {
2054 request_play_loop (true);
2057 /* slave change, reset any DiskIO block on disk output because it is no
2058 longer valid with a new slave.
2061 DiskReader::set_no_disk_output (false);
2064 we should not be treating specific transport masters as special cases because there maybe > 1 of a particular type
2066 boost::shared_ptr<MTC_TransportMaster> mtc_master = boost::dynamic_pointer_cast<MTC_TransportMaster> (master);
2069 mtc_master->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
2070 MTCSyncStateChanged(mtc_master->locked() );
2072 if (g_atomic_int_compare_and_exchange (&_mtc_active, 1, 0)) {
2073 MTCSyncStateChanged( false );
2075 mtc_status_connection.disconnect ();
2078 boost::shared_ptr<LTC_TransportMaster> ltc_master = boost::dynamic_pointer_cast<LTC_TransportMaster> (master);
2081 ltc_master->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
2082 LTCSyncStateChanged (ltc_master->locked() );
2084 if (g_atomic_int_compare_and_exchange (&_ltc_active, 1, 0)) {
2085 LTCSyncStateChanged( false );
2087 ltc_status_connection.disconnect ();
2091 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", master));
2093 // need to queue this for next process() cycle
2094 _send_timecode_update = true;
2096 boost::shared_ptr<RouteList> rl = routes.reader();
2097 const bool externally_slaved = transport_master_is_external();
2099 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2100 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2101 if (tr && !tr->is_private_route()) {
2102 tr->set_slaved (externally_slaved);