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/tempo.h"
49 #include "ardour/operations.h"
54 using namespace ARDOUR;
58 Session::add_post_transport_work (PostTransportWork ptw)
60 PostTransportWork oldval;
61 PostTransportWork newval;
65 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
66 newval = PostTransportWork (oldval | ptw);
67 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
73 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
77 Session::request_input_change_handling ()
79 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
80 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
86 Session::request_sync_source (Slave* new_slave)
88 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
91 seamless = Config->get_seamless_loop ();
93 if (dynamic_cast<Engine_Slave*>(new_slave)) {
94 /* JACK cannot support seamless looping at present */
95 Config->set_seamless_loop (false);
97 /* reset to whatever the value was before we last switched slaves */
98 Config->set_seamless_loop (_was_seamless);
101 /* save value of seamless from before the switch */
102 _was_seamless = seamless;
104 ev->slave = new_slave;
105 DEBUG_TRACE (DEBUG::Slave, "sent request for new slave\n");
110 Session::request_transport_speed (double speed, bool as_default)
112 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
113 ev->third_yes_or_no = as_default; // as_default
114 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
118 /** Request a new transport speed, but if the speed parameter is exactly zero then use
119 * a very small +ve value to prevent the transport actually stopping. This method should
120 * be used by callers who are varying transport speed but don't ever want to stop it.
123 Session::request_transport_speed_nonzero (double speed, bool as_default)
129 request_transport_speed (speed, as_default);
133 Session::request_track_speed (Track* tr, double speed)
135 SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
141 Session::request_stop (bool abort, bool clear_state)
143 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_frame(), 0.0, abort, clear_state);
144 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));
149 Session::request_locate (framepos_t target_frame, bool with_roll)
151 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
152 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
157 Session::force_locate (framepos_t target_frame, bool with_roll)
159 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
160 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
165 Session::request_play_loop (bool yn, bool change_transport_roll)
168 // don't attempt to loop when not using Internal Transport
169 // see also gtk2_ardour/ardour_ui_options.cc parameter_changed()
174 Location *location = _locations->auto_loop_location();
177 if (location == 0 && yn) {
178 error << _("Cannot loop - no loop range defined")
183 if (change_transport_roll) {
184 if (transport_rolling()) {
185 /* start looping at current speed */
186 target_speed = transport_speed ();
188 /* currently stopped */
190 /* start looping at normal speed */
197 /* leave the speed alone */
198 target_speed = transport_speed ();
201 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
202 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
206 if (!change_transport_roll) {
207 if (!transport_rolling()) {
208 /* we're not changing transport state, but we do want
209 to set up position for the new loop. Don't
210 do this if we're rolling already.
212 request_locate (location->start(), false);
216 if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
217 // request an immediate locate to refresh the tracks
218 // after disabling looping
219 request_locate (_transport_frame-1, false);
225 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
227 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
229 ev->audio_range = *range;
231 ev->audio_range.clear ();
233 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
238 Session::request_cancel_play_range ()
240 SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
246 Session::realtime_stop (bool abort, bool clear_state)
248 DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_frame));
249 PostTransportWork todo = PostTransportWork (0);
251 /* assume that when we start, we'll be moving forwards */
253 if (_transport_speed < 0.0f) {
254 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
255 _default_transport_speed = 1.0;
257 todo = PostTransportWork (todo | PostTransportStop);
262 boost::shared_ptr<RouteList> r = routes.reader ();
264 for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
265 (*i)->realtime_handle_transport_stopped ();
268 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_frame));
270 /* the duration change is not guaranteed to have happened, but is likely */
272 todo = PostTransportWork (todo | PostTransportDuration);
275 todo = PostTransportWork (todo | PostTransportAbort);
279 todo = PostTransportWork (todo | PostTransportClearSubstate);
283 add_post_transport_work (todo);
286 _clear_event_type (SessionEvent::StopOnce);
287 _clear_event_type (SessionEvent::RangeStop);
288 _clear_event_type (SessionEvent::RangeLocate);
290 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
291 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
293 if (clear_state && !Config->get_loop_is_mode()) {
297 reset_slave_state ();
299 _transport_speed = 0;
300 _target_transport_speed = 0;
302 g_atomic_int_set (&_playback_load, 100);
303 g_atomic_int_set (&_capture_load, 100);
305 if (config.get_use_video_sync()) {
306 waiting_for_sync_offset = true;
309 transport_sub_state = 0;
313 Session::realtime_locate ()
315 boost::shared_ptr<RouteList> r = routes.reader ();
316 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
317 (*i)->realtime_locate ();
322 Session::butler_transport_work ()
324 /* Note: this function executes in the butler thread context */
328 PostTransportWork ptw;
329 boost::shared_ptr<RouteList> r = routes.reader ();
332 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
334 ptw = post_transport_work();
336 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
339 if (ptw & PostTransportLocate) {
341 if (get_play_loop() && !Config->get_seamless_loop()) {
343 DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
345 /* this locate might be happening while we are
348 * Non-seamless looping will require a locate (below) that
349 * will reset capture buffers and throw away data.
351 * Rather than first find all tracks and see if they
352 * have outstanding data, just do a flush anyway. It
353 * may be cheaper this way anyway, and is certainly
357 bool more_disk_io_to_do = false;
361 more_disk_io_to_do = _butler->flush_tracks_to_disk_after_locate (r, errors);
367 if (more_disk_io_to_do) {
376 if (ptw & PostTransportAdjustPlaybackBuffering) {
377 /* non_realtime_locate() calls Automatable::transport_located()
378 * for every route. This eventually calls
379 * ARDOUR::AutomationList::state () which has a LocaleGuard,
380 * and would switch locales forth/back every time.
383 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
384 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
386 tr->adjust_playback_buffering ();
387 /* and refill those buffers ... */
389 (*i)->non_realtime_locate (_transport_frame);
394 if (ptw & PostTransportAdjustCaptureBuffering) {
395 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
396 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
398 tr->adjust_capture_buffering ();
403 if (ptw & PostTransportCurveRealloc) {
404 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
405 (*i)->curve_reallocate();
409 if (ptw & PostTransportInputChange) {
410 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
411 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
413 tr->non_realtime_input_change ();
418 if (ptw & PostTransportSpeed) {
419 non_realtime_set_speed ();
422 if (ptw & PostTransportReverse) {
425 cumulative_rf_motion = 0;
428 /* don't seek if locate will take care of that in non_realtime_stop() */
430 if (!(ptw & PostTransportLocate)) {
431 LocaleGuard lg; // see note for non_realtime_locate() above
432 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
433 (*i)->non_realtime_locate (_transport_frame);
435 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
436 /* new request, stop seeking, and start again */
437 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
444 if (ptw & PostTransportLocate) {
445 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
446 non_realtime_locate ();
449 if (ptw & PostTransportStop) {
450 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
452 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
457 if (ptw & PostTransportOverWrite) {
458 non_realtime_overwrite (on_entry, finished);
460 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
465 if (ptw & PostTransportAudition) {
466 non_realtime_set_audition ();
469 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
471 DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs\n"), g_get_monotonic_time() - before));
472 DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame)));
476 Session::non_realtime_set_speed ()
478 boost::shared_ptr<RouteList> rl = routes.reader();
479 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
480 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
482 tr->non_realtime_set_speed ();
488 Session::non_realtime_overwrite (int on_entry, bool& finished)
490 boost::shared_ptr<RouteList> rl = routes.reader();
491 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
492 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
493 if (tr && tr->pending_overwrite ()) {
494 tr->overwrite_existing_buffers ();
496 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
505 Session::non_realtime_locate ()
507 DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_frame));
509 if (Config->get_loop_is_mode() && get_play_loop()) {
511 Location *loc = _locations->auto_loop_location();
513 if (!loc || (_transport_frame < loc->start() || _transport_frame >= loc->end())) {
514 /* jumped out of loop range: stop tracks from looping,
515 but leave loop (mode) enabled.
517 set_track_loop (false);
519 } else if (loc && Config->get_seamless_loop() &&
520 ((loc->start() <= _transport_frame) ||
521 (loc->end() > _transport_frame) ) ) {
523 /* jumping to start of loop. This might have been done before but it is
524 * idempotent and cheap. Doing it here ensures that when we start playback
525 * outside the loop we still flip tracks into the magic seamless mode
528 set_track_loop (true);
531 set_track_loop (false);
536 /* no more looping .. should have been noticed elsewhere */
541 LocaleGuard lg; // see note for non_realtime_locate() above
542 boost::shared_ptr<RouteList> rl = routes.reader();
543 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
544 (*i)->non_realtime_locate (_transport_frame);
548 _scene_changer->locate (_transport_frame);
550 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
551 rather than clearing them so that the RT thread has to spend time constructing
552 them (in Session::click).
557 #ifdef USE_TRACKS_CODE_FEATURES
559 Session::select_playhead_priority_target (framepos_t& jump_to)
563 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
569 if (Profile->get_trx() && transport_rolling() ) {
570 // We're playing, so do nothing.
571 // Next stop will put us where we need to be.
575 /* Note that the order of checking each AutoReturnTarget flag defines
576 the priority each flag.
578 Ardour/Mixbus: Last Locate
583 Tracks: Range Selection
589 if (autoreturn & RangeSelectionStart) {
590 if (!_range_selection.empty()) {
591 jump_to = _range_selection.from;
593 if (transport_rolling ()) {
594 /* Range selection no longer exists, but we're playing,
595 so do nothing. Next stop will put us where
603 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
604 /* don't try to handle loop play when synced to JACK */
606 if (!synced_to_engine()) {
607 Location *location = _locations->auto_loop_location();
610 jump_to = location->start();
612 if (Config->get_seamless_loop()) {
613 /* need to get track buffers reloaded */
614 set_track_loop (true);
620 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
621 if (!_object_selection.empty()) {
622 jump_to = _object_selection.from;
626 if (jump_to < 0 && (autoreturn & LastLocate)) {
627 jump_to = _last_roll_location;
635 Session::select_playhead_priority_target (framepos_t& jump_to)
637 if (config.get_external_sync() || !config.get_auto_return()) {
641 jump_to = _last_roll_location;
648 Session::follow_playhead_priority ()
652 if (select_playhead_priority_target (target)) {
653 request_locate (target);
658 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
664 PostTransportWork ptw = post_transport_work();
669 boost::shared_ptr<RouteList> rl = routes.reader();
670 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
671 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
672 if (tr && tr->get_captured_frames () != 0) {
678 /* stop and locate are merged here because they share a lot of common stuff */
681 now = localtime (&xnow);
684 auditioner->cancel_audition ();
687 cumulative_rf_motion = 0;
691 begin_reversible_command (Operations::capture);
692 _have_captured = true;
695 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
697 if (abort && did_record) {
698 /* no reason to save the session file when we remove sources
700 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
703 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
704 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
706 tr->transport_stopped_wallclock (*now, xnow, abort);
710 if (abort && did_record) {
711 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
714 boost::shared_ptr<RouteList> r = routes.reader ();
716 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
717 if (!(*i)->is_auditioner()) {
718 (*i)->set_pending_declick (0);
723 commit_reversible_command ();
724 /* increase take name */
725 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
726 string newname = config.get_take_name();
727 config.set_take_name(bump_name_number (newname));
731 if (_engine.running()) {
732 PostTransportWork ptw = post_transport_work ();
733 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
734 (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
736 update_latency_compensation ();
739 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
741 if (auto_return_enabled ||
742 (ptw & PostTransportLocate) ||
743 (_requested_return_frame >= 0) ||
744 synced_to_engine()) {
746 if (pending_locate_flush) {
747 flush_all_inserts ();
750 // rg: what is the logic behind this case?
751 // _requested_return_frame should be ignored when synced_to_engine/slaved.
752 // currently worked around in MTC_Slave by forcing _requested_return_frame to -1
754 if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
755 !(ptw & PostTransportLocate)) {
757 /* no explicit locate queued */
759 bool do_locate = false;
761 if (_requested_return_frame >= 0) {
763 /* explicit return request pre-queued in event list. overrides everything else */
765 _transport_frame = _requested_return_frame;
771 if (select_playhead_priority_target (jump_to)) {
773 _transport_frame = jump_to;
778 _transport_frame = _last_roll_location;
783 _requested_return_frame = -1;
786 _engine.transport_locate (_transport_frame);
794 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
797 if (ptw & PostTransportClearSubstate) {
799 if (!Config->get_loop_is_mode()) {
804 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
807 LocaleGuard lg; // see note for non_realtime_locate() above
808 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
809 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
810 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
811 (*i)->non_realtime_locate (_transport_frame);
813 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
815 /* we will be back */
823 /* don't bother with this stuff if we're disconnected from the engine,
824 because there will be no process callbacks to deliver stuff from
827 if (_engine.connected() && !_engine.freewheeling()) {
828 // need to queue this in the next RT cycle
829 _send_timecode_update = true;
831 if (!dynamic_cast<MTC_Slave*>(_slave)) {
832 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
834 /* This (::non_realtime_stop()) gets called by main
835 process thread, which will lead to confusion
836 when calling AsyncMIDIPort::write().
838 Something must be done. XXX
840 send_mmc_locate (_transport_frame);
844 if ((ptw & PostTransportLocate) && get_record_enabled()) {
845 /* This is scheduled by realtime_stop(), which is also done
846 * when a slave requests /locate/ for an initial sync.
847 * We can't hold up the slave for long with a save() here,
848 * without breaking its initial sync cycle.
850 * save state only if there's no slave or if it's not yet locked.
852 if (!_slave || !_slave->locked()) {
853 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
854 SaveSessionRequested (_current_snapshot_name);
859 /* always try to get rid of this */
861 remove_pending_capture_state ();
863 /* save the current state of things if appropriate */
865 if (did_record && !saved) {
866 SaveSessionRequested (_current_snapshot_name);
869 if (ptw & PostTransportStop) {
871 if (!Config->get_loop_is_mode()) {
876 PositionChanged (_transport_frame); /* EMIT SIGNAL */
877 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
878 TransportStateChange (); /* EMIT SIGNAL */
880 /* and start it up again if relevant */
882 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
883 request_transport_speed (1.0);
886 /* Even if we didn't do a pending locate roll this time, we don't want it hanging
887 around for next time.
889 pending_locate_roll = false;
893 Session::check_declick_out ()
895 bool locate_required = transport_sub_state & PendingLocate;
897 /* this is called after a process() iteration. if PendingDeclickOut was set,
898 it means that we were waiting to declick the output (which has just been
899 done) before maybe doing something else. this is where we do that "something else".
901 note: called from the audio thread.
904 if (transport_sub_state & PendingDeclickOut) {
906 if (locate_required) {
907 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
908 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
910 if (!(transport_sub_state & StopPendingCapture)) {
911 stop_transport (pending_abort);
912 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
916 } else if (transport_sub_state & PendingLoopDeclickOut) {
917 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
918 transport_sub_state &= ~PendingLoopDeclickOut;
923 Session::unset_play_loop ()
927 clear_events (SessionEvent::AutoLoop);
928 clear_events (SessionEvent::AutoLoopDeclick);
929 set_track_loop (false);
932 if (Config->get_seamless_loop()) {
933 /* likely need to flush track buffers: this will locate us to wherever we are */
934 add_post_transport_work (PostTransportLocate);
935 _butler->schedule_transport_work ();
941 Session::set_track_loop (bool yn)
943 Location* loc = _locations->auto_loop_location ();
949 boost::shared_ptr<RouteList> rl = routes.reader ();
951 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
952 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
953 if (tr && !tr->hidden()) {
954 tr->set_loop (yn ? loc : 0);
960 Session::set_play_loop (bool yn, double speed)
962 /* Called from event-handling context */
966 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
967 /* nothing to do, or can't change loop status while recording */
971 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
972 warning << string_compose (
973 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
974 "Recommend changing the configured options"), PROGRAM_NAME)
988 if (Config->get_seamless_loop()) {
989 if (!Config->get_loop_is_mode()) {
990 /* set all tracks to use internal looping */
991 set_track_loop (true);
993 /* we will do this in the locate to the start OR when we hit the end
994 * of the loop for the first time
998 /* set all tracks to NOT use internal looping */
999 set_track_loop (false);
1002 /* Put the delick and loop events in into the event list. The declick event will
1003 cause a de-clicking fade-out just before the end of the loop, and it will also result
1004 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
1009 auto_loop_declick_range (loc, dcp, dcl);
1010 merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
1011 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
1013 /* if requested to roll, locate to start of loop and
1014 * roll but ONLY if we're not already rolling.
1016 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
1019 if (Config->get_loop_is_mode()) {
1020 /* loop IS a transport mode: if already
1021 rolling, do not locate to loop start.
1023 if (!transport_rolling() && (speed != 0.0)) {
1024 start_locate (loc->start(), true, true, false, true);
1028 start_locate (loc->start(), true, true, false, true);
1038 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
1039 TransportStateChange ();
1042 Session::flush_all_inserts ()
1044 boost::shared_ptr<RouteList> r = routes.reader ();
1046 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1047 (*i)->flush_processors ();
1052 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
1054 if (target_frame < 0) {
1055 error << _("Locate called for negative sample position - ignored") << endmsg;
1059 if (synced_to_engine()) {
1064 _slave->speed_and_position (sp, pos);
1066 if (target_frame != pos) {
1068 if (config.get_jack_time_master()) {
1069 /* actually locate now, since otherwise jack_timebase_callback
1070 will use the incorrect _transport_frame and report an old
1071 and incorrect time to Jack transport
1073 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1076 /* tell JACK to change transport position, and we will
1077 follow along later in ::follow_slave()
1080 _engine.transport_locate (target_frame);
1082 if (sp != 1.0f && with_roll) {
1083 _engine.transport_start ();
1089 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1094 Session::micro_locate (framecnt_t distance)
1096 boost::shared_ptr<RouteList> rl = routes.reader();
1097 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1098 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1099 if (tr && !tr->can_internal_playback_seek (distance)) {
1104 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1105 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1107 tr->internal_playback_seek (distance);
1111 _transport_frame += distance;
1115 /** @param with_mmc true to send a MMC locate command when the locate is done */
1117 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
1119 bool need_butler = false;
1121 /* Locates for seamless looping are fairly different from other
1122 * locates. They assume that the diskstream buffers for each track
1123 * already have the correct data in them, and thus there is no need to
1124 * actually tell the tracks to locate. What does need to be done,
1125 * though, is all the housekeeping that is associated with non-linear
1126 * changes in the value of _transport_frame.
1129 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
1130 target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
1132 if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
1134 /* already at the desired position. Not forced to locate,
1135 the loop isn't changing, so unless we're told to
1136 start rolling also, there's nothing to do but
1137 tell the world where we are (again).
1141 set_transport_speed (1.0, 0, false);
1143 loop_changing = false;
1144 Located (); /* EMIT SIGNAL */
1148 if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
1149 /* Schedule a declick. We'll be called again when its done.
1150 We only do it this way for ordinary locates, not those
1151 due to **seamless** loops.
1154 if (!(transport_sub_state & PendingDeclickOut)) {
1155 transport_sub_state |= (PendingDeclickOut|PendingLocate);
1156 pending_locate_frame = target_frame;
1157 pending_locate_roll = with_roll;
1158 pending_locate_flush = with_flush;
1163 // Update Timecode time
1164 _transport_frame = target_frame;
1165 _last_roll_or_reversal_location = target_frame;
1166 timecode_time(_transport_frame, transmitting_timecode_time);
1168 /* do "stopped" stuff if:
1170 * we are rolling AND
1171 * no autoplay in effect AND
1172 * we're not going to keep rolling after the locate AND
1173 * !(playing a loop with JACK sync)
1177 bool transport_was_stopped = !transport_rolling();
1179 if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1180 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1181 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1182 transport_was_stopped = true;
1184 /* otherwise tell the world that we located */
1188 if (force || !for_loop_enabled || loop_changing) {
1190 PostTransportWork todo = PostTransportLocate;
1192 if (with_roll && transport_was_stopped) {
1193 todo = PostTransportWork (todo | PostTransportRoll);
1196 add_post_transport_work (todo);
1201 /* this is functionally what clear_clicks() does but with a tentative lock */
1203 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1205 if (clickm.locked()) {
1207 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1216 /* switch from input if we're going to roll */
1217 if (Config->get_monitoring_model() == HardwareMonitoring) {
1218 set_track_monitor_input_status (!config.get_auto_input());
1221 /* otherwise we're going to stop, so do the opposite */
1222 if (Config->get_monitoring_model() == HardwareMonitoring) {
1223 set_track_monitor_input_status (true);
1227 /* cancel looped playback if transport pos outside of loop range */
1230 Location* al = _locations->auto_loop_location();
1233 if (_transport_frame < al->start() || _transport_frame >= al->end()) {
1235 // located outside the loop: cancel looping directly, this is called from event handling context
1237 have_looped = false;
1239 if (!Config->get_loop_is_mode()) {
1240 set_play_loop (false, _transport_speed);
1242 if (Config->get_seamless_loop()) {
1243 /* this will make the non_realtime_locate() in the butler
1244 which then causes seek() in tracks actually do the right
1247 set_track_loop (false);
1251 } else if (_transport_frame == al->start()) {
1253 // located to start of loop - this is looping, basically
1257 if (_last_roll_location != al->start()) {
1258 /* didn't start at loop start - playback must have
1259 * started before loop since we've now hit the loop
1262 add_post_transport_work (PostTransportLocate);
1268 boost::shared_ptr<RouteList> rl = routes.reader();
1270 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1271 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1273 if (tr && tr->rec_enable_control()->get_value()) {
1274 // tell it we've looped, so it can deal with the record state
1275 tr->transport_looped (_transport_frame);
1280 TransportLooped(); // EMIT SIGNAL
1286 _butler->schedule_transport_work ();
1289 loop_changing = false;
1291 _send_timecode_update = true;
1294 send_mmc_locate (_transport_frame);
1297 _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
1298 Located (); /* EMIT SIGNAL */
1301 /** Set the transport speed.
1302 * Called from the process thread.
1303 * @param speed New speed
1306 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1308 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1309 speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1311 if (_transport_speed == speed) {
1312 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1313 _default_transport_speed = 1.0;
1318 if (actively_recording() && speed != 1.0 && speed != 0.0) {
1319 /* no varispeed during recording */
1320 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1321 _transport_speed, _transport_frame));
1325 _target_transport_speed = fabs(speed);
1327 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1328 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1332 speed = min (8.0, speed);
1333 } else if (speed < 0) {
1334 speed = max (-8.0, speed);
1337 if (transport_rolling() && speed == 0.0) {
1339 /* we are rolling and we want to stop */
1341 if (Config->get_monitoring_model() == HardwareMonitoring) {
1342 set_track_monitor_input_status (true);
1345 if (synced_to_engine ()) {
1347 /* do this here because our response to the slave won't
1350 _play_range = false;
1353 _engine.transport_stop ();
1355 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1357 if (!auto_return_enabled) {
1358 _requested_return_frame = destination_frame;
1361 stop_transport (abort);
1364 } else if (transport_stopped() && speed == 1.0) {
1366 _default_transport_speed = speed;
1368 /* we are stopped and we want to start rolling at speed 1 */
1370 if (Config->get_loop_is_mode() && play_loop) {
1372 Location *location = _locations->auto_loop_location();
1374 if (location != 0) {
1375 if (_transport_frame != location->start()) {
1377 if (Config->get_seamless_loop()) {
1378 /* force tracks to do their thing */
1379 set_track_loop (true);
1382 /* jump to start and then roll from there */
1384 request_locate (location->start(), true);
1390 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1391 set_track_monitor_input_status (false);
1394 if (synced_to_engine()) {
1395 _engine.transport_start ();
1402 /* not zero, not 1.0 ... varispeed */
1404 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1405 warning << string_compose (
1406 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1412 if (actively_recording()) {
1416 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1420 if (speed < 0.0 && _transport_frame == 0) {
1426 /* if we are reversing relative to the current speed, or relative to the speed
1427 before the last stop, then we have to do extra work.
1430 PostTransportWork todo = PostTransportWork (0);
1432 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
1433 todo = PostTransportWork (todo | PostTransportReverse);
1434 _last_roll_or_reversal_location = _transport_frame;
1437 _last_transport_speed = _transport_speed;
1438 _transport_speed = speed;
1441 _default_transport_speed = speed;
1444 boost::shared_ptr<RouteList> rl = routes.reader();
1445 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1446 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1447 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1448 todo = PostTransportWork (todo | PostTransportSpeed);
1453 add_post_transport_work (todo);
1454 _butler->schedule_transport_work ();
1457 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1459 /* throttle signal emissions.
1460 * when slaved [_last]_transport_speed
1461 * usually changes every cycle (tiny amounts due to DLL).
1462 * Emitting a signal every cycle is overkill and unwarranted.
1464 * Using _last_transport_speed is not acceptable,
1465 * since it allows for large changes over a long period
1466 * of time. Hence we introduce a dedicated variable to keep track
1468 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1469 * for TransportStateChange() here is the ShuttleControl display.
1471 if (fabs (_signalled_varispeed - speed) > .002
1472 // still, signal hard changes to 1.0 and 0.0:
1473 || ( speed == 1.0 && _signalled_varispeed != 1.0)
1474 || ( speed == 0.0 && _signalled_varispeed != 0.0)
1477 TransportStateChange (); /* EMIT SIGNAL */
1478 _signalled_varispeed = speed;
1484 /** Stop the transport. */
1486 Session::stop_transport (bool abort, bool clear_state)
1488 if (_transport_speed == 0.0f) {
1492 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
1494 if (!get_transport_declick_required()) {
1496 /* stop has not yet been scheduled */
1498 boost::shared_ptr<RouteList> rl = routes.reader();
1499 framepos_t stop_target = audible_frame();
1501 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1502 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1504 tr->prepare_to_stop (_transport_frame, stop_target);
1510 if (actively_recording() && /* we are recording */
1511 worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1513 /* we need to capture the audio that is still somewhere in the pipeline between
1514 wherever it was generated and the process callback. This means that even though
1515 the user (or something else) has asked us to stop, we have to roll
1516 past this point and then reset the playhead/transport location to
1517 the position at which the stop was requested.
1519 we still need playback to "stop" now, however, which is why we schedule
1523 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1524 _transport_frame, _worst_input_latency,
1525 _transport_frame + _worst_input_latency,
1528 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1529 _transport_frame + _worst_input_latency,
1534 /* request a declick at the start of the next process cycle() so that playback ceases.
1535 It will remain silent until we actually stop (at the StopOnce event somewhere in
1536 the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1537 does not stop the transport too early.
1539 new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1543 /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1545 new_bits = PendingDeclickOut;
1546 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
1549 /* we'll be called again after the declick */
1550 transport_sub_state = SubState (transport_sub_state|new_bits);
1551 pending_abort = abort;
1557 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
1559 /* declick was scheduled, but we've been called again, which means it is really time to stop
1561 XXX: we should probably split this off into its own method and call it explicitly.
1564 realtime_stop (abort, clear_state);
1565 _butler->schedule_transport_work ();
1569 /** Called from the process thread */
1571 Session::start_transport ()
1573 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1575 _last_roll_location = _transport_frame;
1576 _last_roll_or_reversal_location = _transport_frame;
1578 have_looped = false;
1580 /* if record status is Enabled, move it to Recording. if its
1581 already Recording, move it to Disabled.
1584 switch (record_status()) {
1586 if (!config.get_punch_in()) {
1593 disable_record (false);
1601 transport_sub_state |= PendingDeclickIn;
1603 _transport_speed = _default_transport_speed;
1604 _target_transport_speed = _transport_speed;
1606 boost::shared_ptr<RouteList> rl = routes.reader();
1607 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1608 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1610 tr->realtime_set_speed (tr->speed(), true);
1614 if (!_engine.freewheeling()) {
1615 Timecode::Time time;
1616 timecode_time_subframes (_transport_frame, time);
1617 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1618 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1621 if (actively_recording() && click_data && config.get_count_in ()) {
1622 /* calculate count-in duration (in audio samples)
1623 * - use [fixed] tempo/meter at _transport_frame
1624 * - calc duration of 1 bar + time-to-beat before or at transport_frame
1626 const Tempo& tempo = _tempo_map->tempo_at_frame (_transport_frame);
1627 const Meter& meter = _tempo_map->meter_at_frame (_transport_frame);
1629 double div = meter.divisions_per_bar ();
1630 double pulses = _tempo_map->exact_qn_at_frame (_transport_frame, 0) * div / 4.0;
1631 double beats_left = fmod (pulses, div);
1633 _count_in_samples = meter.frames_per_bar (tempo, _current_frame_rate);
1635 double dt = _count_in_samples / div;
1636 if (beats_left == 0) {
1637 /* at bar boundary, count-in 2 bars before start. */
1638 _count_in_samples *= 2;
1640 /* beats left after full bar until roll position */
1641 _count_in_samples += meter.frames_per_grid (tempo, _current_frame_rate) * beats_left;
1645 framepos_t cf = _transport_frame - _count_in_samples;
1646 while (cf < _transport_frame) {
1647 add_click (cf - _worst_track_latency, clickbeat == 0);
1649 clickbeat = fmod (clickbeat + 1, div);
1654 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1655 TransportStateChange (); /* EMIT SIGNAL */
1658 /** Do any transport work in the audio thread that needs to be done after the
1659 * transport thread is finished. Audio thread, realtime safe.
1662 Session::post_transport ()
1664 PostTransportWork ptw = post_transport_work ();
1666 if (ptw & PostTransportAudition) {
1667 if (auditioner && auditioner->auditioning()) {
1668 process_function = &Session::process_audition;
1670 process_function = &Session::process_with_events;
1674 if (ptw & PostTransportStop) {
1676 transport_sub_state = 0;
1679 if (ptw & PostTransportLocate) {
1681 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1684 transport_sub_state = 0;
1689 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1692 set_post_transport_work (PostTransportWork (0));
1696 Session::reset_rf_scale (framecnt_t motion)
1698 cumulative_rf_motion += motion;
1700 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1702 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1704 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1716 Session::mtc_status_changed (bool yn)
1718 g_atomic_int_set (&_mtc_active, yn);
1719 MTCSyncStateChanged( yn );
1723 Session::ltc_status_changed (bool yn)
1725 g_atomic_int_set (&_ltc_active, yn);
1726 LTCSyncStateChanged( yn );
1730 Session::use_sync_source (Slave* new_slave)
1732 /* Runs in process() context */
1734 bool non_rt_required = false;
1736 /* XXX this deletion is problematic because we're in RT context */
1741 MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1743 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1744 MTCSyncStateChanged(mtc_slave->locked() );
1746 if (g_atomic_int_get (&_mtc_active) ){
1747 g_atomic_int_set (&_mtc_active, 0);
1748 MTCSyncStateChanged( false );
1750 mtc_status_connection.disconnect ();
1753 LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1755 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1756 LTCSyncStateChanged (ltc_slave->locked() );
1758 if (g_atomic_int_get (&_ltc_active) ){
1759 g_atomic_int_set (&_ltc_active, 0);
1760 LTCSyncStateChanged( false );
1762 ltc_status_connection.disconnect ();
1765 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1767 // need to queue this for next process() cycle
1768 _send_timecode_update = true;
1770 boost::shared_ptr<RouteList> rl = routes.reader();
1771 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1772 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1773 if (tr && !tr->hidden()) {
1774 if (tr->realtime_set_speed (tr->speed(), true)) {
1775 non_rt_required = true;
1777 tr->set_slaved (_slave != 0);
1781 if (non_rt_required) {
1782 add_post_transport_work (PostTransportSpeed);
1783 _butler->schedule_transport_work ();
1790 Session::drop_sync_source ()
1792 request_sync_source (0);
1796 Session::switch_to_sync_source (SyncSource src)
1800 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1804 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1809 new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1812 catch (failed_constructor& err) {
1818 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1823 new_slave = new LTC_Slave (*this);
1826 catch (failed_constructor& err) {
1833 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1838 new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1841 catch (failed_constructor& err) {
1847 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1851 if (config.get_video_pullup() != 0.0f) {
1855 new_slave = new Engine_Slave (*AudioEngine::instance());
1863 request_sync_source (new_slave);
1867 Session::set_track_speed (Track* track, double speed)
1869 if (track->realtime_set_speed (speed, false)) {
1870 add_post_transport_work (PostTransportSpeed);
1871 _butler->schedule_transport_work ();
1877 Session::unset_play_range ()
1879 _play_range = false;
1880 _clear_event_type (SessionEvent::RangeStop);
1881 _clear_event_type (SessionEvent::RangeLocate);
1885 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1889 /* Called from event-processing context */
1891 unset_play_range ();
1893 if (range.empty()) {
1894 /* _play_range set to false in unset_play_range()
1896 if (!leave_rolling) {
1897 /* stop transport */
1898 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1906 /* cancel loop play */
1909 list<AudioRange>::size_type sz = range.size();
1913 list<AudioRange>::iterator i = range.begin();
1914 list<AudioRange>::iterator next;
1916 while (i != range.end()) {
1921 /* locating/stopping is subject to delays for declicking.
1924 framepos_t requested_frame = i->end;
1926 if (requested_frame > current_block_size) {
1927 requested_frame -= current_block_size;
1929 requested_frame = 0;
1932 if (next == range.end()) {
1933 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1935 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1943 } else if (sz == 1) {
1945 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1950 /* save range so we can do auto-return etc. */
1952 current_audio_range = range;
1954 /* now start rolling at the right place */
1956 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1959 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
1960 TransportStateChange ();
1964 Session::request_bounded_roll (framepos_t start, framepos_t end)
1966 AudioRange ar (start, end, 0);
1967 list<AudioRange> lar;
1970 request_play_range (&lar, true);
1974 Session::set_requested_return_frame (framepos_t return_to)
1976 _requested_return_frame = return_to;
1980 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
1982 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1983 ev->target2_frame = start;
1988 Session::engine_halted ()
1992 /* there will be no more calls to process(), so
1993 we'd better clean up for ourselves, right now.
1995 but first, make sure the butler is out of
2003 realtime_stop (false, true);
2004 non_realtime_stop (false, 0, ignored);
2005 transport_sub_state = 0;
2007 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
2008 TransportStateChange (); /* EMIT SIGNAL */
2013 Session::xrun_recovery ()
2017 Xrun (_transport_frame); /* EMIT SIGNAL */
2019 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
2021 /* it didn't actually halt, but we need
2022 to handle things in the same way.
2030 Session::route_processors_changed (RouteProcessorChange c)
2032 if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
2036 if (c.type == RouteProcessorChange::MeterPointChange) {
2041 if (c.type == RouteProcessorChange::RealTimeChange) {
2046 update_latency_compensation ();
2053 Session::allow_auto_play (bool yn)
2055 auto_play_legal = yn;
2059 Session::maybe_stop (framepos_t limit)
2061 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
2062 if (synced_to_engine () && config.get_jack_time_master ()) {
2063 _engine.transport_stop ();
2064 } else if (!synced_to_engine ()) {
2073 Session::send_mmc_locate (framepos_t t)
2079 if (!_engine.freewheeling()) {
2080 Timecode::Time time;
2081 timecode_time_subframes (t, time);
2082 send_immediate_mmc (MIDI::MachineControlCommand (time));
2086 /** Ask the transport to not send timecode until further notice. The suspension
2087 * will come into effect some finite time after this call, and timecode_transmission_suspended()
2088 * should be checked by the caller to find out when.
2091 Session::request_suspend_timecode_transmission ()
2093 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2098 Session::request_resume_timecode_transmission ()
2100 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2105 Session::timecode_transmission_suspended () const
2107 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;