2 Copyright (C) 1999-2003 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "libardour-config.h"
29 #include "pbd/error.h"
30 #include "pbd/enumwriter.h"
31 #include "pbd/pthread_utils.h"
32 #include "pbd/memento_command.h"
33 #include "pbd/stacktrace.h"
35 #include "midi++/mmc.h"
36 #include "midi++/port.h"
38 #include "ardour/audioengine.h"
39 #include "ardour/auditioner.h"
40 #include "ardour/butler.h"
41 #include "ardour/click.h"
42 #include "ardour/debug.h"
43 #include "ardour/location.h"
44 #include "ardour/profile.h"
45 #include "ardour/scene_changer.h"
46 #include "ardour/session.h"
47 #include "ardour/slave.h"
48 #include "ardour/operations.h"
53 using namespace ARDOUR;
57 Session::add_post_transport_work (PostTransportWork ptw)
59 PostTransportWork oldval;
60 PostTransportWork newval;
64 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
65 newval = PostTransportWork (oldval | ptw);
66 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
72 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
76 Session::request_input_change_handling ()
78 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
79 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
85 Session::request_sync_source (Slave* new_slave)
87 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
90 seamless = Config->get_seamless_loop ();
92 if (dynamic_cast<Engine_Slave*>(new_slave)) {
93 /* JACK cannot support seamless looping at present */
94 Config->set_seamless_loop (false);
96 /* reset to whatever the value was before we last switched slaves */
97 Config->set_seamless_loop (_was_seamless);
100 /* save value of seamless from before the switch */
101 _was_seamless = seamless;
103 ev->slave = new_slave;
104 DEBUG_TRACE (DEBUG::Slave, "sent request for new slave\n");
109 Session::request_transport_speed (double speed, bool as_default)
111 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
112 ev->third_yes_or_no = as_default; // as_default
113 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
117 /** Request a new transport speed, but if the speed parameter is exactly zero then use
118 * a very small +ve value to prevent the transport actually stopping. This method should
119 * be used by callers who are varying transport speed but don't ever want to stop it.
122 Session::request_transport_speed_nonzero (double speed, bool as_default)
128 request_transport_speed (speed, as_default);
132 Session::request_track_speed (Track* tr, double speed)
134 SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
140 Session::request_stop (bool abort, bool clear_state)
142 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_frame(), 0.0, abort, clear_state);
143 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, audible %3 transport %4 abort = %1, clear state = %2\n", abort, clear_state, audible_frame(), _transport_frame));
148 Session::request_locate (framepos_t target_frame, bool with_roll)
150 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
151 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
156 Session::force_locate (framepos_t target_frame, bool with_roll)
158 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
159 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
164 Session::request_play_loop (bool yn, bool change_transport_roll)
167 // don't attempt to loop when not using Internal Transport
168 // see also gtk2_ardour/ardour_ui_options.cc parameter_changed()
173 Location *location = _locations->auto_loop_location();
176 if (location == 0 && yn) {
177 error << _("Cannot loop - no loop range defined")
182 if (change_transport_roll) {
183 if (transport_rolling()) {
184 /* start looping at current speed */
185 target_speed = transport_speed ();
187 /* currently stopped */
189 /* start looping at normal speed */
196 /* leave the speed alone */
197 target_speed = transport_speed ();
200 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
201 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
205 if (!change_transport_roll) {
206 if (!transport_rolling()) {
207 /* we're not changing transport state, but we do want
208 to set up position for the new loop. Don't
209 do this if we're rolling already.
211 request_locate (location->start(), false);
215 if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
216 // request an immediate locate to refresh the tracks
217 // after disabling looping
218 request_locate (_transport_frame-1, false);
224 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
226 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
228 ev->audio_range = *range;
230 ev->audio_range.clear ();
232 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
237 Session::request_cancel_play_range ()
239 SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
245 Session::realtime_stop (bool abort, bool clear_state)
247 DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_frame));
248 PostTransportWork todo = PostTransportWork (0);
250 /* assume that when we start, we'll be moving forwards */
252 if (_transport_speed < 0.0f) {
253 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
254 _default_transport_speed = 1.0;
256 todo = PostTransportWork (todo | PostTransportStop);
261 boost::shared_ptr<RouteList> r = routes.reader ();
263 for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
264 (*i)->realtime_handle_transport_stopped ();
267 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_frame));
269 /* the duration change is not guaranteed to have happened, but is likely */
271 todo = PostTransportWork (todo | PostTransportDuration);
274 todo = PostTransportWork (todo | PostTransportAbort);
278 todo = PostTransportWork (todo | PostTransportClearSubstate);
282 add_post_transport_work (todo);
285 _clear_event_type (SessionEvent::StopOnce);
286 _clear_event_type (SessionEvent::RangeStop);
287 _clear_event_type (SessionEvent::RangeLocate);
289 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
290 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
292 if (clear_state && !Config->get_loop_is_mode()) {
296 reset_slave_state ();
298 _transport_speed = 0;
299 _target_transport_speed = 0;
301 g_atomic_int_set (&_playback_load, 100);
302 g_atomic_int_set (&_capture_load, 100);
304 if (config.get_use_video_sync()) {
305 waiting_for_sync_offset = true;
308 transport_sub_state = 0;
312 Session::realtime_locate ()
314 boost::shared_ptr<RouteList> r = routes.reader ();
315 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
316 (*i)->realtime_locate ();
321 Session::butler_transport_work ()
323 /* Note: this function executes in the butler thread context */
327 PostTransportWork ptw;
328 boost::shared_ptr<RouteList> r = routes.reader ();
331 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
333 ptw = post_transport_work();
335 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
338 if (ptw & PostTransportLocate) {
340 if (get_play_loop() && !Config->get_seamless_loop()) {
342 DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
344 /* this locate might be happening while we are
347 * Non-seamless looping will require a locate (below) that
348 * will reset capture buffers and throw away data.
350 * Rather than first find all tracks and see if they
351 * have outstanding data, just do a flush anyway. It
352 * may be cheaper this way anyway, and is certainly
356 bool more_disk_io_to_do = false;
360 more_disk_io_to_do = _butler->flush_tracks_to_disk_after_locate (r, errors);
366 if (more_disk_io_to_do) {
375 if (ptw & PostTransportAdjustPlaybackBuffering) {
376 /* non_realtime_locate() calls Automatable::transport_located()
377 * for every route. This eventually calls
378 * ARDOUR::AutomationList::state () which has a LocaleGuard,
379 * and would switch locales forth/back every time.
382 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
383 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
385 tr->adjust_playback_buffering ();
386 /* and refill those buffers ... */
388 (*i)->non_realtime_locate (_transport_frame);
393 if (ptw & PostTransportAdjustCaptureBuffering) {
394 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
395 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
397 tr->adjust_capture_buffering ();
402 if (ptw & PostTransportCurveRealloc) {
403 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
404 (*i)->curve_reallocate();
408 if (ptw & PostTransportInputChange) {
409 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
410 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
412 tr->non_realtime_input_change ();
417 if (ptw & PostTransportSpeed) {
418 non_realtime_set_speed ();
421 if (ptw & PostTransportReverse) {
424 cumulative_rf_motion = 0;
427 /* don't seek if locate will take care of that in non_realtime_stop() */
429 if (!(ptw & PostTransportLocate)) {
430 LocaleGuard lg; // see note for non_realtime_locate() above
431 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
432 (*i)->non_realtime_locate (_transport_frame);
434 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
435 /* new request, stop seeking, and start again */
436 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
443 if (ptw & PostTransportLocate) {
444 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
445 non_realtime_locate ();
448 if (ptw & PostTransportStop) {
449 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
451 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
456 if (ptw & PostTransportOverWrite) {
457 non_realtime_overwrite (on_entry, finished);
459 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
464 if (ptw & PostTransportAudition) {
465 non_realtime_set_audition ();
468 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
470 DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs\n"), g_get_monotonic_time() - before));
471 DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame)));
475 Session::non_realtime_set_speed ()
477 boost::shared_ptr<RouteList> rl = routes.reader();
478 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
479 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
481 tr->non_realtime_set_speed ();
487 Session::non_realtime_overwrite (int on_entry, bool& finished)
489 boost::shared_ptr<RouteList> rl = routes.reader();
490 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
491 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
492 if (tr && tr->pending_overwrite ()) {
493 tr->overwrite_existing_buffers ();
495 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
504 Session::non_realtime_locate ()
506 DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_frame));
508 if (Config->get_loop_is_mode() && get_play_loop()) {
510 Location *loc = _locations->auto_loop_location();
512 if (!loc || (_transport_frame < loc->start() || _transport_frame >= loc->end())) {
513 /* jumped out of loop range: stop tracks from looping,
514 but leave loop (mode) enabled.
516 set_track_loop (false);
518 } else if (loc && Config->get_seamless_loop() &&
519 ((loc->start() <= _transport_frame) ||
520 (loc->end() > _transport_frame) ) ) {
522 /* jumping to start of loop. This might have been done before but it is
523 * idempotent and cheap. Doing it here ensures that when we start playback
524 * outside the loop we still flip tracks into the magic seamless mode
527 set_track_loop (true);
530 set_track_loop (false);
535 /* no more looping .. should have been noticed elsewhere */
540 LocaleGuard lg; // see note for non_realtime_locate() above
541 boost::shared_ptr<RouteList> rl = routes.reader();
542 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
543 (*i)->non_realtime_locate (_transport_frame);
547 _scene_changer->locate (_transport_frame);
549 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
550 rather than clearing them so that the RT thread has to spend time constructing
551 them (in Session::click).
556 #ifdef USE_TRACKS_CODE_FEATURES
558 Session::select_playhead_priority_target (framepos_t& jump_to)
562 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
568 if (Profile->get_trx() && transport_rolling() ) {
569 // We're playing, so do nothing.
570 // Next stop will put us where we need to be.
574 /* Note that the order of checking each AutoReturnTarget flag defines
575 the priority each flag.
577 Ardour/Mixbus: Last Locate
582 Tracks: Range Selection
588 if (autoreturn & RangeSelectionStart) {
589 if (!_range_selection.empty()) {
590 jump_to = _range_selection.from;
592 if (transport_rolling ()) {
593 /* Range selection no longer exists, but we're playing,
594 so do nothing. Next stop will put us where
602 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
603 /* don't try to handle loop play when synced to JACK */
605 if (!synced_to_engine()) {
606 Location *location = _locations->auto_loop_location();
609 jump_to = location->start();
611 if (Config->get_seamless_loop()) {
612 /* need to get track buffers reloaded */
613 set_track_loop (true);
619 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
620 if (!_object_selection.empty()) {
621 jump_to = _object_selection.from;
625 if (jump_to < 0 && (autoreturn & LastLocate)) {
626 jump_to = _last_roll_location;
634 Session::select_playhead_priority_target (framepos_t& jump_to)
636 if (config.get_external_sync() || !config.get_auto_return()) {
640 jump_to = _last_roll_location;
647 Session::follow_playhead_priority ()
651 if (select_playhead_priority_target (target)) {
652 request_locate (target);
657 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
663 PostTransportWork ptw = post_transport_work();
668 boost::shared_ptr<RouteList> rl = routes.reader();
669 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
670 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
671 if (tr && tr->get_captured_frames () != 0) {
677 /* stop and locate are merged here because they share a lot of common stuff */
680 now = localtime (&xnow);
683 auditioner->cancel_audition ();
686 cumulative_rf_motion = 0;
690 begin_reversible_command (Operations::capture);
691 _have_captured = true;
694 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
696 if (abort && did_record) {
697 /* no reason to save the session file when we remove sources
699 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
702 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
703 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
705 tr->transport_stopped_wallclock (*now, xnow, abort);
709 if (abort && did_record) {
710 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
713 boost::shared_ptr<RouteList> r = routes.reader ();
715 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
716 if (!(*i)->is_auditioner()) {
717 (*i)->set_pending_declick (0);
722 commit_reversible_command ();
723 /* increase take name */
724 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
725 string newname = config.get_take_name();
726 config.set_take_name(bump_name_number (newname));
730 if (_engine.running()) {
731 PostTransportWork ptw = post_transport_work ();
732 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
733 (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
735 update_latency_compensation ();
738 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
740 if (auto_return_enabled ||
741 (ptw & PostTransportLocate) ||
742 (_requested_return_frame >= 0) ||
743 synced_to_engine()) {
745 if (pending_locate_flush) {
746 flush_all_inserts ();
749 // rg: what is the logic behind this case?
750 // _requested_return_frame should be ignored when synced_to_engine/slaved.
751 // currently worked around in MTC_Slave by forcing _requested_return_frame to -1
753 if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
754 !(ptw & PostTransportLocate)) {
756 /* no explicit locate queued */
758 bool do_locate = false;
760 if (_requested_return_frame >= 0) {
762 /* explicit return request pre-queued in event list. overrides everything else */
764 _transport_frame = _requested_return_frame;
770 if (select_playhead_priority_target (jump_to)) {
772 _transport_frame = jump_to;
777 _transport_frame = _last_roll_location;
782 _requested_return_frame = -1;
785 _engine.transport_locate (_transport_frame);
793 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
796 if (ptw & PostTransportClearSubstate) {
798 if (!Config->get_loop_is_mode()) {
803 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
806 LocaleGuard lg; // see note for non_realtime_locate() above
807 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
808 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
809 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
810 (*i)->non_realtime_locate (_transport_frame);
812 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
814 /* we will be back */
822 /* don't bother with this stuff if we're disconnected from the engine,
823 because there will be no process callbacks to deliver stuff from
826 if (_engine.connected() && !_engine.freewheeling()) {
827 // need to queue this in the next RT cycle
828 _send_timecode_update = true;
830 if (!dynamic_cast<MTC_Slave*>(_slave)) {
831 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
833 /* This (::non_realtime_stop()) gets called by main
834 process thread, which will lead to confusion
835 when calling AsyncMIDIPort::write().
837 Something must be done. XXX
839 send_mmc_locate (_transport_frame);
843 if ((ptw & PostTransportLocate) && get_record_enabled()) {
844 /* This is scheduled by realtime_stop(), which is also done
845 * when a slave requests /locate/ for an initial sync.
846 * We can't hold up the slave for long with a save() here,
847 * without breaking its initial sync cycle.
849 * save state only if there's no slave or if it's not yet locked.
851 if (!_slave || !_slave->locked()) {
852 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
853 SaveSessionRequested (_current_snapshot_name);
858 /* always try to get rid of this */
860 remove_pending_capture_state ();
862 /* save the current state of things if appropriate */
864 if (did_record && !saved) {
865 SaveSessionRequested (_current_snapshot_name);
868 if (ptw & PostTransportStop) {
870 if (!Config->get_loop_is_mode()) {
875 PositionChanged (_transport_frame); /* EMIT SIGNAL */
876 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
877 TransportStateChange (); /* EMIT SIGNAL */
879 /* and start it up again if relevant */
881 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
882 request_transport_speed (1.0);
885 /* Even if we didn't do a pending locate roll this time, we don't want it hanging
886 around for next time.
888 pending_locate_roll = false;
892 Session::check_declick_out ()
894 bool locate_required = transport_sub_state & PendingLocate;
896 /* this is called after a process() iteration. if PendingDeclickOut was set,
897 it means that we were waiting to declick the output (which has just been
898 done) before maybe doing something else. this is where we do that "something else".
900 note: called from the audio thread.
903 if (transport_sub_state & PendingDeclickOut) {
905 if (locate_required) {
906 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
907 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
909 if (!(transport_sub_state & StopPendingCapture)) {
910 stop_transport (pending_abort);
911 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
915 } else if (transport_sub_state & PendingLoopDeclickOut) {
916 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
917 transport_sub_state &= ~PendingLoopDeclickOut;
922 Session::unset_play_loop ()
926 clear_events (SessionEvent::AutoLoop);
927 clear_events (SessionEvent::AutoLoopDeclick);
928 set_track_loop (false);
931 if (Config->get_seamless_loop()) {
932 /* likely need to flush track buffers: this will locate us to wherever we are */
933 add_post_transport_work (PostTransportLocate);
934 _butler->schedule_transport_work ();
940 Session::set_track_loop (bool yn)
942 Location* loc = _locations->auto_loop_location ();
948 boost::shared_ptr<RouteList> rl = routes.reader ();
950 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
951 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
952 if (tr && !tr->hidden()) {
953 tr->set_loop (yn ? loc : 0);
959 Session::set_play_loop (bool yn, double speed)
961 /* Called from event-handling context */
965 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
966 /* nothing to do, or can't change loop status while recording */
970 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
971 warning << string_compose (
972 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
973 "Recommend changing the configured options"), PROGRAM_NAME)
987 if (Config->get_seamless_loop()) {
988 if (!Config->get_loop_is_mode()) {
989 /* set all tracks to use internal looping */
990 set_track_loop (true);
992 /* we will do this in the locate to the start OR when we hit the end
993 * of the loop for the first time
997 /* set all tracks to NOT use internal looping */
998 set_track_loop (false);
1001 /* Put the delick and loop events in into the event list. The declick event will
1002 cause a de-clicking fade-out just before the end of the loop, and it will also result
1003 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
1008 auto_loop_declick_range (loc, dcp, dcl);
1009 merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
1010 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
1012 /* if requested to roll, locate to start of loop and
1013 * roll but ONLY if we're not already rolling.
1015 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
1018 if (Config->get_loop_is_mode()) {
1019 /* loop IS a transport mode: if already
1020 rolling, do not locate to loop start.
1022 if (!transport_rolling() && (speed != 0.0)) {
1023 start_locate (loc->start(), true, true, false, true);
1027 start_locate (loc->start(), true, true, false, true);
1037 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
1038 TransportStateChange ();
1041 Session::flush_all_inserts ()
1043 boost::shared_ptr<RouteList> r = routes.reader ();
1045 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1046 (*i)->flush_processors ();
1051 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
1053 if (target_frame < 0) {
1054 error << _("Locate called for negative sample position - ignored") << endmsg;
1058 if (synced_to_engine()) {
1063 _slave->speed_and_position (sp, pos);
1065 if (target_frame != pos) {
1067 if (config.get_jack_time_master()) {
1068 /* actually locate now, since otherwise jack_timebase_callback
1069 will use the incorrect _transport_frame and report an old
1070 and incorrect time to Jack transport
1072 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1075 /* tell JACK to change transport position, and we will
1076 follow along later in ::follow_slave()
1079 _engine.transport_locate (target_frame);
1081 if (sp != 1.0f && with_roll) {
1082 _engine.transport_start ();
1088 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1093 Session::micro_locate (framecnt_t distance)
1095 boost::shared_ptr<RouteList> rl = routes.reader();
1096 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1097 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1098 if (tr && !tr->can_internal_playback_seek (distance)) {
1103 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1104 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1106 tr->internal_playback_seek (distance);
1110 _transport_frame += distance;
1114 /** @param with_mmc true to send a MMC locate command when the locate is done */
1116 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
1118 bool need_butler = false;
1120 /* Locates for seamless looping are fairly different from other
1121 * locates. They assume that the diskstream buffers for each track
1122 * already have the correct data in them, and thus there is no need to
1123 * actually tell the tracks to locate. What does need to be done,
1124 * though, is all the housekeeping that is associated with non-linear
1125 * changes in the value of _transport_frame.
1128 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
1129 target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
1131 if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
1133 /* already at the desired position. Not forced to locate,
1134 the loop isn't changing, so unless we're told to
1135 start rolling also, there's nothing to do but
1136 tell the world where we are (again).
1140 set_transport_speed (1.0, 0, false);
1142 loop_changing = false;
1143 Located (); /* EMIT SIGNAL */
1147 if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
1148 /* Schedule a declick. We'll be called again when its done.
1149 We only do it this way for ordinary locates, not those
1150 due to **seamless** loops.
1153 if (!(transport_sub_state & PendingDeclickOut)) {
1154 transport_sub_state |= (PendingDeclickOut|PendingLocate);
1155 pending_locate_frame = target_frame;
1156 pending_locate_roll = with_roll;
1157 pending_locate_flush = with_flush;
1162 // Update Timecode time
1163 _transport_frame = target_frame;
1164 _last_roll_or_reversal_location = target_frame;
1165 timecode_time(_transport_frame, transmitting_timecode_time);
1167 /* do "stopped" stuff if:
1169 * we are rolling AND
1170 * no autoplay in effect AND
1171 * we're not going to keep rolling after the locate AND
1172 * !(playing a loop with JACK sync)
1176 bool transport_was_stopped = !transport_rolling();
1178 if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1179 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1180 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1181 transport_was_stopped = true;
1183 /* otherwise tell the world that we located */
1187 if (force || !for_loop_enabled || loop_changing) {
1189 PostTransportWork todo = PostTransportLocate;
1191 if (with_roll && transport_was_stopped) {
1192 todo = PostTransportWork (todo | PostTransportRoll);
1195 add_post_transport_work (todo);
1200 /* this is functionally what clear_clicks() does but with a tentative lock */
1202 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1204 if (clickm.locked()) {
1206 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1215 /* switch from input if we're going to roll */
1216 if (Config->get_monitoring_model() == HardwareMonitoring) {
1217 set_track_monitor_input_status (!config.get_auto_input());
1220 /* otherwise we're going to stop, so do the opposite */
1221 if (Config->get_monitoring_model() == HardwareMonitoring) {
1222 set_track_monitor_input_status (true);
1226 /* cancel looped playback if transport pos outside of loop range */
1229 Location* al = _locations->auto_loop_location();
1232 if (_transport_frame < al->start() || _transport_frame >= al->end()) {
1234 // located outside the loop: cancel looping directly, this is called from event handling context
1236 have_looped = false;
1238 if (!Config->get_loop_is_mode()) {
1239 set_play_loop (false, _transport_speed);
1241 if (Config->get_seamless_loop()) {
1242 /* this will make the non_realtime_locate() in the butler
1243 which then causes seek() in tracks actually do the right
1246 set_track_loop (false);
1250 } else if (_transport_frame == al->start()) {
1252 // located to start of loop - this is looping, basically
1256 if (_last_roll_location != al->start()) {
1257 /* didn't start at loop start - playback must have
1258 * started before loop since we've now hit the loop
1261 add_post_transport_work (PostTransportLocate);
1267 boost::shared_ptr<RouteList> rl = routes.reader();
1269 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1270 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1272 if (tr && tr->rec_enable_control()->get_value()) {
1273 // tell it we've looped, so it can deal with the record state
1274 tr->transport_looped (_transport_frame);
1279 TransportLooped(); // EMIT SIGNAL
1285 _butler->schedule_transport_work ();
1288 loop_changing = false;
1290 _send_timecode_update = true;
1293 send_mmc_locate (_transport_frame);
1296 _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
1297 Located (); /* EMIT SIGNAL */
1300 /** Set the transport speed.
1301 * Called from the process thread.
1302 * @param speed New speed
1305 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1307 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1308 speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1310 if (_transport_speed == speed) {
1311 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1312 _default_transport_speed = 1.0;
1317 if (actively_recording() && speed != 1.0 && speed != 0.0) {
1318 /* no varispeed during recording */
1319 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1320 _transport_speed, _transport_frame));
1324 _target_transport_speed = fabs(speed);
1326 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1327 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1331 speed = min (8.0, speed);
1332 } else if (speed < 0) {
1333 speed = max (-8.0, speed);
1336 if (transport_rolling() && speed == 0.0) {
1338 /* we are rolling and we want to stop */
1340 if (Config->get_monitoring_model() == HardwareMonitoring) {
1341 set_track_monitor_input_status (true);
1344 if (synced_to_engine ()) {
1346 /* do this here because our response to the slave won't
1349 _play_range = false;
1352 _engine.transport_stop ();
1354 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1356 if (!auto_return_enabled) {
1357 _requested_return_frame = destination_frame;
1360 stop_transport (abort);
1363 } else if (transport_stopped() && speed == 1.0) {
1365 _default_transport_speed = speed;
1367 /* we are stopped and we want to start rolling at speed 1 */
1369 if (Config->get_loop_is_mode() && play_loop) {
1371 Location *location = _locations->auto_loop_location();
1373 if (location != 0) {
1374 if (_transport_frame != location->start()) {
1376 if (Config->get_seamless_loop()) {
1377 /* force tracks to do their thing */
1378 set_track_loop (true);
1381 /* jump to start and then roll from there */
1383 request_locate (location->start(), true);
1389 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1390 set_track_monitor_input_status (false);
1393 if (synced_to_engine()) {
1394 _engine.transport_start ();
1401 /* not zero, not 1.0 ... varispeed */
1403 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1404 warning << string_compose (
1405 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1411 if (actively_recording()) {
1415 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1419 if (speed < 0.0 && _transport_frame == 0) {
1425 /* if we are reversing relative to the current speed, or relative to the speed
1426 before the last stop, then we have to do extra work.
1429 PostTransportWork todo = PostTransportWork (0);
1431 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
1432 todo = PostTransportWork (todo | PostTransportReverse);
1433 _last_roll_or_reversal_location = _transport_frame;
1436 _last_transport_speed = _transport_speed;
1437 _transport_speed = speed;
1440 _default_transport_speed = speed;
1443 boost::shared_ptr<RouteList> rl = routes.reader();
1444 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1445 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1446 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1447 todo = PostTransportWork (todo | PostTransportSpeed);
1452 add_post_transport_work (todo);
1453 _butler->schedule_transport_work ();
1456 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1458 /* throttle signal emissions.
1459 * when slaved [_last]_transport_speed
1460 * usually changes every cycle (tiny amounts due to DLL).
1461 * Emitting a signal every cycle is overkill and unwarranted.
1463 * Using _last_transport_speed is not acceptable,
1464 * since it allows for large changes over a long period
1465 * of time. Hence we introduce a dedicated variable to keep track
1467 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1468 * for TransportStateChange() here is the ShuttleControl display.
1470 if (fabs (_signalled_varispeed - speed) > .002
1471 // still, signal hard changes to 1.0 and 0.0:
1472 || ( speed == 1.0 && _signalled_varispeed != 1.0)
1473 || ( speed == 0.0 && _signalled_varispeed != 0.0)
1476 TransportStateChange (); /* EMIT SIGNAL */
1477 _signalled_varispeed = speed;
1483 /** Stop the transport. */
1485 Session::stop_transport (bool abort, bool clear_state)
1487 if (_transport_speed == 0.0f) {
1491 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
1493 if (!get_transport_declick_required()) {
1495 /* stop has not yet been scheduled */
1497 boost::shared_ptr<RouteList> rl = routes.reader();
1498 framepos_t stop_target = audible_frame();
1500 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1501 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1503 tr->prepare_to_stop (_transport_frame, stop_target);
1509 if (actively_recording() && /* we are recording */
1510 worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1512 /* we need to capture the audio that is still somewhere in the pipeline between
1513 wherever it was generated and the process callback. This means that even though
1514 the user (or something else) has asked us to stop, we have to roll
1515 past this point and then reset the playhead/transport location to
1516 the position at which the stop was requested.
1518 we still need playback to "stop" now, however, which is why we schedule
1522 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1523 _transport_frame, _worst_input_latency,
1524 _transport_frame + _worst_input_latency,
1527 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1528 _transport_frame + _worst_input_latency,
1533 /* request a declick at the start of the next process cycle() so that playback ceases.
1534 It will remain silent until we actually stop (at the StopOnce event somewhere in
1535 the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1536 does not stop the transport too early.
1538 new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1542 /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1544 new_bits = PendingDeclickOut;
1545 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
1548 /* we'll be called again after the declick */
1549 transport_sub_state = SubState (transport_sub_state|new_bits);
1550 pending_abort = abort;
1556 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
1558 /* declick was scheduled, but we've been called again, which means it is really time to stop
1560 XXX: we should probably split this off into its own method and call it explicitly.
1563 realtime_stop (abort, clear_state);
1564 _butler->schedule_transport_work ();
1568 /** Called from the process thread */
1570 Session::start_transport ()
1572 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1574 _last_roll_location = _transport_frame;
1575 _last_roll_or_reversal_location = _transport_frame;
1577 have_looped = false;
1579 /* if record status is Enabled, move it to Recording. if its
1580 already Recording, move it to Disabled.
1583 switch (record_status()) {
1585 if (!config.get_punch_in()) {
1592 disable_record (false);
1600 transport_sub_state |= PendingDeclickIn;
1602 _transport_speed = _default_transport_speed;
1603 _target_transport_speed = _transport_speed;
1605 boost::shared_ptr<RouteList> rl = routes.reader();
1606 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1607 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1609 tr->realtime_set_speed (tr->speed(), true);
1613 if (!_engine.freewheeling()) {
1614 Timecode::Time time;
1615 timecode_time_subframes (_transport_frame, time);
1616 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1617 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1621 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1622 TransportStateChange (); /* EMIT SIGNAL */
1625 /** Do any transport work in the audio thread that needs to be done after the
1626 * transport thread is finished. Audio thread, realtime safe.
1629 Session::post_transport ()
1631 PostTransportWork ptw = post_transport_work ();
1633 if (ptw & PostTransportAudition) {
1634 if (auditioner && auditioner->auditioning()) {
1635 process_function = &Session::process_audition;
1637 process_function = &Session::process_with_events;
1641 if (ptw & PostTransportStop) {
1643 transport_sub_state = 0;
1646 if (ptw & PostTransportLocate) {
1648 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1651 transport_sub_state = 0;
1656 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1659 set_post_transport_work (PostTransportWork (0));
1663 Session::reset_rf_scale (framecnt_t motion)
1665 cumulative_rf_motion += motion;
1667 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1669 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1671 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1683 Session::mtc_status_changed (bool yn)
1685 g_atomic_int_set (&_mtc_active, yn);
1686 MTCSyncStateChanged( yn );
1690 Session::ltc_status_changed (bool yn)
1692 g_atomic_int_set (&_ltc_active, yn);
1693 LTCSyncStateChanged( yn );
1697 Session::use_sync_source (Slave* new_slave)
1699 /* Runs in process() context */
1701 bool non_rt_required = false;
1703 /* XXX this deletion is problematic because we're in RT context */
1708 MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1710 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1711 MTCSyncStateChanged(mtc_slave->locked() );
1713 if (g_atomic_int_get (&_mtc_active) ){
1714 g_atomic_int_set (&_mtc_active, 0);
1715 MTCSyncStateChanged( false );
1717 mtc_status_connection.disconnect ();
1720 LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1722 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1723 LTCSyncStateChanged (ltc_slave->locked() );
1725 if (g_atomic_int_get (&_ltc_active) ){
1726 g_atomic_int_set (&_ltc_active, 0);
1727 LTCSyncStateChanged( false );
1729 ltc_status_connection.disconnect ();
1732 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1734 // need to queue this for next process() cycle
1735 _send_timecode_update = true;
1737 boost::shared_ptr<RouteList> rl = routes.reader();
1738 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1739 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1740 if (tr && !tr->hidden()) {
1741 if (tr->realtime_set_speed (tr->speed(), true)) {
1742 non_rt_required = true;
1744 tr->set_slaved (_slave != 0);
1748 if (non_rt_required) {
1749 add_post_transport_work (PostTransportSpeed);
1750 _butler->schedule_transport_work ();
1757 Session::drop_sync_source ()
1759 request_sync_source (0);
1763 Session::switch_to_sync_source (SyncSource src)
1767 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1771 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1776 new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1779 catch (failed_constructor& err) {
1785 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1790 new_slave = new LTC_Slave (*this);
1793 catch (failed_constructor& err) {
1800 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1805 new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1808 catch (failed_constructor& err) {
1814 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1818 if (config.get_video_pullup() != 0.0f) {
1822 new_slave = new Engine_Slave (*AudioEngine::instance());
1830 request_sync_source (new_slave);
1834 Session::set_track_speed (Track* track, double speed)
1836 if (track->realtime_set_speed (speed, false)) {
1837 add_post_transport_work (PostTransportSpeed);
1838 _butler->schedule_transport_work ();
1844 Session::unset_play_range ()
1846 _play_range = false;
1847 _clear_event_type (SessionEvent::RangeStop);
1848 _clear_event_type (SessionEvent::RangeLocate);
1852 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1856 /* Called from event-processing context */
1858 unset_play_range ();
1860 if (range.empty()) {
1861 /* _play_range set to false in unset_play_range()
1863 if (!leave_rolling) {
1864 /* stop transport */
1865 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1873 /* cancel loop play */
1876 list<AudioRange>::size_type sz = range.size();
1880 list<AudioRange>::iterator i = range.begin();
1881 list<AudioRange>::iterator next;
1883 while (i != range.end()) {
1888 /* locating/stopping is subject to delays for declicking.
1891 framepos_t requested_frame = i->end;
1893 if (requested_frame > current_block_size) {
1894 requested_frame -= current_block_size;
1896 requested_frame = 0;
1899 if (next == range.end()) {
1900 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1902 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1910 } else if (sz == 1) {
1912 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1917 /* save range so we can do auto-return etc. */
1919 current_audio_range = range;
1921 /* now start rolling at the right place */
1923 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1926 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
1927 TransportStateChange ();
1931 Session::request_bounded_roll (framepos_t start, framepos_t end)
1933 AudioRange ar (start, end, 0);
1934 list<AudioRange> lar;
1937 request_play_range (&lar, true);
1941 Session::set_requested_return_frame (framepos_t return_to)
1943 _requested_return_frame = return_to;
1947 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
1949 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1950 ev->target2_frame = start;
1955 Session::engine_halted ()
1959 /* there will be no more calls to process(), so
1960 we'd better clean up for ourselves, right now.
1962 but first, make sure the butler is out of
1970 realtime_stop (false, true);
1971 non_realtime_stop (false, 0, ignored);
1972 transport_sub_state = 0;
1974 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
1975 TransportStateChange (); /* EMIT SIGNAL */
1980 Session::xrun_recovery ()
1984 Xrun (_transport_frame); /* EMIT SIGNAL */
1986 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1988 /* it didn't actually halt, but we need
1989 to handle things in the same way.
1997 Session::route_processors_changed (RouteProcessorChange c)
1999 if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
2003 if (c.type == RouteProcessorChange::MeterPointChange) {
2008 if (c.type == RouteProcessorChange::RealTimeChange) {
2013 update_latency_compensation ();
2020 Session::allow_auto_play (bool yn)
2022 auto_play_legal = yn;
2026 Session::maybe_stop (framepos_t limit)
2028 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
2029 if (synced_to_engine () && config.get_jack_time_master ()) {
2030 _engine.transport_stop ();
2031 } else if (!synced_to_engine ()) {
2040 Session::send_mmc_locate (framepos_t t)
2046 if (!_engine.freewheeling()) {
2047 Timecode::Time time;
2048 timecode_time_subframes (t, time);
2049 send_immediate_mmc (MIDI::MachineControlCommand (time));
2053 /** Ask the transport to not send timecode until further notice. The suspension
2054 * will come into effect some finite time after this call, and timecode_transmission_suspended()
2055 * should be checked by the caller to find out when.
2058 Session::request_suspend_timecode_transmission ()
2060 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2065 Session::request_resume_timecode_transmission ()
2067 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2072 Session::timecode_transmission_suspended () const
2074 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;