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/disk_reader.h"
45 #include "ardour/location.h"
46 #include "ardour/profile.h"
47 #include "ardour/scene_changer.h"
48 #include "ardour/session.h"
49 #include "ardour/slave.h"
50 #include "ardour/tempo.h"
51 #include "ardour/operations.h"
52 #include "ardour/vca.h"
53 #include "ardour/vca_manager.h"
58 using namespace ARDOUR;
62 Session::add_post_transport_work (PostTransportWork ptw)
64 PostTransportWork oldval;
65 PostTransportWork newval;
69 oldval = (PostTransportWork) g_atomic_int_get (&_post_transport_work);
70 newval = PostTransportWork (oldval | ptw);
71 if (g_atomic_int_compare_and_exchange (&_post_transport_work, oldval, newval)) {
77 error << "Could not set post transport work! Crazy thread madness, call the programmers" << endmsg;
81 Session::request_sync_source (Slave* new_slave)
83 SessionEvent* ev = new SessionEvent (SessionEvent::SetSyncSource, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
86 seamless = Config->get_seamless_loop ();
88 if (dynamic_cast<Engine_Slave*>(new_slave)) {
89 /* JACK cannot support seamless looping at present */
90 Config->set_seamless_loop (false);
92 /* reset to whatever the value was before we last switched slaves */
93 Config->set_seamless_loop (_was_seamless);
96 /* save value of seamless from before the switch */
97 _was_seamless = seamless;
99 ev->slave = new_slave;
100 DEBUG_TRACE (DEBUG::Slave, "sent request for new slave\n");
105 Session::request_transport_speed (double speed, bool as_default)
107 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, speed);
108 ev->third_yes_or_no = as_default; // as_default
109 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request transport speed = %1 as default = %2\n", speed, as_default));
113 /** Request a new transport speed, but if the speed parameter is exactly zero then use
114 * a very small +ve value to prevent the transport actually stopping. This method should
115 * be used by callers who are varying transport speed but don't ever want to stop it.
118 Session::request_transport_speed_nonzero (double speed, bool as_default)
124 request_transport_speed (speed, as_default);
128 Session::request_stop (bool abort, bool clear_state)
130 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, audible_frame(), 0.0, abort, clear_state);
131 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));
136 Session::request_locate (framepos_t target_frame, bool with_roll)
138 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, false);
139 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request locate to %1\n", target_frame));
144 Session::force_locate (framepos_t target_frame, bool with_roll)
146 SessionEvent *ev = new SessionEvent (with_roll ? SessionEvent::LocateRoll : SessionEvent::Locate, SessionEvent::Add, SessionEvent::Immediate, target_frame, 0, true);
147 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request forced locate to %1\n", target_frame));
152 Session::unset_preroll_record_punch ()
154 if (_preroll_record_punch_pos >= 0) {
155 remove_event (_preroll_record_punch_pos, SessionEvent::RecordStart);
157 _preroll_record_punch_pos = -1;
161 Session::unset_preroll_record_trim ()
163 _preroll_record_trim_len = 0;
167 Session::request_preroll_record_punch (framepos_t rec_in, framecnt_t preroll)
169 if (actively_recording ()) {
172 unset_preroll_record_punch ();
173 unset_preroll_record_trim ();
174 framepos_t start = std::max ((framepos_t)0, rec_in - preroll);
176 _preroll_record_punch_pos = rec_in;
177 if (_preroll_record_punch_pos >= 0) {
178 replace_event (SessionEvent::RecordStart, _preroll_record_punch_pos);
179 config.set_punch_in (false);
180 config.set_punch_out (false);
182 maybe_enable_record ();
183 request_locate (start, true);
184 set_requested_return_frame (rec_in);
188 Session::request_preroll_record_trim (framepos_t rec_in, framecnt_t preroll)
190 if (actively_recording ()) {
193 unset_preroll_record_punch ();
194 unset_preroll_record_trim ();
196 config.set_punch_in (false);
197 config.set_punch_out (false);
199 framepos_t pos = std::max ((framepos_t)0, rec_in - preroll);
200 _preroll_record_trim_len = preroll;
201 maybe_enable_record ();
202 request_locate (pos, true);
203 set_requested_return_frame (rec_in);
207 Session::request_count_in_record ()
209 if (actively_recording ()) {
212 if (transport_rolling()) {
215 maybe_enable_record ();
216 _count_in_once = true;
217 request_transport_speed (1.0, true);
221 Session::request_play_loop (bool yn, bool change_transport_roll)
224 // don't attempt to loop when not using Internal Transport
225 // see also gtk2_ardour/ardour_ui_options.cc parameter_changed()
230 Location *location = _locations->auto_loop_location();
233 if (location == 0 && yn) {
234 error << _("Cannot loop - no loop range defined")
239 if (change_transport_roll) {
240 if (transport_rolling()) {
241 /* start looping at current speed */
242 target_speed = transport_speed ();
244 /* currently stopped */
246 /* start looping at normal speed */
253 /* leave the speed alone */
254 target_speed = transport_speed ();
257 ev = new SessionEvent (SessionEvent::SetLoop, SessionEvent::Add, SessionEvent::Immediate, 0, target_speed, yn);
258 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request set loop = %1, change roll state ? %2\n", yn, change_transport_roll));
262 if (!change_transport_roll) {
263 if (!transport_rolling()) {
264 /* we're not changing transport state, but we do want
265 to set up position for the new loop. Don't
266 do this if we're rolling already.
268 request_locate (location->start(), false);
272 if (!change_transport_roll && Config->get_seamless_loop() && transport_rolling()) {
273 // request an immediate locate to refresh the tracks
274 // after disabling looping
275 request_locate (_transport_frame-1, false);
281 Session::request_play_range (list<AudioRange>* range, bool leave_rolling)
283 SessionEvent* ev = new SessionEvent (SessionEvent::SetPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, (leave_rolling ? 1.0 : 0.0));
285 ev->audio_range = *range;
287 ev->audio_range.clear ();
289 DEBUG_TRACE (DEBUG::Transport, string_compose ("Request play range, leave rolling ? %1\n", leave_rolling));
294 Session::request_cancel_play_range ()
296 SessionEvent* ev = new SessionEvent (SessionEvent::CancelPlayAudioRange, SessionEvent::Add, SessionEvent::Immediate, 0, 0);
302 Session::realtime_stop (bool abort, bool clear_state)
304 DEBUG_TRACE (DEBUG::Transport, string_compose ("realtime stop @ %1\n", _transport_frame));
305 PostTransportWork todo = PostTransportWork (0);
307 /* assume that when we start, we'll be moving forwards */
309 if (_transport_speed < 0.0f) {
310 todo = (PostTransportWork (todo | PostTransportStop | PostTransportReverse));
311 _default_transport_speed = 1.0;
313 todo = PostTransportWork (todo | PostTransportStop);
318 boost::shared_ptr<RouteList> r = routes.reader ();
320 for (RouteList::iterator i = r->begin (); i != r->end(); ++i) {
321 (*i)->realtime_handle_transport_stopped ();
324 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop complete, auto-return scheduled for return to %1\n", _requested_return_frame));
326 /* the duration change is not guaranteed to have happened, but is likely */
328 todo = PostTransportWork (todo | PostTransportDuration);
331 todo = PostTransportWork (todo | PostTransportAbort);
335 todo = PostTransportWork (todo | PostTransportClearSubstate);
339 add_post_transport_work (todo);
342 _clear_event_type (SessionEvent::StopOnce);
343 _clear_event_type (SessionEvent::RangeStop);
344 _clear_event_type (SessionEvent::RangeLocate);
346 /* if we're going to clear loop state, then force disabling record BUT only if we're not doing latched rec-enable */
347 disable_record (true, (!Config->get_latched_record_enable() && clear_state));
349 if (clear_state && !Config->get_loop_is_mode()) {
353 reset_slave_state ();
355 _transport_speed = 0;
356 _target_transport_speed = 0;
358 g_atomic_int_set (&_playback_load, 100);
359 g_atomic_int_set (&_capture_load, 100);
361 if (config.get_use_video_sync()) {
362 waiting_for_sync_offset = true;
365 transport_sub_state = 0;
369 Session::realtime_locate ()
371 boost::shared_ptr<RouteList> r = routes.reader ();
372 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
373 (*i)->realtime_locate ();
378 Session::butler_transport_work ()
380 /* Note: this function executes in the butler thread context */
384 PostTransportWork ptw;
385 boost::shared_ptr<RouteList> r = routes.reader ();
388 int on_entry = g_atomic_int_get (&_butler->should_do_transport_work);
390 ptw = post_transport_work();
392 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler transport work, todo = %1 at %2\n", enum_2_string (ptw), (before = g_get_monotonic_time())));
395 if (ptw & PostTransportLocate) {
397 if (get_play_loop() && !Config->get_seamless_loop()) {
399 DEBUG_TRACE (DEBUG::Butler, "flush loop recording fragment to disk\n");
401 /* this locate might be happening while we are
404 * Non-seamless looping will require a locate (below) that
405 * will reset capture buffers and throw away data.
407 * Rather than first find all tracks and see if they
408 * have outstanding data, just do a flush anyway. It
409 * may be cheaper this way anyway, and is certainly
413 bool more_disk_io_to_do = false;
417 more_disk_io_to_do = _butler->flush_tracks_to_disk_after_locate (r, errors);
423 if (more_disk_io_to_do) {
432 if (ptw & PostTransportAdjustPlaybackBuffering) {
433 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
434 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
436 tr->adjust_playback_buffering ();
437 /* and refill those buffers ... */
439 (*i)->non_realtime_locate (_transport_frame);
441 VCAList v = _vca_manager->vcas ();
442 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
443 (*i)->non_realtime_locate (_transport_frame);
447 if (ptw & PostTransportAdjustCaptureBuffering) {
448 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
449 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
451 tr->adjust_capture_buffering ();
456 if (ptw & PostTransportCurveRealloc) {
457 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
458 (*i)->curve_reallocate();
462 if (ptw & PostTransportSpeed) {
463 non_realtime_set_speed ();
466 if (ptw & PostTransportReverse) {
469 cumulative_rf_motion = 0;
472 /* don't seek if locate will take care of that in non_realtime_stop() */
474 if (!(ptw & PostTransportLocate)) {
475 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
476 (*i)->non_realtime_locate (_transport_frame);
478 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
479 /* new request, stop seeking, and start again */
480 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
484 VCAList v = _vca_manager->vcas ();
485 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
486 (*i)->non_realtime_locate (_transport_frame);
491 if (ptw & PostTransportLocate) {
492 DEBUG_TRACE (DEBUG::Transport, "nonrealtime locate invoked from BTW\n");
493 non_realtime_locate ();
496 if (ptw & PostTransportStop) {
497 non_realtime_stop (ptw & PostTransportAbort, on_entry, finished);
499 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
504 if (ptw & PostTransportOverWrite) {
505 non_realtime_overwrite (on_entry, finished);
507 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
512 if (ptw & PostTransportAudition) {
513 non_realtime_set_audition ();
516 g_atomic_int_dec_and_test (&_butler->should_do_transport_work);
518 DEBUG_TRACE (DEBUG::Transport, string_compose (X_("Butler transport work all done after %1 usecs @ %2 trw = %3\n"), g_get_monotonic_time() - before, _transport_frame, _butler->transport_work_requested()));
522 Session::non_realtime_set_speed ()
524 boost::shared_ptr<RouteList> rl = routes.reader();
525 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
526 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
528 tr->non_realtime_speed_change ();
534 Session::non_realtime_overwrite (int on_entry, bool& finished)
536 boost::shared_ptr<RouteList> rl = routes.reader();
537 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
538 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
539 if (tr && tr->pending_overwrite ()) {
540 tr->overwrite_existing_buffers ();
542 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
551 Session::non_realtime_locate ()
553 DEBUG_TRACE (DEBUG::Transport, string_compose ("locate tracks to %1\n", _transport_frame));
555 if (Config->get_loop_is_mode() && get_play_loop()) {
557 Location *loc = _locations->auto_loop_location();
559 if (!loc || (_transport_frame < loc->start() || _transport_frame >= loc->end())) {
560 /* jumped out of loop range: stop tracks from looping,
561 but leave loop (mode) enabled.
563 set_track_loop (false);
565 } else if (loc && Config->get_seamless_loop() &&
566 ((loc->start() <= _transport_frame) ||
567 (loc->end() > _transport_frame) ) ) {
569 /* jumping to start of loop. This might have been done before but it is
570 * idempotent and cheap. Doing it here ensures that when we start playback
571 * outside the loop we still flip tracks into the magic seamless mode
574 set_track_loop (true);
577 set_track_loop (false);
582 /* no more looping .. should have been noticed elsewhere */
586 microseconds_t begin = get_microseconds ();
588 const framepos_t tf = _transport_frame;
591 boost::shared_ptr<RouteList> rl = routes.reader();
594 cerr << "\n\n >>> START Non-RT locate on routes to " << tf << "\n\n";
596 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
597 (*i)->non_realtime_locate (tf);
600 cerr << "\n\n <<< DONE Non-RT locate on routes\n\n";
604 VCAList v = _vca_manager->vcas ();
605 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
606 (*i)->non_realtime_locate (tf);
610 microseconds_t end = get_microseconds ();
611 cerr << "Locate took " << setprecision (3) << ((end - begin) /1000000.0) << " secs\n";
613 _scene_changer->locate (_transport_frame);
615 /* XXX: it would be nice to generate the new clicks here (in the non-RT thread)
616 rather than clearing them so that the RT thread has to spend time constructing
617 them (in Session::click).
622 #ifdef USE_TRACKS_CODE_FEATURES
624 Session::select_playhead_priority_target (framepos_t& jump_to)
628 AutoReturnTarget autoreturn = Config->get_auto_return_target_list ();
634 if (Profile->get_trx() && transport_rolling() ) {
635 // We're playing, so do nothing.
636 // Next stop will put us where we need to be.
640 /* Note that the order of checking each AutoReturnTarget flag defines
641 the priority each flag.
643 Ardour/Mixbus: Last Locate
648 Tracks: Range Selection
654 if (autoreturn & RangeSelectionStart) {
655 if (!_range_selection.empty()) {
656 jump_to = _range_selection.from;
658 if (transport_rolling ()) {
659 /* Range selection no longer exists, but we're playing,
660 so do nothing. Next stop will put us where
668 if (jump_to < 0 && (autoreturn & Loop) && get_play_loop()) {
669 /* don't try to handle loop play when synced to JACK */
671 if (!synced_to_engine()) {
672 Location *location = _locations->auto_loop_location();
675 jump_to = location->start();
677 if (Config->get_seamless_loop()) {
678 /* need to get track buffers reloaded */
679 set_track_loop (true);
685 if (jump_to < 0 && (autoreturn & RegionSelectionStart)) {
686 if (!_object_selection.empty()) {
687 jump_to = _object_selection.from;
691 if (jump_to < 0 && (autoreturn & LastLocate)) {
692 jump_to = _last_roll_location;
700 Session::select_playhead_priority_target (framepos_t& jump_to)
702 if (config.get_external_sync() || !config.get_auto_return()) {
706 jump_to = _last_roll_location;
713 Session::follow_playhead_priority ()
717 if (select_playhead_priority_target (target)) {
718 request_locate (target);
723 Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
729 PostTransportWork ptw = post_transport_work();
734 boost::shared_ptr<RouteList> rl = routes.reader();
735 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
736 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
737 if (tr && tr->get_captured_frames () != 0) {
743 /* stop and locate are merged here because they share a lot of common stuff */
746 now = localtime (&xnow);
749 auditioner->cancel_audition ();
752 cumulative_rf_motion = 0;
756 begin_reversible_command (Operations::capture);
757 _have_captured = true;
760 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: DS stop\n"));
762 if (abort && did_record) {
763 /* no reason to save the session file when we remove sources
765 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
768 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
769 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
771 tr->transport_stopped_wallclock (*now, xnow, abort);
775 if (abort && did_record) {
776 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
779 boost::shared_ptr<RouteList> r = routes.reader ();
781 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
782 if (!(*i)->is_auditioner()) {
783 (*i)->set_pending_declick (0);
788 commit_reversible_command ();
789 /* increase take name */
790 if (config.get_track_name_take () && !config.get_take_name ().empty()) {
791 string newname = config.get_take_name();
792 config.set_take_name(bump_name_number (newname));
796 if (_engine.running()) {
797 PostTransportWork ptw = post_transport_work ();
799 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
800 (*i)->non_realtime_transport_stop (_transport_frame, !(ptw & PostTransportLocate) || pending_locate_flush);
802 VCAList v = _vca_manager->vcas ();
803 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
804 (*i)->non_realtime_transport_stop (_transport_frame, !(ptw & PostTransportLocate) || pending_locate_flush);
807 update_latency_compensation ();
810 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
812 if (auto_return_enabled ||
813 (ptw & PostTransportLocate) ||
814 (_requested_return_frame >= 0) ||
815 synced_to_engine()) {
817 if (pending_locate_flush) {
818 flush_all_inserts ();
821 // rg: what is the logic behind this case?
822 // _requested_return_frame should be ignored when synced_to_engine/slaved.
823 // currently worked around in MTC_Slave by forcing _requested_return_frame to -1
825 if ((auto_return_enabled || synced_to_engine() || _requested_return_frame >= 0) &&
826 !(ptw & PostTransportLocate)) {
828 /* no explicit locate queued */
830 bool do_locate = false;
832 if (_requested_return_frame >= 0) {
834 /* explicit return request pre-queued in event list. overrides everything else */
836 _transport_frame = _requested_return_frame;
842 if (select_playhead_priority_target (jump_to)) {
844 _transport_frame = jump_to;
849 _transport_frame = _last_roll_location;
854 _requested_return_frame = -1;
857 _engine.transport_locate (_transport_frame);
864 unset_preroll_record_trim ();
866 /* do this before seeking, because otherwise the tracks will do the wrong thing in seamless loop mode.
869 if (ptw & PostTransportClearSubstate) {
871 if (!Config->get_loop_is_mode()) {
876 /* this for() block can be put inside the previous if() and has the effect of ... ??? what */
879 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: locate\n"));
880 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
881 DEBUG_TRACE (DEBUG::Transport, string_compose ("Butler PTW: locate on %1\n", (*i)->name()));
882 (*i)->non_realtime_locate (_transport_frame);
884 if (on_entry != g_atomic_int_get (&_butler->should_do_transport_work)) {
886 /* we will be back */
893 VCAList v = _vca_manager->vcas ();
894 for (VCAList::const_iterator i = v.begin(); i != v.end(); ++i) {
895 (*i)->non_realtime_locate (_transport_frame);
901 /* don't bother with this stuff if we're disconnected from the engine,
902 because there will be no process callbacks to deliver stuff from
905 if (_engine.connected() && !_engine.freewheeling()) {
906 // need to queue this in the next RT cycle
907 _send_timecode_update = true;
909 if (!dynamic_cast<MTC_Slave*>(_slave)) {
910 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdStop));
912 /* This (::non_realtime_stop()) gets called by main
913 process thread, which will lead to confusion
914 when calling AsyncMIDIPort::write().
916 Something must be done. XXX
918 send_mmc_locate (_transport_frame);
922 if ((ptw & PostTransportLocate) && get_record_enabled()) {
923 /* This is scheduled by realtime_stop(), which is also done
924 * when a slave requests /locate/ for an initial sync.
925 * We can't hold up the slave for long with a save() here,
926 * without breaking its initial sync cycle.
928 * save state only if there's no slave or if it's not yet locked.
930 if (!_slave || !_slave->locked()) {
931 DEBUG_TRACE (DEBUG::Transport, X_("Butler PTW: requests save\n"));
932 SaveSessionRequested (_current_snapshot_name);
937 /* always try to get rid of this */
939 remove_pending_capture_state ();
941 /* save the current state of things if appropriate */
943 if (did_record && !saved) {
944 SaveSessionRequested (_current_snapshot_name);
947 if (ptw & PostTransportStop) {
949 if (!Config->get_loop_is_mode()) {
954 PositionChanged (_transport_frame); /* EMIT SIGNAL */
955 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed));
956 TransportStateChange (); /* EMIT SIGNAL */
957 AutomationWatch::instance().transport_stop_automation_watches (_transport_frame);
959 /* and start it up again if relevant */
961 if ((ptw & PostTransportLocate) && !config.get_external_sync() && pending_locate_roll) {
962 request_transport_speed (1.0);
965 /* Even if we didn't do a pending locate roll this time, we don't want it hanging
966 around for next time.
968 pending_locate_roll = false;
972 Session::check_declick_out ()
974 bool locate_required = transport_sub_state & PendingLocate;
976 /* this is called after a process() iteration. if PendingDeclickOut was set,
977 it means that we were waiting to declick the output (which has just been
978 done) before maybe doing something else. this is where we do that "something else".
980 note: called from the audio thread.
983 if (transport_sub_state & PendingDeclickOut) {
985 if (locate_required) {
986 start_locate (pending_locate_frame, pending_locate_roll, pending_locate_flush);
987 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
989 if (!(transport_sub_state & StopPendingCapture)) {
990 stop_transport (pending_abort);
991 transport_sub_state &= ~(PendingDeclickOut|PendingLocate);
995 } else if (transport_sub_state & PendingLoopDeclickOut) {
996 /* Nothing else to do here; we've declicked, and the loop event will be along shortly */
997 transport_sub_state &= ~PendingLoopDeclickOut;
1002 Session::unset_play_loop ()
1006 clear_events (SessionEvent::AutoLoop);
1007 clear_events (SessionEvent::AutoLoopDeclick);
1008 set_track_loop (false);
1011 if (Config->get_seamless_loop()) {
1012 /* likely need to flush track buffers: this will locate us to wherever we are */
1013 add_post_transport_work (PostTransportLocate);
1014 _butler->schedule_transport_work ();
1020 Session::set_track_loop (bool yn)
1022 Location* loc = _locations->auto_loop_location ();
1028 boost::shared_ptr<RouteList> rl = routes.reader ();
1030 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1031 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1032 if (tr && !tr->is_private_route()) {
1033 tr->set_loop (yn ? loc : 0);
1039 Session::set_play_loop (bool yn, double speed)
1041 /* Called from event-handling context */
1045 if (yn == play_loop || (actively_recording() && yn) || (loc = _locations->auto_loop_location()) == 0) {
1046 /* nothing to do, or can't change loop status while recording */
1050 if (yn && Config->get_seamless_loop() && synced_to_engine()) {
1051 warning << string_compose (
1052 _("Seamless looping cannot be supported while %1 is using JACK transport.\n"
1053 "Recommend changing the configured options"), PROGRAM_NAME)
1061 have_looped = false;
1065 unset_play_range ();
1067 if (Config->get_seamless_loop()) {
1068 if (!Config->get_loop_is_mode()) {
1069 /* set all tracks to use internal looping */
1070 set_track_loop (true);
1072 /* we will do this in the locate to the start OR when we hit the end
1073 * of the loop for the first time
1077 /* set all tracks to NOT use internal looping */
1078 set_track_loop (false);
1081 /* Put the delick and loop events in into the event list. The declick event will
1082 cause a de-clicking fade-out just before the end of the loop, and it will also result
1083 in a fade-in when the loop restarts. The AutoLoop event will peform the actual loop.
1088 auto_loop_declick_range (loc, dcp, dcl);
1089 merge_event (new SessionEvent (SessionEvent::AutoLoopDeclick, SessionEvent::Replace, dcp, dcl, 0.0f));
1090 merge_event (new SessionEvent (SessionEvent::AutoLoop, SessionEvent::Replace, loc->end(), loc->start(), 0.0f));
1092 /* if requested to roll, locate to start of loop and
1093 * roll but ONLY if we're not already rolling.
1095 args: positition, roll=true, flush=true, with_loop=false, force buffer refill if seamless looping
1098 if (Config->get_loop_is_mode()) {
1099 /* loop IS a transport mode: if already
1100 rolling, do not locate to loop start.
1102 if (!transport_rolling() && (speed != 0.0)) {
1103 start_locate (loc->start(), true, true, false, true);
1107 start_locate (loc->start(), true, true, false, true);
1117 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed));
1118 TransportStateChange ();
1121 Session::flush_all_inserts ()
1123 boost::shared_ptr<RouteList> r = routes.reader ();
1125 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1126 (*i)->flush_processors ();
1131 Session::start_locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force)
1133 if (target_frame < 0) {
1134 error << _("Locate called for negative sample position - ignored") << endmsg;
1138 if (synced_to_engine()) {
1143 _slave->speed_and_position (sp, pos);
1145 if (target_frame != pos) {
1147 if (config.get_jack_time_master()) {
1148 /* actually locate now, since otherwise jack_timebase_callback
1149 will use the incorrect _transport_frame and report an old
1150 and incorrect time to Jack transport
1152 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1155 /* tell JACK to change transport position, and we will
1156 follow along later in ::follow_slave()
1159 _engine.transport_locate (target_frame);
1161 if (sp != 1.0f && with_roll) {
1162 _engine.transport_start ();
1168 locate (target_frame, with_roll, with_flush, for_loop_enabled, force);
1173 Session::micro_locate (framecnt_t distance)
1175 boost::shared_ptr<RouteList> rl = routes.reader();
1176 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1177 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1178 if (tr && !tr->can_internal_playback_seek (distance)) {
1183 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1184 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1186 tr->internal_playback_seek (distance);
1190 _transport_frame += distance;
1194 /** @param with_mmc true to send a MMC locate command when the locate is done */
1196 Session::locate (framepos_t target_frame, bool with_roll, bool with_flush, bool for_loop_enabled, bool force, bool with_mmc)
1198 bool need_butler = false;
1200 /* Locates for seamless looping are fairly different from other
1201 * locates. They assume that the diskstream buffers for each track
1202 * already have the correct data in them, and thus there is no need to
1203 * actually tell the tracks to locate. What does need to be done,
1204 * though, is all the housekeeping that is associated with non-linear
1205 * changes in the value of _transport_frame.
1208 DEBUG_TRACE (DEBUG::Transport, string_compose ("rt-locate to %1, roll %2 flush %3 loop-enabled %4 force %5 mmc %6\n",
1209 target_frame, with_roll, with_flush, for_loop_enabled, force, with_mmc));
1211 if (!force && _transport_frame == target_frame && !loop_changing && !for_loop_enabled) {
1213 /* already at the desired position. Not forced to locate,
1214 the loop isn't changing, so unless we're told to
1215 start rolling also, there's nothing to do but
1216 tell the world where we are (again).
1220 set_transport_speed (1.0, 0, false);
1222 loop_changing = false;
1223 Located (); /* EMIT SIGNAL */
1227 if (_transport_speed && !(for_loop_enabled && Config->get_seamless_loop())) {
1228 /* Schedule a declick. We'll be called again when its done.
1229 We only do it this way for ordinary locates, not those
1230 due to **seamless** loops.
1233 if (!(transport_sub_state & PendingDeclickOut)) {
1234 transport_sub_state |= (PendingDeclickOut|PendingLocate);
1235 pending_locate_frame = target_frame;
1236 pending_locate_roll = with_roll;
1237 pending_locate_flush = with_flush;
1242 // Update Timecode time
1243 _transport_frame = target_frame;
1244 _last_roll_or_reversal_location = target_frame;
1245 timecode_time(_transport_frame, transmitting_timecode_time);
1247 /* do "stopped" stuff if:
1249 * we are rolling AND
1250 * no autoplay in effect AND
1251 * we're not going to keep rolling after the locate AND
1252 * !(playing a loop with JACK sync)
1256 bool transport_was_stopped = !transport_rolling();
1258 if (!transport_was_stopped && (!auto_play_legal || !config.get_auto_play()) && !with_roll && !(synced_to_engine() && play_loop) &&
1259 (!Profile->get_trx() || !(config.get_external_sync() && !synced_to_engine()))) {
1260 realtime_stop (false, true); // XXX paul - check if the 2nd arg is really correct
1261 transport_was_stopped = true;
1263 /* otherwise tell the world that we located */
1267 if (force || !for_loop_enabled || loop_changing) {
1269 PostTransportWork todo = PostTransportLocate;
1271 if (with_roll && transport_was_stopped) {
1272 todo = PostTransportWork (todo | PostTransportRoll);
1275 add_post_transport_work (todo);
1280 /* this is functionally what clear_clicks() does but with a tentative lock */
1282 Glib::Threads::RWLock::WriterLock clickm (click_lock, Glib::Threads::TRY_LOCK);
1284 if (clickm.locked()) {
1286 for (Clicks::iterator i = clicks.begin(); i != clicks.end(); ++i) {
1295 /* switch from input if we're going to roll */
1296 if (Config->get_monitoring_model() == HardwareMonitoring) {
1297 set_track_monitor_input_status (!config.get_auto_input());
1300 /* otherwise we're going to stop, so do the opposite */
1301 if (Config->get_monitoring_model() == HardwareMonitoring) {
1302 set_track_monitor_input_status (true);
1306 /* cancel looped playback if transport pos outside of loop range */
1309 Location* al = _locations->auto_loop_location();
1312 if (_transport_frame < al->start() || _transport_frame >= al->end()) {
1314 // located outside the loop: cancel looping directly, this is called from event handling context
1316 have_looped = false;
1318 if (!Config->get_loop_is_mode()) {
1319 set_play_loop (false, _transport_speed);
1321 if (Config->get_seamless_loop()) {
1322 /* this will make the non_realtime_locate() in the butler
1323 which then causes seek() in tracks actually do the right
1326 set_track_loop (false);
1330 } else if (_transport_frame == al->start()) {
1332 // located to start of loop - this is looping, basically
1336 if (_last_roll_location != al->start()) {
1337 /* didn't start at loop start - playback must have
1338 * started before loop since we've now hit the loop
1341 add_post_transport_work (PostTransportLocate);
1347 boost::shared_ptr<RouteList> rl = routes.reader();
1349 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1350 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1352 if (tr && tr->rec_enable_control()->get_value()) {
1353 // tell it we've looped, so it can deal with the record state
1354 tr->transport_looped (_transport_frame);
1359 TransportLooped(); // EMIT SIGNAL
1365 _butler->schedule_transport_work ();
1368 loop_changing = false;
1370 _send_timecode_update = true;
1373 send_mmc_locate (_transport_frame);
1376 _last_roll_location = _last_roll_or_reversal_location = _transport_frame;
1377 if (!synced_to_engine () || _transport_frame == _engine.transport_frame ()) {
1378 Located (); /* EMIT SIGNAL */
1382 /** Set the transport speed.
1383 * Called from the process thread.
1384 * @param speed New speed
1387 Session::set_transport_speed (double speed, framepos_t destination_frame, bool abort, bool clear_state, bool as_default)
1389 DEBUG_TRACE (DEBUG::Transport, string_compose ("@ %5 Set transport speed to %1, abort = %2 clear_state = %3, current = %4 as_default %6\n",
1390 speed, abort, clear_state, _transport_speed, _transport_frame, as_default));
1392 if (_transport_speed == speed) {
1393 if (as_default && speed == 0.0) { // => reset default transport speed. hacky or what?
1394 _default_transport_speed = 1.0;
1399 if (actively_recording() && speed != 1.0 && speed != 0.0) {
1400 /* no varispeed during recording */
1401 DEBUG_TRACE (DEBUG::Transport, string_compose ("No varispeed during recording cur_speed %1, frame %2\n",
1402 _transport_speed, _transport_frame));
1406 _target_transport_speed = fabs(speed);
1408 /* 8.0 max speed is somewhat arbitrary but based on guestimates regarding disk i/o capability
1409 and user needs. We really need CD-style "skip" playback for ffwd and rewind.
1413 speed = min (8.0, speed);
1414 } else if (speed < 0) {
1415 speed = max (-8.0, speed);
1418 if (transport_rolling() && speed == 0.0) {
1420 /* we are rolling and we want to stop */
1422 if (Config->get_monitoring_model() == HardwareMonitoring) {
1423 set_track_monitor_input_status (true);
1426 if (synced_to_engine ()) {
1428 /* do this here because our response to the slave won't
1431 _play_range = false;
1432 _count_in_once = false;
1435 _engine.transport_stop ();
1437 bool const auto_return_enabled = (!config.get_external_sync() && (Config->get_auto_return_target_list() || abort));
1439 if (!auto_return_enabled) {
1440 _requested_return_frame = destination_frame;
1443 stop_transport (abort);
1446 } else if (transport_stopped() && speed == 1.0) {
1448 _default_transport_speed = speed;
1450 /* we are stopped and we want to start rolling at speed 1 */
1452 if (Config->get_loop_is_mode() && play_loop) {
1454 Location *location = _locations->auto_loop_location();
1456 if (location != 0) {
1457 if (_transport_frame != location->start()) {
1459 if (Config->get_seamless_loop()) {
1460 /* force tracks to do their thing */
1461 set_track_loop (true);
1464 /* jump to start and then roll from there */
1466 request_locate (location->start(), true);
1472 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1473 set_track_monitor_input_status (false);
1476 if (synced_to_engine()) {
1477 _engine.transport_start ();
1478 _count_in_once = false;
1485 /* not zero, not 1.0 ... varispeed */
1487 if ((synced_to_engine()) && speed != 0.0 && speed != 1.0) {
1488 warning << string_compose (
1489 _("Global varispeed cannot be supported while %1 is connected to JACK transport control"),
1495 if (actively_recording()) {
1499 if (speed > 0.0 && _transport_frame == current_end_frame()) {
1503 if (speed < 0.0 && _transport_frame == 0) {
1509 /* if we are reversing relative to the current speed, or relative to the speed
1510 before the last stop, then we have to do extra work.
1513 PostTransportWork todo = PostTransportWork (0);
1515 if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0 && speed < 0.0)) {
1516 todo = PostTransportWork (todo | PostTransportReverse);
1517 _last_roll_or_reversal_location = _transport_frame;
1520 _last_transport_speed = _transport_speed;
1521 _transport_speed = speed;
1524 _default_transport_speed = speed;
1527 boost::shared_ptr<RouteList> rl = routes.reader();
1528 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1529 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1530 if (tr && tr->realtime_speed_change()) {
1531 todo = PostTransportWork (todo | PostTransportSpeed);
1536 add_post_transport_work (todo);
1537 _butler->schedule_transport_work ();
1540 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed));
1542 /* throttle signal emissions.
1543 * when slaved [_last]_transport_speed
1544 * usually changes every cycle (tiny amounts due to DLL).
1545 * Emitting a signal every cycle is overkill and unwarranted.
1547 * Using _last_transport_speed is not acceptable,
1548 * since it allows for large changes over a long period
1549 * of time. Hence we introduce a dedicated variable to keep track
1551 * The 0.2% dead-zone is somewhat arbitrary. Main use-case
1552 * for TransportStateChange() here is the ShuttleControl display.
1554 if (fabs (_signalled_varispeed - speed) > .002
1555 // still, signal hard changes to 1.0 and 0.0:
1556 || ( speed == 1.0 && _signalled_varispeed != 1.0)
1557 || ( speed == 0.0 && _signalled_varispeed != 0.0)
1560 TransportStateChange (); /* EMIT SIGNAL */
1561 _signalled_varispeed = speed;
1567 /** Stop the transport. */
1569 Session::stop_transport (bool abort, bool clear_state)
1571 _count_in_once = false;
1572 if (_transport_speed == 0.0f) {
1576 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop_transport, declick required? %1\n", get_transport_declick_required()));
1578 if (!get_transport_declick_required()) {
1580 /* stop has not yet been scheduled */
1582 boost::shared_ptr<RouteList> rl = routes.reader();
1583 framepos_t stop_target = audible_frame();
1585 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1586 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1588 tr->prepare_to_stop (_transport_frame, stop_target);
1594 if (actively_recording() && /* we are recording */
1595 worst_input_latency() > current_block_size) { /* input latency exceeds block size, so simple 1 cycle delay before stop is not enough */
1597 /* we need to capture the audio that is still somewhere in the pipeline between
1598 wherever it was generated and the process callback. This means that even though
1599 the user (or something else) has asked us to stop, we have to roll
1600 past this point and then reset the playhead/transport location to
1601 the position at which the stop was requested.
1603 we still need playback to "stop" now, however, which is why we schedule
1607 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop transport requested @ %1, scheduled for + %2 = %3, abort = %4\n",
1608 _transport_frame, _worst_input_latency,
1609 _transport_frame + _worst_input_latency,
1612 SessionEvent *ev = new SessionEvent (SessionEvent::StopOnce, SessionEvent::Replace,
1613 _transport_frame + _worst_input_latency,
1618 /* request a declick at the start of the next process cycle() so that playback ceases.
1619 It will remain silent until we actually stop (at the StopOnce event somewhere in
1620 the future). The extra flag (StopPendingCapture) is set to ensure that check_declick_out()
1621 does not stop the transport too early.
1623 new_bits = SubState (PendingDeclickOut|StopPendingCapture);
1627 /* Not recording, schedule a declick in the next process() cycle and then stop at its end */
1629 new_bits = PendingDeclickOut;
1630 DEBUG_TRACE (DEBUG::Transport, string_compose ("stop scheduled for next process cycle @ %1\n", _transport_frame));
1633 /* we'll be called again after the declick */
1634 transport_sub_state = SubState (transport_sub_state|new_bits);
1635 pending_abort = abort;
1641 DEBUG_TRACE (DEBUG::Transport, "time to actually stop\n");
1643 /* declick was scheduled, but we've been called again, which means it is really time to stop
1645 XXX: we should probably split this off into its own method and call it explicitly.
1648 realtime_stop (abort, clear_state);
1649 _butler->schedule_transport_work ();
1653 /** Called from the process thread */
1655 Session::start_transport ()
1657 DEBUG_TRACE (DEBUG::Transport, "start_transport\n");
1659 _last_roll_location = _transport_frame;
1660 _last_roll_or_reversal_location = _transport_frame;
1662 have_looped = false;
1664 /* if record status is Enabled, move it to Recording. if its
1665 already Recording, move it to Disabled.
1668 switch (record_status()) {
1670 if (!config.get_punch_in() && !preroll_record_punch_enabled()) {
1677 disable_record (false);
1685 transport_sub_state |= PendingDeclickIn;
1687 _transport_speed = _default_transport_speed;
1688 _target_transport_speed = _transport_speed;
1690 boost::shared_ptr<RouteList> rl = routes.reader();
1691 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1692 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1694 tr->realtime_speed_change ();
1698 if (!_engine.freewheeling()) {
1699 Timecode::Time time;
1700 timecode_time_subframes (_transport_frame, time);
1701 if (!dynamic_cast<MTC_Slave*>(_slave)) {
1702 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdDeferredPlay));
1705 if (actively_recording() && click_data && (config.get_count_in () || _count_in_once)) {
1706 _count_in_once = false;
1707 /* calculate count-in duration (in audio samples)
1708 * - use [fixed] tempo/meter at _transport_frame
1709 * - calc duration of 1 bar + time-to-beat before or at transport_frame
1711 const Tempo& tempo = _tempo_map->tempo_at_frame (_transport_frame);
1712 const Meter& meter = _tempo_map->meter_at_frame (_transport_frame);
1714 const double num = meter.divisions_per_bar ();
1715 const double den = meter.note_divisor ();
1716 const double barbeat = _tempo_map->exact_qn_at_frame (_transport_frame, 0) * den / (4. * num);
1717 const double bar_fract = fmod (barbeat, 1.0); // fraction of bar elapsed.
1719 _count_in_samples = meter.frames_per_bar (tempo, _current_frame_rate);
1721 double dt = _count_in_samples / num;
1722 if (bar_fract == 0) {
1723 /* at bar boundary, count-in 2 bars before start. */
1724 _count_in_samples *= 2;
1726 /* beats left after full bar until roll position */
1727 _count_in_samples *= 1. + bar_fract;
1731 framepos_t cf = _transport_frame - _count_in_samples;
1732 while (cf < _transport_frame) {
1733 add_click (cf - _worst_track_latency, clickbeat == 0);
1735 clickbeat = fmod (clickbeat + 1, num);
1740 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed));
1741 TransportStateChange (); /* EMIT SIGNAL */
1744 /** Do any transport work in the audio thread that needs to be done after the
1745 * transport thread is finished. Audio thread, realtime safe.
1748 Session::post_transport ()
1750 PostTransportWork ptw = post_transport_work ();
1752 if (ptw & PostTransportAudition) {
1753 if (auditioner && auditioner->auditioning()) {
1754 process_function = &Session::process_audition;
1756 process_function = &Session::process_with_events;
1760 if (ptw & PostTransportStop) {
1762 transport_sub_state = 0;
1765 if (ptw & PostTransportLocate) {
1767 if (((!config.get_external_sync() && (auto_play_legal && config.get_auto_play())) && !_exporting) || (ptw & PostTransportRoll)) {
1768 _count_in_once = false;
1771 transport_sub_state = 0;
1776 /* XXX is this really safe? shouldn't we just be unsetting the bits that we actually
1779 set_post_transport_work (PostTransportWork (0));
1783 Session::reset_rf_scale (framecnt_t motion)
1785 cumulative_rf_motion += motion;
1787 if (cumulative_rf_motion < 4 * _current_frame_rate) {
1789 } else if (cumulative_rf_motion < 8 * _current_frame_rate) {
1791 } else if (cumulative_rf_motion < 16 * _current_frame_rate) {
1803 Session::mtc_status_changed (bool yn)
1805 g_atomic_int_set (&_mtc_active, yn);
1806 MTCSyncStateChanged( yn );
1810 Session::ltc_status_changed (bool yn)
1812 g_atomic_int_set (&_ltc_active, yn);
1813 LTCSyncStateChanged( yn );
1817 Session::use_sync_source (Slave* new_slave)
1819 /* Runs in process() context */
1821 bool non_rt_required = false;
1823 /* XXX this deletion is problematic because we're in RT context */
1829 /* slave change, reset any DiskIO block on disk output because it is no
1830 longer valid with a new slave.
1832 DiskReader::set_no_disk_output (false);
1834 MTC_Slave* mtc_slave = dynamic_cast<MTC_Slave*>(_slave);
1836 mtc_slave->ActiveChanged.connect_same_thread (mtc_status_connection, boost::bind (&Session::mtc_status_changed, this, _1));
1837 MTCSyncStateChanged(mtc_slave->locked() );
1839 if (g_atomic_int_get (&_mtc_active) ){
1840 g_atomic_int_set (&_mtc_active, 0);
1841 MTCSyncStateChanged( false );
1843 mtc_status_connection.disconnect ();
1846 LTC_Slave* ltc_slave = dynamic_cast<LTC_Slave*> (_slave);
1848 ltc_slave->ActiveChanged.connect_same_thread (ltc_status_connection, boost::bind (&Session::ltc_status_changed, this, _1));
1849 LTCSyncStateChanged (ltc_slave->locked() );
1851 if (g_atomic_int_get (&_ltc_active) ){
1852 g_atomic_int_set (&_ltc_active, 0);
1853 LTCSyncStateChanged( false );
1855 ltc_status_connection.disconnect ();
1858 DEBUG_TRACE (DEBUG::Slave, string_compose ("set new slave to %1\n", _slave));
1860 // need to queue this for next process() cycle
1861 _send_timecode_update = true;
1863 boost::shared_ptr<RouteList> rl = routes.reader();
1864 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1865 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1866 if (tr && !tr->is_private_route()) {
1867 if (tr->realtime_speed_change()) {
1868 non_rt_required = true;
1870 tr->set_slaved (_slave != 0);
1874 if (non_rt_required) {
1875 add_post_transport_work (PostTransportSpeed);
1876 _butler->schedule_transport_work ();
1883 Session::drop_sync_source ()
1885 request_sync_source (0);
1889 Session::switch_to_sync_source (SyncSource src)
1893 DEBUG_TRACE (DEBUG::Slave, string_compose ("Setting up sync source %1\n", enum_2_string (src)));
1897 if (_slave && dynamic_cast<MTC_Slave*>(_slave)) {
1902 new_slave = new MTC_Slave (*this, *_midi_ports->mtc_input_port());
1905 catch (failed_constructor& err) {
1911 if (_slave && dynamic_cast<LTC_Slave*>(_slave)) {
1916 new_slave = new LTC_Slave (*this);
1919 catch (failed_constructor& err) {
1926 if (_slave && dynamic_cast<MIDIClock_Slave*>(_slave)) {
1931 new_slave = new MIDIClock_Slave (*this, *_midi_ports->midi_clock_input_port(), 24);
1934 catch (failed_constructor& err) {
1940 if (_slave && dynamic_cast<Engine_Slave*>(_slave)) {
1944 if (config.get_video_pullup() != 0.0f) {
1948 new_slave = new Engine_Slave (*AudioEngine::instance());
1956 request_sync_source (new_slave);
1960 Session::unset_play_range ()
1962 _play_range = false;
1963 _clear_event_type (SessionEvent::RangeStop);
1964 _clear_event_type (SessionEvent::RangeLocate);
1968 Session::set_play_range (list<AudioRange>& range, bool leave_rolling)
1972 /* Called from event-processing context */
1974 unset_play_range ();
1976 if (range.empty()) {
1977 /* _play_range set to false in unset_play_range()
1979 if (!leave_rolling) {
1980 /* stop transport */
1981 SessionEvent* ev = new SessionEvent (SessionEvent::SetTransportSpeed, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0f, false);
1989 /* cancel loop play */
1992 list<AudioRange>::size_type sz = range.size();
1996 list<AudioRange>::iterator i = range.begin();
1997 list<AudioRange>::iterator next;
1999 while (i != range.end()) {
2004 /* locating/stopping is subject to delays for declicking.
2007 framepos_t requested_frame = i->end;
2009 if (requested_frame > current_block_size) {
2010 requested_frame -= current_block_size;
2012 requested_frame = 0;
2015 if (next == range.end()) {
2016 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, requested_frame, 0, 0.0f);
2018 ev = new SessionEvent (SessionEvent::RangeLocate, SessionEvent::Add, requested_frame, (*next).start, 0.0f);
2026 } else if (sz == 1) {
2028 ev = new SessionEvent (SessionEvent::RangeStop, SessionEvent::Add, range.front().end, 0, 0.0f);
2033 /* save range so we can do auto-return etc. */
2035 current_audio_range = range;
2037 /* now start rolling at the right place */
2039 ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false);
2042 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed));
2043 TransportStateChange ();
2047 Session::request_bounded_roll (framepos_t start, framepos_t end)
2049 AudioRange ar (start, end, 0);
2050 list<AudioRange> lar;
2053 request_play_range (&lar, true);
2057 Session::set_requested_return_frame (framepos_t return_to)
2059 _requested_return_frame = return_to;
2063 Session::request_roll_at_and_return (framepos_t start, framepos_t return_to)
2065 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRollLocate, SessionEvent::Add, SessionEvent::Immediate, return_to, 1.0);
2066 ev->target2_frame = start;
2071 Session::engine_halted ()
2075 /* there will be no more calls to process(), so
2076 we'd better clean up for ourselves, right now.
2078 but first, make sure the butler is out of
2086 realtime_stop (false, true);
2087 non_realtime_stop (false, 0, ignored);
2088 transport_sub_state = 0;
2090 DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed));
2091 TransportStateChange (); /* EMIT SIGNAL */
2096 Session::xrun_recovery ()
2100 Xrun (_transport_frame); /* EMIT SIGNAL */
2102 if (Config->get_stop_recording_on_xrun() && actively_recording()) {
2104 /* it didn't actually halt, but we need
2105 to handle things in the same way.
2113 Session::route_processors_changed (RouteProcessorChange c)
2115 if (g_atomic_int_get (&_ignore_route_processor_changes) > 0) {
2119 if (c.type == RouteProcessorChange::MeterPointChange) {
2124 if (c.type == RouteProcessorChange::RealTimeChange) {
2129 update_latency_compensation ();
2136 Session::allow_auto_play (bool yn)
2138 auto_play_legal = yn;
2142 Session::maybe_stop (framepos_t limit)
2144 if ((_transport_speed > 0.0f && _transport_frame >= limit) || (_transport_speed < 0.0f && _transport_frame == 0)) {
2145 if (synced_to_engine () && config.get_jack_time_master ()) {
2146 _engine.transport_stop ();
2147 } else if (!synced_to_engine ()) {
2156 Session::send_mmc_locate (framepos_t t)
2162 if (!_engine.freewheeling()) {
2163 Timecode::Time time;
2164 timecode_time_subframes (t, time);
2165 send_immediate_mmc (MIDI::MachineControlCommand (time));
2169 /** Ask the transport to not send timecode until further notice. The suspension
2170 * will come into effect some finite time after this call, and timecode_transmission_suspended()
2171 * should be checked by the caller to find out when.
2174 Session::request_suspend_timecode_transmission ()
2176 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, false);
2181 Session::request_resume_timecode_transmission ()
2183 SessionEvent* ev = new SessionEvent (SessionEvent::SetTimecodeTransmission, SessionEvent::Add, SessionEvent::Immediate, 0, 0, true);
2188 Session::timecode_transmission_suspended () const
2190 return g_atomic_int_get (&_suspend_timecode_transmission) == 1;