2 Copyright (C) 1999-2003 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "libardour-config.h"
29 #include "pbd/error.h"
30 #include "pbd/enumwriter.h"
31 #include "pbd/pthread_utils.h"
32 #include "pbd/memento_command.h"
33 #include "pbd/stacktrace.h"
35 #include "midi++/mmc.h"
36 #include "midi++/port.h"
38 #include "ardour/audioengine.h"
39 #include "ardour/auditioner.h"
40 #include "ardour/butler.h"
41 #include "ardour/click.h"
42 #include "ardour/debug.h"
43 #include "ardour/location.h"
44 #include "ardour/profile.h"
45 #include "ardour/scene_changer.h"
46 #include "ardour/session.h"
47 #include "ardour/slave.h"
48 #include "ardour/operations.h"
53 using namespace ARDOUR;
57 Session::add_post_transport_work (PostTransportWork ptw)
59 PostTransportWork oldval;
60 PostTransportWork newval;
64 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
65 newval = PostTransportWork (oldval | ptw);
66 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
72 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
76 Session::request_input_change_handling ()
78 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
79 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
85 Session::request_sync_source (Slave* new_slave)
87 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
90 seamless = Config->get_seamless_loop ();
92 if (dynamic_cast<Engine_Slave*>(new_slave)) {
93 /* JACK cannot support seamless looping at present */
94 Config->set_seamless_loop (false);
96 /* reset to whatever the value was before we last switched slaves */
97 Config->set_seamless_loop (_was_seamless);
100 /* save value of seamless from before the switch */
101 _was_seamless = seamless;
103 ev->slave = new_slave;
104 DEBUG_TRACE (DEBUG::Slave, "sent request for new slave\n");
109 Session::request_transport_speed (double speed, bool as_default)
111 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
112 ev->third_yes_or_no = as_default; // as_default
113 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
117 /** Request a new transport speed, but if the speed parameter is exactly zero then use
118 * a very small +ve value to prevent the transport actually stopping. This method should
119 * be used by callers who are varying transport speed but don't ever want to stop it.
122 Session::request_transport_speed_nonzero (double speed, bool as_default)
128 request_transport_speed (speed, as_default);
132 Session::request_track_speed (Track* tr, double speed)
134 SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
140 Session::request_stop (bool abort, bool clear_state)
142 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_frame(), 0.0, abort, clear_state);
143 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport stop, audible %3 transport %4 abort = %1, clear state = %2\n", abort, clear_state, audible_frame(), _transport_frame));
148 Session::request_locate (framepos_t target_frame, bool with_roll)
150 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
151 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
156 Session::force_locate (framepos_t target_frame, bool with_roll)
158 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
159 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
164 Session::request_play_loop (bool yn, bool change_transport_roll)
167 // don't attempt to loop when not using Internal Transport
168 // see also gtk2_ardour/ardour_ui_options.cc parameter_changed()
173 Location *location = _locations->auto_loop_location();
176 if (location == 0 && yn) {
177 error << _("Cannot loop - no loop range defined")
182 if (change_transport_roll) {
183 if (transport_rolling()) {
184 /* start looping at current speed */
185 target_speed = transport_speed ();
187 /* currently stopped */
189 /* start looping at normal speed */
196 /* leave the speed alone */
197 target_speed = transport_speed ();
200 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
201 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
205 if (!change_transport_roll) {
206 if (!transport_rolling()) {
207 /* we're not changing transport state, but we do want
208 to set up position for the new loop. Don't
209 do this if we're rolling already.
211 request_locate (location->start(), false);
215 if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
216 // request an immediate locate to refresh the tracks
217 // after disabling looping
218 request_locate (_transport_frame-1, false);
224 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
226 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
228 ev->audio_range = *range;
230 ev->audio_range.clear ();
232 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
237 Session::request_cancel_play_range ()
239 SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
245 Session::realtime_stop (bool abort, bool clear_state)
247 DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_frame));
248 PostTransportWork todo = PostTransportWork (0);
250 /* assume that when we start, we'll be moving forwards */
252 if (_transport_speed < 0.0f) {
253 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
254 _default_transport_speed = 1.0;
256 todo = PostTransportWork (todo | PostTransportStop);
261 boost::shared_ptr<RouteList> r = routes.reader ();
263 for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
264 (*i)->realtime_handle_transport_stopped ();
267 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_frame));
269 /* the duration change is not guaranteed to have happened, but is likely */
271 todo = PostTransportWork (todo | PostTransportDuration);
274 todo = PostTransportWork (todo | PostTransportAbort);
278 todo = PostTransportWork (todo | PostTransportClearSubstate);
282 add_post_transport_work (todo);
285 _clear_event_type (SessionEvent::StopOnce);
286 _clear_event_type (SessionEvent::RangeStop);
287 _clear_event_type (SessionEvent::RangeLocate);
289 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
290 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
292 if (clear_state && !Config->get_loop_is_mode()) {
296 reset_slave_state ();
298 _transport_speed = 0;
299 _target_transport_speed = 0;
301 g_atomic_int_set (&_playback_load, 100);
302 g_atomic_int_set (&_capture_load, 100);
304 if (config.get_use_video_sync()) {
305 waiting_for_sync_offset = true;
308 transport_sub_state = 0;
312 Session::realtime_locate ()
314 boost::shared_ptr<RouteList> r = routes.reader ();
315 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
316 (*i)->realtime_locate ();
321 Session::butler_transport_work ()
323 /* Note: this function executes in the butler thread context */
327 PostTransportWork ptw;
328 boost::shared_ptr<RouteList> r = routes.reader ();
331 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
333 ptw = post_transport_work();
335 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
338 if (ptw & PostTransportLocate) {
340 if (get_play_loop() && !Config->get_seamless_loop()) {
342 DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
344 /* this locate might be happening while we are
347 * Non-seamless looping will require a locate (below) that
348 * will reset capture buffers and throw away data.
350 * Rather than first find all tracks and see if they
351 * have outstanding data, just do a flush anyway. It
352 * may be cheaper this way anyway, and is certainly
356 bool more_disk_io_to_do = false;
360 more_disk_io_to_do = _butler->flush_tracks_to_disk_after_locate (r, errors);
366 if (more_disk_io_to_do) {
375 if (ptw & PostTransportAdjustPlaybackBuffering) {
376 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
377 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
379 tr->adjust_playback_buffering ();
380 /* and refill those buffers ... */
382 (*i)->non_realtime_locate (_transport_frame);
387 if (ptw & PostTransportAdjustCaptureBuffering) {
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->adjust_capture_buffering ();
396 if (ptw & PostTransportCurveRealloc) {
397 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
398 (*i)->curve_reallocate();
402 if (ptw & PostTransportInputChange) {
403 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
404 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
406 tr->non_realtime_input_change ();
411 if (ptw & PostTransportSpeed) {
412 non_realtime_set_speed ();
415 if (ptw & PostTransportReverse) {
418 cumulative_rf_motion = 0;
421 /* don't seek if locate will take care of that in non_realtime_stop() */
423 if (!(ptw & PostTransportLocate)) {
425 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
426 (*i)->non_realtime_locate (_transport_frame);
428 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
429 /* new request, stop seeking, and start again */
430 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
437 if (ptw & PostTransportLocate) {
438 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
439 non_realtime_locate ();
442 if (ptw & PostTransportStop) {
443 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
445 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
450 if (ptw & PostTransportOverWrite) {
451 non_realtime_overwrite (on_entry, finished);
453 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
458 if (ptw & PostTransportAudition) {
459 non_realtime_set_audition ();
462 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
464 DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs\n"), g_get_monotonic_time() - before));
465 DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame)));
469 Session::non_realtime_set_speed ()
471 boost::shared_ptr<RouteList> rl = routes.reader();
472 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
473 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
475 tr->non_realtime_set_speed ();
481 Session::non_realtime_overwrite (int on_entry, bool& finished)
483 boost::shared_ptr<RouteList> rl = routes.reader();
484 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
485 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
486 if (tr && tr->pending_overwrite ()) {
487 tr->overwrite_existing_buffers ();
489 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
498 Session::non_realtime_locate ()
500 DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_frame));
502 if (Config->get_loop_is_mode() && get_play_loop()) {
504 Location *loc = _locations->auto_loop_location();
506 if (!loc || (_transport_frame < loc->start() || _transport_frame >= loc->end())) {
507 /* jumped out of loop range: stop tracks from looping,
508 but leave loop (mode) enabled.
510 set_track_loop (false);
512 } else if (loc && Config->get_seamless_loop() &&
513 ((loc->start() <= _transport_frame) ||
514 (loc->end() > _transport_frame) ) ) {
516 /* jumping to start of loop. This might have been done before but it is
517 * idempotent and cheap. Doing it here ensures that when we start playback
518 * outside the loop we still flip tracks into the magic seamless mode
521 set_track_loop (true);
524 set_track_loop (false);
529 /* no more looping .. should have been noticed elsewhere */
533 boost::shared_ptr<RouteList> rl = routes.reader();
534 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
535 (*i)->non_realtime_locate (_transport_frame);
538 _scene_changer->locate (_transport_frame);
540 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
541 rather than clearing them so that the RT thread has to spend time constructing
542 them (in Session::click).
547 #ifdef USE_TRACKS_CODE_FEATURES
549 Session::select_playhead_priority_target (framepos_t& jump_to)
553 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
559 if (Profile->get_trx() && transport_rolling() ) {
560 // We're playing, so do nothing.
561 // Next stop will put us where we need to be.
565 /* Note that the order of checking each AutoReturnTarget flag defines
566 the priority each flag.
568 Ardour/Mixbus: Last Locate
573 Tracks: Range Selection
579 if (autoreturn & RangeSelectionStart) {
580 if (!_range_selection.empty()) {
581 jump_to = _range_selection.from;
583 if (transport_rolling ()) {
584 /* Range selection no longer exists, but we're playing,
585 so do nothing. Next stop will put us where
593 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
594 /* don't try to handle loop play when synced to JACK */
596 if (!synced_to_engine()) {
597 Location *location = _locations->auto_loop_location();
600 jump_to = location->start();
602 if (Config->get_seamless_loop()) {
603 /* need to get track buffers reloaded */
604 set_track_loop (true);
610 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
611 if (!_object_selection.empty()) {
612 jump_to = _object_selection.from;
616 if (jump_to < 0 && (autoreturn & LastLocate)) {
617 jump_to = _last_roll_location;
625 Session::select_playhead_priority_target (framepos_t& jump_to)
627 if (config.get_external_sync() || !config.get_auto_return()) {
631 jump_to = _last_roll_location;
638 Session::follow_playhead_priority ()
642 if (select_playhead_priority_target (target)) {
643 request_locate (target);
648 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
654 PostTransportWork ptw = post_transport_work();
659 boost::shared_ptr<RouteList> rl = routes.reader();
660 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
661 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
662 if (tr && tr->get_captured_frames () != 0) {
668 /* stop and locate are merged here because they share a lot of common stuff */
671 now = localtime (&xnow);
674 auditioner->cancel_audition ();
677 cumulative_rf_motion = 0;
681 begin_reversible_command (Operations::capture);
682 _have_captured = true;
685 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
687 if (abort && did_record) {
688 /* no reason to save the session file when we remove sources
690 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
693 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
694 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
696 tr->transport_stopped_wallclock (*now, xnow, abort);
700 if (abort && did_record) {
701 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
704 boost::shared_ptr<RouteList> r = routes.reader ();
706 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
707 if (!(*i)->is_auditioner()) {
708 (*i)->set_pending_declick (0);
713 commit_reversible_command ();
714 /* increase take name */
715 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
716 string newname = config.get_take_name();
717 config.set_take_name(bump_name_number (newname));
721 if (_engine.running()) {
722 PostTransportWork ptw = post_transport_work ();
723 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
724 (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
726 update_latency_compensation ();
729 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
731 if (auto_return_enabled ||
732 (ptw & PostTransportLocate) ||
733 (_requested_return_frame >= 0) ||
734 synced_to_engine()) {
736 if (pending_locate_flush) {
737 flush_all_inserts ();
740 if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
741 !(ptw & PostTransportLocate)) {
743 /* no explicit locate queued */
745 bool do_locate = false;
747 if (_requested_return_frame >= 0) {
749 /* explicit return request pre-queued in event list. overrides everything else */
751 _transport_frame = _requested_return_frame;
757 if (select_playhead_priority_target (jump_to)) {
759 _transport_frame = jump_to;
764 _transport_frame = _last_roll_location;
769 _requested_return_frame = -1;
772 _engine.transport_locate (_transport_frame);
780 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
783 if (ptw & PostTransportClearSubstate) {
785 if (!Config->get_loop_is_mode()) {
790 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
792 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
793 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
794 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
795 (*i)->non_realtime_locate (_transport_frame);
797 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
799 /* we will be back */
806 /* don't bother with this stuff if we're disconnected from the engine,
807 because there will be no process callbacks to deliver stuff from
810 if (_engine.connected() && !_engine.freewheeling()) {
811 // need to queue this in the next RT cycle
812 _send_timecode_update = true;
814 if (!dynamic_cast<MTC_Slave*>(_slave)) {
815 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
817 /* This (::non_realtime_stop()) gets called by main
818 process thread, which will lead to confusion
819 when calling AsyncMIDIPort::write().
821 Something must be done. XXX
823 send_mmc_locate (_transport_frame);
827 if ((ptw & PostTransportLocate) && get_record_enabled()) {
828 /* This is scheduled by realtime_stop(), which is also done
829 * when a slave requests /locate/ for an initial sync.
830 * We can't hold up the slave for long with a save() here,
831 * without breaking its initial sync cycle.
833 * save state only if there's no slave or if it's not yet locked.
835 if (!_slave || !_slave->locked()) {
836 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
837 SaveSessionRequested (_current_snapshot_name);
842 /* always try to get rid of this */
844 remove_pending_capture_state ();
846 /* save the current state of things if appropriate */
848 if (did_record && !saved) {
849 SaveSessionRequested (_current_snapshot_name);
852 if (ptw & PostTransportStop) {
854 if (!Config->get_loop_is_mode()) {
859 PositionChanged (_transport_frame); /* EMIT SIGNAL */
860 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
861 TransportStateChange (); /* EMIT SIGNAL */
863 /* and start it up again if relevant */
865 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
866 request_transport_speed (1.0);
869 /* Even if we didn't do a pending locate roll this time, we don't want it hanging
870 around for next time.
872 pending_locate_roll = false;
876 Session::check_declick_out ()
878 bool locate_required = transport_sub_state & PendingLocate;
880 /* this is called after a process() iteration. if PendingDeclickOut was set,
881 it means that we were waiting to declick the output (which has just been
882 done) before maybe doing something else. this is where we do that "something else".
884 note: called from the audio thread.
887 if (transport_sub_state & PendingDeclickOut) {
889 if (locate_required) {
890 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
891 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
893 if (!(transport_sub_state & StopPendingCapture)) {
894 stop_transport (pending_abort);
895 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
899 } else if (transport_sub_state & PendingLoopDeclickOut) {
900 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
901 transport_sub_state &= ~PendingLoopDeclickOut;
906 Session::unset_play_loop ()
910 clear_events (SessionEvent::AutoLoop);
911 clear_events (SessionEvent::AutoLoopDeclick);
912 set_track_loop (false);
915 if (Config->get_seamless_loop()) {
916 /* likely need to flush track buffers: this will locate us to wherever we are */
917 add_post_transport_work (PostTransportLocate);
918 _butler->schedule_transport_work ();
924 Session::set_track_loop (bool yn)
926 Location* loc = _locations->auto_loop_location ();
932 boost::shared_ptr<RouteList> rl = routes.reader ();
934 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
935 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
936 if (tr && !tr->hidden()) {
937 tr->set_loop (yn ? loc : 0);
943 Session::set_play_loop (bool yn, double speed)
945 /* Called from event-handling context */
949 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
950 /* nothing to do, or can't change loop status while recording */
954 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
955 warning << string_compose (
956 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
957 "Recommend changing the configured options"), PROGRAM_NAME)
971 if (Config->get_seamless_loop()) {
972 if (!Config->get_loop_is_mode()) {
973 /* set all tracks to use internal looping */
974 set_track_loop (true);
976 /* we will do this in the locate to the start OR when we hit the end
977 * of the loop for the first time
981 /* set all tracks to NOT use internal looping */
982 set_track_loop (false);
985 /* Put the delick and loop events in into the event list. The declick event will
986 cause a de-clicking fade-out just before the end of the loop, and it will also result
987 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
992 auto_loop_declick_range (loc, dcp, dcl);
993 merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
994 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
996 /* if requested to roll, locate to start of loop and
997 * roll but ONLY if we're not already rolling.
999 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
1002 if (Config->get_loop_is_mode()) {
1003 /* loop IS a transport mode: if already
1004 rolling, do not locate to loop start.
1006 if (!transport_rolling() && (speed != 0.0)) {
1007 start_locate (loc->start(), true, true, false, true);
1011 start_locate (loc->start(), true, true, false, true);
1021 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
1022 TransportStateChange ();
1025 Session::flush_all_inserts ()
1027 boost::shared_ptr<RouteList> r = routes.reader ();
1029 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1030 (*i)->flush_processors ();
1035 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
1037 if (target_frame < 0) {
1038 error << _("Locate called for negative sample position - ignored") << endmsg;
1042 if (synced_to_engine()) {
1047 _slave->speed_and_position (sp, pos);
1049 if (target_frame != pos) {
1051 if (config.get_jack_time_master()) {
1052 /* actually locate now, since otherwise jack_timebase_callback
1053 will use the incorrect _transport_frame and report an old
1054 and incorrect time to Jack transport
1056 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1059 /* tell JACK to change transport position, and we will
1060 follow along later in ::follow_slave()
1063 _engine.transport_locate (target_frame);
1065 if (sp != 1.0f && with_roll) {
1066 _engine.transport_start ();
1072 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1077 Session::micro_locate (framecnt_t distance)
1079 boost::shared_ptr<RouteList> rl = routes.reader();
1080 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1081 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1082 if (tr && !tr->can_internal_playback_seek (distance)) {
1087 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1088 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1090 tr->internal_playback_seek (distance);
1094 _transport_frame += distance;
1098 /** @param with_mmc true to send a MMC locate command when the locate is done */
1100 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
1102 bool need_butler = false;
1104 /* Locates for seamless looping are fairly different from other
1105 * locates. They assume that the diskstream buffers for each track
1106 * already have the correct data in them, and thus there is no need to
1107 * actually tell the tracks to locate. What does need to be done,
1108 * though, is all the housekeeping that is associated with non-linear
1109 * changes in the value of _transport_frame.
1112 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
1113 target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
1115 if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
1117 /* already at the desired position. Not forced to locate,
1118 the loop isn't changing, so unless we're told to
1119 start rolling also, there's nothing to do but
1120 tell the world where we are (again).
1124 set_transport_speed (1.0, 0, false);
1126 loop_changing = false;
1127 Located (); /* EMIT SIGNAL */
1131 if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
1132 /* Schedule a declick. We'll be called again when its done.
1133 We only do it this way for ordinary locates, not those
1134 due to **seamless** loops.
1137 if (!(transport_sub_state & PendingDeclickOut)) {
1138 transport_sub_state |= (PendingDeclickOut|PendingLocate);
1139 pending_locate_frame = target_frame;
1140 pending_locate_roll = with_roll;
1141 pending_locate_flush = with_flush;
1146 // Update Timecode time
1147 // [DR] FIXME: find out exactly where this should go below
1148 _transport_frame = target_frame;
1149 _last_roll_or_reversal_location = target_frame;
1150 timecode_time(_transport_frame, transmitting_timecode_time);
1151 outbound_mtc_timecode_frame = _transport_frame;
1152 next_quarter_frame_to_send = 0;
1154 /* do "stopped" stuff if:
1156 * we are rolling AND
1157 * no autoplay in effect AND
1158 * we're not going to keep rolling after the locate AND
1159 * !(playing a loop with JACK sync)
1163 bool transport_was_stopped = !transport_rolling();
1165 if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1166 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1167 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1168 transport_was_stopped = true;
1170 /* otherwise tell the world that we located */
1174 if (force || !for_loop_enabled || loop_changing) {
1176 PostTransportWork todo = PostTransportLocate;
1178 if (with_roll && transport_was_stopped) {
1179 todo = PostTransportWork (todo | PostTransportRoll);
1182 add_post_transport_work (todo);
1187 /* this is functionally what clear_clicks() does but with a tentative lock */
1189 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1191 if (clickm.locked()) {
1193 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1202 /* switch from input if we're going to roll */
1203 if (Config->get_monitoring_model() == HardwareMonitoring) {
1204 set_track_monitor_input_status (!config.get_auto_input());
1207 /* otherwise we're going to stop, so do the opposite */
1208 if (Config->get_monitoring_model() == HardwareMonitoring) {
1209 set_track_monitor_input_status (true);
1213 /* cancel looped playback if transport pos outside of loop range */
1216 Location* al = _locations->auto_loop_location();
1219 if (_transport_frame < al->start() || _transport_frame >= al->end()) {
1221 // located outside the loop: cancel looping directly, this is called from event handling context
1223 have_looped = false;
1225 if (!Config->get_loop_is_mode()) {
1226 set_play_loop (false, _transport_speed);
1228 if (Config->get_seamless_loop()) {
1229 /* this will make the non_realtime_locate() in the butler
1230 which then causes seek() in tracks actually do the right
1233 set_track_loop (false);
1237 } else if (_transport_frame == al->start()) {
1239 // located to start of loop - this is looping, basically
1243 if (_last_roll_location != al->start()) {
1244 /* didn't start at loop start - playback must have
1245 * started before loop since we've now hit the loop
1248 add_post_transport_work (PostTransportLocate);
1254 boost::shared_ptr<RouteList> rl = routes.reader();
1256 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1257 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1259 if (tr && tr->record_enabled ()) {
1260 // tell it we've looped, so it can deal with the record state
1261 tr->transport_looped (_transport_frame);
1266 TransportLooped(); // EMIT SIGNAL
1272 _butler->schedule_transport_work ();
1275 loop_changing = false;
1277 _send_timecode_update = true;
1280 send_mmc_locate (_transport_frame);
1283 _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
1284 Located (); /* EMIT SIGNAL */
1287 /** Set the transport speed.
1288 * Called from the process thread.
1289 * @param speed New speed
1292 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1294 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1295 speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1297 if (_transport_speed == speed) {
1298 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1299 _default_transport_speed = 1.0;
1304 if (actively_recording() && speed != 1.0 && speed != 0.0) {
1305 /* no varispeed during recording */
1306 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1307 _transport_speed, _transport_frame));
1311 _target_transport_speed = fabs(speed);
1313 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1314 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1318 speed = min (8.0, speed);
1319 } else if (speed < 0) {
1320 speed = max (-8.0, speed);
1323 if (transport_rolling() && speed == 0.0) {
1325 /* we are rolling and we want to stop */
1327 if (Config->get_monitoring_model() == HardwareMonitoring) {
1328 set_track_monitor_input_status (true);
1331 if (synced_to_engine ()) {
1333 /* do this here because our response to the slave won't
1336 _play_range = false;
1339 _engine.transport_stop ();
1341 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1343 if (!auto_return_enabled) {
1344 _requested_return_frame = destination_frame;
1347 stop_transport (abort);
1350 } else if (transport_stopped() && speed == 1.0) {
1352 _default_transport_speed = speed;
1354 /* we are stopped and we want to start rolling at speed 1 */
1356 if (Config->get_loop_is_mode() && play_loop) {
1358 Location *location = _locations->auto_loop_location();
1360 if (location != 0) {
1361 if (_transport_frame != location->start()) {
1363 if (Config->get_seamless_loop()) {
1364 /* force tracks to do their thing */
1365 set_track_loop (true);
1368 /* jump to start and then roll from there */
1370 request_locate (location->start(), true);
1376 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1377 set_track_monitor_input_status (false);
1380 if (synced_to_engine()) {
1381 _engine.transport_start ();
1388 /* not zero, not 1.0 ... varispeed */
1390 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1391 warning << string_compose (
1392 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1398 if (actively_recording()) {
1402 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1406 if (speed < 0.0 && _transport_frame == 0) {
1412 /* if we are reversing relative to the current speed, or relative to the speed
1413 before the last stop, then we have to do extra work.
1416 PostTransportWork todo = PostTransportWork (0);
1418 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
1419 todo = PostTransportWork (todo | PostTransportReverse);
1420 _last_roll_or_reversal_location = _transport_frame;
1423 _last_transport_speed = _transport_speed;
1424 _transport_speed = speed;
1427 _default_transport_speed = speed;
1430 boost::shared_ptr<RouteList> rl = routes.reader();
1431 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1432 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1433 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1434 todo = PostTransportWork (todo | PostTransportSpeed);
1439 add_post_transport_work (todo);
1440 _butler->schedule_transport_work ();
1443 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1445 /* throttle signal emissions.
1446 * when slaved [_last]_transport_speed
1447 * usually changes every cycle (tiny amounts due to DLL).
1448 * Emitting a signal every cycle is overkill and unwarranted.
1450 * Using _last_transport_speed is not acceptable,
1451 * since it allows for large changes over a long period
1452 * of time. Hence we introduce a dedicated variable to keep track
1454 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1455 * for TransportStateChange() here is the ShuttleControl display.
1457 if (fabs (_signalled_varispeed - speed) > .002
1458 // still, signal hard changes to 1.0 and 0.0:
1459 || ( speed == 1.0 && _signalled_varispeed != 1.0)
1460 || ( speed == 0.0 && _signalled_varispeed != 0.0)
1463 TransportStateChange (); /* EMIT SIGNAL */
1464 _signalled_varispeed = speed;
1470 /** Stop the transport. */
1472 Session::stop_transport (bool abort, bool clear_state)
1474 if (_transport_speed == 0.0f) {
1478 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
1480 if (!get_transport_declick_required()) {
1482 /* stop has not yet been scheduled */
1484 boost::shared_ptr<RouteList> rl = routes.reader();
1485 framepos_t stop_target = audible_frame();
1487 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1488 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1490 tr->prepare_to_stop (_transport_frame, stop_target);
1496 if (actively_recording() && /* we are recording */
1497 worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1499 /* we need to capture the audio that is still somewhere in the pipeline between
1500 wherever it was generated and the process callback. This means that even though
1501 the user (or something else) has asked us to stop, we have to roll
1502 past this point and then reset the playhead/transport location to
1503 the position at which the stop was requested.
1505 we still need playback to "stop" now, however, which is why we schedule
1509 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1510 _transport_frame, _worst_input_latency,
1511 _transport_frame + _worst_input_latency,
1514 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1515 _transport_frame + _worst_input_latency,
1520 /* request a declick at the start of the next process cycle() so that playback ceases.
1521 It will remain silent until we actually stop (at the StopOnce event somewhere in
1522 the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1523 does not stop the transport too early.
1525 new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1529 /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1531 new_bits = PendingDeclickOut;
1532 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
1535 /* we'll be called again after the declick */
1536 transport_sub_state = SubState (transport_sub_state|new_bits);
1537 pending_abort = abort;
1543 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
1545 /* declick was scheduled, but we've been called again, which means it is really time to stop
1547 XXX: we should probably split this off into its own method and call it explicitly.
1550 realtime_stop (abort, clear_state);
1551 _butler->schedule_transport_work ();
1555 /** Called from the process thread */
1557 Session::start_transport ()
1559 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1561 _last_roll_location = _transport_frame;
1562 _last_roll_or_reversal_location = _transport_frame;
1564 have_looped = false;
1566 /* if record status is Enabled, move it to Recording. if its
1567 already Recording, move it to Disabled.
1570 switch (record_status()) {
1572 if (!config.get_punch_in()) {
1579 disable_record (false);
1587 transport_sub_state |= PendingDeclickIn;
1589 _transport_speed = _default_transport_speed;
1590 _target_transport_speed = _transport_speed;
1592 boost::shared_ptr<RouteList> rl = routes.reader();
1593 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1594 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1596 tr->realtime_set_speed (tr->speed(), true);
1600 if (!_engine.freewheeling()) {
1601 Timecode::Time time;
1602 timecode_time_subframes (_transport_frame, time);
1603 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1604 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1608 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1609 TransportStateChange (); /* EMIT SIGNAL */
1612 /** Do any transport work in the audio thread that needs to be done after the
1613 * transport thread is finished. Audio thread, realtime safe.
1616 Session::post_transport ()
1618 PostTransportWork ptw = post_transport_work ();
1620 if (ptw & PostTransportAudition) {
1621 if (auditioner && auditioner->auditioning()) {
1622 process_function = &Session::process_audition;
1624 process_function = &Session::process_with_events;
1628 if (ptw & PostTransportStop) {
1630 transport_sub_state = 0;
1633 if (ptw & PostTransportLocate) {
1635 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1638 transport_sub_state = 0;
1643 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1646 set_post_transport_work (PostTransportWork (0));
1650 Session::reset_rf_scale (framecnt_t motion)
1652 cumulative_rf_motion += motion;
1654 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1656 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1658 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1670 Session::mtc_status_changed (bool yn)
1672 g_atomic_int_set (&_mtc_active, yn);
1673 MTCSyncStateChanged( yn );
1677 Session::ltc_status_changed (bool yn)
1679 g_atomic_int_set (&_ltc_active, yn);
1680 LTCSyncStateChanged( yn );
1684 Session::use_sync_source (Slave* new_slave)
1686 /* Runs in process() context */
1688 bool non_rt_required = false;
1690 /* XXX this deletion is problematic because we're in RT context */
1695 MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1697 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1698 MTCSyncStateChanged(mtc_slave->locked() );
1700 if (g_atomic_int_get (&_mtc_active) ){
1701 g_atomic_int_set (&_mtc_active, 0);
1702 MTCSyncStateChanged( false );
1704 mtc_status_connection.disconnect ();
1707 LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1709 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1710 LTCSyncStateChanged (ltc_slave->locked() );
1712 if (g_atomic_int_get (&_ltc_active) ){
1713 g_atomic_int_set (&_ltc_active, 0);
1714 LTCSyncStateChanged( false );
1716 ltc_status_connection.disconnect ();
1719 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1721 // need to queue this for next process() cycle
1722 _send_timecode_update = true;
1724 boost::shared_ptr<RouteList> rl = routes.reader();
1725 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1726 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1727 if (tr && !tr->hidden()) {
1728 if (tr->realtime_set_speed (tr->speed(), true)) {
1729 non_rt_required = true;
1731 tr->set_slaved (_slave != 0);
1735 if (non_rt_required) {
1736 add_post_transport_work (PostTransportSpeed);
1737 _butler->schedule_transport_work ();
1744 Session::drop_sync_source ()
1746 request_sync_source (0);
1750 Session::switch_to_sync_source (SyncSource src)
1754 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1758 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1763 new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1766 catch (failed_constructor& err) {
1772 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1777 new_slave = new LTC_Slave (*this);
1780 catch (failed_constructor& err) {
1787 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1792 new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1795 catch (failed_constructor& err) {
1801 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1805 if (config.get_video_pullup() != 0.0f) {
1809 new_slave = new Engine_Slave (*AudioEngine::instance());
1817 request_sync_source (new_slave);
1821 Session::set_track_speed (Track* track, double speed)
1823 if (track->realtime_set_speed (speed, false)) {
1824 add_post_transport_work (PostTransportSpeed);
1825 _butler->schedule_transport_work ();
1831 Session::unset_play_range ()
1833 _play_range = false;
1834 _clear_event_type (SessionEvent::RangeStop);
1835 _clear_event_type (SessionEvent::RangeLocate);
1839 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1843 /* Called from event-processing context */
1845 unset_play_range ();
1847 if (range.empty()) {
1848 /* _play_range set to false in unset_play_range()
1850 if (!leave_rolling) {
1851 /* stop transport */
1852 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1860 /* cancel loop play */
1863 list<AudioRange>::size_type sz = range.size();
1867 list<AudioRange>::iterator i = range.begin();
1868 list<AudioRange>::iterator next;
1870 while (i != range.end()) {
1875 /* locating/stopping is subject to delays for declicking.
1878 framepos_t requested_frame = i->end;
1880 if (requested_frame > current_block_size) {
1881 requested_frame -= current_block_size;
1883 requested_frame = 0;
1886 if (next == range.end()) {
1887 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
1889 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
1897 } else if (sz == 1) {
1899 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
1904 /* save range so we can do auto-return etc. */
1906 current_audio_range = range;
1908 /* now start rolling at the right place */
1910 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
1913 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
1914 TransportStateChange ();
1918 Session::request_bounded_roll (framepos_t start, framepos_t end)
1920 AudioRange ar (start, end, 0);
1921 list<AudioRange> lar;
1924 request_play_range (&lar, true);
1928 Session::set_requested_return_frame (framepos_t return_to)
1930 _requested_return_frame = return_to;
1934 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
1936 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
1937 ev->target2_frame = start;
1942 Session::engine_halted ()
1946 /* there will be no more calls to process(), so
1947 we'd better clean up for ourselves, right now.
1949 but first, make sure the butler is out of
1957 realtime_stop (false, true);
1958 non_realtime_stop (false, 0, ignored);
1959 transport_sub_state = 0;
1961 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
1962 TransportStateChange (); /* EMIT SIGNAL */
1967 Session::xrun_recovery ()
1971 Xrun (_transport_frame); /* EMIT SIGNAL */
1973 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
1975 /* it didn't actually halt, but we need
1976 to handle things in the same way.
1984 Session::route_processors_changed (RouteProcessorChange c)
1986 if (ignore_route_processor_changes) {
1990 if (c.type == RouteProcessorChange::MeterPointChange) {
1995 if (c.type == RouteProcessorChange::RealTimeChange) {
2000 update_latency_compensation ();
2007 Session::allow_auto_play (bool yn)
2009 auto_play_legal = yn;
2013 Session::maybe_stop (framepos_t limit)
2015 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
2016 if (synced_to_engine () && config.get_jack_time_master ()) {
2017 _engine.transport_stop ();
2018 } else if (!synced_to_engine ()) {
2027 Session::send_mmc_locate (framepos_t t)
2033 if (!_engine.freewheeling()) {
2034 Timecode::Time time;
2035 timecode_time_subframes (t, time);
2036 send_immediate_mmc (MIDI::MachineControlCommand (time));
2040 /** Ask the transport to not send timecode until further notice. The suspension
2041 * will come into effect some finite time after this call, and timecode_transmission_suspended()
2042 * should be checked by the caller to find out when.
2045 Session::request_suspend_timecode_transmission ()
2047 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2052 Session::request_resume_timecode_transmission ()
2054 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2059 Session::timecode_transmission_suspended () const
2061 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;