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/automation_watch.h"
41 #include "ardour/butler.h"
42 #include "ardour/click.h"
43 #include "ardour/debug.h"
44 #include "ardour/location.h"
45 #include "ardour/profile.h"
46 #include "ardour/scene_changer.h"
47 #include "ardour/session.h"
48 #include "ardour/slave.h"
49 #include "ardour/tempo.h"
50 #include "ardour/operations.h"
51 #include "ardour/vca.h"
52 #include "ardour/vca_manager.h"
57 using namespace ARDOUR;
61 Session::add_post_transport_work (PostTransportWork ptw)
63 PostTransportWork oldval;
64 PostTransportWork newval;
68 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
69 newval = PostTransportWork (oldval | ptw);
70 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
76 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
80 Session::request_input_change_handling ()
82 if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
83 SessionEvent* ev = new SessionEvent (SessionEvent::InputConfigurationChange, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
89 Session::request_sync_source (Slave* new_slave)
91 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
94 seamless = Config->get_seamless_loop ();
96 if (dynamic_cast<Engine_Slave*>(new_slave)) {
97 /* JACK cannot support seamless looping at present */
98 Config->set_seamless_loop (false);
100 /* reset to whatever the value was before we last switched slaves */
101 Config->set_seamless_loop (_was_seamless);
104 /* save value of seamless from before the switch */
105 _was_seamless = seamless;
107 ev->slave = new_slave;
108 DEBUG_TRACE (DEBUG::Slave, "sent request for new slave\n");
113 Session::request_transport_speed (double speed, bool as_default)
115 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
116 ev->third_yes_or_no = as_default; // as_default
117 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
121 /** Request a new transport speed, but if the speed parameter is exactly zero then use
122 * a very small +ve value to prevent the transport actually stopping. This method should
123 * be used by callers who are varying transport speed but don't ever want to stop it.
126 Session::request_transport_speed_nonzero (double speed, bool as_default)
132 request_transport_speed (speed, as_default);
136 Session::request_track_speed (Track* tr, double speed)
138 SessionEvent* ev = new SessionEvent (SessionEvent::SetTrackSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
144 Session::request_stop (bool abort, bool clear_state)
146 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_frame(), 0.0, abort, clear_state);
147 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));
152 Session::request_locate (framepos_t target_frame, bool with_roll)
154 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
155 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
160 Session::force_locate (framepos_t target_frame, bool with_roll)
162 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
163 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
168 Session::unset_preroll_record_punch ()
170 if (_preroll_record_punch_pos >= 0) {
171 remove_event (_preroll_record_punch_pos, SessionEvent::RecordStart);
173 _preroll_record_punch_pos = -1;
177 Session::unset_preroll_record_trim ()
179 _preroll_record_trim_len = 0;
183 Session::request_preroll_record_punch (framepos_t rec_in, framecnt_t preroll)
185 if (actively_recording ()) {
188 unset_preroll_record_punch ();
189 unset_preroll_record_trim ();
190 framepos_t start = std::max ((framepos_t)0, rec_in - preroll);
192 _preroll_record_punch_pos = rec_in;
193 if (_preroll_record_punch_pos >= 0) {
194 replace_event (SessionEvent::RecordStart, _preroll_record_punch_pos);
195 config.set_punch_in (false);
196 config.set_punch_out (false);
198 maybe_enable_record ();
199 request_locate (start, true);
200 set_requested_return_frame (rec_in);
204 Session::request_preroll_record_trim (framepos_t rec_in, framecnt_t preroll)
206 if (actively_recording ()) {
209 unset_preroll_record_punch ();
210 unset_preroll_record_trim ();
212 config.set_punch_in (false);
213 config.set_punch_out (false);
215 framepos_t pos = std::max ((framepos_t)0, rec_in - preroll);
216 _preroll_record_trim_len = preroll;
217 maybe_enable_record ();
218 request_locate (pos, true);
219 set_requested_return_frame (rec_in);
223 Session::request_count_in_record ()
225 if (actively_recording ()) {
228 if (transport_rolling()) {
231 maybe_enable_record ();
232 _count_in_once = true;
233 request_transport_speed (1.0, true);
237 Session::request_play_loop (bool yn, bool change_transport_roll)
240 // don't attempt to loop when not using Internal Transport
241 // see also gtk2_ardour/ardour_ui_options.cc parameter_changed()
246 Location *location = _locations->auto_loop_location();
249 if (location == 0 && yn) {
250 error << _("Cannot loop - no loop range defined")
255 if (change_transport_roll) {
256 if (transport_rolling()) {
257 /* start looping at current speed */
258 target_speed = transport_speed ();
260 /* currently stopped */
262 /* start looping at normal speed */
269 /* leave the speed alone */
270 target_speed = transport_speed ();
273 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
274 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
278 if (!change_transport_roll) {
279 if (!transport_rolling()) {
280 /* we're not changing transport state, but we do want
281 to set up position for the new loop. Don't
282 do this if we're rolling already.
284 request_locate (location->start(), false);
288 if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
289 // request an immediate locate to refresh the tracks
290 // after disabling looping
291 request_locate (_transport_frame-1, false);
297 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
299 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
301 ev->audio_range = *range;
303 ev->audio_range.clear ();
305 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
310 Session::request_cancel_play_range ()
312 SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
318 Session::realtime_stop (bool abort, bool clear_state)
320 DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_frame));
321 PostTransportWork todo = PostTransportWork (0);
323 /* assume that when we start, we'll be moving forwards */
325 if (_transport_speed < 0.0f) {
326 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
327 _default_transport_speed = 1.0;
329 todo = PostTransportWork (todo | PostTransportStop);
334 boost::shared_ptr<RouteList> r = routes.reader ();
336 for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
337 (*i)->realtime_handle_transport_stopped ();
340 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_frame));
342 /* the duration change is not guaranteed to have happened, but is likely */
344 todo = PostTransportWork (todo | PostTransportDuration);
347 todo = PostTransportWork (todo | PostTransportAbort);
351 todo = PostTransportWork (todo | PostTransportClearSubstate);
355 add_post_transport_work (todo);
358 _clear_event_type (SessionEvent::StopOnce);
359 _clear_event_type (SessionEvent::RangeStop);
360 _clear_event_type (SessionEvent::RangeLocate);
362 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
363 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
365 if (clear_state && !Config->get_loop_is_mode()) {
369 reset_slave_state ();
371 _transport_speed = 0;
372 _target_transport_speed = 0;
374 g_atomic_int_set (&_playback_load, 100);
375 g_atomic_int_set (&_capture_load, 100);
377 if (config.get_use_video_sync()) {
378 waiting_for_sync_offset = true;
381 transport_sub_state = 0;
385 Session::realtime_locate ()
387 boost::shared_ptr<RouteList> r = routes.reader ();
388 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
389 (*i)->realtime_locate ();
394 Session::butler_transport_work ()
396 /* Note: this function executes in the butler thread context */
400 PostTransportWork ptw;
401 boost::shared_ptr<RouteList> r = routes.reader ();
404 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
406 ptw = post_transport_work();
408 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
411 if (ptw & PostTransportLocate) {
413 if (get_play_loop() && !Config->get_seamless_loop()) {
415 DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
417 /* this locate might be happening while we are
420 * Non-seamless looping will require a locate (below) that
421 * will reset capture buffers and throw away data.
423 * Rather than first find all tracks and see if they
424 * have outstanding data, just do a flush anyway. It
425 * may be cheaper this way anyway, and is certainly
429 bool more_disk_io_to_do = false;
433 more_disk_io_to_do = _butler->flush_tracks_to_disk_after_locate (r, errors);
439 if (more_disk_io_to_do) {
448 if (ptw & PostTransportAdjustPlaybackBuffering) {
449 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
450 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
452 tr->adjust_playback_buffering ();
453 /* and refill those buffers ... */
455 (*i)->non_realtime_locate (_transport_frame);
460 if (ptw & PostTransportAdjustCaptureBuffering) {
461 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
462 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
464 tr->adjust_capture_buffering ();
469 if (ptw & PostTransportCurveRealloc) {
470 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
471 (*i)->curve_reallocate();
475 if (ptw & PostTransportInputChange) {
476 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
477 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
479 tr->non_realtime_input_change ();
484 if (ptw & PostTransportSpeed) {
485 non_realtime_set_speed ();
488 if (ptw & PostTransportReverse) {
491 cumulative_rf_motion = 0;
494 /* don't seek if locate will take care of that in non_realtime_stop() */
496 if (!(ptw & PostTransportLocate)) {
497 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
498 (*i)->non_realtime_locate (_transport_frame);
500 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
501 /* new request, stop seeking, and start again */
502 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
509 if (ptw & PostTransportLocate) {
510 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
511 non_realtime_locate ();
514 if (ptw & PostTransportStop) {
515 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
517 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
522 if (ptw & PostTransportOverWrite) {
523 non_realtime_overwrite (on_entry, finished);
525 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
530 if (ptw & PostTransportAudition) {
531 non_realtime_set_audition ();
534 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
536 DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs\n"), g_get_monotonic_time() - before));
537 DEBUG_TRACE (DEBUG::Transport, X_(string_compose ("Frame %1\n", _transport_frame)));
541 Session::non_realtime_set_speed ()
543 boost::shared_ptr<RouteList> rl = routes.reader();
544 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
545 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
547 tr->non_realtime_set_speed ();
553 Session::non_realtime_overwrite (int on_entry, bool& finished)
555 boost::shared_ptr<RouteList> rl = routes.reader();
556 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
557 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
558 if (tr && tr->pending_overwrite ()) {
559 tr->overwrite_existing_buffers ();
561 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
570 Session::non_realtime_locate ()
572 DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_frame));
574 if (Config->get_loop_is_mode() && get_play_loop()) {
576 Location *loc = _locations->auto_loop_location();
578 if (!loc || (_transport_frame < loc->start() || _transport_frame >= loc->end())) {
579 /* jumped out of loop range: stop tracks from looping,
580 but leave loop (mode) enabled.
582 set_track_loop (false);
584 } else if (loc && Config->get_seamless_loop() &&
585 ((loc->start() <= _transport_frame) ||
586 (loc->end() > _transport_frame) ) ) {
588 /* jumping to start of loop. This might have been done before but it is
589 * idempotent and cheap. Doing it here ensures that when we start playback
590 * outside the loop we still flip tracks into the magic seamless mode
593 set_track_loop (true);
596 set_track_loop (false);
601 /* no more looping .. should have been noticed elsewhere */
606 boost::shared_ptr<RouteList> rl = routes.reader();
607 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
608 (*i)->non_realtime_locate (_transport_frame);
612 _scene_changer->locate (_transport_frame);
614 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
615 rather than clearing them so that the RT thread has to spend time constructing
616 them (in Session::click).
621 #ifdef USE_TRACKS_CODE_FEATURES
623 Session::select_playhead_priority_target (framepos_t& jump_to)
627 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
633 if (Profile->get_trx() && transport_rolling() ) {
634 // We're playing, so do nothing.
635 // Next stop will put us where we need to be.
639 /* Note that the order of checking each AutoReturnTarget flag defines
640 the priority each flag.
642 Ardour/Mixbus: Last Locate
647 Tracks: Range Selection
653 if (autoreturn & RangeSelectionStart) {
654 if (!_range_selection.empty()) {
655 jump_to = _range_selection.from;
657 if (transport_rolling ()) {
658 /* Range selection no longer exists, but we're playing,
659 so do nothing. Next stop will put us where
667 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
668 /* don't try to handle loop play when synced to JACK */
670 if (!synced_to_engine()) {
671 Location *location = _locations->auto_loop_location();
674 jump_to = location->start();
676 if (Config->get_seamless_loop()) {
677 /* need to get track buffers reloaded */
678 set_track_loop (true);
684 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
685 if (!_object_selection.empty()) {
686 jump_to = _object_selection.from;
690 if (jump_to < 0 && (autoreturn & LastLocate)) {
691 jump_to = _last_roll_location;
699 Session::select_playhead_priority_target (framepos_t& jump_to)
701 if (config.get_external_sync() || !config.get_auto_return()) {
705 jump_to = _last_roll_location;
712 Session::follow_playhead_priority ()
716 if (select_playhead_priority_target (target)) {
717 request_locate (target);
722 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
728 PostTransportWork ptw = post_transport_work();
733 boost::shared_ptr<RouteList> rl = routes.reader();
734 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
735 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
736 if (tr && tr->get_captured_frames () != 0) {
742 /* stop and locate are merged here because they share a lot of common stuff */
745 now = localtime (&xnow);
748 auditioner->cancel_audition ();
751 cumulative_rf_motion = 0;
755 begin_reversible_command (Operations::capture);
756 _have_captured = true;
759 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
761 if (abort && did_record) {
762 /* no reason to save the session file when we remove sources
764 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
767 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
768 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
770 tr->transport_stopped_wallclock (*now, xnow, abort);
774 if (abort && did_record) {
775 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
778 boost::shared_ptr<RouteList> r = routes.reader ();
780 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
781 if (!(*i)->is_auditioner()) {
782 (*i)->set_pending_declick (0);
787 commit_reversible_command ();
788 /* increase take name */
789 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
790 string newname = config.get_take_name();
791 config.set_take_name(bump_name_number (newname));
795 if (_engine.running()) {
796 PostTransportWork ptw = post_transport_work ();
798 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
799 (*i)->nonrealtime_handle_transport_stopped (abort, (ptw & PostTransportLocate), (!(ptw & PostTransportLocate) || pending_locate_flush));
801 VCAList v = _vca_manager->vcas ();
802 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
803 (*i)->transport_stopped (_transport_frame);
806 update_latency_compensation ();
809 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
811 if (auto_return_enabled ||
812 (ptw & PostTransportLocate) ||
813 (_requested_return_frame >= 0) ||
814 synced_to_engine()) {
816 if (pending_locate_flush) {
817 flush_all_inserts ();
820 // rg: what is the logic behind this case?
821 // _requested_return_frame should be ignored when synced_to_engine/slaved.
822 // currently worked around in MTC_Slave by forcing _requested_return_frame to -1
824 if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
825 !(ptw & PostTransportLocate)) {
827 /* no explicit locate queued */
829 bool do_locate = false;
831 if (_requested_return_frame >= 0) {
833 /* explicit return request pre-queued in event list. overrides everything else */
835 _transport_frame = _requested_return_frame;
841 if (select_playhead_priority_target (jump_to)) {
843 _transport_frame = jump_to;
848 _transport_frame = _last_roll_location;
853 _requested_return_frame = -1;
856 _engine.transport_locate (_transport_frame);
863 unset_preroll_record_trim ();
865 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
868 if (ptw & PostTransportClearSubstate) {
870 if (!Config->get_loop_is_mode()) {
875 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
878 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
879 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
880 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
881 (*i)->non_realtime_locate (_transport_frame);
883 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
885 /* we will be back */
893 /* don't bother with this stuff if we're disconnected from the engine,
894 because there will be no process callbacks to deliver stuff from
897 if (_engine.connected() && !_engine.freewheeling()) {
898 // need to queue this in the next RT cycle
899 _send_timecode_update = true;
901 if (!dynamic_cast<MTC_Slave*>(_slave)) {
902 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
904 /* This (::non_realtime_stop()) gets called by main
905 process thread, which will lead to confusion
906 when calling AsyncMIDIPort::write().
908 Something must be done. XXX
910 send_mmc_locate (_transport_frame);
914 if ((ptw & PostTransportLocate) && get_record_enabled()) {
915 /* This is scheduled by realtime_stop(), which is also done
916 * when a slave requests /locate/ for an initial sync.
917 * We can't hold up the slave for long with a save() here,
918 * without breaking its initial sync cycle.
920 * save state only if there's no slave or if it's not yet locked.
922 if (!_slave || !_slave->locked()) {
923 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
924 SaveSessionRequested (_current_snapshot_name);
929 /* always try to get rid of this */
931 remove_pending_capture_state ();
933 /* save the current state of things if appropriate */
935 if (did_record && !saved) {
936 SaveSessionRequested (_current_snapshot_name);
939 if (ptw & PostTransportStop) {
941 if (!Config->get_loop_is_mode()) {
946 PositionChanged (_transport_frame); /* EMIT SIGNAL */
947 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
948 TransportStateChange (); /* EMIT SIGNAL */
949 AutomationWatch::instance().transport_stop_automation_watches (_transport_frame);
951 /* and start it up again if relevant */
953 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
954 request_transport_speed (1.0);
957 /* Even if we didn't do a pending locate roll this time, we don't want it hanging
958 around for next time.
960 pending_locate_roll = false;
964 Session::check_declick_out ()
966 bool locate_required = transport_sub_state & PendingLocate;
968 /* this is called after a process() iteration. if PendingDeclickOut was set,
969 it means that we were waiting to declick the output (which has just been
970 done) before maybe doing something else. this is where we do that "something else".
972 note: called from the audio thread.
975 if (transport_sub_state & PendingDeclickOut) {
977 if (locate_required) {
978 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
979 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
981 if (!(transport_sub_state & StopPendingCapture)) {
982 stop_transport (pending_abort);
983 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
987 } else if (transport_sub_state & PendingLoopDeclickOut) {
988 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
989 transport_sub_state &= ~PendingLoopDeclickOut;
994 Session::unset_play_loop ()
998 clear_events (SessionEvent::AutoLoop);
999 clear_events (SessionEvent::AutoLoopDeclick);
1000 set_track_loop (false);
1003 if (Config->get_seamless_loop()) {
1004 /* likely need to flush track buffers: this will locate us to wherever we are */
1005 add_post_transport_work (PostTransportLocate);
1006 _butler->schedule_transport_work ();
1012 Session::set_track_loop (bool yn)
1014 Location* loc = _locations->auto_loop_location ();
1020 boost::shared_ptr<RouteList> rl = routes.reader ();
1022 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1023 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1024 if (tr && !tr->hidden()) {
1025 tr->set_loop (yn ? loc : 0);
1031 Session::set_play_loop (bool yn, double speed)
1033 /* Called from event-handling context */
1037 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
1038 /* nothing to do, or can't change loop status while recording */
1042 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
1043 warning << string_compose (
1044 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
1045 "Recommend changing the configured options"), PROGRAM_NAME)
1053 have_looped = false;
1057 unset_play_range ();
1059 if (Config->get_seamless_loop()) {
1060 if (!Config->get_loop_is_mode()) {
1061 /* set all tracks to use internal looping */
1062 set_track_loop (true);
1064 /* we will do this in the locate to the start OR when we hit the end
1065 * of the loop for the first time
1069 /* set all tracks to NOT use internal looping */
1070 set_track_loop (false);
1073 /* Put the delick and loop events in into the event list. The declick event will
1074 cause a de-clicking fade-out just before the end of the loop, and it will also result
1075 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
1080 auto_loop_declick_range (loc, dcp, dcl);
1081 merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
1082 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
1084 /* if requested to roll, locate to start of loop and
1085 * roll but ONLY if we're not already rolling.
1087 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
1090 if (Config->get_loop_is_mode()) {
1091 /* loop IS a transport mode: if already
1092 rolling, do not locate to loop start.
1094 if (!transport_rolling() && (speed != 0.0)) {
1095 start_locate (loc->start(), true, true, false, true);
1099 start_locate (loc->start(), true, true, false, true);
1109 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
1110 TransportStateChange ();
1113 Session::flush_all_inserts ()
1115 boost::shared_ptr<RouteList> r = routes.reader ();
1117 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1118 (*i)->flush_processors ();
1123 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
1125 if (target_frame < 0) {
1126 error << _("Locate called for negative sample position - ignored") << endmsg;
1130 if (synced_to_engine()) {
1135 _slave->speed_and_position (sp, pos);
1137 if (target_frame != pos) {
1139 if (config.get_jack_time_master()) {
1140 /* actually locate now, since otherwise jack_timebase_callback
1141 will use the incorrect _transport_frame and report an old
1142 and incorrect time to Jack transport
1144 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1147 /* tell JACK to change transport position, and we will
1148 follow along later in ::follow_slave()
1151 _engine.transport_locate (target_frame);
1153 if (sp != 1.0f && with_roll) {
1154 _engine.transport_start ();
1160 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1165 Session::micro_locate (framecnt_t distance)
1167 boost::shared_ptr<RouteList> rl = routes.reader();
1168 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1169 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1170 if (tr && !tr->can_internal_playback_seek (distance)) {
1175 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1176 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1178 tr->internal_playback_seek (distance);
1182 _transport_frame += distance;
1186 /** @param with_mmc true to send a MMC locate command when the locate is done */
1188 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
1190 bool need_butler = false;
1192 /* Locates for seamless looping are fairly different from other
1193 * locates. They assume that the diskstream buffers for each track
1194 * already have the correct data in them, and thus there is no need to
1195 * actually tell the tracks to locate. What does need to be done,
1196 * though, is all the housekeeping that is associated with non-linear
1197 * changes in the value of _transport_frame.
1200 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
1201 target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
1203 if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
1205 /* already at the desired position. Not forced to locate,
1206 the loop isn't changing, so unless we're told to
1207 start rolling also, there's nothing to do but
1208 tell the world where we are (again).
1212 set_transport_speed (1.0, 0, false);
1214 loop_changing = false;
1215 Located (); /* EMIT SIGNAL */
1219 if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
1220 /* Schedule a declick. We'll be called again when its done.
1221 We only do it this way for ordinary locates, not those
1222 due to **seamless** loops.
1225 if (!(transport_sub_state & PendingDeclickOut)) {
1226 transport_sub_state |= (PendingDeclickOut|PendingLocate);
1227 pending_locate_frame = target_frame;
1228 pending_locate_roll = with_roll;
1229 pending_locate_flush = with_flush;
1234 // Update Timecode time
1235 _transport_frame = target_frame;
1236 _last_roll_or_reversal_location = target_frame;
1237 timecode_time(_transport_frame, transmitting_timecode_time);
1239 /* do "stopped" stuff if:
1241 * we are rolling AND
1242 * no autoplay in effect AND
1243 * we're not going to keep rolling after the locate AND
1244 * !(playing a loop with JACK sync)
1248 bool transport_was_stopped = !transport_rolling();
1250 if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1251 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1252 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1253 transport_was_stopped = true;
1255 /* otherwise tell the world that we located */
1259 if (force || !for_loop_enabled || loop_changing) {
1261 PostTransportWork todo = PostTransportLocate;
1263 if (with_roll && transport_was_stopped) {
1264 todo = PostTransportWork (todo | PostTransportRoll);
1267 add_post_transport_work (todo);
1272 /* this is functionally what clear_clicks() does but with a tentative lock */
1274 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1276 if (clickm.locked()) {
1278 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1287 /* switch from input if we're going to roll */
1288 if (Config->get_monitoring_model() == HardwareMonitoring) {
1289 set_track_monitor_input_status (!config.get_auto_input());
1292 /* otherwise we're going to stop, so do the opposite */
1293 if (Config->get_monitoring_model() == HardwareMonitoring) {
1294 set_track_monitor_input_status (true);
1298 /* cancel looped playback if transport pos outside of loop range */
1301 Location* al = _locations->auto_loop_location();
1304 if (_transport_frame < al->start() || _transport_frame >= al->end()) {
1306 // located outside the loop: cancel looping directly, this is called from event handling context
1308 have_looped = false;
1310 if (!Config->get_loop_is_mode()) {
1311 set_play_loop (false, _transport_speed);
1313 if (Config->get_seamless_loop()) {
1314 /* this will make the non_realtime_locate() in the butler
1315 which then causes seek() in tracks actually do the right
1318 set_track_loop (false);
1322 } else if (_transport_frame == al->start()) {
1324 // located to start of loop - this is looping, basically
1328 if (_last_roll_location != al->start()) {
1329 /* didn't start at loop start - playback must have
1330 * started before loop since we've now hit the loop
1333 add_post_transport_work (PostTransportLocate);
1339 boost::shared_ptr<RouteList> rl = routes.reader();
1341 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1342 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1344 if (tr && tr->rec_enable_control()->get_value()) {
1345 // tell it we've looped, so it can deal with the record state
1346 tr->transport_looped (_transport_frame);
1351 TransportLooped(); // EMIT SIGNAL
1357 _butler->schedule_transport_work ();
1360 loop_changing = false;
1362 _send_timecode_update = true;
1365 send_mmc_locate (_transport_frame);
1368 _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
1369 if (!synced_to_engine () || _transport_frame == _engine.transport_frame ()) {
1370 Located (); /* EMIT SIGNAL */
1374 /** Set the transport speed.
1375 * Called from the process thread.
1376 * @param speed New speed
1379 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1381 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1382 speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1384 if (_transport_speed == speed) {
1385 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1386 _default_transport_speed = 1.0;
1391 if (actively_recording() && speed != 1.0 && speed != 0.0) {
1392 /* no varispeed during recording */
1393 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1394 _transport_speed, _transport_frame));
1398 _target_transport_speed = fabs(speed);
1400 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1401 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1405 speed = min (8.0, speed);
1406 } else if (speed < 0) {
1407 speed = max (-8.0, speed);
1410 if (transport_rolling() && speed == 0.0) {
1412 /* we are rolling and we want to stop */
1414 if (Config->get_monitoring_model() == HardwareMonitoring) {
1415 set_track_monitor_input_status (true);
1418 if (synced_to_engine ()) {
1420 /* do this here because our response to the slave won't
1423 _play_range = false;
1424 _count_in_once = false;
1427 _engine.transport_stop ();
1429 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1431 if (!auto_return_enabled) {
1432 _requested_return_frame = destination_frame;
1435 stop_transport (abort);
1438 } else if (transport_stopped() && speed == 1.0) {
1440 _default_transport_speed = speed;
1442 /* we are stopped and we want to start rolling at speed 1 */
1444 if (Config->get_loop_is_mode() && play_loop) {
1446 Location *location = _locations->auto_loop_location();
1448 if (location != 0) {
1449 if (_transport_frame != location->start()) {
1451 if (Config->get_seamless_loop()) {
1452 /* force tracks to do their thing */
1453 set_track_loop (true);
1456 /* jump to start and then roll from there */
1458 request_locate (location->start(), true);
1464 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1465 set_track_monitor_input_status (false);
1468 if (synced_to_engine()) {
1469 _engine.transport_start ();
1470 _count_in_once = false;
1477 /* not zero, not 1.0 ... varispeed */
1479 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1480 warning << string_compose (
1481 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1487 if (actively_recording()) {
1491 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1495 if (speed < 0.0 && _transport_frame == 0) {
1501 /* if we are reversing relative to the current speed, or relative to the speed
1502 before the last stop, then we have to do extra work.
1505 PostTransportWork todo = PostTransportWork (0);
1507 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
1508 todo = PostTransportWork (todo | PostTransportReverse);
1509 _last_roll_or_reversal_location = _transport_frame;
1512 _last_transport_speed = _transport_speed;
1513 _transport_speed = speed;
1516 _default_transport_speed = speed;
1519 boost::shared_ptr<RouteList> rl = routes.reader();
1520 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1521 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1522 if (tr && tr->realtime_set_speed (tr->speed(), true)) {
1523 todo = PostTransportWork (todo | PostTransportSpeed);
1528 add_post_transport_work (todo);
1529 _butler->schedule_transport_work ();
1532 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1534 /* throttle signal emissions.
1535 * when slaved [_last]_transport_speed
1536 * usually changes every cycle (tiny amounts due to DLL).
1537 * Emitting a signal every cycle is overkill and unwarranted.
1539 * Using _last_transport_speed is not acceptable,
1540 * since it allows for large changes over a long period
1541 * of time. Hence we introduce a dedicated variable to keep track
1543 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1544 * for TransportStateChange() here is the ShuttleControl display.
1546 if (fabs (_signalled_varispeed - speed) > .002
1547 // still, signal hard changes to 1.0 and 0.0:
1548 || ( speed == 1.0 && _signalled_varispeed != 1.0)
1549 || ( speed == 0.0 && _signalled_varispeed != 0.0)
1552 TransportStateChange (); /* EMIT SIGNAL */
1553 _signalled_varispeed = speed;
1559 /** Stop the transport. */
1561 Session::stop_transport (bool abort, bool clear_state)
1563 _count_in_once = false;
1564 if (_transport_speed == 0.0f) {
1568 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
1570 if (!get_transport_declick_required()) {
1572 /* stop has not yet been scheduled */
1574 boost::shared_ptr<RouteList> rl = routes.reader();
1575 framepos_t stop_target = audible_frame();
1577 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1578 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1580 tr->prepare_to_stop (_transport_frame, stop_target);
1586 if (actively_recording() && /* we are recording */
1587 worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1589 /* we need to capture the audio that is still somewhere in the pipeline between
1590 wherever it was generated and the process callback. This means that even though
1591 the user (or something else) has asked us to stop, we have to roll
1592 past this point and then reset the playhead/transport location to
1593 the position at which the stop was requested.
1595 we still need playback to "stop" now, however, which is why we schedule
1599 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1600 _transport_frame, _worst_input_latency,
1601 _transport_frame + _worst_input_latency,
1604 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1605 _transport_frame + _worst_input_latency,
1610 /* request a declick at the start of the next process cycle() so that playback ceases.
1611 It will remain silent until we actually stop (at the StopOnce event somewhere in
1612 the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1613 does not stop the transport too early.
1615 new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1619 /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1621 new_bits = PendingDeclickOut;
1622 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
1625 /* we'll be called again after the declick */
1626 transport_sub_state = SubState (transport_sub_state|new_bits);
1627 pending_abort = abort;
1633 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
1635 /* declick was scheduled, but we've been called again, which means it is really time to stop
1637 XXX: we should probably split this off into its own method and call it explicitly.
1640 realtime_stop (abort, clear_state);
1641 _butler->schedule_transport_work ();
1645 /** Called from the process thread */
1647 Session::start_transport ()
1649 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1651 _last_roll_location = _transport_frame;
1652 _last_roll_or_reversal_location = _transport_frame;
1654 have_looped = false;
1656 /* if record status is Enabled, move it to Recording. if its
1657 already Recording, move it to Disabled.
1660 switch (record_status()) {
1662 if (!config.get_punch_in() && !preroll_record_punch_enabled()) {
1669 disable_record (false);
1677 transport_sub_state |= PendingDeclickIn;
1679 _transport_speed = _default_transport_speed;
1680 _target_transport_speed = _transport_speed;
1682 boost::shared_ptr<RouteList> rl = routes.reader();
1683 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1684 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1686 tr->realtime_set_speed (tr->speed(), true);
1690 if (!_engine.freewheeling()) {
1691 Timecode::Time time;
1692 timecode_time_subframes (_transport_frame, time);
1693 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1694 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1697 if (actively_recording() && click_data && (config.get_count_in () || _count_in_once)) {
1698 _count_in_once = false;
1699 /* calculate count-in duration (in audio samples)
1700 * - use [fixed] tempo/meter at _transport_frame
1701 * - calc duration of 1 bar + time-to-beat before or at transport_frame
1703 const Tempo& tempo = _tempo_map->tempo_at_frame (_transport_frame);
1704 const Meter& meter = _tempo_map->meter_at_frame (_transport_frame);
1706 const double num = meter.divisions_per_bar ();
1707 const double den = meter.note_divisor ();
1708 const double barbeat = _tempo_map->exact_qn_at_frame (_transport_frame, 0) * den / (4. * num);
1709 const double bar_fract = fmod (barbeat, 1.0); // fraction of bar elapsed.
1711 _count_in_samples = meter.frames_per_bar (tempo, _current_frame_rate);
1713 double dt = _count_in_samples / num;
1714 if (bar_fract == 0) {
1715 /* at bar boundary, count-in 2 bars before start. */
1716 _count_in_samples *= 2;
1718 /* beats left after full bar until roll position */
1719 _count_in_samples *= 1. + bar_fract;
1723 framepos_t cf = _transport_frame - _count_in_samples;
1724 while (cf < _transport_frame) {
1725 add_click (cf - _worst_track_latency, clickbeat == 0);
1727 clickbeat = fmod (clickbeat + 1, num);
1732 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1733 TransportStateChange (); /* EMIT SIGNAL */
1736 /** Do any transport work in the audio thread that needs to be done after the
1737 * transport thread is finished. Audio thread, realtime safe.
1740 Session::post_transport ()
1742 PostTransportWork ptw = post_transport_work ();
1744 if (ptw & PostTransportAudition) {
1745 if (auditioner && auditioner->auditioning()) {
1746 process_function = &Session::process_audition;
1748 process_function = &Session::process_with_events;
1752 if (ptw & PostTransportStop) {
1754 transport_sub_state = 0;
1757 if (ptw & PostTransportLocate) {
1759 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1760 _count_in_once = false;
1763 transport_sub_state = 0;
1768 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1771 set_post_transport_work (PostTransportWork (0));
1775 Session::reset_rf_scale (framecnt_t motion)
1777 cumulative_rf_motion += motion;
1779 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1781 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1783 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1795 Session::mtc_status_changed (bool yn)
1797 g_atomic_int_set (&_mtc_active, yn);
1798 MTCSyncStateChanged( yn );
1802 Session::ltc_status_changed (bool yn)
1804 g_atomic_int_set (&_ltc_active, yn);
1805 LTCSyncStateChanged( yn );
1809 Session::use_sync_source (Slave* new_slave)
1811 /* Runs in process() context */
1813 bool non_rt_required = false;
1815 /* XXX this deletion is problematic because we're in RT context */
1820 MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1822 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1823 MTCSyncStateChanged(mtc_slave->locked() );
1825 if (g_atomic_int_get (&_mtc_active) ){
1826 g_atomic_int_set (&_mtc_active, 0);
1827 MTCSyncStateChanged( false );
1829 mtc_status_connection.disconnect ();
1832 LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1834 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1835 LTCSyncStateChanged (ltc_slave->locked() );
1837 if (g_atomic_int_get (&_ltc_active) ){
1838 g_atomic_int_set (&_ltc_active, 0);
1839 LTCSyncStateChanged( false );
1841 ltc_status_connection.disconnect ();
1844 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1846 // need to queue this for next process() cycle
1847 _send_timecode_update = true;
1849 boost::shared_ptr<RouteList> rl = routes.reader();
1850 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1851 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1852 if (tr && !tr->hidden()) {
1853 if (tr->realtime_set_speed (tr->speed(), true)) {
1854 non_rt_required = true;
1856 tr->set_slaved (_slave != 0);
1860 if (non_rt_required) {
1861 add_post_transport_work (PostTransportSpeed);
1862 _butler->schedule_transport_work ();
1869 Session::drop_sync_source ()
1871 request_sync_source (0);
1875 Session::switch_to_sync_source (SyncSource src)
1879 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1883 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1888 new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1891 catch (failed_constructor& err) {
1897 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1902 new_slave = new LTC_Slave (*this);
1905 catch (failed_constructor& err) {
1912 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1917 new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1920 catch (failed_constructor& err) {
1926 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1930 if (config.get_video_pullup() != 0.0f) {
1934 new_slave = new Engine_Slave (*AudioEngine::instance());
1942 request_sync_source (new_slave);
1946 Session::set_track_speed (Track* track, double speed)
1948 if (track->realtime_set_speed (speed, false)) {
1949 add_post_transport_work (PostTransportSpeed);
1950 _butler->schedule_transport_work ();
1956 Session::unset_play_range ()
1958 _play_range = false;
1959 _clear_event_type (SessionEvent::RangeStop);
1960 _clear_event_type (SessionEvent::RangeLocate);
1964 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1968 /* Called from event-processing context */
1970 unset_play_range ();
1972 if (range.empty()) {
1973 /* _play_range set to false in unset_play_range()
1975 if (!leave_rolling) {
1976 /* stop transport */
1977 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1985 /* cancel loop play */
1988 list<AudioRange>::size_type sz = range.size();
1992 list<AudioRange>::iterator i = range.begin();
1993 list<AudioRange>::iterator next;
1995 while (i != range.end()) {
2000 /* locating/stopping is subject to delays for declicking.
2003 framepos_t requested_frame = i->end;
2005 if (requested_frame > current_block_size) {
2006 requested_frame -= current_block_size;
2008 requested_frame = 0;
2011 if (next == range.end()) {
2012 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
2014 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
2022 } else if (sz == 1) {
2024 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
2029 /* save range so we can do auto-return etc. */
2031 current_audio_range = range;
2033 /* now start rolling at the right place */
2035 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
2038 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
2039 TransportStateChange ();
2043 Session::request_bounded_roll (framepos_t start, framepos_t end)
2045 AudioRange ar (start, end, 0);
2046 list<AudioRange> lar;
2049 request_play_range (&lar, true);
2053 Session::set_requested_return_frame (framepos_t return_to)
2055 _requested_return_frame = return_to;
2059 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
2061 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
2062 ev->target2_frame = start;
2067 Session::engine_halted ()
2071 /* there will be no more calls to process(), so
2072 we'd better clean up for ourselves, right now.
2074 but first, make sure the butler is out of
2082 realtime_stop (false, true);
2083 non_realtime_stop (false, 0, ignored);
2084 transport_sub_state = 0;
2086 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
2087 TransportStateChange (); /* EMIT SIGNAL */
2092 Session::xrun_recovery ()
2096 Xrun (_transport_frame); /* EMIT SIGNAL */
2098 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
2100 /* it didn't actually halt, but we need
2101 to handle things in the same way.
2109 Session::route_processors_changed (RouteProcessorChange c)
2111 if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
2115 if (c.type == RouteProcessorChange::MeterPointChange) {
2120 if (c.type == RouteProcessorChange::RealTimeChange) {
2125 update_latency_compensation ();
2132 Session::allow_auto_play (bool yn)
2134 auto_play_legal = yn;
2138 Session::maybe_stop (framepos_t limit)
2140 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
2141 if (synced_to_engine () && config.get_jack_time_master ()) {
2142 _engine.transport_stop ();
2143 } else if (!synced_to_engine ()) {
2152 Session::send_mmc_locate (framepos_t t)
2158 if (!_engine.freewheeling()) {
2159 Timecode::Time time;
2160 timecode_time_subframes (t, time);
2161 send_immediate_mmc (MIDI::MachineControlCommand (time));
2165 /** Ask the transport to not send timecode until further notice. The suspension
2166 * will come into effect some finite time after this call, and timecode_transmission_suspended()
2167 * should be checked by the caller to find out when.
2170 Session::request_suspend_timecode_transmission ()
2172 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2177 Session::request_resume_timecode_transmission ()
2179 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2184 Session::timecode_transmission_suspended () const
2186 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;