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 = true; // 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 Location *location = _locations->auto_loop_location();
170 if (location == 0 && yn) {
171 error << _("Cannot loop - no loop range defined")
176 if (change_transport_roll) {
177 if (transport_rolling()) {
178 /* start looping at current speed */
179 target_speed = transport_speed ();
181 /* currently stopped */
183 /* start looping at normal speed */
190 /* leave the speed alone */
191 target_speed = transport_speed ();
194 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
195 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
199 if (!change_transport_roll) {
200 if (!transport_rolling()) {
201 /* we're not changing transport state, but we do want
202 to set up position for the new loop. Don't
203 do this if we're rolling already.
205 request_locate (location->start(), false);
209 if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
210 // request an immediate locate to refresh the tracks
211 // after disabling looping
212 request_locate (_transport_frame-1, false);
218 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
220 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
222 ev->audio_range = *range;
224 ev->audio_range.clear ();
226 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
231 Session::request_cancel_play_range ()
233 SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
239 Session::realtime_stop (bool abort, bool clear_state)
241 DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_frame));
242 PostTransportWork todo = PostTransportWork (0);
244 /* assume that when we start, we'll be moving forwards */
246 if (_transport_speed < 0.0f) {
247 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
248 _default_transport_speed = 1.0;
250 todo = PostTransportWork (todo | PostTransportStop);
255 boost::shared_ptr<RouteList> r = routes.reader ();
257 for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
258 (*i)->realtime_handle_transport_stopped ();
261 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_frame));
263 /* the duration change is not guaranteed to have happened, but is likely */
265 todo = PostTransportWork (todo | PostTransportDuration);
268 todo = PostTransportWork (todo | PostTransportAbort);
272 todo = PostTransportWork (todo | PostTransportClearSubstate);
276 add_post_transport_work (todo);
279 _clear_event_type (SessionEvent::StopOnce);
280 _clear_event_type (SessionEvent::RangeStop);
281 _clear_event_type (SessionEvent::RangeLocate);
283 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
284 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
286 if (clear_state && !Config->get_loop_is_mode()) {
290 reset_slave_state ();
292 _transport_speed = 0;
293 _target_transport_speed = 0;
295 g_atomic_int_set (&_playback_load, 100);
296 g_atomic_int_set (&_capture_load, 100);
298 if (config.get_use_video_sync()) {
299 waiting_for_sync_offset = true;
302 transport_sub_state = 0;
306 Session::realtime_locate ()
308 boost::shared_ptr<RouteList> r = routes.reader ();
309 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
310 (*i)->realtime_locate ();
315 Session::butler_transport_work ()
319 PostTransportWork ptw;
320 boost::shared_ptr<RouteList> r = routes.reader ();
323 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
325 ptw = post_transport_work();
327 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
330 if (ptw & PostTransportLocate) {
332 if (get_play_loop() && !Config->get_seamless_loop() && actively_recording()) {
334 /* this locate is happening while we are doing loop
335 * recording but with seam-ed (non-seamless) looping.
336 * We must flush any data to disk before resetting
337 * buffers as part of the pending locate (which happens
338 * a little later in this method).
341 bool more_disk_io_to_do = false;
345 more_disk_io_to_do = _butler->flush_tracks_to_disk (r, errors, true);
351 if (more_disk_io_to_do) {
360 if (ptw & PostTransportAdjustPlaybackBuffering) {
361 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
362 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
364 tr->adjust_playback_buffering ();
365 /* and refill those buffers ... */
367 (*i)->non_realtime_locate (_transport_frame);
372 if (ptw & PostTransportAdjustCaptureBuffering) {
373 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
374 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
376 tr->adjust_capture_buffering ();
381 if (ptw & PostTransportCurveRealloc) {
382 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
383 (*i)->curve_reallocate();
387 if (ptw & PostTransportInputChange) {
388 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
389 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
391 tr->non_realtime_input_change ();
396 if (ptw & PostTransportSpeed) {
397 non_realtime_set_speed ();
400 if (ptw & PostTransportReverse) {
403 cumulative_rf_motion = 0;
406 /* don't seek if locate will take care of that in non_realtime_stop() */
408 if (!(ptw & PostTransportLocate)) {
410 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
411 (*i)->non_realtime_locate (_transport_frame);
413 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
414 /* new request, stop seeking, and start again */
415 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
422 if (ptw & PostTransportLocate) {
423 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
424 non_realtime_locate ();
427 if (ptw & PostTransportStop) {
428 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
430 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
435 if (ptw & PostTransportOverWrite) {
436 non_realtime_overwrite (on_entry, finished);
438 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
443 if (ptw & PostTransportAudition) {
444 non_realtime_set_audition ();
447 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
449 DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs\n"), g_get_monotonic_time() - before));
450 DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame)));
454 Session::non_realtime_set_speed ()
456 boost::shared_ptr<RouteList> rl = routes.reader();
457 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
458 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
460 tr->non_realtime_set_speed ();
466 Session::non_realtime_overwrite (int on_entry, bool& finished)
468 boost::shared_ptr<RouteList> rl = routes.reader();
469 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
470 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
471 if (tr && tr->pending_overwrite ()) {
472 tr->overwrite_existing_buffers ();
474 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
483 Session::non_realtime_locate ()
485 DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_frame));
487 if (Config->get_loop_is_mode() && get_play_loop()) {
489 Location *loc = _locations->auto_loop_location();
491 if (!loc || (_transport_frame < loc->start() || _transport_frame >= loc->end())) {
492 /* jumped out of loop range: stop tracks from looping,
493 but leave loop (mode) enabled.
495 set_track_loop (false);
497 } else if (loc && Config->get_seamless_loop() &&
498 ((loc->start() <= _transport_frame) ||
499 (loc->end() > _transport_frame) ) ) {
501 /* jumping to start of loop. This might have been done before but it is
502 * idempotent and cheap. Doing it here ensures that when we start playback
503 * outside the loop we still flip tracks into the magic seamless mode
506 set_track_loop (true);
509 set_track_loop (false);
514 /* no more looping .. should have been noticed elsewhere */
518 boost::shared_ptr<RouteList> rl = routes.reader();
519 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
520 (*i)->non_realtime_locate (_transport_frame);
523 _scene_changer->locate (_transport_frame);
525 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
526 rather than clearing them so that the RT thread has to spend time constructing
527 them (in Session::click).
532 #ifdef USE_TRACKS_CODE_FEATURES
534 Session::select_playhead_priority_target (framepos_t& jump_to)
538 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
544 if (Profile->get_trx() && transport_rolling() ) {
545 // We're playing, so do nothing.
546 // Next stop will put us where we need to be.
550 /* Note that the order of checking each AutoReturnTarget flag defines
551 the priority each flag.
553 Ardour/Mixbus: Last Locate
558 Tracks: Range Selection
564 if (autoreturn & RangeSelectionStart) {
565 if (!_range_selection.empty()) {
566 jump_to = _range_selection.from;
568 if (transport_rolling ()) {
569 /* Range selection no longer exists, but we're playing,
570 so do nothing. Next stop will put us where
578 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
579 /* don't try to handle loop play when synced to JACK */
581 if (!synced_to_engine()) {
582 Location *location = _locations->auto_loop_location();
585 jump_to = location->start();
587 if (Config->get_seamless_loop()) {
588 /* need to get track buffers reloaded */
589 set_track_loop (true);
595 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
596 if (!_object_selection.empty()) {
597 jump_to = _object_selection.from;
601 if (jump_to < 0 && (autoreturn & LastLocate)) {
602 jump_to = _last_roll_location;
610 Session::select_playhead_priority_target (framepos_t& jump_to)
612 if (!config.get_auto_return()) {
616 jump_to = _last_roll_location;
623 Session::follow_playhead_priority ()
627 if (select_playhead_priority_target (target)) {
628 request_locate (target);
633 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
639 PostTransportWork ptw = post_transport_work();
644 boost::shared_ptr<RouteList> rl = routes.reader();
645 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
646 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
647 if (tr && tr->get_captured_frames () != 0) {
653 /* stop and locate are merged here because they share a lot of common stuff */
656 now = localtime (&xnow);
659 auditioner->cancel_audition ();
662 cumulative_rf_motion = 0;
666 begin_reversible_command (Operations::capture);
667 _have_captured = true;
670 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
672 if (abort && did_record) {
673 /* no reason to save the session file when we remove sources
675 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
678 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
679 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
681 tr->transport_stopped_wallclock (*now, xnow, abort);
685 if (abort && did_record) {
686 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
689 boost::shared_ptr<RouteList> r = routes.reader ();
691 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
692 if (!(*i)->is_auditioner()) {
693 (*i)->set_pending_declick (0);
698 commit_reversible_command ();
699 /* increase take name */
700 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
701 string newname = config.get_take_name();
702 config.set_take_name(bump_name_number (newname));
706 if (_engine.running()) {
707 PostTransportWork ptw = post_transport_work ();
708 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
709 (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
711 update_latency_compensation ();
714 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
716 if (auto_return_enabled ||
717 (ptw & PostTransportLocate) ||
718 (_requested_return_frame >= 0) ||
719 synced_to_engine()) {
721 if (pending_locate_flush) {
722 flush_all_inserts ();
725 if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
726 !(ptw & PostTransportLocate)) {
728 /* no explicit locate queued */
730 bool do_locate = false;
732 if (_requested_return_frame >= 0) {
734 /* explicit return request pre-queued in event list. overrides everything else */
736 _transport_frame = _requested_return_frame;
742 if (select_playhead_priority_target (jump_to)) {
744 _transport_frame = jump_to;
749 _transport_frame = _last_roll_location;
754 _requested_return_frame = -1;
757 _engine.transport_locate (_transport_frame);
765 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
768 if (ptw & PostTransportClearSubstate) {
770 if (!Config->get_loop_is_mode()) {
775 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
777 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
778 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
779 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
780 (*i)->non_realtime_locate (_transport_frame);
782 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
784 /* we will be back */
791 /* don't bother with this stuff if we're disconnected from the engine,
792 because there will be no process callbacks to deliver stuff from
795 if (_engine.connected() && !_engine.freewheeling()) {
796 // need to queue this in the next RT cycle
797 _send_timecode_update = true;
799 if (!dynamic_cast<MTC_Slave*>(_slave)) {
800 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
802 /* This (::non_realtime_stop()) gets called by main
803 process thread, which will lead to confusion
804 when calling AsyncMIDIPort::write().
806 Something must be done. XXX
808 send_mmc_locate (_transport_frame);
812 if ((ptw & PostTransportLocate) && get_record_enabled()) {
813 /* This is scheduled by realtime_stop(), which is also done
814 * when a slave requests /locate/ for an initial sync.
815 * We can't hold up the slave for long with a save() here,
816 * without breaking its initial sync cycle.
818 * save state only if there's no slave or if it's not yet locked.
820 if (!_slave || !_slave->locked()) {
821 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
822 SaveSessionRequested (_current_snapshot_name);
827 /* always try to get rid of this */
829 remove_pending_capture_state ();
831 /* save the current state of things if appropriate */
833 if (did_record && !saved) {
834 SaveSessionRequested (_current_snapshot_name);
837 if (ptw & PostTransportStop) {
839 if (!Config->get_loop_is_mode()) {
844 PositionChanged (_transport_frame); /* EMIT SIGNAL */
845 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
846 TransportStateChange (); /* EMIT SIGNAL */
848 /* and start it up again if relevant */
850 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
851 request_transport_speed (1.0);
854 /* Even if we didn't do a pending locate roll this time, we don't want it hanging
855 around for next time.
857 pending_locate_roll = false;
861 Session::check_declick_out ()
863 bool locate_required = transport_sub_state & PendingLocate;
865 /* this is called after a process() iteration. if PendingDeclickOut was set,
866 it means that we were waiting to declick the output (which has just been
867 done) before maybe doing something else. this is where we do that "something else".
869 note: called from the audio thread.
872 if (transport_sub_state & PendingDeclickOut) {
874 if (locate_required) {
875 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
876 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
878 if (!(transport_sub_state & StopPendingCapture)) {
879 stop_transport (pending_abort);
880 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
884 } else if (transport_sub_state & PendingLoopDeclickOut) {
885 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
886 transport_sub_state &= ~PendingLoopDeclickOut;
891 Session::unset_play_loop ()
895 clear_events (SessionEvent::AutoLoop);
896 clear_events (SessionEvent::AutoLoopDeclick);
897 set_track_loop (false);
900 if (Config->get_seamless_loop()) {
901 /* likely need to flush track buffers: this will locate us to wherever we are */
902 add_post_transport_work (PostTransportLocate);
903 _butler->schedule_transport_work ();
909 Session::set_track_loop (bool yn)
911 Location* loc = _locations->auto_loop_location ();
917 boost::shared_ptr<RouteList> rl = routes.reader ();
919 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
920 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
921 if (tr && !tr->hidden()) {
922 tr->set_loop (yn ? loc : 0);
928 Session::set_play_loop (bool yn, double speed)
930 /* Called from event-handling context */
934 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
935 /* nothing to do, or can't change loop status while recording */
939 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
940 warning << string_compose (
941 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
942 "Recommend changing the configured options"), PROGRAM_NAME)
956 if (Config->get_seamless_loop()) {
957 if (!Config->get_loop_is_mode()) {
958 /* set all tracks to use internal looping */
959 set_track_loop (true);
961 /* we will do this in the locate to the start OR when we hit the end
962 * of the loop for the first time
966 /* set all tracks to NOT use internal looping */
967 set_track_loop (false);
970 /* Put the delick and loop events in into the event list. The declick event will
971 cause a de-clicking fade-out just before the end of the loop, and it will also result
972 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
977 auto_loop_declick_range (loc, dcp, dcl);
978 merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
979 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
981 /* if requested to roll, locate to start of loop and
982 * roll but ONLY if we're not already rolling.
984 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
987 if (Config->get_loop_is_mode()) {
988 /* loop IS a transport mode: if already
989 rolling, do not locate to loop start.
991 if (!transport_rolling() && (speed != 0.0)) {
992 start_locate (loc->start(), true, true, false, true);
996 start_locate (loc->start(), true, true, false, true);
1006 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
1007 TransportStateChange ();
1010 Session::flush_all_inserts ()
1012 boost::shared_ptr<RouteList> r = routes.reader ();
1014 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1015 (*i)->flush_processors ();
1020 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
1022 if (target_frame < 0) {
1023 error << _("Locate called for negative sample position - ignored") << endmsg;
1027 if (synced_to_engine()) {
1032 _slave->speed_and_position (sp, pos);
1034 if (target_frame != pos) {
1036 if (config.get_jack_time_master()) {
1037 /* actually locate now, since otherwise jack_timebase_callback
1038 will use the incorrect _transport_frame and report an old
1039 and incorrect time to Jack transport
1041 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1044 /* tell JACK to change transport position, and we will
1045 follow along later in ::follow_slave()
1048 _engine.transport_locate (target_frame);
1050 if (sp != 1.0f && with_roll) {
1051 _engine.transport_start ();
1057 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1062 Session::micro_locate (framecnt_t distance)
1064 boost::shared_ptr<RouteList> rl = routes.reader();
1065 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1066 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1067 if (tr && !tr->can_internal_playback_seek (distance)) {
1072 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1073 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1075 tr->internal_playback_seek (distance);
1079 _transport_frame += distance;
1083 /** @param with_mmc true to send a MMC locate command when the locate is done */
1085 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
1087 bool need_butler = false;
1089 /* Locates for seamless looping are fairly different from other
1090 * locates. They assume that the diskstream buffers for each track
1091 * already have the correct data in them, and thus there is no need to
1092 * actually tell the tracks to locate. What does need to be done,
1093 * though, is all the housekeeping that is associated with non-linear
1094 * changes in the value of _transport_frame.
1097 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
1098 target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
1100 if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
1102 /* already at the desired position. Not forced to locate,
1103 the loop isn't changing, so unless we're told to
1104 start rolling also, there's nothing to do but
1105 tell the world where we are (again).
1109 set_transport_speed (1.0, 0, false);
1111 loop_changing = false;
1112 Located (); /* EMIT SIGNAL */
1116 if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
1117 /* Schedule a declick. We'll be called again when its done.
1118 We only do it this way for ordinary locates, not those
1119 due to **seamless** loops.
1122 if (!(transport_sub_state & PendingDeclickOut)) {
1123 transport_sub_state |= (PendingDeclickOut|PendingLocate);
1124 pending_locate_frame = target_frame;
1125 pending_locate_roll = with_roll;
1126 pending_locate_flush = with_flush;
1131 // Update Timecode time
1132 // [DR] FIXME: find out exactly where this should go below
1133 _transport_frame = target_frame;
1134 _last_roll_or_reversal_location = target_frame;
1135 timecode_time(_transport_frame, transmitting_timecode_time);
1136 outbound_mtc_timecode_frame = _transport_frame;
1137 next_quarter_frame_to_send = 0;
1139 /* do "stopped" stuff if:
1141 * we are rolling AND
1142 * no autoplay in effect AND
1143 * we're not going to keep rolling after the locate AND
1144 * !(playing a loop with JACK sync)
1148 bool transport_was_stopped = !transport_rolling();
1150 if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1151 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1152 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1153 transport_was_stopped = true;
1155 /* otherwise tell the world that we located */
1159 if (force || !for_loop_enabled || loop_changing) {
1161 PostTransportWork todo = PostTransportLocate;
1163 if (with_roll && transport_was_stopped) {
1164 todo = PostTransportWork (todo | PostTransportRoll);
1167 add_post_transport_work (todo);
1172 /* this is functionally what clear_clicks() does but with a tentative lock */
1174 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1176 if (clickm.locked()) {
1178 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1187 /* switch from input if we're going to roll */
1188 if (Config->get_monitoring_model() == HardwareMonitoring) {
1189 set_track_monitor_input_status (!config.get_auto_input());
1192 /* otherwise we're going to stop, so do the opposite */
1193 if (Config->get_monitoring_model() == HardwareMonitoring) {
1194 set_track_monitor_input_status (true);
1198 /* cancel looped playback if transport pos outside of loop range */
1201 Location* al = _locations->auto_loop_location();
1204 if (_transport_frame < al->start() || _transport_frame >= al->end()) {
1206 // located outside the loop: cancel looping directly, this is called from event handling context
1208 have_looped = false;
1210 if (!Config->get_loop_is_mode()) {
1211 set_play_loop (false, _transport_speed);
1213 if (Config->get_seamless_loop()) {
1214 /* this will make the non_realtime_locate() in the butler
1215 which then causes seek() in tracks actually do the right
1218 set_track_loop (false);
1222 } else if (_transport_frame == al->start()) {
1224 // located to start of loop - this is looping, basically
1228 if (_last_roll_location != al->start()) {
1229 /* didn't start at loop start - playback must have
1230 * started before loop since we've now hit the loop
1233 add_post_transport_work (PostTransportLocate);
1239 boost::shared_ptr<RouteList> rl = routes.reader();
1241 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1242 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1244 if (tr && tr->record_enabled ()) {
1245 // tell it we've looped, so it can deal with the record state
1246 tr->transport_looped (_transport_frame);
1251 TransportLooped(); // EMIT SIGNAL
1257 _butler->schedule_transport_work ();
1260 loop_changing = false;
1262 _send_timecode_update = true;
1265 send_mmc_locate (_transport_frame);
1268 _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
1269 Located (); /* EMIT SIGNAL */
1272 /** Set the transport speed.
1273 * Called from the process thread.
1274 * @param speed New speed
1277 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1279 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1280 speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1282 if (_transport_speed == speed) {
1283 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1284 _default_transport_speed = 1.0;
1289 if (actively_recording() && speed != 1.0 && speed != 0.0) {
1290 /* no varispeed during recording */
1291 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1292 _transport_speed, _transport_frame));
1296 _target_transport_speed = fabs(speed);
1298 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1299 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1303 speed = min (8.0, speed);
1304 } else if (speed < 0) {
1305 speed = max (-8.0, speed);
1308 if (transport_rolling() && speed == 0.0) {
1310 /* we are rolling and we want to stop */
1312 if (Config->get_monitoring_model() == HardwareMonitoring) {
1313 set_track_monitor_input_status (true);
1316 if (synced_to_engine ()) {
1318 /* do this here because our response to the slave won't
1321 _play_range = false;
1324 _engine.transport_stop ();
1326 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1328 if (!auto_return_enabled) {
1329 _requested_return_frame = destination_frame;
1332 stop_transport (abort);
1335 } else if (transport_stopped() && speed == 1.0) {
1337 /* we are stopped and we want to start rolling at speed 1 */
1339 if (Config->get_loop_is_mode() && play_loop) {
1341 Location *location = _locations->auto_loop_location();
1343 if (location != 0) {
1344 if (_transport_frame != location->start()) {
1346 if (Config->get_seamless_loop()) {
1347 /* force tracks to do their thing */
1348 set_track_loop (true);
1351 /* jump to start and then roll from there */
1353 request_locate (location->start(), true);
1359 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1360 set_track_monitor_input_status (false);
1363 if (synced_to_engine()) {
1364 _engine.transport_start ();
1371 /* not zero, not 1.0 ... varispeed */
1373 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1374 warning << string_compose (
1375 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1381 if (actively_recording()) {
1385 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1389 if (speed < 0.0 && _transport_frame == 0) {
1395 /* if we are reversing relative to the current speed, or relative to the speed
1396 before the last stop, then we have to do extra work.
1399 PostTransportWork todo = PostTransportWork (0);
1401 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
1402 todo = PostTransportWork (todo | PostTransportReverse);
1403 _last_roll_or_reversal_location = _transport_frame;
1406 _last_transport_speed = _transport_speed;
1407 _transport_speed = speed;
1410 _default_transport_speed = speed;
1413 boost::shared_ptr<RouteList> rl = routes.reader();
1414 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1415 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1416 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1417 todo = PostTransportWork (todo | PostTransportSpeed);
1422 add_post_transport_work (todo);
1423 _butler->schedule_transport_work ();
1426 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1428 /* throttle signal emissions.
1429 * when slaved [_last]_transport_speed
1430 * usually changes every cycle (tiny amounts due to DLL).
1431 * Emitting a signal every cycle is overkill and unwarranted.
1433 * Using _last_transport_speed is not acceptable,
1434 * since it allows for large changes over a long period
1435 * of time. Hence we introduce a dedicated variable to keep track
1437 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1438 * for TransportStateChange() here is the ShuttleControl display.
1440 if (fabs (_signalled_varispeed - speed) > .002
1441 // still, signal hard changes to 1.0 and 0.0:
1442 || ( speed == 1.0 && _signalled_varispeed != 1.0)
1443 || ( speed == 0.0 && _signalled_varispeed != 0.0)
1446 TransportStateChange (); /* EMIT SIGNAL */
1447 _signalled_varispeed = speed;
1453 /** Stop the transport. */
1455 Session::stop_transport (bool abort, bool clear_state)
1457 if (_transport_speed == 0.0f) {
1461 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
1463 if (!get_transport_declick_required()) {
1465 /* stop has not yet been scheduled */
1467 boost::shared_ptr<RouteList> rl = routes.reader();
1468 framepos_t stop_target = audible_frame();
1470 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1471 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1473 tr->prepare_to_stop (_transport_frame, stop_target);
1479 if (actively_recording() && /* we are recording */
1480 worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1482 /* we need to capture the audio that is still somewhere in the pipeline between
1483 wherever it was generated and the process callback. This means that even though
1484 the user (or something else) has asked us to stop, we have to roll
1485 past this point and then reset the playhead/transport location to
1486 the position at which the stop was requested.
1488 we still need playback to "stop" now, however, which is why we schedule
1492 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1493 _transport_frame, _worst_input_latency,
1494 _transport_frame + _worst_input_latency,
1497 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1498 _transport_frame + _worst_input_latency,
1503 /* request a declick at the start of the next process cycle() so that playback ceases.
1504 It will remain silent until we actually stop (at the StopOnce event somewhere in
1505 the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1506 does not stop the transport too early.
1508 new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1512 /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1514 new_bits = PendingDeclickOut;
1515 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
1518 /* we'll be called again after the declick */
1519 transport_sub_state = SubState (transport_sub_state|new_bits);
1520 pending_abort = abort;
1526 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
1528 /* declick was scheduled, but we've been called again, which means it is really time to stop
1530 XXX: we should probably split this off into its own method and call it explicitly.
1533 realtime_stop (abort, clear_state);
1534 _butler->schedule_transport_work ();
1538 /** Called from the process thread */
1540 Session::start_transport ()
1542 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1544 _last_roll_location = _transport_frame;
1545 _last_roll_or_reversal_location = _transport_frame;
1547 have_looped = false;
1549 /* if record status is Enabled, move it to Recording. if its
1550 already Recording, move it to Disabled.
1553 switch (record_status()) {
1555 if (!config.get_punch_in()) {
1562 disable_record (false);
1570 transport_sub_state |= PendingDeclickIn;
1572 _transport_speed = _default_transport_speed;
1573 _target_transport_speed = _transport_speed;
1575 boost::shared_ptr<RouteList> rl = routes.reader();
1576 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1577 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1579 tr->realtime_set_speed (tr->speed(), true);
1583 if (!_engine.freewheeling()) {
1584 Timecode::Time time;
1585 timecode_time_subframes (_transport_frame, time);
1586 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1587 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1591 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1592 TransportStateChange (); /* EMIT SIGNAL */
1595 /** Do any transport work in the audio thread that needs to be done after the
1596 * transport thread is finished. Audio thread, realtime safe.
1599 Session::post_transport ()
1601 PostTransportWork ptw = post_transport_work ();
1603 if (ptw & PostTransportAudition) {
1604 if (auditioner && auditioner->auditioning()) {
1605 process_function = &Session::process_audition;
1607 process_function = &Session::process_with_events;
1611 if (ptw & PostTransportStop) {
1613 transport_sub_state = 0;
1616 if (ptw & PostTransportLocate) {
1618 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1621 transport_sub_state = 0;
1626 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1629 set_post_transport_work (PostTransportWork (0));
1633 Session::reset_rf_scale (framecnt_t motion)
1635 cumulative_rf_motion += motion;
1637 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1639 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1641 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1653 Session::mtc_status_changed (bool yn)
1655 g_atomic_int_set (&_mtc_active, yn);
1656 MTCSyncStateChanged( yn );
1660 Session::ltc_status_changed (bool yn)
1662 g_atomic_int_set (&_ltc_active, yn);
1663 LTCSyncStateChanged( yn );
1667 Session::use_sync_source (Slave* new_slave)
1669 /* Runs in process() context */
1671 bool non_rt_required = false;
1673 /* XXX this deletion is problematic because we're in RT context */
1678 MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1680 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1681 MTCSyncStateChanged(mtc_slave->locked() );
1683 if (g_atomic_int_get (&_mtc_active) ){
1684 g_atomic_int_set (&_mtc_active, 0);
1685 MTCSyncStateChanged( false );
1687 mtc_status_connection.disconnect ();
1690 LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1692 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1693 LTCSyncStateChanged (ltc_slave->locked() );
1695 if (g_atomic_int_get (&_ltc_active) ){
1696 g_atomic_int_set (&_ltc_active, 0);
1697 LTCSyncStateChanged( false );
1699 ltc_status_connection.disconnect ();
1702 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1704 // need to queue this for next process() cycle
1705 _send_timecode_update = true;
1707 boost::shared_ptr<RouteList> rl = routes.reader();
1708 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1709 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1710 if (tr && !tr->hidden()) {
1711 if (tr->realtime_set_speed (tr->speed(), true)) {
1712 non_rt_required = true;
1714 tr->set_slaved (_slave != 0);
1718 if (non_rt_required) {
1719 add_post_transport_work (PostTransportSpeed);
1720 _butler->schedule_transport_work ();
1727 Session::drop_sync_source ()
1729 request_sync_source (0);
1733 Session::switch_to_sync_source (SyncSource src)
1737 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1741 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1746 new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1749 catch (failed_constructor& err) {
1755 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1760 new_slave = new LTC_Slave (*this);
1763 catch (failed_constructor& err) {
1770 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1775 new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1778 catch (failed_constructor& err) {
1784 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1788 if (config.get_video_pullup() != 0.0f) {
1792 new_slave = new Engine_Slave (*AudioEngine::instance());
1800 request_sync_source (new_slave);
1804 Session::set_track_speed (Track* track, double speed)
1806 if (track->realtime_set_speed (speed, false)) {
1807 add_post_transport_work (PostTransportSpeed);
1808 _butler->schedule_transport_work ();
1814 Session::unset_play_range ()
1816 _play_range = false;
1817 _clear_event_type (SessionEvent::RangeStop);
1818 _clear_event_type (SessionEvent::RangeLocate);
1822 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1826 /* Called from event-processing context */
1828 unset_play_range ();
1830 if (range.empty()) {
1831 /* _play_range set to false in unset_play_range()
1833 if (!leave_rolling) {
1834 /* stop transport */
1835 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1843 /* cancel loop play */
1846 list<AudioRange>::size_type sz = range.size();
1850 list<AudioRange>::iterator i = range.begin();
1851 list<AudioRange>::iterator next;
1853 while (i != range.end()) {
1858 /* locating/stopping is subject to delays for declicking.
1861 framepos_t requested_frame = i->end;
1863 if (requested_frame > current_block_size) {
1864 requested_frame -= current_block_size;
1866 requested_frame = 0;
1869 if (next == range.end()) {
1870 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1872 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1880 } else if (sz == 1) {
1882 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1887 /* save range so we can do auto-return etc. */
1889 current_audio_range = range;
1891 /* now start rolling at the right place */
1893 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1896 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
1897 TransportStateChange ();
1901 Session::request_bounded_roll (framepos_t start, framepos_t end)
1903 AudioRange ar (start, end, 0);
1904 list<AudioRange> lar;
1907 request_play_range (&lar, true);
1911 Session::set_requested_return_frame (framepos_t return_to)
1913 _requested_return_frame = return_to;
1917 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
1919 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1920 ev->target2_frame = start;
1925 Session::engine_halted ()
1929 /* there will be no more calls to process(), so
1930 we'd better clean up for ourselves, right now.
1932 but first, make sure the butler is out of
1940 realtime_stop (false, true);
1941 non_realtime_stop (false, 0, ignored);
1942 transport_sub_state = 0;
1944 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
1945 TransportStateChange (); /* EMIT SIGNAL */
1950 Session::xrun_recovery ()
1954 Xrun (_transport_frame); /* EMIT SIGNAL */
1956 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1958 /* it didn't actually halt, but we need
1959 to handle things in the same way.
1967 Session::route_processors_changed (RouteProcessorChange c)
1969 if (ignore_route_processor_changes) {
1973 if (c.type == RouteProcessorChange::MeterPointChange) {
1978 if (c.type == RouteProcessorChange::RealTimeChange) {
1983 update_latency_compensation ();
1990 Session::allow_auto_play (bool yn)
1992 auto_play_legal = yn;
1996 Session::maybe_stop (framepos_t limit)
1998 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
1999 if (synced_to_engine () && config.get_jack_time_master ()) {
2000 _engine.transport_stop ();
2001 } else if (!synced_to_engine ()) {
2010 Session::send_mmc_locate (framepos_t t)
2016 if (!_engine.freewheeling()) {
2017 Timecode::Time time;
2018 timecode_time_subframes (t, time);
2019 send_immediate_mmc (MIDI::MachineControlCommand (time));
2023 /** Ask the transport to not send timecode until further notice. The suspension
2024 * will come into effect some finite time after this call, and timecode_transmission_suspended()
2025 * should be checked by the caller to find out when.
2028 Session::request_suspend_timecode_transmission ()
2030 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2035 Session::request_resume_timecode_transmission ()
2037 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2042 Session::timecode_transmission_suspended () const
2044 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;